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"
54 typedef void (*adpcm_f)(const snd_pcm_channel_area_t *dst_areas,
55 snd_pcm_uframes_t dst_offset,
56 const snd_pcm_channel_area_t *src_areas,
57 snd_pcm_uframes_t src_offset,
58 unsigned int channels, snd_pcm_uframes_t frames, int getputidx,
59 snd_pcm_adpcm_state_t *states);
62 /* This field need to be the first */
63 snd_pcm_plugin_t plug;
66 snd_pcm_format_t sformat;
67 snd_pcm_adpcm_state_t *states;
70 /* First table lookup for Ima-ADPCM quantizer */
71 static char IndexAdjust[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
73 /* Second table lookup for Ima-ADPCM quantizer */
74 static short StepSize[89] = {
75 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
76 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
77 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
78 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
79 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
80 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
81 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
82 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
83 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
86 static char adpcm_encoder(int sl, snd_pcm_adpcm_state_t * state)
88 short diff; /* Difference between sl and predicted sample */
89 short pred_diff; /* Predicted difference to next sample */
91 unsigned char sign; /* sign of diff */
92 short step; /* holds previous StepSize value */
93 unsigned char adjust_idx; /* Index to IndexAdjust lookup table */
97 /* Compute difference to previous predicted value */
98 diff = sl - state->pred_val;
99 sign = (diff < 0) ? 0x8 : 0x0;
105 * This code *approximately* computes:
106 * adjust_idx = diff * 4 / step;
107 * pred_diff = (adjust_idx + 0.5) * step / 4;
109 * But in shift step bits are dropped. The net result of this is
110 * that even if you have fast mul/div hardware you cannot put it to
111 * good use since the fixup would be too expensive.
114 step = StepSize[state->step_idx];
116 /* Divide and clamp */
117 pred_diff = step >> 3;
118 for (adjust_idx = 0, i = 0x4; i; i >>= 1, step >>= 1) {
126 /* Update and clamp previous predicted value */
127 state->pred_val += sign ? -pred_diff : pred_diff;
129 if (state->pred_val > 32767) {
130 state->pred_val = 32767;
131 } else if (state->pred_val < -32768) {
132 state->pred_val = -32768;
135 /* Update and clamp StepSize lookup table index */
136 state->step_idx += IndexAdjust[adjust_idx];
138 if (state->step_idx < 0) {
140 } else if (state->step_idx > 88) {
141 state->step_idx = 88;
143 return (sign | adjust_idx);
147 static int adpcm_decoder(unsigned char code, snd_pcm_adpcm_state_t * state)
149 short pred_diff; /* Predicted difference to next sample */
150 short step; /* holds previous StepSize value */
155 /* Separate sign and magnitude */
160 * Computes pred_diff = (code + 0.5) * step / 4,
161 * but see comment in adpcm_coder.
164 step = StepSize[state->step_idx];
166 /* Compute difference and new predicted value */
167 pred_diff = step >> 3;
168 for (i = 0x4; i; i >>= 1, step >>= 1) {
173 state->pred_val += (sign) ? -pred_diff : pred_diff;
175 /* Clamp output value */
176 if (state->pred_val > 32767) {
177 state->pred_val = 32767;
178 } else if (state->pred_val < -32768) {
179 state->pred_val = -32768;
182 /* Find new StepSize index value */
183 state->step_idx += IndexAdjust[code];
185 if (state->step_idx < 0) {
187 } else if (state->step_idx > 88) {
188 state->step_idx = 88;
190 return (state->pred_val);
193 void snd_pcm_adpcm_decode(const snd_pcm_channel_area_t *dst_areas,
194 snd_pcm_uframes_t dst_offset,
195 const snd_pcm_channel_area_t *src_areas,
196 snd_pcm_uframes_t src_offset,
197 unsigned int channels, snd_pcm_uframes_t frames, int putidx,
198 snd_pcm_adpcm_state_t *states)
201 #include "plugin_ops.h"
203 void *put = put16_labels[putidx];
204 unsigned int channel;
205 for (channel = 0; channel < channels; ++channel, ++states) {
209 int src_step, srcbit_step, dst_step;
210 snd_pcm_uframes_t frames1;
211 const snd_pcm_channel_area_t *src_area = &src_areas[channel];
212 const snd_pcm_channel_area_t *dst_area = &dst_areas[channel];
214 if (!src_area->enabled) {
215 if (dst_area->wanted)
216 snd_pcm_area_silence(dst_area, dst_offset, frames, dst_sfmt);
217 dst_area->enabled = 0;
220 dst_area->enabled = 1;
222 srcbit = src_area->first + src_area->step * src_offset;
223 src = src_area->addr + srcbit / 8;
225 src_step = src_area->step / 8;
226 srcbit_step = src_area->step % 8;
227 dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
228 dst_step = snd_pcm_channel_area_step(dst_area);
230 while (frames1-- > 0) {
236 v = (*src >> 4) & 0x0f;
237 sample = adpcm_decoder(v, states);
239 #define PUT16_END after
240 #include "plugin_ops.h"
244 srcbit += srcbit_step;
254 void snd_pcm_adpcm_encode(const snd_pcm_channel_area_t *dst_areas,
255 snd_pcm_uframes_t dst_offset,
256 const snd_pcm_channel_area_t *src_areas,
257 snd_pcm_uframes_t src_offset,
258 unsigned int channels, snd_pcm_uframes_t frames, int getidx,
259 snd_pcm_adpcm_state_t *states)
262 #include "plugin_ops.h"
264 void *get = get16_labels[getidx];
265 unsigned int channel;
267 for (channel = 0; channel < channels; ++channel, ++states) {
271 int src_step, dst_step, dstbit_step;
272 snd_pcm_uframes_t frames1;
273 const snd_pcm_channel_area_t *src_area = &src_areas[channel];
274 const snd_pcm_channel_area_t *dst_area = &dst_areas[channel];
276 if (!src_area->enabled) {
277 if (dst_area->wanted)
278 snd_pcm_area_silence(dst_area, dst_offset, frames, dst_sfmt);
279 dst_area->enabled = 0;
282 dst_area->enabled = 1;
284 src = snd_pcm_channel_area_addr(src_area, src_offset);
285 src_step = snd_pcm_channel_area_step(src_area);
286 dstbit = dst_area->first + dst_area->step * dst_offset;
287 dst = dst_area->addr + dstbit / 8;
289 dst_step = dst_area->step / 8;
290 dstbit_step = dst_area->step % 8;
292 while (frames1-- > 0) {
295 #define GET16_END after
296 #include "plugin_ops.h"
299 v = adpcm_encoder(sample, states);
301 *dst = (*dst & 0xf0) | v;
303 *dst = (*dst & 0x0f) | (v << 4);
306 dstbit += dstbit_step;
315 static int snd_pcm_adpcm_hw_refine_cprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
317 snd_pcm_adpcm_t *adpcm = pcm->private;
319 snd_pcm_access_mask_t access_mask = { SND_PCM_ACCBIT_PLUGIN };
320 err = _snd_pcm_hw_param_set_mask(params, SND_PCM_HW_PARAM_ACCESS,
324 if (adpcm->sformat == SND_PCM_FORMAT_IMA_ADPCM) {
325 snd_pcm_format_mask_t format_mask = { SND_PCM_FMTBIT_LINEAR };
326 err = _snd_pcm_hw_param_set_mask(params, SND_PCM_HW_PARAM_FORMAT,
329 err = _snd_pcm_hw_params_set_format(params,
330 SND_PCM_FORMAT_IMA_ADPCM);
334 err = _snd_pcm_hw_params_set_subformat(params,
335 SND_PCM_SUBFORMAT_STD);
338 params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
342 static int snd_pcm_adpcm_hw_refine_sprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *sparams)
344 snd_pcm_adpcm_t *adpcm = pcm->private;
345 snd_pcm_access_mask_t saccess_mask = { SND_PCM_ACCBIT_MMAP };
346 _snd_pcm_hw_params_any(sparams);
347 _snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
349 _snd_pcm_hw_params_set_format(sparams, adpcm->sformat);
350 _snd_pcm_hw_params_set_subformat(sparams, SND_PCM_SUBFORMAT_STD);
354 static int snd_pcm_adpcm_hw_refine_schange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
355 snd_pcm_hw_params_t *sparams)
358 unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
359 SND_PCM_HW_PARBIT_RATE |
360 SND_PCM_HW_PARBIT_PERIOD_SIZE |
361 SND_PCM_HW_PARBIT_BUFFER_SIZE |
362 SND_PCM_HW_PARBIT_PERIODS |
363 SND_PCM_HW_PARBIT_PERIOD_TIME |
364 SND_PCM_HW_PARBIT_BUFFER_TIME |
365 SND_PCM_HW_PARBIT_TICK_TIME);
366 err = _snd_pcm_hw_params_refine(sparams, links, params);
372 static int snd_pcm_adpcm_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
373 snd_pcm_hw_params_t *sparams)
376 unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
377 SND_PCM_HW_PARBIT_RATE |
378 SND_PCM_HW_PARBIT_PERIOD_SIZE |
379 SND_PCM_HW_PARBIT_BUFFER_SIZE |
380 SND_PCM_HW_PARBIT_PERIODS |
381 SND_PCM_HW_PARBIT_PERIOD_TIME |
382 SND_PCM_HW_PARBIT_BUFFER_TIME |
383 SND_PCM_HW_PARBIT_TICK_TIME);
384 err = _snd_pcm_hw_params_refine(params, links, sparams);
390 static int snd_pcm_adpcm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
392 return snd_pcm_hw_refine_slave(pcm, params,
393 snd_pcm_adpcm_hw_refine_cprepare,
394 snd_pcm_adpcm_hw_refine_cchange,
395 snd_pcm_adpcm_hw_refine_sprepare,
396 snd_pcm_adpcm_hw_refine_schange,
397 snd_pcm_plugin_hw_refine_slave);
400 static int snd_pcm_adpcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
402 snd_pcm_adpcm_t *adpcm = pcm->private;
403 int err = snd_pcm_hw_params_slave(pcm, params,
404 snd_pcm_adpcm_hw_refine_cchange,
405 snd_pcm_adpcm_hw_refine_sprepare,
406 snd_pcm_adpcm_hw_refine_schange,
407 snd_pcm_plugin_hw_params_slave);
412 if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
413 if (adpcm->sformat == SND_PCM_FORMAT_IMA_ADPCM) {
414 adpcm->getput_idx = snd_pcm_linear_get_index(snd_pcm_hw_params_get_format(params), SND_PCM_FORMAT_S16);
415 adpcm->func = snd_pcm_adpcm_encode;
417 adpcm->getput_idx = snd_pcm_linear_put_index(SND_PCM_FORMAT_S16, adpcm->sformat);
418 adpcm->func = snd_pcm_adpcm_decode;
421 if (adpcm->sformat == SND_PCM_FORMAT_IMA_ADPCM) {
422 adpcm->getput_idx = snd_pcm_linear_put_index(SND_PCM_FORMAT_S16, snd_pcm_hw_params_get_format(params));
423 adpcm->func = snd_pcm_adpcm_decode;
425 adpcm->getput_idx = snd_pcm_linear_get_index(adpcm->sformat, SND_PCM_FORMAT_S16);
426 adpcm->func = snd_pcm_adpcm_encode;
429 assert(!adpcm->states);
430 adpcm->states = malloc(snd_pcm_hw_param_get(params, SND_PCM_HW_PARAM_CHANNELS, 0) * sizeof(*adpcm->states));
434 static int snd_pcm_adpcm_hw_free(snd_pcm_t *pcm)
436 snd_pcm_adpcm_t *adpcm = pcm->private;
441 return snd_pcm_hw_free(adpcm->plug.slave);
444 static int snd_pcm_adpcm_init(snd_pcm_t *pcm)
446 snd_pcm_adpcm_t *adpcm = pcm->private;
448 for (k = 0; k < pcm->channels; ++k) {
449 adpcm->states[k].pred_val = 0;
450 adpcm->states[k].step_idx = 0;
455 static snd_pcm_sframes_t snd_pcm_adpcm_write_areas(snd_pcm_t *pcm,
456 const snd_pcm_channel_area_t *areas,
457 snd_pcm_uframes_t offset,
458 snd_pcm_uframes_t size,
459 snd_pcm_uframes_t *slave_sizep)
461 snd_pcm_adpcm_t *adpcm = pcm->private;
462 snd_pcm_t *slave = adpcm->plug.slave;
463 snd_pcm_uframes_t xfer = 0;
464 snd_pcm_sframes_t err = 0;
465 if (slave_sizep && *slave_sizep < size)
468 while (xfer < size) {
469 snd_pcm_uframes_t frames = snd_pcm_mmap_playback_xfer(slave, size - xfer);
470 adpcm->func(snd_pcm_mmap_areas(slave), snd_pcm_mmap_offset(slave),
472 pcm->channels, frames,
473 adpcm->getput_idx, adpcm->states);
474 err = snd_pcm_mmap_forward(slave, frames);
477 assert((snd_pcm_uframes_t)err == frames);
480 snd_pcm_mmap_hw_forward(pcm, err);
490 static snd_pcm_sframes_t snd_pcm_adpcm_read_areas(snd_pcm_t *pcm,
491 const snd_pcm_channel_area_t *areas,
492 snd_pcm_uframes_t offset,
493 snd_pcm_uframes_t size,
494 snd_pcm_uframes_t *slave_sizep)
496 snd_pcm_adpcm_t *adpcm = pcm->private;
497 snd_pcm_t *slave = adpcm->plug.slave;
498 snd_pcm_uframes_t xfer = 0;
499 snd_pcm_sframes_t err = 0;
500 if (slave_sizep && *slave_sizep < size)
503 while (xfer < size) {
504 snd_pcm_uframes_t frames = snd_pcm_mmap_capture_xfer(slave, size - xfer);
505 adpcm->func(areas, offset,
506 snd_pcm_mmap_areas(slave), snd_pcm_mmap_offset(slave),
507 pcm->channels, frames,
508 adpcm->getput_idx, adpcm->states);
509 err = snd_pcm_mmap_forward(slave, frames);
512 assert((snd_pcm_uframes_t)err == frames);
515 snd_pcm_mmap_hw_forward(pcm, err);
525 static void snd_pcm_adpcm_dump(snd_pcm_t *pcm, snd_output_t *out)
527 snd_pcm_adpcm_t *adpcm = pcm->private;
528 snd_output_printf(out, "Ima-ADPCM conversion PCM (%s)\n",
529 snd_pcm_format_name(adpcm->sformat));
531 snd_output_printf(out, "Its setup is:\n");
532 snd_pcm_dump_setup(pcm, out);
534 snd_output_printf(out, "Slave: ");
535 snd_pcm_dump(adpcm->plug.slave, out);
538 snd_pcm_ops_t snd_pcm_adpcm_ops = {
539 close: snd_pcm_plugin_close,
540 info: snd_pcm_plugin_info,
541 hw_refine: snd_pcm_adpcm_hw_refine,
542 hw_params: snd_pcm_adpcm_hw_params,
543 hw_free: snd_pcm_adpcm_hw_free,
544 sw_params: snd_pcm_plugin_sw_params,
545 channel_info: snd_pcm_plugin_channel_info,
546 dump: snd_pcm_adpcm_dump,
547 nonblock: snd_pcm_plugin_nonblock,
548 async: snd_pcm_plugin_async,
549 mmap: snd_pcm_plugin_mmap,
550 munmap: snd_pcm_plugin_munmap,
553 int snd_pcm_adpcm_open(snd_pcm_t **pcmp, char *name, snd_pcm_format_t sformat, snd_pcm_t *slave, int close_slave)
556 snd_pcm_adpcm_t *adpcm;
557 assert(pcmp && slave);
558 if (snd_pcm_format_linear(sformat) != 1 &&
559 sformat != SND_PCM_FORMAT_IMA_ADPCM)
561 adpcm = calloc(1, sizeof(snd_pcm_adpcm_t));
565 adpcm->sformat = sformat;
566 adpcm->plug.read = snd_pcm_adpcm_read_areas;
567 adpcm->plug.write = snd_pcm_adpcm_write_areas;
568 adpcm->plug.init = snd_pcm_adpcm_init;
569 adpcm->plug.slave = slave;
570 adpcm->plug.close_slave = close_slave;
572 pcm = calloc(1, sizeof(snd_pcm_t));
578 pcm->name = strdup(name);
579 pcm->type = SND_PCM_TYPE_ADPCM;
580 pcm->stream = slave->stream;
581 pcm->mode = slave->mode;
582 pcm->ops = &snd_pcm_adpcm_ops;
584 pcm->fast_ops = &snd_pcm_plugin_fast_ops;
585 pcm->fast_op_arg = pcm;
586 pcm->private = adpcm;
587 pcm->poll_fd = slave->poll_fd;
588 pcm->hw_ptr = &adpcm->plug.hw_ptr;
589 pcm->appl_ptr = &adpcm->plug.appl_ptr;
595 int _snd_pcm_adpcm_open(snd_pcm_t **pcmp, char *name,
597 snd_pcm_stream_t stream, int mode)
599 snd_config_iterator_t i;
600 const char *sname = NULL;
603 snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
604 snd_config_foreach(i, conf) {
605 snd_config_t *n = snd_config_iterator_entry(i);
606 const char *id = snd_config_get_id(n);
607 if (strcmp(id, "comment") == 0)
609 if (strcmp(id, "type") == 0)
611 if (strcmp(id, "stream") == 0)
613 if (strcmp(id, "sname") == 0) {
614 err = snd_config_get_string(n, &sname);
616 ERR("Invalid type for %s", id);
621 if (strcmp(id, "sformat") == 0) {
623 err = snd_config_get_string(n, &f);
625 ERR("Invalid type for %s", id);
628 sformat = snd_pcm_format_value(f);
629 if (sformat == SND_PCM_FORMAT_UNKNOWN) {
630 ERR("Unknown sformat");
633 if (snd_pcm_format_linear(sformat) != 1 &&
634 sformat != SND_PCM_FORMAT_IMA_ADPCM) {
635 ERR("Invalid sformat");
640 ERR("Unknown field %s", id);
644 ERR("sname is not defined");
647 if (sformat == SND_PCM_FORMAT_UNKNOWN) {
648 ERR("sformat is not defined");
651 /* This is needed cause snd_config_update may destroy config */
652 sname = strdup(sname);
655 err = snd_pcm_open(&spcm, sname, stream, mode);
656 free((void *) sname);
659 err = snd_pcm_adpcm_open(pcmp, name, sformat, spcm, 1);