|
| 1 | +// SPDX-License-Identifier: BSD-3-Clause |
| 2 | +// |
| 3 | +// Copyright(c) 2025 Intel Corporation. |
| 4 | +// |
| 5 | +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> |
| 6 | + |
| 7 | +#include <sof/audio/format.h> |
| 8 | +#include <sof/math/mu_law.h> |
| 9 | +#include <stdint.h> |
| 10 | + |
| 11 | +#define SOFM_MULAW_BIAS 33 |
| 12 | +#define SOFM_MULAW_MAX 8191 |
| 13 | +#define SOFM_MULAW_TOGGLE_BITS 0x7f |
| 14 | +#define SOFM_MULAW_SIGN_BIT 0x80 |
| 15 | +#define SOFM_MULAW_MANTISSA_MASK 0x0f |
| 16 | +#define SOFM_MULAW_MANTISSA_BITS 4 |
| 17 | +#define SOFM_MULAW_SHIFT_MASK 0x07 |
| 18 | +#define SOFM_MULAW_DEC_ONES_MASK 0x21 /* 0b100001 for "1abcd1", see below */ |
| 19 | + |
| 20 | +/* |
| 21 | + * mu-law encode table (sign bit is b12) |
| 22 | + * |
| 23 | + * Input values 12:0 Output values 6:0 |
| 24 | + * |
| 25 | + * 0 0 0 0 0 0 0 1 a b c d x 0 0 0 a b c d |
| 26 | + * 0 0 0 0 0 0 1 a b c d x x 0 0 1 a b c d |
| 27 | + * 0 0 0 0 0 1 a b c d x x x 0 1 0 a b c d |
| 28 | + * 0 0 0 0 1 a b c d x x x x 0 1 1 a b c d |
| 29 | + * 0 0 0 1 a b c d x x x x x 1 0 0 a b c d |
| 30 | + * 0 0 1 a b c d x x x x x x 1 0 1 a b c d |
| 31 | + * 0 1 a b c d x x x x x x x 1 1 0 a b c d |
| 32 | + * 1 a b c d x x x x x x x x 1 1 1 a b c d |
| 33 | + * |
| 34 | + * mu-law decode table (sign bit is b7) |
| 35 | + * |
| 36 | + * Input values 6:0 Output values 12:0 |
| 37 | + * |
| 38 | + * 0 0 0 a b c d 0 0 0 0 0 0 0 1 a b c d 1 |
| 39 | + * 0 0 1 a b c d 0 0 0 0 0 0 1 a b c d 1 0 |
| 40 | + * 0 1 0 a b c d 0 0 0 0 0 1 a b c d 1 0 0 |
| 41 | + * 0 1 1 a b c d 0 0 0 0 1 a b c d 1 0 0 0 |
| 42 | + * 1 0 0 a b c d 0 0 0 1 a b c d 1 0 0 0 0 |
| 43 | + * 1 0 1 a b c d 0 0 1 a b c d 1 0 0 0 0 0 |
| 44 | + * 1 1 0 a b c d 0 1 a b c d 1 0 0 0 0 0 0 |
| 45 | + * 1 1 1 a b c d 1 a b c d 1 0 0 0 0 0 0 0 |
| 46 | + */ |
| 47 | + |
| 48 | +/* Shift values lookup table for above table for 7 |
| 49 | + * highest sample value bits. |
| 50 | + */ |
| 51 | +static uint8_t mulaw_encode_shifts[128] = { |
| 52 | + 0, 1, 2, 2, 3, 3, 3, 3, |
| 53 | + 4, 4, 4, 4, 4, 4, 4, 4, |
| 54 | + 5, 5, 5, 5, 5, 5, 5, 5, |
| 55 | + 5, 5, 5, 5, 5, 5, 5, 5, |
| 56 | + 6, 6, 6, 6, 6, 6, 6, 6, |
| 57 | + 6, 6, 6, 6, 6, 6, 6, 6, |
| 58 | + 6, 6, 6, 6, 6, 6, 6, 6, |
| 59 | + 6, 6, 6, 6, 6, 6, 6, 6, |
| 60 | + 7, 7, 7, 7, 7, 7, 7, 7, |
| 61 | + 7, 7, 7, 7, 7, 7, 7, 7, |
| 62 | + 7, 7, 7, 7, 7, 7, 7, 7, |
| 63 | + 7, 7, 7, 7, 7, 7, 7, 7, |
| 64 | + 7, 7, 7, 7, 7, 7, 7, 7, |
| 65 | + 7, 7, 7, 7, 7, 7, 7, 7, |
| 66 | + 7, 7, 7, 7, 7, 7, 7, 7, |
| 67 | + 7, 7, 7, 7, 7, 7, 7, 7, |
| 68 | +}; |
| 69 | + |
| 70 | +/** |
| 71 | + * sofm_mu_law_encode() - Encode sample with mu-law coding |
| 72 | + * @param sample: A s16 sample value |
| 73 | + * |
| 74 | + * The mu-law codec is defined in ITU-T G.711 standard and has been used |
| 75 | + * in telecommunications in USA and Japan. The mu-law coding compresses |
| 76 | + * 14 bit samples to 8 bit data stream. In SOF the high 14 bits of s16 |
| 77 | + * format are used for compatibility with normal audios. |
| 78 | + * |
| 79 | + * @return: Compressed 8 bit code value |
| 80 | + */ |
| 81 | + |
| 82 | +uint8_t sofm_mu_law_encode(int16_t sample) |
| 83 | +{ |
| 84 | + int sign = SOFM_MULAW_SIGN_BIT; |
| 85 | + int shift = 0; |
| 86 | + int low_bits; |
| 87 | + uint8_t byte; |
| 88 | + |
| 89 | + /* Convert to 14 bits with shift */ |
| 90 | + sample >>= 2; |
| 91 | + |
| 92 | + /* Negative samples are 1's complement with zero sign bit */ |
| 93 | + if (sample < 0) { |
| 94 | + sign = 0; |
| 95 | + sample = -sample - 1; |
| 96 | + } |
| 97 | + |
| 98 | + sample += SOFM_MULAW_BIAS; |
| 99 | + if (sample > SOFM_MULAW_MAX) |
| 100 | + sample = SOFM_MULAW_MAX; |
| 101 | + |
| 102 | + shift = mulaw_encode_shifts[sample >> 6]; |
| 103 | + low_bits = (sample >> (shift + 1)) & SOFM_MULAW_MANTISSA_MASK; |
| 104 | + |
| 105 | + byte = (shift << SOFM_MULAW_MANTISSA_BITS) | low_bits | sign; |
| 106 | + byte ^= SOFM_MULAW_TOGGLE_BITS; |
| 107 | + return byte; |
| 108 | +} |
| 109 | + |
| 110 | +/** |
| 111 | + * sofm_mu_law_decode() - Decode mu-law encoded code word |
| 112 | + * @param byte: Encoded code word |
| 113 | + * |
| 114 | + * The mu-law decoder expands a 8 bit code word into a 14 bit sample value. |
| 115 | + * In the SOF the high 14 bits are aligned to the most significant bits |
| 116 | + * to be compatible with normal s16 Q1.15 samples. |
| 117 | + * |
| 118 | + * @return: Sampple value in s16 format |
| 119 | + */ |
| 120 | +int16_t sofm_mu_law_decode(int8_t byte) |
| 121 | +{ |
| 122 | + int low_bits; |
| 123 | + int shift; |
| 124 | + int sign; |
| 125 | + int16_t value; |
| 126 | + |
| 127 | + sign = byte & SOFM_MULAW_SIGN_BIT; |
| 128 | + byte ^= SOFM_MULAW_TOGGLE_BITS; |
| 129 | + low_bits = byte & SOFM_MULAW_MANTISSA_MASK; |
| 130 | + shift = (byte >> SOFM_MULAW_MANTISSA_BITS) & SOFM_MULAW_SHIFT_MASK; |
| 131 | + value = (low_bits << (shift + 1)) | (SOFM_MULAW_DEC_ONES_MASK << shift); |
| 132 | + value -= SOFM_MULAW_BIAS; |
| 133 | + if (!sign) |
| 134 | + value = -value; |
| 135 | + |
| 136 | + /* Shift 14 bit Q1.13 to 16 bit Q1.15 */ |
| 137 | + return value << 2; |
| 138 | +} |
0 commit comments