2 * PCM - Ima-ADPC conversion
3 * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
4 * Copyright (c) 1999 by Uros Bizjak <uros@kss-loka.si>
5 * Jaroslav Kysela <perex@suse.cz>
7 * Based on Version 1.2, 18-Dec-92 implementation of Intel/DVI ADPCM code
8 * by Jack Jansen, CWI, Amsterdam <Jack.Jansen@cwi.nl>, Copyright 1992
9 * by Stichting Mathematisch Centrum, Amsterdam, The Netherlands.
11 * This library is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU Library General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Library General Public License for more details.
21 * You should have received a copy of the GNU Library General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 These routines convert 16 bit linear PCM samples to 4 bit ADPCM code
29 and vice versa. The ADPCM code used is the Intel/DVI ADPCM code which
30 is being recommended by the IMA Digital Audio Technical Working Group.
32 The algorithm for this coder was taken from:
33 Proposal for Standardized Audio Interstreamge Formats,
34 IMA compatability project proceedings, Vol 2, Issue 2, May 1992.
36 - No, this is *not* a G.721 coder/decoder. The algorithm used by G.721
37 is very complicated, requiring oodles of floating-point ops per
38 sample (resulting in very poor performance). I have not done any
39 tests myself but various people have assured my that 721 quality is
40 actually lower than DVI quality.
42 - No, it probably isn't a RIFF ADPCM decoder either. Trying to decode
43 RIFF ADPCM with these routines seems to result in something
44 recognizable but very distorted.
46 - No, it is not a CDROM-XA coder either, as far as I know. I haven't
47 come across a good description of XA yet.
51 #include "pcm_local.h"
52 #include "pcm_plugin.h"
55 int pred_val; /* Calculated predicted value */
56 int step_idx; /* Previous StepSize lookup index */
59 typedef void (*adpcm_f)(snd_pcm_channel_area_t *src_areas,
61 snd_pcm_channel_area_t *dst_areas,
63 size_t frames, size_t channels, int getputidx,
64 adpcm_state_t *states);
67 /* This field need to be the first */
68 snd_pcm_plugin_t plug;
73 int cxfer_mode, cmmap_shape;
74 adpcm_state_t *states;
77 /* First table lookup for Ima-ADPCM quantizer */
78 static char IndexAdjust[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
80 /* Second table lookup for Ima-ADPCM quantizer */
81 static short StepSize[89] = {
82 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
83 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
84 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
85 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
86 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
87 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
88 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
89 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
90 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
93 static char adpcm_encoder(int sl, adpcm_state_t * state)
95 short diff; /* Difference between sl and predicted sample */
96 short pred_diff; /* Predicted difference to next sample */
98 unsigned char sign; /* sign of diff */
99 short step; /* holds previous StepSize value */
100 unsigned char adjust_idx; /* Index to IndexAdjust lookup table */
104 /* Compute difference to previous predicted value */
105 diff = sl - state->pred_val;
106 sign = (diff < 0) ? 0x8 : 0x0;
112 * This code *approximately* computes:
113 * adjust_idx = diff * 4 / step;
114 * pred_diff = (adjust_idx + 0.5) * step / 4;
116 * But in shift step bits are dropped. The net result of this is
117 * that even if you have fast mul/div hardware you cannot put it to
118 * good use since the fixup would be too expensive.
121 step = StepSize[state->step_idx];
123 /* Divide and clamp */
124 pred_diff = step >> 3;
125 for (adjust_idx = 0, i = 0x4; i; i >>= 1, step >>= 1) {
133 /* Update and clamp previous predicted value */
134 state->pred_val += sign ? -pred_diff : pred_diff;
136 if (state->pred_val > 32767) {
137 state->pred_val = 32767;
138 } else if (state->pred_val < -32768) {
139 state->pred_val = -32768;
142 /* Update and clamp StepSize lookup table index */
143 state->step_idx += IndexAdjust[adjust_idx];
145 if (state->step_idx < 0) {
147 } else if (state->step_idx > 88) {
148 state->step_idx = 88;
150 return (sign | adjust_idx);
154 static int adpcm_decoder(unsigned char code, adpcm_state_t * state)
156 short pred_diff; /* Predicted difference to next sample */
157 short step; /* holds previous StepSize value */
162 /* Separate sign and magnitude */
167 * Computes pred_diff = (code + 0.5) * step / 4,
168 * but see comment in adpcm_coder.
171 step = StepSize[state->step_idx];
173 /* Compute difference and new predicted value */
174 pred_diff = step >> 3;
175 for (i = 0x4; i; i >>= 1, step >>= 1) {
180 state->pred_val += (sign) ? -pred_diff : pred_diff;
182 /* Clamp output value */
183 if (state->pred_val > 32767) {
184 state->pred_val = 32767;
185 } else if (state->pred_val < -32768) {
186 state->pred_val = -32768;
189 /* Find new StepSize index value */
190 state->step_idx += IndexAdjust[code];
192 if (state->step_idx < 0) {
194 } else if (state->step_idx > 88) {
195 state->step_idx = 88;
197 return (state->pred_val);
200 static void adpcm_decode(snd_pcm_channel_area_t *src_areas,
202 snd_pcm_channel_area_t *dst_areas,
204 size_t frames, size_t channels, int putidx,
205 adpcm_state_t *states)
207 #define PUT_S16_LABELS
208 #include "plugin_ops.h"
209 #undef PUT_S16_LABELS
210 void *put = put_s16_labels[putidx];
212 for (channel = 0; channel < channels; ++channel, ++states) {
216 int src_step, srcbit_step, dst_step;
218 snd_pcm_channel_area_t *src_area = &src_areas[channel];
219 snd_pcm_channel_area_t *dst_area = &dst_areas[channel];
221 if (!src_area->enabled) {
222 if (dst_area->wanted)
223 snd_pcm_area_silence(dst_area, dst_offset, frames, dst_sfmt);
224 dst_area->enabled = 0;
227 dst_area->enabled = 1;
229 srcbit = src_area->first + src_area->step * src_offset;
230 src = src_area->addr + srcbit / 8;
232 src_step = src_area->step / 8;
233 srcbit_step = src_area->step % 8;
234 dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
235 dst_step = snd_pcm_channel_area_step(dst_area);
237 while (frames1-- > 0) {
243 v = (*src >> 4) & 0x0f;
244 sample = adpcm_decoder(v, states);
246 #define PUT_S16_END after
247 #include "plugin_ops.h"
251 srcbit += srcbit_step;
261 static void adpcm_encode(snd_pcm_channel_area_t *src_areas,
263 snd_pcm_channel_area_t *dst_areas,
265 size_t frames, size_t channels, int getidx,
266 adpcm_state_t *states)
268 #define GET_S16_LABELS
269 #include "plugin_ops.h"
270 #undef GET_S16_LABELS
271 void *get = get_s16_labels[getidx];
274 for (channel = 0; channel < channels; ++channel, ++states) {
278 int src_step, dst_step, dstbit_step;
280 snd_pcm_channel_area_t *src_area = &src_areas[channel];
281 snd_pcm_channel_area_t *dst_area = &dst_areas[channel];
283 if (!src_area->enabled) {
284 if (dst_area->wanted)
285 snd_pcm_area_silence(dst_area, dst_offset, frames, dst_sfmt);
286 dst_area->enabled = 0;
289 dst_area->enabled = 1;
291 src = snd_pcm_channel_area_addr(src_area, src_offset);
292 src_step = snd_pcm_channel_area_step(src_area);
293 dstbit = dst_area->first + dst_area->step * dst_offset;
294 dst = dst_area->addr + dstbit / 8;
296 dst_step = dst_area->step / 8;
297 dstbit_step = dst_area->step % 8;
299 while (frames1-- > 0) {
302 #define GET_S16_END after
303 #include "plugin_ops.h"
306 v = adpcm_encoder(sample, states);
308 *dst = (*dst & 0xf0) | v;
310 *dst = (*dst & 0x0f) | (v << 4);
313 dstbit += dstbit_step;
322 static int snd_pcm_adpcm_close(snd_pcm_t *pcm)
324 snd_pcm_adpcm_t *adpcm = pcm->private;
326 if (adpcm->plug.close_slave)
327 err = snd_pcm_close(adpcm->plug.slave);
334 static int snd_pcm_adpcm_params_info(snd_pcm_t *pcm, snd_pcm_params_info_t * info)
336 snd_pcm_adpcm_t *adpcm = pcm->private;
337 unsigned int req_mask = info->req_mask;
338 unsigned int sfmt = info->req.format.sfmt;
340 if (req_mask & SND_PCM_PARAMS_SFMT) {
341 if (adpcm->sformat == SND_PCM_SFMT_IMA_ADPCM ?
342 !snd_pcm_format_linear(sfmt) :
343 sfmt != SND_PCM_SFMT_IMA_ADPCM) {
344 info->req.fail_mask = SND_PCM_PARAMS_SFMT;
345 info->req.fail_reason = SND_PCM_PARAMS_FAIL_INVAL;
349 info->req_mask |= SND_PCM_PARAMS_SFMT;
350 info->req_mask &= ~(SND_PCM_PARAMS_MMAP_SHAPE |
351 SND_PCM_PARAMS_XFER_MODE);
352 info->req.format.sfmt = adpcm->sformat;
353 err = snd_pcm_params_info(adpcm->plug.slave, info);
354 info->req_mask = req_mask;
355 info->req.format.sfmt = sfmt;
358 if (req_mask & SND_PCM_PARAMS_SFMT)
359 info->formats = 1 << sfmt;
361 info->formats = adpcm->sformat == SND_PCM_SFMT_IMA_ADPCM ?
362 SND_PCM_LINEAR_FORMATS : 1 << SND_PCM_SFMT_IMA_ADPCM;
363 info->flags &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
364 info->flags |= SND_PCM_INFO_INTERLEAVED | SND_PCM_INFO_NONINTERLEAVED;
368 static int snd_pcm_adpcm_params(snd_pcm_t *pcm, snd_pcm_params_t * params)
370 snd_pcm_adpcm_t *adpcm = pcm->private;
371 snd_pcm_t *slave = adpcm->plug.slave;
373 if (adpcm->sformat == SND_PCM_SFMT_IMA_ADPCM ?
374 !snd_pcm_format_linear(params->format.sfmt) :
375 params->format.sfmt != SND_PCM_SFMT_IMA_ADPCM) {
376 params->fail_mask = SND_PCM_PARAMS_SFMT;
377 params->fail_reason = SND_PCM_PARAMS_FAIL_INVAL;
380 if (slave->mmap_data) {
381 err = snd_pcm_munmap_data(slave);
385 adpcm->cformat = params->format.sfmt;
386 adpcm->cxfer_mode = params->xfer_mode;
387 adpcm->cmmap_shape = params->mmap_shape;
388 params->format.sfmt = adpcm->sformat;
389 params->xfer_mode = SND_PCM_XFER_UNSPECIFIED;
390 params->mmap_shape = SND_PCM_MMAP_UNSPECIFIED;;
391 err = snd_pcm_params(slave, params);
392 params->format.sfmt = adpcm->cformat;
393 params->xfer_mode = adpcm->cxfer_mode;
394 params->mmap_shape = adpcm->cmmap_shape;
395 if (slave->valid_setup) {
396 int r = snd_pcm_mmap_data(slave, NULL);
402 static int snd_pcm_adpcm_setup(snd_pcm_t *pcm, snd_pcm_setup_t * setup)
404 snd_pcm_adpcm_t *adpcm = pcm->private;
405 int err = snd_pcm_setup(adpcm->plug.slave, setup);
408 assert(adpcm->sformat == setup->format.sfmt);
409 if (adpcm->cxfer_mode == SND_PCM_XFER_UNSPECIFIED)
410 setup->xfer_mode = SND_PCM_XFER_NONINTERLEAVED;
412 setup->xfer_mode = adpcm->cxfer_mode;
413 if (adpcm->cmmap_shape == SND_PCM_MMAP_UNSPECIFIED)
414 setup->mmap_shape = SND_PCM_MMAP_NONINTERLEAVED;
416 setup->mmap_shape = adpcm->cmmap_shape;
417 setup->format.sfmt = adpcm->cformat;
418 setup->mmap_bytes = 0;
419 if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
420 if (adpcm->sformat == SND_PCM_SFMT_IMA_ADPCM) {
421 adpcm->getput_idx = getput_index(adpcm->cformat);
422 adpcm->func = adpcm_encode;
424 adpcm->getput_idx = getput_index(adpcm->sformat);
425 adpcm->func = adpcm_decode;
428 if (adpcm->sformat == SND_PCM_SFMT_IMA_ADPCM) {
429 adpcm->getput_idx = getput_index(adpcm->cformat);
430 adpcm->func = adpcm_decode;
432 adpcm->getput_idx = getput_index(adpcm->sformat);
433 adpcm->func = adpcm_encode;
438 adpcm->states = malloc(setup->format.channels * sizeof(*adpcm->states));
442 static int snd_pcm_adpcm_init(snd_pcm_t *pcm)
444 snd_pcm_adpcm_t *adpcm = pcm->private;
446 for (k = 0; k < pcm->setup.format.channels; ++k) {
447 adpcm->states[k].pred_val = 0;
448 adpcm->states[k].step_idx = 0;
453 static ssize_t snd_pcm_adpcm_write_areas(snd_pcm_t *pcm,
454 snd_pcm_channel_area_t *areas,
459 snd_pcm_adpcm_t *adpcm = pcm->private;
460 snd_pcm_t *slave = adpcm->plug.slave;
463 if (slave_sizep && *slave_sizep < size)
466 while (xfer < size) {
467 size_t frames = snd_pcm_mmap_playback_xfer(slave, size - xfer);
468 adpcm->func(areas, offset,
469 snd_pcm_mmap_areas(slave), snd_pcm_mmap_offset(slave),
470 frames, pcm->setup.format.channels,
471 adpcm->getput_idx, adpcm->states);
472 err = snd_pcm_mmap_forward(slave, frames);
475 assert((size_t)err == frames);
478 snd_pcm_mmap_hw_forward(pcm, err);
488 static ssize_t snd_pcm_adpcm_read_areas(snd_pcm_t *pcm,
489 snd_pcm_channel_area_t *areas,
494 snd_pcm_adpcm_t *adpcm = pcm->private;
495 snd_pcm_t *slave = adpcm->plug.slave;
498 if (slave_sizep && *slave_sizep < size)
501 while (xfer < size) {
502 size_t frames = snd_pcm_mmap_capture_xfer(slave, size - xfer);
503 adpcm->func(snd_pcm_mmap_areas(slave), snd_pcm_mmap_offset(slave),
505 frames, pcm->setup.format.channels,
506 adpcm->getput_idx, adpcm->states);
507 err = snd_pcm_mmap_forward(slave, frames);
510 assert((size_t)err == frames);
513 snd_pcm_mmap_hw_forward(pcm, err);
523 static void snd_pcm_adpcm_dump(snd_pcm_t *pcm, FILE *fp)
525 snd_pcm_adpcm_t *adpcm = pcm->private;
526 fprintf(fp, "Ima-ADPCM conversion PCM (%s)\n",
527 snd_pcm_format_name(adpcm->sformat));
528 if (pcm->valid_setup) {
529 fprintf(fp, "Its setup is:\n");
530 snd_pcm_dump_setup(pcm, fp);
532 fprintf(fp, "Slave: ");
533 snd_pcm_dump(adpcm->plug.slave, fp);
536 struct snd_pcm_ops snd_pcm_adpcm_ops = {
537 close: snd_pcm_adpcm_close,
538 info: snd_pcm_plugin_info,
539 params_info: snd_pcm_adpcm_params_info,
540 params: snd_pcm_adpcm_params,
541 setup: snd_pcm_adpcm_setup,
542 channel_info: snd_pcm_plugin_channel_info,
543 channel_params: snd_pcm_plugin_channel_params,
544 channel_setup: snd_pcm_plugin_channel_setup,
545 dump: snd_pcm_adpcm_dump,
546 nonblock: snd_pcm_plugin_nonblock,
547 mmap_status: snd_pcm_plugin_mmap_status,
548 mmap_control: snd_pcm_plugin_mmap_control,
549 mmap_data: snd_pcm_plugin_mmap_data,
550 munmap_status: snd_pcm_plugin_munmap_status,
551 munmap_control: snd_pcm_plugin_munmap_control,
552 munmap_data: snd_pcm_plugin_munmap_data,
555 int snd_pcm_adpcm_open(snd_pcm_t **handlep, char *name, int sformat, snd_pcm_t *slave, int close_slave)
558 snd_pcm_adpcm_t *adpcm;
560 assert(handlep && slave);
561 if (snd_pcm_format_linear(sformat) != 1 &&
562 sformat != SND_PCM_SFMT_IMA_ADPCM)
564 adpcm = calloc(1, sizeof(snd_pcm_adpcm_t));
568 adpcm->sformat = sformat;
569 adpcm->plug.read = snd_pcm_adpcm_read_areas;
570 adpcm->plug.write = snd_pcm_adpcm_write_areas;
571 adpcm->plug.init = snd_pcm_adpcm_init;
572 adpcm->plug.slave = slave;
573 adpcm->plug.close_slave = close_slave;
575 handle = calloc(1, sizeof(snd_pcm_t));
581 handle->name = strdup(name);
582 handle->type = SND_PCM_TYPE_ADPCM;
583 handle->stream = slave->stream;
584 handle->ops = &snd_pcm_adpcm_ops;
585 handle->op_arg = handle;
586 handle->fast_ops = &snd_pcm_plugin_fast_ops;
587 handle->fast_op_arg = handle;
588 handle->mode = slave->mode;
589 handle->private = adpcm;
590 err = snd_pcm_init(handle);
592 snd_pcm_close(handle);
600 int _snd_pcm_adpcm_open(snd_pcm_t **pcmp, char *name,
602 int stream, int mode)
604 snd_config_iterator_t i;
609 snd_config_foreach(i, conf) {
610 snd_config_t *n = snd_config_entry(i);
611 if (strcmp(n->id, "comment") == 0)
613 if (strcmp(n->id, "type") == 0)
615 if (strcmp(n->id, "stream") == 0)
617 if (strcmp(n->id, "sname") == 0) {
618 err = snd_config_string_get(n, &sname);
623 if (strcmp(n->id, "sformat") == 0) {
625 err = snd_config_string_get(n, &f);
628 sformat = snd_pcm_format_value(f);
631 if (snd_pcm_format_linear(sformat) != 1 &&
632 sformat != SND_PCM_SFMT_IMA_ADPCM)
638 if (!sname || !sformat)
640 /* This is needed cause snd_config_update may destroy config */
641 sname = strdup(sname);
644 err = snd_pcm_open(&spcm, sname, stream, mode);
648 err = snd_pcm_adpcm_open(pcmp, name, sformat, spcm, 1);