Alexandre Lision | 7c6f4a6 | 2013-09-05 13:27:01 -0400 | [diff] [blame] | 1 | /* |
| 2 | ** Copyright (C) 2007-2011 Erik de Castro Lopo <erikd@mega-nerd.com> |
| 3 | ** Copyright (c) 2007 <robs@users.sourceforge.net> |
| 4 | ** |
| 5 | ** This library is free software; you can redistribute it and/or modify it |
| 6 | ** under the terms of the GNU Lesser General Public License as published by |
| 7 | ** the Free Software Foundation; either version 2 of the License, or (at |
| 8 | ** your option) any later version. |
| 9 | ** |
| 10 | ** This library is distributed in the hope that it will be useful, but |
| 11 | ** WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser |
| 13 | ** General Public License for more details. |
| 14 | ** |
| 15 | ** You should have received a copy of the GNU Lesser General Public License |
| 16 | ** along with this library. If not, write to the Free Software Foundation, |
| 17 | ** Fifth Floor, 51 Franklin Street, Boston, MA 02111-1301, USA. |
| 18 | */ |
| 19 | |
| 20 | /* ADPCM: IMA, OKI <==> 16-bit PCM. */ |
| 21 | |
| 22 | #include "sfconfig.h" |
| 23 | |
| 24 | #include <string.h> |
| 25 | |
| 26 | /* Set up for libsndfile environment: */ |
| 27 | #include "common.h" |
| 28 | |
| 29 | #include "ima_oki_adpcm.h" |
| 30 | |
| 31 | #define MIN_SAMPLE -0x8000 |
| 32 | #define MAX_SAMPLE 0x7fff |
| 33 | |
| 34 | static int const ima_steps [] = /* ~16-bit precision */ |
| 35 | { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, |
| 36 | 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, |
| 37 | 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, |
| 38 | 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, |
| 39 | 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442, |
| 40 | 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, |
| 41 | 32767 |
| 42 | } ; |
| 43 | |
| 44 | static int const oki_steps [] = /* ~12-bit precision */ |
| 45 | { 256, 272, 304, 336, 368, 400, 448, 496, 544, 592, 656, 720, 800, 880, 960, |
| 46 | 1056, 1168, 1280, 1408, 1552, 1712, 1888, 2080, 2288, 2512, 2768, 3040, 3344, |
| 47 | 3680, 4048, 4464, 4912, 5392, 5936, 6528, 7184, 7904, 8704, 9568, 10528, |
| 48 | 11584, 12736, 14016, 15408, 16960, 18656, 20512, 22576, 24832 |
| 49 | } ; |
| 50 | |
| 51 | static int const step_changes [] = { -1, -1, -1, -1, 2, 4, 6, 8 } ; |
| 52 | |
| 53 | void |
| 54 | ima_oki_adpcm_init (IMA_OKI_ADPCM * state, IMA_OKI_ADPCM_TYPE type) |
| 55 | { |
| 56 | memset (state, 0, sizeof (*state)) ; |
| 57 | |
| 58 | if (type == IMA_OKI_ADPCM_TYPE_IMA) |
| 59 | { state->max_step_index = ARRAY_LEN (ima_steps) - 1 ; |
| 60 | state->steps = ima_steps ; |
| 61 | state->mask = (~0) ; |
| 62 | } |
| 63 | else |
| 64 | { state->max_step_index = ARRAY_LEN (oki_steps) - 1 ; |
| 65 | state->steps = oki_steps ; |
| 66 | state->mask = (~0) << 4 ; |
| 67 | } ; |
| 68 | |
| 69 | } /* ima_oki_adpcm_init */ |
| 70 | |
| 71 | |
| 72 | int |
| 73 | adpcm_decode (IMA_OKI_ADPCM * state, int code) |
| 74 | { int s ; |
| 75 | |
| 76 | s = ((code & 7) << 1) | 1 ; |
| 77 | s = ((state->steps [state->step_index] * s) >> 3) & state->mask ; |
| 78 | |
| 79 | if (code & 8) |
| 80 | s = -s ; |
| 81 | s += state->last_output ; |
| 82 | |
| 83 | if (s < MIN_SAMPLE || s > MAX_SAMPLE) |
| 84 | { int grace ; |
| 85 | |
| 86 | grace = (state->steps [state->step_index] >> 3) & state->mask ; |
| 87 | |
| 88 | if (s < MIN_SAMPLE - grace || s > MAX_SAMPLE + grace) |
| 89 | state->errors ++ ; |
| 90 | |
| 91 | s = s < MIN_SAMPLE ? MIN_SAMPLE : MAX_SAMPLE ; |
| 92 | } ; |
| 93 | |
| 94 | state->step_index += step_changes [code & 7] ; |
| 95 | state->step_index = SF_MIN (SF_MAX (state->step_index, 0), state->max_step_index) ; |
| 96 | state->last_output = s ; |
| 97 | |
| 98 | return s ; |
| 99 | } /* adpcm_decode */ |
| 100 | |
| 101 | int |
| 102 | adpcm_encode (IMA_OKI_ADPCM * state, int sample) |
| 103 | { int delta, sign = 0, code ; |
| 104 | |
| 105 | delta = sample - state->last_output ; |
| 106 | |
| 107 | if (delta < 0) |
| 108 | { sign = 8 ; |
| 109 | delta = -delta ; |
| 110 | } ; |
| 111 | |
| 112 | code = 4 * delta / state->steps [state->step_index] ; |
| 113 | code = sign | SF_MIN (code, 7) ; |
| 114 | adpcm_decode (state, code) ; /* Update encoder state */ |
| 115 | |
| 116 | return code ; |
| 117 | } /* adpcm_encode */ |
| 118 | |
| 119 | |
| 120 | void |
| 121 | ima_oki_adpcm_decode_block (IMA_OKI_ADPCM * state) |
| 122 | { unsigned char code ; |
| 123 | int k ; |
| 124 | |
| 125 | for (k = 0 ; k < state->code_count ; k++) |
| 126 | { code = state->codes [k] ; |
| 127 | state->pcm [2 * k] = adpcm_decode (state, code >> 4) ; |
| 128 | state->pcm [2 * k + 1] = adpcm_decode (state, code) ; |
| 129 | } ; |
| 130 | |
| 131 | state->pcm_count = 2 * k ; |
| 132 | } /* ima_oki_adpcm_decode_block */ |
| 133 | |
| 134 | |
| 135 | void |
| 136 | ima_oki_adpcm_encode_block (IMA_OKI_ADPCM * state) |
| 137 | { unsigned char code ; |
| 138 | int k ; |
| 139 | |
| 140 | /* |
| 141 | ** The codec expects an even number of input samples. |
| 142 | ** |
| 143 | ** Samples should always be passed in even length blocks. If the last block to |
| 144 | ** be encoded is odd length, extend that block by one zero valued sample. |
| 145 | */ |
| 146 | if (state->pcm_count % 2 == 1) |
| 147 | state->pcm [state->pcm_count ++] = 0 ; |
| 148 | |
| 149 | for (k = 0 ; k < state->pcm_count / 2 ; k++) |
| 150 | { code = adpcm_encode (state, state->pcm [2 * k]) << 4 ; |
| 151 | code |= adpcm_encode (state, state->pcm [2 * k + 1]) ; |
| 152 | state->codes [k] = code ; |
| 153 | } ; |
| 154 | |
| 155 | state->code_count = k ; |
| 156 | } /* ima_oki_adpcm_encode_block */ |
| 157 | |
| 158 | |
| 159 | #ifdef TEST |
| 160 | |
| 161 | static const unsigned char test_codes [] = |
| 162 | { 0x08, 0x08, 0x04, 0x7f, 0x72, 0xf7, 0x9f, 0x7c, 0xd7, 0xbc, 0x7a, 0xa7, 0xb8, |
| 163 | 0x4b, 0x0b, 0x38, 0xf6, 0x9d, 0x7a, 0xd7, 0xbc, 0x7a, 0xd7, 0xa8, 0x6c, 0x81, |
| 164 | 0x98, 0xe4, 0x0e, 0x7a, 0xd7, 0x9e, 0x7b, 0xc7, 0xab, 0x7a, 0x85, 0xc0, 0xb3, |
| 165 | 0x8f, 0x58, 0xd7, 0xad, 0x7a, 0xd7, 0xad, 0x7a, 0x87, 0xd0, 0x2b, 0x0e, 0x48, |
| 166 | 0xd7, 0xad, 0x78, 0xf7, 0xbc, 0x7a, 0xb7, 0xa8, 0x4b, 0x88, 0x18, 0xd5, 0x8d, |
| 167 | 0x6a, 0xa4, 0x98, 0x08, 0x00, 0x80, 0x88, |
| 168 | } ; |
| 169 | |
| 170 | static const short test_pcm [] = |
| 171 | { 32, 0, 32, 0, 32, 320, 880, -336, 2304, 4192, -992, 10128, 5360, -16352, |
| 172 | 30208, 2272, -31872, 14688, -7040, -32432, 14128, -1392, -15488, 22960, |
| 173 | 1232, -1584, 21488, -240, 2576, -15360, 960, -1152, -30032, 10320, 1008, |
| 174 | -30032, 16528, 1008, -30032, 16528, -5200, -30592, 15968, 448, -30592, |
| 175 | 15968, 448, -2368, 30960, 3024, -80, 8384, 704, -1616, -29168, -1232, 1872, |
| 176 | -32768, 13792, -1728, -32768, 13792, 4480, -32192, 14368, -7360, -32752, |
| 177 | 13808, -1712, -21456, 16992, 1472, -1344, 26848, -1088, 2016, -17728, 208, |
| 178 | -2112, -32768, 1376, -1728, -32768, 13792, -1728, -32768, 13792, -1728, |
| 179 | -32768, 13792, -1728, -32768, 13792, -1728, -4544, 32767, -1377, 1727, |
| 180 | 15823, -2113, 207, -27345, 591, -2513, -32768, 13792, -1728, -32768, 13792, |
| 181 | 10688, -31632, 14928, -6800, -32192, 14368, -1152, -20896, 17552, 2032, |
| 182 | -784, 22288, 560, -2256, -4816, 2176, 64, -21120, 9920, 6816, -24224, 16128, |
| 183 | 608, -13488, 9584, 272, -2544, 16, -2304, -192, 1728, -16, 1568, 128, -1184, |
| 184 | } ; |
| 185 | |
| 186 | |
| 187 | static void |
| 188 | test_oki_adpcm (void) |
| 189 | { |
| 190 | IMA_OKI_ADPCM adpcm ; |
| 191 | unsigned char code ; |
| 192 | int i, j ; |
| 193 | |
| 194 | printf (" Testing encoder : ") ; |
| 195 | fflush (stdout) ; |
| 196 | |
| 197 | ima_oki_adpcm_init (&adpcm, IMA_OKI_ADPCM_TYPE_OKI) ; |
| 198 | for (i = 0 ; i < ARRAY_LEN (test_codes) ; i++) |
| 199 | for (j = 0, code = test_codes [i] ; j < 2 ; j++, code <<= 4) |
| 200 | if (adpcm_decode (&adpcm, code >> 4) != test_pcm [2 * i + j]) |
| 201 | { printf ("\n\nFail at i = %d, j = %d.\n\n", i, j) ; |
| 202 | exit (1) ; |
| 203 | } ; |
| 204 | |
| 205 | puts ("ok") ; |
| 206 | |
| 207 | printf (" Testing decoder : ") ; |
| 208 | fflush (stdout) ; |
| 209 | |
| 210 | ima_oki_adpcm_init (&adpcm, IMA_OKI_ADPCM_TYPE_OKI) ; |
| 211 | for (i = 0 ; i < ARRAY_LEN (test_pcm) ; i += j) |
| 212 | { code = adpcm_encode (&adpcm, test_pcm [i]) ; |
| 213 | code = (code << 4) | adpcm_encode (&adpcm, test_pcm [i + 1]) ; |
| 214 | if (code != test_codes [i / 2]) |
| 215 | { printf ("\n\nFail at i = %d, %d should be %d\n\n", i, code, test_codes [i / 2]) ; |
| 216 | exit (1) ; |
| 217 | } ; |
| 218 | } ; |
| 219 | |
| 220 | puts ("ok") ; |
| 221 | } /* test_oki_adpcm */ |
| 222 | |
| 223 | static void |
| 224 | test_oki_adpcm_block (void) |
| 225 | { |
| 226 | IMA_OKI_ADPCM adpcm ; |
| 227 | int k ; |
| 228 | |
| 229 | if (ARRAY_LEN (adpcm.pcm) < ARRAY_LEN (test_pcm)) |
| 230 | { printf ("\n\nLine %d : ARRAY_LEN (adpcm->pcm) > ARRAY_LEN (test_pcm) (%d > %d).\n\n", __LINE__, ARRAY_LEN (adpcm.pcm), ARRAY_LEN (test_pcm)) ; |
| 231 | exit (1) ; |
| 232 | } ; |
| 233 | |
| 234 | if (ARRAY_LEN (adpcm.codes) < ARRAY_LEN (test_codes)) |
| 235 | { printf ("\n\nLine %d : ARRAY_LEN (adcodes->codes) > ARRAY_LEN (test_codes).n", __LINE__) ; |
| 236 | exit (1) ; |
| 237 | } ; |
| 238 | |
| 239 | printf (" Testing block encoder : ") ; |
| 240 | fflush (stdout) ; |
| 241 | |
| 242 | ima_oki_adpcm_init (&adpcm, IMA_OKI_ADPCM_TYPE_OKI) ; |
| 243 | |
| 244 | memcpy (adpcm.pcm, test_pcm, sizeof (adpcm.pcm [0]) * ARRAY_LEN (test_pcm)) ; |
| 245 | adpcm.pcm_count = ARRAY_LEN (test_pcm) ; |
| 246 | adpcm.code_count = 13 ; |
| 247 | |
| 248 | ima_oki_adpcm_encode_block (&adpcm) ; |
| 249 | |
| 250 | if (adpcm.code_count * 2 != ARRAY_LEN (test_pcm)) |
| 251 | { printf ("\n\nLine %d : %d * 2 != %d\n\n", __LINE__, adpcm.code_count * 2, ARRAY_LEN (test_pcm)) ; |
| 252 | exit (1) ; |
| 253 | } ; |
| 254 | |
| 255 | for (k = 0 ; k < ARRAY_LEN (test_codes) ; k++) |
| 256 | if (adpcm.codes [k] != test_codes [k]) |
| 257 | { printf ("\n\nLine %d : Fail at k = %d, %d should be %d\n\n", __LINE__, k, adpcm.codes [k], test_codes [k]) ; |
| 258 | exit (1) ; |
| 259 | } ; |
| 260 | |
| 261 | puts ("ok") ; |
| 262 | |
| 263 | printf (" Testing block decoder : ") ; |
| 264 | fflush (stdout) ; |
| 265 | |
| 266 | ima_oki_adpcm_init (&adpcm, IMA_OKI_ADPCM_TYPE_OKI) ; |
| 267 | |
| 268 | memcpy (adpcm.codes, test_codes, sizeof (adpcm.codes [0]) * ARRAY_LEN (test_codes)) ; |
| 269 | adpcm.code_count = ARRAY_LEN (test_codes) ; |
| 270 | adpcm.pcm_count = 13 ; |
| 271 | |
| 272 | ima_oki_adpcm_decode_block (&adpcm) ; |
| 273 | |
| 274 | if (adpcm.pcm_count != 2 * ARRAY_LEN (test_codes)) |
| 275 | { printf ("\n\nLine %d : %d * 2 != %d\n\n", __LINE__, adpcm.pcm_count, 2 * ARRAY_LEN (test_codes)) ; |
| 276 | exit (1) ; |
| 277 | } ; |
| 278 | |
| 279 | for (k = 0 ; k < ARRAY_LEN (test_pcm) ; k++) |
| 280 | if (adpcm.pcm [k] != test_pcm [k]) |
| 281 | { printf ("\n\nLine %d : Fail at i = %d, %d should be %d.\n\n", __LINE__, k, adpcm.pcm [k], test_pcm [k]) ; |
| 282 | exit (1) ; |
| 283 | } ; |
| 284 | |
| 285 | puts ("ok") ; |
| 286 | } /* test_oki_adpcm_block */ |
| 287 | |
| 288 | int |
| 289 | main (void) |
| 290 | { |
| 291 | test_oki_adpcm () ; |
| 292 | test_oki_adpcm_block () ; |
| 293 | |
| 294 | return 0 ; |
| 295 | } /* main */ |
| 296 | |
| 297 | #endif |