1 1.5 isaki /* $NetBSD: linear.c,v 1.5 2024/04/20 05:38:40 isaki Exp $ */ 2 1.2 isaki 3 1.2 isaki /* 4 1.2 isaki * Copyright (C) 2017 Tetsuya Isaki. All rights reserved. 5 1.2 isaki * Copyright (C) 2017 Y.Sugahara (moveccr). All rights reserved. 6 1.2 isaki * 7 1.2 isaki * Redistribution and use in source and binary forms, with or without 8 1.2 isaki * modification, are permitted provided that the following conditions 9 1.2 isaki * are met: 10 1.2 isaki * 1. Redistributions of source code must retain the above copyright 11 1.2 isaki * notice, this list of conditions and the following disclaimer. 12 1.2 isaki * 2. Redistributions in binary form must reproduce the above copyright 13 1.2 isaki * notice, this list of conditions and the following disclaimer in the 14 1.2 isaki * documentation and/or other materials provided with the distribution. 15 1.2 isaki * 16 1.2 isaki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.2 isaki * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.2 isaki * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.2 isaki * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.2 isaki * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 1.2 isaki * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 1.2 isaki * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 1.2 isaki * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 1.2 isaki * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.2 isaki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.2 isaki * SUCH DAMAGE. 27 1.2 isaki */ 28 1.2 isaki 29 1.2 isaki #include <sys/cdefs.h> 30 1.5 isaki __KERNEL_RCSID(0, "$NetBSD: linear.c,v 1.5 2024/04/20 05:38:40 isaki Exp $"); 31 1.2 isaki 32 1.4 skrll #include <sys/param.h> 33 1.2 isaki #include <sys/types.h> 34 1.2 isaki #include <sys/systm.h> 35 1.2 isaki #include <sys/device.h> 36 1.2 isaki #include <dev/audio/audiovar.h> 37 1.2 isaki #include <dev/audio/linear.h> 38 1.2 isaki 39 1.2 isaki /* 40 1.2 isaki * audio_linear8_to_internal: 41 1.2 isaki * This filter performs conversion from [US]LINEAR8 to internal format. 42 1.2 isaki */ 43 1.2 isaki void 44 1.2 isaki audio_linear8_to_internal(audio_filter_arg_t *arg) 45 1.2 isaki { 46 1.2 isaki const uint8_t *s; 47 1.2 isaki aint_t *d; 48 1.2 isaki uint8_t xor; 49 1.2 isaki u_int sample_count; 50 1.2 isaki u_int i; 51 1.2 isaki 52 1.2 isaki DIAGNOSTIC_filter_arg(arg); 53 1.2 isaki KASSERT(audio_format2_is_linear(arg->srcfmt)); 54 1.2 isaki KASSERT(arg->srcfmt->precision == 8); 55 1.2 isaki KASSERT(arg->srcfmt->stride == 8); 56 1.2 isaki KASSERT(audio_format2_is_internal(arg->dstfmt)); 57 1.2 isaki KASSERT(arg->srcfmt->channels == arg->dstfmt->channels); 58 1.2 isaki 59 1.2 isaki s = arg->src; 60 1.2 isaki d = arg->dst; 61 1.2 isaki sample_count = arg->count * arg->srcfmt->channels; 62 1.2 isaki xor = audio_format2_is_signed(arg->srcfmt) ? 0 : 0x80; 63 1.2 isaki 64 1.2 isaki for (i = 0; i < sample_count; i++) { 65 1.2 isaki uint8_t val; 66 1.2 isaki val = *s++; 67 1.2 isaki val ^= xor; 68 1.2 isaki *d++ = (auint_t)val << (AUDIO_INTERNAL_BITS - 8); 69 1.2 isaki } 70 1.2 isaki } 71 1.2 isaki 72 1.2 isaki /* 73 1.2 isaki * audio_internal_to_linear8: 74 1.2 isaki * This filter performs conversion from internal format to [US]LINEAR8. 75 1.2 isaki */ 76 1.2 isaki void 77 1.2 isaki audio_internal_to_linear8(audio_filter_arg_t *arg) 78 1.2 isaki { 79 1.2 isaki const aint_t *s; 80 1.2 isaki uint8_t *d; 81 1.2 isaki uint8_t xor; 82 1.2 isaki u_int sample_count; 83 1.2 isaki u_int i; 84 1.2 isaki 85 1.2 isaki DIAGNOSTIC_filter_arg(arg); 86 1.2 isaki KASSERT(audio_format2_is_linear(arg->dstfmt)); 87 1.2 isaki KASSERT(arg->dstfmt->precision == 8); 88 1.2 isaki KASSERT(arg->dstfmt->stride == 8); 89 1.2 isaki KASSERT(audio_format2_is_internal(arg->srcfmt)); 90 1.2 isaki KASSERT(arg->srcfmt->channels == arg->dstfmt->channels); 91 1.2 isaki 92 1.2 isaki s = arg->src; 93 1.2 isaki d = arg->dst; 94 1.2 isaki sample_count = arg->count * arg->srcfmt->channels; 95 1.2 isaki xor = audio_format2_is_signed(arg->dstfmt) ? 0 : 0x80; 96 1.2 isaki 97 1.2 isaki for (i = 0; i < sample_count; i++) { 98 1.2 isaki uint8_t val; 99 1.2 isaki val = (*s++) >> (AUDIO_INTERNAL_BITS - 8); 100 1.2 isaki val ^= xor; 101 1.2 isaki *d++ = val; 102 1.2 isaki } 103 1.2 isaki } 104 1.2 isaki 105 1.2 isaki /* 106 1.2 isaki * audio_linear16_to_internal: 107 1.2 isaki * This filter performs conversion from [US]LINEAR16{LE,BE} to internal 108 1.2 isaki * format. 109 1.2 isaki */ 110 1.2 isaki void 111 1.2 isaki audio_linear16_to_internal(audio_filter_arg_t *arg) 112 1.2 isaki { 113 1.2 isaki const uint16_t *s; 114 1.2 isaki aint_t *d; 115 1.2 isaki uint16_t xor; 116 1.2 isaki u_int sample_count; 117 1.2 isaki u_int shift; 118 1.2 isaki u_int i; 119 1.2 isaki bool is_src_NE; 120 1.2 isaki 121 1.2 isaki DIAGNOSTIC_filter_arg(arg); 122 1.2 isaki KASSERT(audio_format2_is_linear(arg->srcfmt)); 123 1.2 isaki KASSERT(arg->srcfmt->precision == 16); 124 1.2 isaki KASSERT(arg->srcfmt->stride == 16); 125 1.2 isaki KASSERT(audio_format2_is_internal(arg->dstfmt)); 126 1.2 isaki KASSERT(arg->srcfmt->channels == arg->dstfmt->channels); 127 1.2 isaki 128 1.2 isaki s = arg->src; 129 1.2 isaki d = arg->dst; 130 1.2 isaki sample_count = arg->count * arg->srcfmt->channels; 131 1.2 isaki 132 1.2 isaki shift = AUDIO_INTERNAL_BITS - 16; 133 1.2 isaki xor = audio_format2_is_signed(arg->srcfmt) ? 0 : 0x8000; 134 1.2 isaki is_src_NE = (audio_format2_endian(arg->srcfmt) == BYTE_ORDER); 135 1.2 isaki 136 1.2 isaki /* 137 1.2 isaki * Since slinear16_OppositeEndian to slinear_NativeEndian is used 138 1.2 isaki * so much especially on big endian machines, so it's expanded. 139 1.2 isaki * Other conversions are rarely used, so they are compressed. 140 1.2 isaki */ 141 1.2 isaki if (__predict_true(xor == 0) && is_src_NE == false) { 142 1.2 isaki /* slinear16_OE to slinear<AI>_NE */ 143 1.2 isaki for (i = 0; i < sample_count; i++) { 144 1.2 isaki uint16_t val; 145 1.2 isaki val = *s++; 146 1.2 isaki val = bswap16(val); 147 1.2 isaki *d++ = (auint_t)val << shift; 148 1.2 isaki } 149 1.2 isaki } else { 150 1.2 isaki /* slinear16_NE to slinear<AI>_NE */ 151 1.2 isaki /* ulinear16_{NE,OE} to slinear<AI>_NE */ 152 1.2 isaki for (i = 0; i < sample_count; i++) { 153 1.2 isaki uint16_t val; 154 1.2 isaki val = *s++; 155 1.2 isaki if (!is_src_NE) 156 1.2 isaki val = bswap16(val); 157 1.2 isaki val ^= xor; 158 1.2 isaki *d++ = (auint_t)val << shift; 159 1.2 isaki } 160 1.2 isaki } 161 1.2 isaki } 162 1.2 isaki 163 1.2 isaki /* 164 1.2 isaki * audio_internal_to_linear16: 165 1.2 isaki * This filter performs conversion from internal format to 166 1.2 isaki * [US]LINEAR16{LE,BE}. 167 1.2 isaki */ 168 1.2 isaki void 169 1.2 isaki audio_internal_to_linear16(audio_filter_arg_t *arg) 170 1.2 isaki { 171 1.2 isaki const aint_t *s; 172 1.2 isaki uint16_t *d; 173 1.2 isaki uint16_t xor; 174 1.2 isaki u_int sample_count; 175 1.2 isaki u_int shift; 176 1.2 isaki u_int i; 177 1.2 isaki bool is_dst_NE; 178 1.2 isaki 179 1.2 isaki DIAGNOSTIC_filter_arg(arg); 180 1.2 isaki KASSERT(audio_format2_is_linear(arg->dstfmt)); 181 1.2 isaki KASSERT(arg->dstfmt->precision == 16); 182 1.2 isaki KASSERT(arg->dstfmt->stride == 16); 183 1.2 isaki KASSERT(audio_format2_is_internal(arg->srcfmt)); 184 1.2 isaki KASSERT(arg->srcfmt->channels == arg->dstfmt->channels); 185 1.2 isaki 186 1.2 isaki s = arg->src; 187 1.2 isaki d = arg->dst; 188 1.2 isaki sample_count = arg->count * arg->srcfmt->channels; 189 1.2 isaki 190 1.2 isaki shift = AUDIO_INTERNAL_BITS - 16; 191 1.2 isaki xor = audio_format2_is_signed(arg->dstfmt) ? 0 : 0x8000; 192 1.2 isaki is_dst_NE = (audio_format2_endian(arg->dstfmt) == BYTE_ORDER); 193 1.2 isaki 194 1.2 isaki /* 195 1.2 isaki * Since slinear_NativeEndian to slinear16_OppositeEndian is used 196 1.2 isaki * so much especially on big endian machines, so it's expanded. 197 1.2 isaki * Other conversions are rarely used, so they are compressed. 198 1.2 isaki */ 199 1.2 isaki if (__predict_true(xor == 0) && is_dst_NE == false) { 200 1.2 isaki /* slinear<AI>_NE -> slinear16_OE */ 201 1.2 isaki for (i = 0; i < sample_count; i++) { 202 1.2 isaki uint16_t val; 203 1.2 isaki val = (*s++) >> shift; 204 1.2 isaki val = bswap16(val); 205 1.2 isaki *d++ = val; 206 1.2 isaki } 207 1.2 isaki } else { 208 1.2 isaki /* slinear<AI>_NE -> slinear16_NE */ 209 1.2 isaki /* slinear<AI>_NE -> ulinear16_{NE,OE} */ 210 1.2 isaki for (i = 0; i < sample_count; i++) { 211 1.2 isaki uint16_t val; 212 1.2 isaki val = (*s++) >> shift; 213 1.2 isaki val ^= xor; 214 1.2 isaki if (!is_dst_NE) 215 1.2 isaki val = bswap16(val); 216 1.2 isaki *d++ = val; 217 1.2 isaki } 218 1.2 isaki } 219 1.2 isaki } 220 1.2 isaki 221 1.2 isaki #if defined(AUDIO_SUPPORT_LINEAR24) 222 1.2 isaki /* 223 1.2 isaki * audio_linear24_to_internal: 224 1.2 isaki * This filter performs conversion from [US]LINEAR24/24{LE,BE} to 225 1.5 isaki * internal format. Since it's rarely used, it's size optimized. 226 1.2 isaki */ 227 1.2 isaki void 228 1.2 isaki audio_linear24_to_internal(audio_filter_arg_t *arg) 229 1.2 isaki { 230 1.2 isaki const uint8_t *s; 231 1.2 isaki aint_t *d; 232 1.2 isaki auint_t xor; 233 1.2 isaki u_int sample_count; 234 1.2 isaki u_int i; 235 1.2 isaki bool is_src_LE; 236 1.2 isaki 237 1.2 isaki DIAGNOSTIC_filter_arg(arg); 238 1.2 isaki KASSERT(audio_format2_is_linear(arg->srcfmt)); 239 1.2 isaki KASSERT(arg->srcfmt->precision == 24); 240 1.2 isaki KASSERT(arg->srcfmt->stride == 24); 241 1.2 isaki KASSERT(audio_format2_is_internal(arg->dstfmt)); 242 1.2 isaki KASSERT(arg->srcfmt->channels == arg->dstfmt->channels); 243 1.2 isaki 244 1.2 isaki s = arg->src; 245 1.2 isaki d = arg->dst; 246 1.2 isaki sample_count = arg->count * arg->srcfmt->channels; 247 1.2 isaki xor = audio_format2_is_signed(arg->srcfmt) 248 1.2 isaki ? 0 : (1 << (AUDIO_INTERNAL_BITS - 1)); 249 1.2 isaki is_src_LE = (audio_format2_endian(arg->srcfmt) == LITTLE_ENDIAN); 250 1.2 isaki 251 1.2 isaki for (i = 0; i < sample_count; i++) { 252 1.2 isaki uint32_t val; 253 1.2 isaki if (is_src_LE) { 254 1.2 isaki val = s[0] | (s[1] << 8) | (s[2] << 16); 255 1.2 isaki } else { 256 1.2 isaki val = (s[0] << 16) | (s[1] << 8) | s[2]; 257 1.2 isaki } 258 1.2 isaki s += 3; 259 1.2 isaki 260 1.2 isaki #if AUDIO_INTERNAL_BITS < 24 261 1.2 isaki val >>= 24 - AUDIO_INTERNAL_BITS; 262 1.2 isaki #else 263 1.2 isaki val <<= AUDIO_INTERNAL_BITS - 24; 264 1.2 isaki #endif 265 1.2 isaki val ^= xor; 266 1.2 isaki *d++ = val; 267 1.2 isaki } 268 1.2 isaki } 269 1.2 isaki 270 1.2 isaki /* 271 1.2 isaki * audio_internal_to_linear24: 272 1.2 isaki * This filter performs conversion from internal format to 273 1.2 isaki * [US]LINEAR24/24{LE,BE}. Since it's rarely used, it's size optimized. 274 1.2 isaki */ 275 1.2 isaki void 276 1.2 isaki audio_internal_to_linear24(audio_filter_arg_t *arg) 277 1.2 isaki { 278 1.2 isaki const aint_t *s; 279 1.2 isaki uint8_t *d; 280 1.2 isaki auint_t xor; 281 1.2 isaki u_int sample_count; 282 1.2 isaki u_int i; 283 1.2 isaki bool is_dst_LE; 284 1.2 isaki 285 1.2 isaki DIAGNOSTIC_filter_arg(arg); 286 1.2 isaki KASSERT(audio_format2_is_linear(arg->dstfmt)); 287 1.2 isaki KASSERT(arg->dstfmt->precision == 24); 288 1.2 isaki KASSERT(arg->dstfmt->stride == 24); 289 1.2 isaki KASSERT(audio_format2_is_internal(arg->srcfmt)); 290 1.2 isaki KASSERT(arg->srcfmt->channels == arg->dstfmt->channels); 291 1.2 isaki 292 1.2 isaki s = arg->src; 293 1.2 isaki d = arg->dst; 294 1.2 isaki sample_count = arg->count * arg->srcfmt->channels; 295 1.2 isaki xor = audio_format2_is_signed(arg->dstfmt) 296 1.2 isaki ? 0 : (1 << (AUDIO_INTERNAL_BITS - 1)); 297 1.2 isaki is_dst_LE = (audio_format2_endian(arg->dstfmt) == LITTLE_ENDIAN); 298 1.2 isaki 299 1.2 isaki for (i = 0; i < sample_count; i++) { 300 1.2 isaki uint32_t val; 301 1.2 isaki val = *s++; 302 1.2 isaki val ^= xor; 303 1.2 isaki #if AUDIO_INTERNAL_BITS < 24 304 1.2 isaki val <<= 24 - AUDIO_INTERNAL_BITS; 305 1.2 isaki #else 306 1.2 isaki val >>= AUDIO_INTERNAL_BITS - 24; 307 1.2 isaki #endif 308 1.2 isaki if (is_dst_LE) { 309 1.2 isaki d[0] = val & 0xff; 310 1.2 isaki d[1] = (val >> 8) & 0xff; 311 1.2 isaki d[2] = (val >> 16) & 0xff; 312 1.2 isaki } else { 313 1.2 isaki d[0] = (val >> 16) & 0xff; 314 1.2 isaki d[1] = (val >> 8) & 0xff; 315 1.2 isaki d[2] = val & 0xff; 316 1.2 isaki } 317 1.2 isaki d += 3; 318 1.2 isaki } 319 1.2 isaki } 320 1.2 isaki #endif /* AUDIO_SUPPORT_LINEAR24 */ 321 1.2 isaki 322 1.2 isaki /* 323 1.2 isaki * audio_linear32_to_internal: 324 1.2 isaki * This filter performs conversion from [US]LINEAR32{LE,BE} to internal 325 1.2 isaki * format. Since it's rarely used, it's size optimized. 326 1.2 isaki */ 327 1.2 isaki void 328 1.2 isaki audio_linear32_to_internal(audio_filter_arg_t *arg) 329 1.2 isaki { 330 1.2 isaki const uint32_t *s; 331 1.2 isaki aint_t *d; 332 1.2 isaki auint_t xor; 333 1.2 isaki u_int sample_count; 334 1.2 isaki u_int i; 335 1.2 isaki bool is_src_NE; 336 1.2 isaki 337 1.2 isaki DIAGNOSTIC_filter_arg(arg); 338 1.2 isaki KASSERT(audio_format2_is_linear(arg->srcfmt)); 339 1.2 isaki KASSERT(arg->srcfmt->precision == 32); 340 1.2 isaki KASSERT(arg->srcfmt->stride == 32); 341 1.2 isaki KASSERT(audio_format2_is_internal(arg->dstfmt)); 342 1.2 isaki KASSERT(arg->srcfmt->channels == arg->dstfmt->channels); 343 1.2 isaki 344 1.2 isaki s = arg->src; 345 1.2 isaki d = arg->dst; 346 1.2 isaki sample_count = arg->count * arg->srcfmt->channels; 347 1.2 isaki xor = audio_format2_is_signed(arg->srcfmt) 348 1.2 isaki ? 0 : (1 << (AUDIO_INTERNAL_BITS - 1)); 349 1.2 isaki is_src_NE = (audio_format2_endian(arg->srcfmt) == BYTE_ORDER); 350 1.2 isaki 351 1.2 isaki for (i = 0; i < sample_count; i++) { 352 1.2 isaki uint32_t val; 353 1.2 isaki val = *s++; 354 1.2 isaki if (!is_src_NE) 355 1.2 isaki val = bswap32(val); 356 1.2 isaki val >>= 32 - AUDIO_INTERNAL_BITS; 357 1.2 isaki val ^= xor; 358 1.2 isaki *d++ = val; 359 1.2 isaki } 360 1.2 isaki } 361 1.2 isaki 362 1.2 isaki /* 363 1.2 isaki * audio_internal_to_linear32: 364 1.2 isaki * This filter performs conversion from internal format to 365 1.2 isaki * [US]LINEAR32{LE,BE}. Since it's rarely used, it's size optimized. 366 1.2 isaki */ 367 1.2 isaki void 368 1.2 isaki audio_internal_to_linear32(audio_filter_arg_t *arg) 369 1.2 isaki { 370 1.2 isaki const aint_t *s; 371 1.2 isaki uint32_t *d; 372 1.2 isaki auint_t xor; 373 1.2 isaki u_int sample_count; 374 1.2 isaki u_int i; 375 1.2 isaki bool is_dst_NE; 376 1.2 isaki 377 1.2 isaki DIAGNOSTIC_filter_arg(arg); 378 1.2 isaki KASSERT(audio_format2_is_linear(arg->dstfmt)); 379 1.2 isaki KASSERT(arg->dstfmt->precision == 32); 380 1.2 isaki KASSERT(arg->dstfmt->stride == 32); 381 1.2 isaki KASSERT(audio_format2_is_internal(arg->srcfmt)); 382 1.2 isaki KASSERT(arg->srcfmt->channels == arg->dstfmt->channels); 383 1.2 isaki 384 1.2 isaki s = arg->src; 385 1.2 isaki d = arg->dst; 386 1.2 isaki sample_count = arg->count * arg->srcfmt->channels; 387 1.2 isaki xor = audio_format2_is_signed(arg->dstfmt) 388 1.2 isaki ? 0 : (1 << (AUDIO_INTERNAL_BITS - 1)); 389 1.2 isaki is_dst_NE = (audio_format2_endian(arg->dstfmt) == BYTE_ORDER); 390 1.2 isaki 391 1.2 isaki for (i = 0; i < sample_count; i++) { 392 1.2 isaki uint32_t val; 393 1.2 isaki val = *s++; 394 1.2 isaki val ^= xor; 395 1.2 isaki val <<= 32 - AUDIO_INTERNAL_BITS; 396 1.2 isaki if (!is_dst_NE) 397 1.2 isaki val = bswap32(val); 398 1.2 isaki *d++ = val; 399 1.2 isaki } 400 1.2 isaki } 401