Home | History | Annotate | Line # | Download | only in audio
alaw.c revision 1.2
      1 /*	$NetBSD: alaw.c,v 1.2 2019/05/08 13:40:17 isaki Exp $	*/
      2 
      3 /*
      4  * Copyright (C) 2018 Tetsuya Isaki. All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     20  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     22  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     23  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25  * SUCH DAMAGE.
     26  */
     27 
     28 #include <sys/cdefs.h>
     29 __KERNEL_RCSID(0, "$NetBSD: alaw.c,v 1.2 2019/05/08 13:40:17 isaki Exp $");
     30 
     31 #if defined(_KERNEL)
     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 #endif
     38 
     39 static const uint16_t alaw_to_slinear16[256] = {
     40 	0xea80, 0xeb80, 0xe880, 0xe980, 0xee80, 0xef80, 0xec80, 0xed80,
     41 	0xe280, 0xe380, 0xe080, 0xe180, 0xe680, 0xe780, 0xe480, 0xe580,
     42 	0xf540, 0xf5c0, 0xf440, 0xf4c0, 0xf740, 0xf7c0, 0xf640, 0xf6c0,
     43 	0xf140, 0xf1c0, 0xf040, 0xf0c0, 0xf340, 0xf3c0, 0xf240, 0xf2c0,
     44 	0xaa00, 0xae00, 0xa200, 0xa600, 0xba00, 0xbe00, 0xb200, 0xb600,
     45 	0x8a00, 0x8e00, 0x8200, 0x8600, 0x9a00, 0x9e00, 0x9200, 0x9600,
     46 	0xd500, 0xd700, 0xd100, 0xd300, 0xdd00, 0xdf00, 0xd900, 0xdb00,
     47 	0xc500, 0xc700, 0xc100, 0xc300, 0xcd00, 0xcf00, 0xc900, 0xcb00,
     48 	0xfea8, 0xfeb8, 0xfe88, 0xfe98, 0xfee8, 0xfef8, 0xfec8, 0xfed8,
     49 	0xfe28, 0xfe38, 0xfe08, 0xfe18, 0xfe68, 0xfe78, 0xfe48, 0xfe58,
     50 	0xffa8, 0xffb8, 0xff88, 0xff98, 0xffe8, 0xfff8, 0xffc8, 0xffd8,
     51 	0xff28, 0xff38, 0xff08, 0xff18, 0xff68, 0xff78, 0xff48, 0xff58,
     52 	0xfaa0, 0xfae0, 0xfa20, 0xfa60, 0xfba0, 0xfbe0, 0xfb20, 0xfb60,
     53 	0xf8a0, 0xf8e0, 0xf820, 0xf860, 0xf9a0, 0xf9e0, 0xf920, 0xf960,
     54 	0xfd50, 0xfd70, 0xfd10, 0xfd30, 0xfdd0, 0xfdf0, 0xfd90, 0xfdb0,
     55 	0xfc50, 0xfc70, 0xfc10, 0xfc30, 0xfcd0, 0xfcf0, 0xfc90, 0xfcb0,
     56 	0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280,
     57 	0x1d80, 0x1c80, 0x1f80, 0x1e80, 0x1980, 0x1880, 0x1b80, 0x1a80,
     58 	0x0ac0, 0x0a40, 0x0bc0, 0x0b40, 0x08c0, 0x0840, 0x09c0, 0x0940,
     59 	0x0ec0, 0x0e40, 0x0fc0, 0x0f40, 0x0cc0, 0x0c40, 0x0dc0, 0x0d40,
     60 	0x5600, 0x5200, 0x5e00, 0x5a00, 0x4600, 0x4200, 0x4e00, 0x4a00,
     61 	0x7600, 0x7200, 0x7e00, 0x7a00, 0x6600, 0x6200, 0x6e00, 0x6a00,
     62 	0x2b00, 0x2900, 0x2f00, 0x2d00, 0x2300, 0x2100, 0x2700, 0x2500,
     63 	0x3b00, 0x3900, 0x3f00, 0x3d00, 0x3300, 0x3100, 0x3700, 0x3500,
     64 	0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128,
     65 	0x01d8, 0x01c8, 0x01f8, 0x01e8, 0x0198, 0x0188, 0x01b8, 0x01a8,
     66 	0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028,
     67 	0x00d8, 0x00c8, 0x00f8, 0x00e8, 0x0098, 0x0088, 0x00b8, 0x00a8,
     68 	0x0560, 0x0520, 0x05e0, 0x05a0, 0x0460, 0x0420, 0x04e0, 0x04a0,
     69 	0x0760, 0x0720, 0x07e0, 0x07a0, 0x0660, 0x0620, 0x06e0, 0x06a0,
     70 	0x02b0, 0x0290, 0x02f0, 0x02d0, 0x0230, 0x0210, 0x0270, 0x0250,
     71 	0x03b0, 0x0390, 0x03f0, 0x03d0, 0x0330, 0x0310, 0x0370, 0x0350,
     72 };
     73 
     74 static const uint8_t slinear8_to_alaw[256] = {
     75 	0xd5, 0xc5, 0xf5, 0xfd, 0xe5, 0xe1, 0xed, 0xe9,
     76 	0x95, 0x97, 0x91, 0x93, 0x9d, 0x9f, 0x99, 0x9b,
     77 	0x85, 0x84, 0x87, 0x86, 0x81, 0x80, 0x83, 0x82,
     78 	0x8d, 0x8c, 0x8f, 0x8e, 0x89, 0x88, 0x8b, 0x8a,
     79 	0xb5, 0xb5, 0xb4, 0xb4, 0xb7, 0xb7, 0xb6, 0xb6,
     80 	0xb1, 0xb1, 0xb0, 0xb0, 0xb3, 0xb3, 0xb2, 0xb2,
     81 	0xbd, 0xbd, 0xbc, 0xbc, 0xbf, 0xbf, 0xbe, 0xbe,
     82 	0xb9, 0xb9, 0xb8, 0xb8, 0xbb, 0xbb, 0xba, 0xba,
     83 	0xa5, 0xa5, 0xa5, 0xa5, 0xa4, 0xa4, 0xa4, 0xa4,
     84 	0xa7, 0xa7, 0xa7, 0xa7, 0xa6, 0xa6, 0xa6, 0xa6,
     85 	0xa1, 0xa1, 0xa1, 0xa1, 0xa0, 0xa0, 0xa0, 0xa0,
     86 	0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0xa2, 0xa2, 0xa2,
     87 	0xad, 0xad, 0xad, 0xad, 0xac, 0xac, 0xac, 0xac,
     88 	0xaf, 0xaf, 0xaf, 0xaf, 0xae, 0xae, 0xae, 0xae,
     89 	0xa9, 0xa9, 0xa9, 0xa9, 0xa8, 0xa8, 0xa8, 0xa8,
     90 	0xab, 0xab, 0xab, 0xab, 0xaa, 0xaa, 0xaa, 0xaa,
     91 	0x2a, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b,
     92 	0x28, 0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x29,
     93 	0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x2f,
     94 	0x2c, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d,
     95 	0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x23,
     96 	0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x21,
     97 	0x26, 0x26, 0x26, 0x26, 0x27, 0x27, 0x27, 0x27,
     98 	0x24, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x25,
     99 	0x3a, 0x3a, 0x3b, 0x3b, 0x38, 0x38, 0x39, 0x39,
    100 	0x3e, 0x3e, 0x3f, 0x3f, 0x3c, 0x3c, 0x3d, 0x3d,
    101 	0x32, 0x32, 0x33, 0x33, 0x30, 0x30, 0x31, 0x31,
    102 	0x36, 0x36, 0x37, 0x37, 0x34, 0x34, 0x35, 0x35,
    103 	0x0a, 0x0b, 0x08, 0x09, 0x0e, 0x0f, 0x0c, 0x0d,
    104 	0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05,
    105 	0x1a, 0x18, 0x1e, 0x1c, 0x12, 0x10, 0x16, 0x14,
    106 	0x6a, 0x6e, 0x62, 0x66, 0x7a, 0x72, 0x4a, 0x5a,
    107 };
    108 
    109 /*
    110  * audio_alaw_to_internal:
    111  *	This filter performs conversion from A-law to internal format.
    112  */
    113 void
    114 audio_alaw_to_internal(audio_filter_arg_t *arg)
    115 {
    116 	const uint8_t *s;
    117 	aint_t *d;
    118 	u_int sample_count;
    119 	u_int i;
    120 
    121 	DIAGNOSTIC_filter_arg(arg);
    122 	KASSERT(arg->srcfmt->encoding == AUDIO_ENCODING_ALAW);
    123 	KASSERT(arg->srcfmt->stride == 8);
    124 	KASSERT(arg->srcfmt->precision == 8);
    125 	KASSERT(audio_format2_is_internal(arg->dstfmt));
    126 	KASSERT(arg->srcfmt->channels == arg->dstfmt->channels);
    127 
    128 	s = arg->src;
    129 	d = arg->dst;
    130 	sample_count = arg->count * arg->srcfmt->channels;
    131 
    132 	for (i = 0; i < sample_count; i++) {
    133 		aint_t val;
    134 		val = alaw_to_slinear16[*s++];
    135 		val <<= AUDIO_INTERNAL_BITS - 16;
    136 		*d++ = val;
    137 	}
    138 }
    139 
    140 /*
    141  * audio_internal_to_alaw:
    142  *	This filter performs conversion from internal format to A-law.
    143  */
    144 void
    145 audio_internal_to_alaw(audio_filter_arg_t *arg)
    146 {
    147 	const aint_t *s;
    148 	uint8_t *d;
    149 	u_int sample_count;
    150 	u_int i;
    151 
    152 	DIAGNOSTIC_filter_arg(arg);
    153 	KASSERT(arg->dstfmt->encoding == AUDIO_ENCODING_ALAW);
    154 	KASSERT(arg->dstfmt->stride == 8);
    155 	KASSERT(arg->dstfmt->precision == 8);
    156 	KASSERT(audio_format2_is_internal(arg->srcfmt));
    157 	KASSERT(arg->srcfmt->channels == arg->dstfmt->channels);
    158 
    159 	s = arg->src;
    160 	d = arg->dst;
    161 	sample_count = arg->count * arg->srcfmt->channels;
    162 
    163 	for (i = 0; i < sample_count; i++) {
    164 		uint8_t val;
    165 		val = (*s++) >> (AUDIO_INTERNAL_BITS - 8);
    166 		*d++ = slinear8_to_alaw[val];
    167 	}
    168 }
    169