1 /* $NetBSD: mulaw.c,v 1.4 2020/09/12 06:09:16 isaki Exp $ */ 2 3 /* 4 * Copyright (C) 2017 Tetsuya Isaki. All rights reserved. 5 * Copyright (C) 2017 Y.Sugahara (moveccr). All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: mulaw.c,v 1.4 2020/09/12 06:09:16 isaki Exp $"); 31 32 #include <sys/types.h> 33 #include <sys/systm.h> 34 #include <sys/device.h> 35 #include <dev/audio/audiovar.h> 36 #include <dev/audio/mulaw.h> 37 38 /* 39 * audio_internal_to_mulaw has two implementations. 40 * 41 * 1. Use 8bit table (MULAW_LQ_ENC) 42 * It's traditional implementation and its precision is 8bit. 43 * It's faster but the size is larger. And you can hear a little noise 44 * in silent part. 45 * 46 * 2. Calculation (default) 47 * It calculates mu-law with full spec and its precision is 14bit. 48 * It's about 3 times slower but the size is less than a half (on m68k, 49 * for example). 50 * 51 * mu-law is no longer a popular format. I think size-optimized is better. 52 */ 53 /* #define MULAW_LQ_ENC */ 54 55 /* 56 * About mulaw32 format. 57 * 58 * The format which I call ``mulaw32'' is only used in dev/tc/bba.c . 59 * It is 8bit mu-law but 16bit left-shifted and its containter is 32bit. 60 * Not mu-law calculated in 32bit. 61 * 62 * When MULAW32 is not defined (it's default), this file outputs 63 * audio_internal_to_mulaw() and audio_mulaw_to_internal(). When 64 * MULAW32 is defined, this file outputs audio_internal_to_mulaw32() 65 * and audio_mulaw32_to_internal() instead. 66 * 67 * Since mu-law is used as userland format and is mandatory, all audio 68 * drivers (including tc/bba) link this mulaw.c in ordinary procedure. 69 * On the other hand, only tc/bba also needs audio_internal_to_mulaw32() 70 * and audio_mulaw32_to_internal() as its hardware drivers codec, so 71 * define MULAW32 and include this file. It's a bit tricky but I think 72 * this is the simplest way. 73 */ 74 75 #if 0 76 #define MPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) 77 #else 78 #define MPRINTF(fmt, ...) /**/ 79 #endif 80 81 static const int16_t mulaw_to_slinear16[256] = { 82 0x8284, 0x8684, 0x8a84, 0x8e84, 0x9284, 0x9684, 0x9a84, 0x9e84, 83 0xa284, 0xa684, 0xaa84, 0xae84, 0xb284, 0xb684, 0xba84, 0xbe84, 84 0xc184, 0xc384, 0xc584, 0xc784, 0xc984, 0xcb84, 0xcd84, 0xcf84, 85 0xd184, 0xd384, 0xd584, 0xd784, 0xd984, 0xdb84, 0xdd84, 0xdf84, 86 0xe104, 0xe204, 0xe304, 0xe404, 0xe504, 0xe604, 0xe704, 0xe804, 87 0xe904, 0xea04, 0xeb04, 0xec04, 0xed04, 0xee04, 0xef04, 0xf004, 88 0xf0c4, 0xf144, 0xf1c4, 0xf244, 0xf2c4, 0xf344, 0xf3c4, 0xf444, 89 0xf4c4, 0xf544, 0xf5c4, 0xf644, 0xf6c4, 0xf744, 0xf7c4, 0xf844, 90 0xf8a4, 0xf8e4, 0xf924, 0xf964, 0xf9a4, 0xf9e4, 0xfa24, 0xfa64, 91 0xfaa4, 0xfae4, 0xfb24, 0xfb64, 0xfba4, 0xfbe4, 0xfc24, 0xfc64, 92 0xfc94, 0xfcb4, 0xfcd4, 0xfcf4, 0xfd14, 0xfd34, 0xfd54, 0xfd74, 93 0xfd94, 0xfdb4, 0xfdd4, 0xfdf4, 0xfe14, 0xfe34, 0xfe54, 0xfe74, 94 0xfe8c, 0xfe9c, 0xfeac, 0xfebc, 0xfecc, 0xfedc, 0xfeec, 0xfefc, 95 0xff0c, 0xff1c, 0xff2c, 0xff3c, 0xff4c, 0xff5c, 0xff6c, 0xff7c, 96 0xff88, 0xff90, 0xff98, 0xffa0, 0xffa8, 0xffb0, 0xffb8, 0xffc0, 97 0xffc8, 0xffd0, 0xffd8, 0xffe0, 0xffe8, 0xfff0, 0xfff8, 0xfffc, 98 0x7d7c, 0x797c, 0x757c, 0x717c, 0x6d7c, 0x697c, 0x657c, 0x617c, 99 0x5d7c, 0x597c, 0x557c, 0x517c, 0x4d7c, 0x497c, 0x457c, 0x417c, 100 0x3e7c, 0x3c7c, 0x3a7c, 0x387c, 0x367c, 0x347c, 0x327c, 0x307c, 101 0x2e7c, 0x2c7c, 0x2a7c, 0x287c, 0x267c, 0x247c, 0x227c, 0x207c, 102 0x1efc, 0x1dfc, 0x1cfc, 0x1bfc, 0x1afc, 0x19fc, 0x18fc, 0x17fc, 103 0x16fc, 0x15fc, 0x14fc, 0x13fc, 0x12fc, 0x11fc, 0x10fc, 0x0ffc, 104 0x0f3c, 0x0ebc, 0x0e3c, 0x0dbc, 0x0d3c, 0x0cbc, 0x0c3c, 0x0bbc, 105 0x0b3c, 0x0abc, 0x0a3c, 0x09bc, 0x093c, 0x08bc, 0x083c, 0x07bc, 106 0x075c, 0x071c, 0x06dc, 0x069c, 0x065c, 0x061c, 0x05dc, 0x059c, 107 0x055c, 0x051c, 0x04dc, 0x049c, 0x045c, 0x041c, 0x03dc, 0x039c, 108 0x036c, 0x034c, 0x032c, 0x030c, 0x02ec, 0x02cc, 0x02ac, 0x028c, 109 0x026c, 0x024c, 0x022c, 0x020c, 0x01ec, 0x01cc, 0x01ac, 0x018c, 110 0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104, 111 0x00f4, 0x00e4, 0x00d4, 0x00c4, 0x00b4, 0x00a4, 0x0094, 0x0084, 112 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040, 113 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000, 114 }; 115 116 #if defined(MULAW_LQ_ENC) 117 static const uint8_t slinear8_to_mulaw[256] = { 118 0xff, 0xe7, 0xdb, 0xd3, 0xcd, 0xc9, 0xc5, 0xc1, 119 0xbe, 0xbc, 0xba, 0xb8, 0xb6, 0xb4, 0xb2, 0xb0, 120 0xaf, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa8, 121 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0, 122 0x9f, 0x9f, 0x9e, 0x9e, 0x9d, 0x9d, 0x9c, 0x9c, 123 0x9b, 0x9b, 0x9a, 0x9a, 0x99, 0x99, 0x98, 0x98, 124 0x97, 0x97, 0x96, 0x96, 0x95, 0x95, 0x94, 0x94, 125 0x93, 0x93, 0x92, 0x92, 0x91, 0x91, 0x90, 0x90, 126 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8e, 127 0x8d, 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8c, 128 0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x8a, 0x8a, 0x8a, 129 0x89, 0x89, 0x89, 0x89, 0x88, 0x88, 0x88, 0x88, 130 0x87, 0x87, 0x87, 0x87, 0x86, 0x86, 0x86, 0x86, 131 0x85, 0x85, 0x85, 0x85, 0x84, 0x84, 0x84, 0x84, 132 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x82, 133 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 134 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 135 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 136 0x03, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 137 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 138 0x07, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 139 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 140 0x0b, 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 141 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 142 0x0f, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x13, 143 0x13, 0x14, 0x14, 0x15, 0x15, 0x16, 0x16, 0x17, 144 0x17, 0x18, 0x18, 0x19, 0x19, 0x1a, 0x1a, 0x1b, 145 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 146 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 147 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 148 0x2f, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 149 0x3e, 0x41, 0x45, 0x49, 0x4d, 0x53, 0x5b, 0x67, 150 }; 151 #endif 152 153 /* 154 * audio_mulaw_to_internal: 155 * This filter performs conversion from mu-law to internal format. 156 * 157 * audio_mulaw32_to_internal: 158 * This filter performs conversion from mulaw32 used only in tc/bba.c 159 * to internal format. 160 */ 161 void 162 #if !defined(MULAW32) 163 audio_mulaw_to_internal(audio_filter_arg_t *arg) 164 #else 165 audio_mulaw32_to_internal(audio_filter_arg_t *arg) 166 #endif 167 { 168 #if defined(MULAW32) 169 const uint32_t *s; 170 #else 171 const uint8_t *s; 172 #endif 173 aint_t *d; 174 u_int sample_count; 175 u_int i; 176 177 DIAGNOSTIC_filter_arg(arg); 178 #if !defined(MULAW32) 179 KASSERT(arg->srcfmt->encoding == AUDIO_ENCODING_ULAW); 180 KASSERT(arg->srcfmt->stride == 8); 181 KASSERT(arg->srcfmt->precision == 8); 182 #endif 183 KASSERT(audio_format2_is_internal(arg->dstfmt)); 184 KASSERT(arg->srcfmt->channels == arg->dstfmt->channels); 185 186 s = arg->src; 187 d = arg->dst; 188 sample_count = arg->count * arg->srcfmt->channels; 189 190 for (i = 0; i < sample_count; i++) { 191 aint_t val; 192 uint m; 193 m = *s++; 194 #if defined(MULAW32) 195 /* 32bit container used only in tc/bba.c */ 196 m = (m >> 16) & 0xff; 197 #endif 198 val = mulaw_to_slinear16[m]; 199 val <<= AUDIO_INTERNAL_BITS - 16; 200 *d++ = val; 201 } 202 } 203 204 /* 205 * audio_internal_to_mulaw: 206 * This filter performs conversion from internal format to mu-law. 207 * 208 * audio_internal_to_mulaw32: 209 * This filter performs conversion from internal format to mulaw32 210 * used only in tc/bba.c. 211 */ 212 void 213 #if !defined(MULAW32) 214 audio_internal_to_mulaw(audio_filter_arg_t *arg) 215 #else 216 audio_internal_to_mulaw32(audio_filter_arg_t *arg) 217 #endif 218 { 219 const aint_t *s; 220 #if defined(MULAW32) 221 uint32_t *d; 222 #else 223 uint8_t *d; 224 #endif 225 u_int sample_count; 226 u_int i; 227 228 DIAGNOSTIC_filter_arg(arg); 229 #if !defined(MULAW32) 230 KASSERT(arg->dstfmt->encoding == AUDIO_ENCODING_ULAW); 231 KASSERT(arg->dstfmt->stride == 8); 232 KASSERT(arg->dstfmt->precision == 8); 233 #endif 234 KASSERT(audio_format2_is_internal(arg->srcfmt)); 235 KASSERT(arg->srcfmt->channels == arg->dstfmt->channels); 236 237 s = arg->src; 238 d = arg->dst; 239 sample_count = arg->count * arg->srcfmt->channels; 240 241 for (i = 0; i < sample_count; i++) { 242 uint8_t m; 243 #if defined(MULAW_LQ_ENC) 244 /* 8bit (low quality, fast but fat) encoder */ 245 uint8_t val; 246 val = (*s++) >> (AUDIO_INTERNAL_BITS - 8); 247 m = slinear8_to_mulaw[val]; 248 #else 249 /* 14bit (fullspec, slow but small) encoder */ 250 uint16_t val; 251 int c; 252 253 val = *s++ >> (AUDIO_INTERNAL_BITS - 16); 254 if ((int16_t)val < 0) { 255 m = 0; 256 } else { 257 val = ~val; 258 m = 0x80; 259 } 260 /* limit */ 261 if ((int16_t)val < -8158 * 4) 262 val = -8158 * 4; 263 val -= 33 * 4; /* bias */ 264 265 // Before(1) Before(2) Before(3) 266 // S0MMMMxx_xxxxxxxx 0MMMMxxx_xxxxxxx0 c=0,v=0MMMMxxx_xxxxxxx0 267 // S10MMMMx_xxxxxxxx 10MMMMxx_xxxxxxx0 c=1,v=0MMMMxxx_xxxxxx00 268 // S110MMMM_xxxxxxxx 110MMMMx_xxxxxxx0 c=2,v=0MMMMxxx_xxxxx000 269 // : : : 270 // S1111110_MMMMxxxx 1111110M_MMMxxxx0 c=6,v=0MMMMxxx_x0000000 271 272 // (1) Push out sign bit 273 val <<= 1; 274 275 // (2) Find first zero (and align val to left) 276 c = 0; 277 if (val >= 0xf000) c += 4, val <<= 4; 278 if (val >= 0xc000) c += 2, val <<= 2; 279 if (val >= 0x8000) c += 1, val <<= 1; 280 281 // (3) 282 m += (c << 4); 283 m += (val >> 11) & 0x0f; 284 #endif 285 286 #if defined(MULAW32) 287 /* 8bit mu-law in 32bit container used only in tc/bba.c */ 288 *d++ = m << 16; 289 #else 290 *d++ = m; 291 #endif 292 } 293 } 294