2 * \file pcm/pcm_adpcm.c
4 * \brief PCM Ima-ADPCM Conversion Plugin Interface
5 * \author Abramo Bagnara <abramo@alsa-project.org>
6 * \author Uros Bizjak <uros@kss-loka.si>
7 * \author Jaroslav Kysela <perex@perex.cz>
11 * PCM - Ima-ADPCM conversion
12 * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
13 * Copyright (c) 1999 by Uros Bizjak <uros@kss-loka.si>
14 * Jaroslav Kysela <perex@perex.cz>
16 * Based on Version 1.2, 18-Dec-92 implementation of Intel/DVI ADPCM code
17 * by Jack Jansen, CWI, Amsterdam <Jack.Jansen@cwi.nl>, Copyright 1992
18 * by Stichting Mathematisch Centrum, Amsterdam, The Netherlands.
20 * This library is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU Lesser General Public License as
22 * published by the Free Software Foundation; either version 2.1 of
23 * the License, or (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU Lesser General Public License for more details.
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37 These routines convert 16 bit linear PCM samples to 4 bit ADPCM code
38 and vice versa. The ADPCM code used is the Intel/DVI ADPCM code which
39 is being recommended by the IMA Digital Audio Technical Working Group.
41 The algorithm for this coder was taken from:
42 Proposal for Standardized Audio Interstreamge Formats,
43 IMA compatibility project proceedings, Vol 2, Issue 2, May 1992.
45 - No, this is *not* a G.721 coder/decoder. The algorithm used by G.721
46 is very complicated, requiring oodles of floating-point ops per
47 sample (resulting in very poor performance). I have not done any
48 tests myself but various people have assured my that 721 quality is
49 actually lower than DVI quality.
51 - No, it probably isn't a RIFF ADPCM decoder either. Trying to decode
52 RIFF ADPCM with these routines seems to result in something
53 recognizable but very distorted.
55 - No, it is not a CDROM-XA coder either, as far as I know. I haven't
56 come across a good description of XA yet.
60 #include "pcm_local.h"
61 #include "pcm_plugin.h"
63 #include "plugin_ops.h"
66 /* entry for static linking */
67 const char *_snd_module_pcm_adpcm = "";
72 typedef void (*adpcm_f)(const snd_pcm_channel_area_t *dst_areas,
73 snd_pcm_uframes_t dst_offset,
74 const snd_pcm_channel_area_t *src_areas,
75 snd_pcm_uframes_t src_offset,
76 unsigned int channels, snd_pcm_uframes_t frames,
77 unsigned int getputidx,
78 snd_pcm_adpcm_state_t *states);
81 /* This field need to be the first */
82 snd_pcm_plugin_t plug;
83 unsigned int getput_idx;
85 snd_pcm_format_t sformat;
86 snd_pcm_adpcm_state_t *states;
91 /* First table lookup for Ima-ADPCM quantizer */
92 static char IndexAdjust[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
94 /* Second table lookup for Ima-ADPCM quantizer */
95 static short StepSize[89] = {
96 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
97 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
98 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
99 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
100 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
101 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
102 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
103 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
104 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
107 static char adpcm_encoder(int sl, snd_pcm_adpcm_state_t * state)
109 short diff; /* Difference between sl and predicted sample */
110 short pred_diff; /* Predicted difference to next sample */
112 unsigned char sign; /* sign of diff */
113 short step; /* holds previous StepSize value */
114 unsigned char adjust_idx; /* Index to IndexAdjust lookup table */
118 /* Compute difference to previous predicted value */
119 diff = sl - state->pred_val;
120 sign = (diff < 0) ? 0x8 : 0x0;
126 * This code *approximately* computes:
127 * adjust_idx = diff * 4 / step;
128 * pred_diff = (adjust_idx + 0.5) * step / 4;
130 * But in shift step bits are dropped. The net result of this is
131 * that even if you have fast mul/div hardware you cannot put it to
132 * good use since the fix-up would be too expensive.
135 step = StepSize[state->step_idx];
137 /* Divide and clamp */
138 pred_diff = step >> 3;
139 for (adjust_idx = 0, i = 0x4; i; i >>= 1, step >>= 1) {
147 /* Update and clamp previous predicted value */
148 state->pred_val += sign ? -pred_diff : pred_diff;
150 if (state->pred_val > 32767) {
151 state->pred_val = 32767;
152 } else if (state->pred_val < -32768) {
153 state->pred_val = -32768;
156 /* Update and clamp StepSize lookup table index */
157 state->step_idx += IndexAdjust[adjust_idx];
159 if (state->step_idx < 0) {
161 } else if (state->step_idx > 88) {
162 state->step_idx = 88;
164 return (sign | adjust_idx);
168 static int adpcm_decoder(unsigned char code, snd_pcm_adpcm_state_t * state)
170 short pred_diff; /* Predicted difference to next sample */
171 short step; /* holds previous StepSize value */
176 /* Separate sign and magnitude */
181 * Computes pred_diff = (code + 0.5) * step / 4,
182 * but see comment in adpcm_coder.
185 step = StepSize[state->step_idx];
187 /* Compute difference and new predicted value */
188 pred_diff = step >> 3;
189 for (i = 0x4; i; i >>= 1, step >>= 1) {
194 state->pred_val += (sign) ? -pred_diff : pred_diff;
196 /* Clamp output value */
197 if (state->pred_val > 32767) {
198 state->pred_val = 32767;
199 } else if (state->pred_val < -32768) {
200 state->pred_val = -32768;
203 /* Find new StepSize index value */
204 state->step_idx += IndexAdjust[code];
206 if (state->step_idx < 0) {
208 } else if (state->step_idx > 88) {
209 state->step_idx = 88;
211 return (state->pred_val);
216 void snd_pcm_adpcm_decode(const snd_pcm_channel_area_t *dst_areas,
217 snd_pcm_uframes_t dst_offset,
218 const snd_pcm_channel_area_t *src_areas,
219 snd_pcm_uframes_t src_offset,
220 unsigned int channels, snd_pcm_uframes_t frames,
222 snd_pcm_adpcm_state_t *states)
225 #include "plugin_ops.h"
227 void *put = put16_labels[putidx];
228 unsigned int channel;
229 for (channel = 0; channel < channels; ++channel, ++states) {
233 int src_step, srcbit_step, dst_step;
234 snd_pcm_uframes_t frames1;
235 const snd_pcm_channel_area_t *src_area = &src_areas[channel];
236 const snd_pcm_channel_area_t *dst_area = &dst_areas[channel];
237 srcbit = src_area->first + src_area->step * src_offset;
238 src = (const char *) src_area->addr + srcbit / 8;
240 src_step = src_area->step / 8;
241 srcbit_step = src_area->step % 8;
242 dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
243 dst_step = snd_pcm_channel_area_step(dst_area);
245 while (frames1-- > 0) {
251 v = (*src >> 4) & 0x0f;
252 sample = adpcm_decoder(v, states);
254 #define PUT16_END after
255 #include "plugin_ops.h"
259 srcbit += srcbit_step;
269 void snd_pcm_adpcm_encode(const snd_pcm_channel_area_t *dst_areas,
270 snd_pcm_uframes_t dst_offset,
271 const snd_pcm_channel_area_t *src_areas,
272 snd_pcm_uframes_t src_offset,
273 unsigned int channels, snd_pcm_uframes_t frames,
275 snd_pcm_adpcm_state_t *states)
278 #include "plugin_ops.h"
280 void *get = get16_labels[getidx];
281 unsigned int channel;
283 for (channel = 0; channel < channels; ++channel, ++states) {
287 int src_step, dst_step, dstbit_step;
288 snd_pcm_uframes_t frames1;
289 const snd_pcm_channel_area_t *src_area = &src_areas[channel];
290 const snd_pcm_channel_area_t *dst_area = &dst_areas[channel];
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 = (char *) 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 GET16_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;
324 static int snd_pcm_adpcm_hw_refine_cprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
326 snd_pcm_adpcm_t *adpcm = pcm->private_data;
328 snd_pcm_access_mask_t access_mask = { SND_PCM_ACCBIT_SHM };
329 err = _snd_pcm_hw_param_set_mask(params, SND_PCM_HW_PARAM_ACCESS,
333 if (adpcm->sformat == SND_PCM_FORMAT_IMA_ADPCM) {
334 snd_pcm_format_mask_t format_mask = { SND_PCM_FMTBIT_LINEAR };
335 err = _snd_pcm_hw_param_set_mask(params, SND_PCM_HW_PARAM_FORMAT,
338 err = _snd_pcm_hw_params_set_format(params,
339 SND_PCM_FORMAT_IMA_ADPCM);
343 err = _snd_pcm_hw_params_set_subformat(params,
344 SND_PCM_SUBFORMAT_STD);
347 params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
351 static int snd_pcm_adpcm_hw_refine_sprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *sparams)
353 snd_pcm_adpcm_t *adpcm = pcm->private_data;
354 snd_pcm_access_mask_t saccess_mask = { SND_PCM_ACCBIT_MMAP };
355 _snd_pcm_hw_params_any(sparams);
356 _snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
358 _snd_pcm_hw_params_set_format(sparams, adpcm->sformat);
359 _snd_pcm_hw_params_set_subformat(sparams, SND_PCM_SUBFORMAT_STD);
363 static int snd_pcm_adpcm_hw_refine_schange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
364 snd_pcm_hw_params_t *sparams)
367 unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
368 SND_PCM_HW_PARBIT_RATE |
369 SND_PCM_HW_PARBIT_PERIOD_SIZE |
370 SND_PCM_HW_PARBIT_BUFFER_SIZE |
371 SND_PCM_HW_PARBIT_PERIODS |
372 SND_PCM_HW_PARBIT_PERIOD_TIME |
373 SND_PCM_HW_PARBIT_BUFFER_TIME |
374 SND_PCM_HW_PARBIT_TICK_TIME);
375 err = _snd_pcm_hw_params_refine(sparams, links, params);
381 static int snd_pcm_adpcm_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
382 snd_pcm_hw_params_t *sparams)
385 unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
386 SND_PCM_HW_PARBIT_RATE |
387 SND_PCM_HW_PARBIT_PERIOD_SIZE |
388 SND_PCM_HW_PARBIT_BUFFER_SIZE |
389 SND_PCM_HW_PARBIT_PERIODS |
390 SND_PCM_HW_PARBIT_PERIOD_TIME |
391 SND_PCM_HW_PARBIT_BUFFER_TIME |
392 SND_PCM_HW_PARBIT_TICK_TIME);
393 err = _snd_pcm_hw_params_refine(params, links, sparams);
399 static int snd_pcm_adpcm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
401 return snd_pcm_hw_refine_slave(pcm, params,
402 snd_pcm_adpcm_hw_refine_cprepare,
403 snd_pcm_adpcm_hw_refine_cchange,
404 snd_pcm_adpcm_hw_refine_sprepare,
405 snd_pcm_adpcm_hw_refine_schange,
406 snd_pcm_generic_hw_refine);
409 static int snd_pcm_adpcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
411 snd_pcm_adpcm_t *adpcm = pcm->private_data;
412 snd_pcm_format_t format;
413 int err = snd_pcm_hw_params_slave(pcm, params,
414 snd_pcm_adpcm_hw_refine_cchange,
415 snd_pcm_adpcm_hw_refine_sprepare,
416 snd_pcm_adpcm_hw_refine_schange,
417 snd_pcm_generic_hw_params);
421 err = INTERNAL(snd_pcm_hw_params_get_format)(params, &format);
425 if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
426 if (adpcm->sformat == SND_PCM_FORMAT_IMA_ADPCM) {
427 adpcm->getput_idx = snd_pcm_linear_get_index(format, SND_PCM_FORMAT_S16);
428 adpcm->func = snd_pcm_adpcm_encode;
430 adpcm->getput_idx = snd_pcm_linear_put_index(SND_PCM_FORMAT_S16, adpcm->sformat);
431 adpcm->func = snd_pcm_adpcm_decode;
434 if (adpcm->sformat == SND_PCM_FORMAT_IMA_ADPCM) {
435 adpcm->getput_idx = snd_pcm_linear_put_index(SND_PCM_FORMAT_S16, format);
436 adpcm->func = snd_pcm_adpcm_decode;
438 adpcm->getput_idx = snd_pcm_linear_get_index(adpcm->sformat, SND_PCM_FORMAT_S16);
439 adpcm->func = snd_pcm_adpcm_encode;
442 assert(!adpcm->states);
443 adpcm->states = malloc(adpcm->plug.gen.slave->channels * sizeof(*adpcm->states));
444 if (adpcm->states == NULL)
449 static int snd_pcm_adpcm_hw_free(snd_pcm_t *pcm)
451 snd_pcm_adpcm_t *adpcm = pcm->private_data;
453 adpcm->states = NULL;
454 return snd_pcm_hw_free(adpcm->plug.gen.slave);
457 static int snd_pcm_adpcm_init(snd_pcm_t *pcm)
459 snd_pcm_adpcm_t *adpcm = pcm->private_data;
461 for (k = 0; k < pcm->channels; ++k) {
462 adpcm->states[k].pred_val = 0;
463 adpcm->states[k].step_idx = 0;
468 static snd_pcm_uframes_t
469 snd_pcm_adpcm_write_areas(snd_pcm_t *pcm,
470 const snd_pcm_channel_area_t *areas,
471 snd_pcm_uframes_t offset,
472 snd_pcm_uframes_t size,
473 const snd_pcm_channel_area_t *slave_areas,
474 snd_pcm_uframes_t slave_offset,
475 snd_pcm_uframes_t *slave_sizep)
477 snd_pcm_adpcm_t *adpcm = pcm->private_data;
478 if (size > *slave_sizep)
480 adpcm->func(slave_areas, slave_offset,
483 adpcm->getput_idx, adpcm->states);
488 static snd_pcm_uframes_t
489 snd_pcm_adpcm_read_areas(snd_pcm_t *pcm,
490 const snd_pcm_channel_area_t *areas,
491 snd_pcm_uframes_t offset,
492 snd_pcm_uframes_t size,
493 const snd_pcm_channel_area_t *slave_areas,
494 snd_pcm_uframes_t slave_offset,
495 snd_pcm_uframes_t *slave_sizep)
497 snd_pcm_adpcm_t *adpcm = pcm->private_data;
498 if (size > *slave_sizep)
500 adpcm->func(areas, offset,
501 slave_areas, slave_offset,
503 adpcm->getput_idx, adpcm->states);
508 static void snd_pcm_adpcm_dump(snd_pcm_t *pcm, snd_output_t *out)
510 snd_pcm_adpcm_t *adpcm = pcm->private_data;
511 snd_output_printf(out, "Ima-ADPCM conversion PCM (%s)\n",
512 snd_pcm_format_name(adpcm->sformat));
514 snd_output_printf(out, "Its setup is:\n");
515 snd_pcm_dump_setup(pcm, out);
517 snd_output_printf(out, "Slave: ");
518 snd_pcm_dump(adpcm->plug.gen.slave, out);
521 static snd_pcm_ops_t snd_pcm_adpcm_ops = {
522 .close = snd_pcm_generic_close,
523 .info = snd_pcm_generic_info,
524 .hw_refine = snd_pcm_adpcm_hw_refine,
525 .hw_params = snd_pcm_adpcm_hw_params,
526 .hw_free = snd_pcm_adpcm_hw_free,
527 .sw_params = snd_pcm_generic_sw_params,
528 .channel_info = snd_pcm_generic_channel_info,
529 .dump = snd_pcm_adpcm_dump,
530 .nonblock = snd_pcm_generic_nonblock,
531 .async = snd_pcm_generic_async,
532 .mmap = snd_pcm_generic_mmap,
533 .munmap = snd_pcm_generic_munmap,
537 * \brief Creates a new Ima-ADPCM conversion PCM
538 * \param pcmp Returns created PCM handle
539 * \param name Name of PCM
540 * \param sformat Slave (destination) format
541 * \param slave Slave PCM handle
542 * \param close_slave When set, the slave PCM handle is closed with copy PCM
543 * \retval zero on success otherwise a negative error code
544 * \warning Using of this function might be dangerous in the sense
545 * of compatibility reasons. The prototype might be freely
548 int snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sformat, snd_pcm_t *slave, int close_slave)
551 snd_pcm_adpcm_t *adpcm;
553 assert(pcmp && slave);
554 if (snd_pcm_format_linear(sformat) != 1 &&
555 sformat != SND_PCM_FORMAT_IMA_ADPCM)
557 adpcm = calloc(1, sizeof(snd_pcm_adpcm_t));
561 adpcm->sformat = sformat;
562 snd_pcm_plugin_init(&adpcm->plug);
563 adpcm->plug.read = snd_pcm_adpcm_read_areas;
564 adpcm->plug.write = snd_pcm_adpcm_write_areas;
565 adpcm->plug.init = snd_pcm_adpcm_init;
566 adpcm->plug.gen.slave = slave;
567 adpcm->plug.gen.close_slave = close_slave;
569 err = snd_pcm_new(&pcm, SND_PCM_TYPE_ADPCM, name, slave->stream, slave->mode);
574 pcm->ops = &snd_pcm_adpcm_ops;
575 pcm->fast_ops = &snd_pcm_plugin_fast_ops;
576 pcm->private_data = adpcm;
577 pcm->poll_fd = slave->poll_fd;
578 pcm->poll_events = slave->poll_events;
579 snd_pcm_set_hw_ptr(pcm, &adpcm->plug.hw_ptr, -1, 0);
580 snd_pcm_set_appl_ptr(pcm, &adpcm->plug.appl_ptr, -1, 0);
586 /*! \page pcm_plugins
588 \section pcm_plugins_adpcm Plugin: Ima-ADPCM
590 This plugin converts Ima-ADPCM samples to linear or linear to Ima-ADPCM samples
591 from master Ima-ADPCM conversion PCM to given slave PCM. The channel count,
592 format and rate must match for both of them.
596 type adpcm # Ima-ADPCM conversion PCM
597 slave STR # Slave name
599 slave { # Slave definition
600 pcm STR # Slave PCM name
602 pcm { } # Slave PCM definition
603 format STR # Slave format
608 \subsection pcm_plugins_adpcm_funcref Function reference
611 <LI>snd_pcm_adpcm_open()
612 <LI>_snd_pcm_adpcm_open()
618 * \brief Creates a new Ima-ADPCM conversion PCM
619 * \param pcmp Returns created PCM handle
620 * \param name Name of PCM
621 * \param root Root configuration node
622 * \param conf Configuration node with copy PCM description
623 * \param stream Stream type
624 * \param mode Stream mode
625 * \retval zero on success otherwise a negative error code
626 * \warning Using of this function might be dangerous in the sense
627 * of compatibility reasons. The prototype might be freely
630 int _snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name,
631 snd_config_t *root, snd_config_t *conf,
632 snd_pcm_stream_t stream, int mode)
634 snd_config_iterator_t i, next;
637 snd_config_t *slave = NULL, *sconf;
638 snd_pcm_format_t sformat;
639 snd_config_for_each(i, next, conf) {
640 snd_config_t *n = snd_config_iterator_entry(i);
642 if (snd_config_get_id(n, &id) < 0)
644 if (snd_pcm_conf_generic_id(id))
646 if (strcmp(id, "slave") == 0) {
650 SNDERR("Unknown field %s", id);
654 SNDERR("slave is not defined");
657 err = snd_pcm_slave_conf(root, slave, &sconf, 1,
658 SND_PCM_HW_PARAM_FORMAT, SCONF_MANDATORY, &sformat);
661 if (snd_pcm_format_linear(sformat) != 1 &&
662 sformat != SND_PCM_FORMAT_IMA_ADPCM) {
663 snd_config_delete(sconf);
664 SNDERR("invalid slave format");
667 err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
668 snd_config_delete(sconf);
671 err = snd_pcm_adpcm_open(pcmp, name, sformat, spcm, 1);
677 SND_DLSYM_BUILD_VERSION(_snd_pcm_adpcm_open, SND_PCM_DLSYM_VERSION);