1 /* $NetBSD: alaw.c,v 1.3 2020/01/11 04:06:13 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.3 2020/01/11 04:06:13 isaki Exp $"); 30 31 #include <sys/types.h> 32 #include <sys/systm.h> 33 #include <sys/device.h> 34 #include <dev/audio/audiovar.h> 35 #include <dev/audio/mulaw.h> 36 37 static const uint16_t alaw_to_slinear16[256] = { 38 0xea80, 0xeb80, 0xe880, 0xe980, 0xee80, 0xef80, 0xec80, 0xed80, 39 0xe280, 0xe380, 0xe080, 0xe180, 0xe680, 0xe780, 0xe480, 0xe580, 40 0xf540, 0xf5c0, 0xf440, 0xf4c0, 0xf740, 0xf7c0, 0xf640, 0xf6c0, 41 0xf140, 0xf1c0, 0xf040, 0xf0c0, 0xf340, 0xf3c0, 0xf240, 0xf2c0, 42 0xaa00, 0xae00, 0xa200, 0xa600, 0xba00, 0xbe00, 0xb200, 0xb600, 43 0x8a00, 0x8e00, 0x8200, 0x8600, 0x9a00, 0x9e00, 0x9200, 0x9600, 44 0xd500, 0xd700, 0xd100, 0xd300, 0xdd00, 0xdf00, 0xd900, 0xdb00, 45 0xc500, 0xc700, 0xc100, 0xc300, 0xcd00, 0xcf00, 0xc900, 0xcb00, 46 0xfea8, 0xfeb8, 0xfe88, 0xfe98, 0xfee8, 0xfef8, 0xfec8, 0xfed8, 47 0xfe28, 0xfe38, 0xfe08, 0xfe18, 0xfe68, 0xfe78, 0xfe48, 0xfe58, 48 0xffa8, 0xffb8, 0xff88, 0xff98, 0xffe8, 0xfff8, 0xffc8, 0xffd8, 49 0xff28, 0xff38, 0xff08, 0xff18, 0xff68, 0xff78, 0xff48, 0xff58, 50 0xfaa0, 0xfae0, 0xfa20, 0xfa60, 0xfba0, 0xfbe0, 0xfb20, 0xfb60, 51 0xf8a0, 0xf8e0, 0xf820, 0xf860, 0xf9a0, 0xf9e0, 0xf920, 0xf960, 52 0xfd50, 0xfd70, 0xfd10, 0xfd30, 0xfdd0, 0xfdf0, 0xfd90, 0xfdb0, 53 0xfc50, 0xfc70, 0xfc10, 0xfc30, 0xfcd0, 0xfcf0, 0xfc90, 0xfcb0, 54 0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280, 55 0x1d80, 0x1c80, 0x1f80, 0x1e80, 0x1980, 0x1880, 0x1b80, 0x1a80, 56 0x0ac0, 0x0a40, 0x0bc0, 0x0b40, 0x08c0, 0x0840, 0x09c0, 0x0940, 57 0x0ec0, 0x0e40, 0x0fc0, 0x0f40, 0x0cc0, 0x0c40, 0x0dc0, 0x0d40, 58 0x5600, 0x5200, 0x5e00, 0x5a00, 0x4600, 0x4200, 0x4e00, 0x4a00, 59 0x7600, 0x7200, 0x7e00, 0x7a00, 0x6600, 0x6200, 0x6e00, 0x6a00, 60 0x2b00, 0x2900, 0x2f00, 0x2d00, 0x2300, 0x2100, 0x2700, 0x2500, 61 0x3b00, 0x3900, 0x3f00, 0x3d00, 0x3300, 0x3100, 0x3700, 0x3500, 62 0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128, 63 0x01d8, 0x01c8, 0x01f8, 0x01e8, 0x0198, 0x0188, 0x01b8, 0x01a8, 64 0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028, 65 0x00d8, 0x00c8, 0x00f8, 0x00e8, 0x0098, 0x0088, 0x00b8, 0x00a8, 66 0x0560, 0x0520, 0x05e0, 0x05a0, 0x0460, 0x0420, 0x04e0, 0x04a0, 67 0x0760, 0x0720, 0x07e0, 0x07a0, 0x0660, 0x0620, 0x06e0, 0x06a0, 68 0x02b0, 0x0290, 0x02f0, 0x02d0, 0x0230, 0x0210, 0x0270, 0x0250, 69 0x03b0, 0x0390, 0x03f0, 0x03d0, 0x0330, 0x0310, 0x0370, 0x0350, 70 }; 71 72 static const uint8_t slinear8_to_alaw[256] = { 73 0xd5, 0xc5, 0xf5, 0xfd, 0xe5, 0xe1, 0xed, 0xe9, 74 0x95, 0x97, 0x91, 0x93, 0x9d, 0x9f, 0x99, 0x9b, 75 0x85, 0x84, 0x87, 0x86, 0x81, 0x80, 0x83, 0x82, 76 0x8d, 0x8c, 0x8f, 0x8e, 0x89, 0x88, 0x8b, 0x8a, 77 0xb5, 0xb5, 0xb4, 0xb4, 0xb7, 0xb7, 0xb6, 0xb6, 78 0xb1, 0xb1, 0xb0, 0xb0, 0xb3, 0xb3, 0xb2, 0xb2, 79 0xbd, 0xbd, 0xbc, 0xbc, 0xbf, 0xbf, 0xbe, 0xbe, 80 0xb9, 0xb9, 0xb8, 0xb8, 0xbb, 0xbb, 0xba, 0xba, 81 0xa5, 0xa5, 0xa5, 0xa5, 0xa4, 0xa4, 0xa4, 0xa4, 82 0xa7, 0xa7, 0xa7, 0xa7, 0xa6, 0xa6, 0xa6, 0xa6, 83 0xa1, 0xa1, 0xa1, 0xa1, 0xa0, 0xa0, 0xa0, 0xa0, 84 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0xa2, 0xa2, 0xa2, 85 0xad, 0xad, 0xad, 0xad, 0xac, 0xac, 0xac, 0xac, 86 0xaf, 0xaf, 0xaf, 0xaf, 0xae, 0xae, 0xae, 0xae, 87 0xa9, 0xa9, 0xa9, 0xa9, 0xa8, 0xa8, 0xa8, 0xa8, 88 0xab, 0xab, 0xab, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 89 0x2a, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b, 90 0x28, 0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x29, 91 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x2f, 92 0x2c, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d, 93 0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x23, 94 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x21, 95 0x26, 0x26, 0x26, 0x26, 0x27, 0x27, 0x27, 0x27, 96 0x24, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x25, 97 0x3a, 0x3a, 0x3b, 0x3b, 0x38, 0x38, 0x39, 0x39, 98 0x3e, 0x3e, 0x3f, 0x3f, 0x3c, 0x3c, 0x3d, 0x3d, 99 0x32, 0x32, 0x33, 0x33, 0x30, 0x30, 0x31, 0x31, 100 0x36, 0x36, 0x37, 0x37, 0x34, 0x34, 0x35, 0x35, 101 0x0a, 0x0b, 0x08, 0x09, 0x0e, 0x0f, 0x0c, 0x0d, 102 0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, 103 0x1a, 0x18, 0x1e, 0x1c, 0x12, 0x10, 0x16, 0x14, 104 0x6a, 0x6e, 0x62, 0x66, 0x7a, 0x72, 0x4a, 0x5a, 105 }; 106 107 /* 108 * audio_alaw_to_internal: 109 * This filter performs conversion from A-law to internal format. 110 */ 111 void 112 audio_alaw_to_internal(audio_filter_arg_t *arg) 113 { 114 const uint8_t *s; 115 aint_t *d; 116 u_int sample_count; 117 u_int i; 118 119 DIAGNOSTIC_filter_arg(arg); 120 KASSERT(arg->srcfmt->encoding == AUDIO_ENCODING_ALAW); 121 KASSERT(arg->srcfmt->stride == 8); 122 KASSERT(arg->srcfmt->precision == 8); 123 KASSERT(audio_format2_is_internal(arg->dstfmt)); 124 KASSERT(arg->srcfmt->channels == arg->dstfmt->channels); 125 126 s = arg->src; 127 d = arg->dst; 128 sample_count = arg->count * arg->srcfmt->channels; 129 130 for (i = 0; i < sample_count; i++) { 131 aint_t val; 132 val = alaw_to_slinear16[*s++]; 133 val <<= AUDIO_INTERNAL_BITS - 16; 134 *d++ = val; 135 } 136 } 137 138 /* 139 * audio_internal_to_alaw: 140 * This filter performs conversion from internal format to A-law. 141 */ 142 void 143 audio_internal_to_alaw(audio_filter_arg_t *arg) 144 { 145 const aint_t *s; 146 uint8_t *d; 147 u_int sample_count; 148 u_int i; 149 150 DIAGNOSTIC_filter_arg(arg); 151 KASSERT(arg->dstfmt->encoding == AUDIO_ENCODING_ALAW); 152 KASSERT(arg->dstfmt->stride == 8); 153 KASSERT(arg->dstfmt->precision == 8); 154 KASSERT(audio_format2_is_internal(arg->srcfmt)); 155 KASSERT(arg->srcfmt->channels == arg->dstfmt->channels); 156 157 s = arg->src; 158 d = arg->dst; 159 sample_count = arg->count * arg->srcfmt->channels; 160 161 for (i = 0; i < sample_count; i++) { 162 uint8_t val; 163 val = (*s++) >> (AUDIO_INTERNAL_BITS - 8); 164 *d++ = slinear8_to_alaw[val]; 165 } 166 } 167