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