• Home
  • History
  • Annotate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/iserver/alsa-lib-1.0.26/src/pcm/

Lines Matching defs:*

2  * \file pcm/pcm_adpcm.c
3 * \ingroup PCM_Plugins
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>
8 * \date 2000-2001
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.
59 #include <byteswap.h>
60 #include "pcm_local.h"
61 #include "pcm_plugin.h"
63 #include "plugin_ops.h"
65 #ifndef PIC
66 /* entry for static linking */
67 const char *_snd_module_pcm_adpcm = "";
68 #endif
70 #ifndef DOC_HIDDEN
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);
80 typedef struct {
81 /* This field need to be the first */
82 snd_pcm_plugin_t plug;
83 unsigned int getput_idx;
84 adpcm_f func;
85 snd_pcm_format_t sformat;
86 snd_pcm_adpcm_state_t *states;
87 } snd_pcm_adpcm_t;
89 #endif
91 /* First table lookup for Ima-ADPCM quantizer */
92 static const char IndexAdjust[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
94 /* Second table lookup for Ima-ADPCM quantizer */
95 static const 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 */
116 int i;
118 /* Compute difference to previous predicted value */
119 diff = sl - state->pred_val;
120 sign = (diff < 0) ? 0x8 : 0x0;
121 if (sign) {
122 diff = -diff;
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) {
140 if (diff >= step) {
141 adjust_idx |= i;
142 diff -= step;
143 pred_diff += step;
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) {
160 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 */
172 char sign;
174 int i;
176 /* Separate sign and magnitude */
177 sign = code & 0x8;
178 code &= 0x7;
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) {
190 if (code & i) {
191 pred_diff += step;
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) {
207 state->step_idx = 0;
208 } else if (state->step_idx > 88) {
209 state->step_idx = 88;
211 return (state->pred_val);
214 #ifndef DOC_HIDDEN
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,
221 unsigned int putidx,
222 snd_pcm_adpcm_state_t *states)
224 #define PUT16_LABELS
225 #include "plugin_ops.h"
226 #undef PUT16_LABELS
227 void *put = put16_labels[putidx];
228 unsigned int channel;
229 for (channel = 0; channel < channels; ++channel, ++states) {
230 const char *src;
231 int srcbit;
232 char *dst;
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;
239 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);
244 frames1 = frames;
245 while (frames1-- > 0) {
246 int16_t sample;
247 unsigned char v;
248 if (srcbit)
249 v = *src & 0x0f;
250 else
251 v = (*src >> 4) & 0x0f;
252 sample = adpcm_decoder(v, states);
253 goto *put;
254 #define PUT16_END after
255 #include "plugin_ops.h"
256 #undef PUT16_END
257 after:
258 src += src_step;
259 srcbit += srcbit_step;
260 if (srcbit == 8) {
261 src++;
262 srcbit = 0;
264 dst += dst_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,
274 unsigned int getidx,
275 snd_pcm_adpcm_state_t *states)
277 #define GET16_LABELS
278 #include "plugin_ops.h"
279 #undef GET16_LABELS
280 void *get = get16_labels[getidx];
281 unsigned int channel;
282 int16_t sample = 0;
283 for (channel = 0; channel < channels; ++channel, ++states) {
284 const char *src;
285 char *dst;
286 int dstbit;
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;
295 dstbit %= 8;
296 dst_step = dst_area->step / 8;
297 dstbit_step = dst_area->step % 8;
298 frames1 = frames;
299 while (frames1-- > 0) {
300 int v;
301 goto *get;
302 #define GET16_END after
303 #include "plugin_ops.h"
304 #undef GET16_END
305 after:
306 v = adpcm_encoder(sample, states);
307 if (dstbit)
308 *dst = (*dst & 0xf0) | v;
309 else
310 *dst = (*dst & 0x0f) | (v << 4);
311 src += src_step;
312 dst += dst_step;
313 dstbit += dstbit_step;
314 if (dstbit == 8) {
315 dst++;
316 dstbit = 0;
322 #endif
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;
327 int err;
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,
330 &access_mask);
331 if (err < 0)
332 return err;
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,
336 &format_mask);
337 } else {
338 err = _snd_pcm_hw_params_set_format(params,
339 SND_PCM_FORMAT_IMA_ADPCM);
341 if (err < 0)
342 return err;
343 err = _snd_pcm_hw_params_set_subformat(params,
344 SND_PCM_SUBFORMAT_STD);
345 if (err < 0)
346 return err;
347 params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
348 return 0;
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,
357 &saccess_mask);
358 _snd_pcm_hw_params_set_format(sparams, adpcm->sformat);
359 _snd_pcm_hw_params_set_subformat(sparams, SND_PCM_SUBFORMAT_STD);
360 return 0;
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)
366 int err;
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);
376 if (err < 0)
377 return err;
378 return 0;
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)
384 int err;
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);
394 if (err < 0)
395 return err;
396 return 0;
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);
418 if (err < 0)
419 return err;
421 err = INTERNAL(snd_pcm_hw_params_get_format)(params, &format);
422 if (err < 0)
423 return err;
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;
429 } else {
430 adpcm->getput_idx = snd_pcm_linear_put_index(SND_PCM_FORMAT_S16, adpcm->sformat);
431 adpcm->func = snd_pcm_adpcm_decode;
433 } else {
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;
437 } else {
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)
445 return -ENOMEM;
446 return 0;
449 static int snd_pcm_adpcm_hw_free(snd_pcm_t *pcm)
451 snd_pcm_adpcm_t *adpcm = pcm->private_data;
452 free(adpcm->states);
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;
460 unsigned int k;
461 for (k = 0; k < pcm->channels; ++k) {
462 adpcm->states[k].pred_val = 0;
463 adpcm->states[k].step_idx = 0;
465 return 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)
479 size = *slave_sizep;
480 adpcm->func(slave_areas, slave_offset,
481 areas, offset,
482 pcm->channels, size,
483 adpcm->getput_idx, adpcm->states);
484 *slave_sizep = size;
485 return size;
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)
499 size = *slave_sizep;
500 adpcm->func(areas, offset,
501 slave_areas, slave_offset,
502 pcm->channels, size,
503 adpcm->getput_idx, adpcm->states);
504 *slave_sizep = size;
505 return size;
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));
513 if (pcm->setup) {
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 const 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
546 * changed in future.
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)
550 snd_pcm_t *pcm;
551 snd_pcm_adpcm_t *adpcm;
552 int err;
553 assert(pcmp && slave);
554 if (snd_pcm_format_linear(sformat) != 1 &&
555 sformat != SND_PCM_FORMAT_IMA_ADPCM)
556 return -EINVAL;
557 adpcm = calloc(1, sizeof(snd_pcm_adpcm_t));
558 if (!adpcm) {
559 return -ENOMEM;
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);
570 if (err < 0) {
571 free(adpcm);
572 return err;
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 pcm->monotonic = slave->monotonic;
580 snd_pcm_set_hw_ptr(pcm, &adpcm->plug.hw_ptr, -1, 0);
581 snd_pcm_set_appl_ptr(pcm, &adpcm->plug.appl_ptr, -1, 0);
582 *pcmp = pcm;
584 return 0;
587 /*! \page pcm_plugins
589 \section pcm_plugins_adpcm Plugin: Ima-ADPCM
591 This plugin converts Ima-ADPCM samples to linear or linear to Ima-ADPCM samples
592 from master Ima-ADPCM conversion PCM to given slave PCM. The channel count,
593 format and rate must match for both of them.
595 \code
596 pcm.name {
597 type adpcm # Ima-ADPCM conversion PCM
598 slave STR # Slave name
599 # or
600 slave { # Slave definition
601 pcm STR # Slave PCM name
602 # or
603 pcm { } # Slave PCM definition
604 format STR # Slave format
607 \endcode
609 \subsection pcm_plugins_adpcm_funcref Function reference
611 <UL>
612 <LI>snd_pcm_adpcm_open()
613 <LI>_snd_pcm_adpcm_open()
614 </UL>
619 * \brief Creates a new Ima-ADPCM conversion PCM
620 * \param pcmp Returns created PCM handle
621 * \param name Name of PCM
622 * \param root Root configuration node
623 * \param conf Configuration node with copy PCM description
624 * \param stream Stream type
625 * \param mode Stream mode
626 * \retval zero on success otherwise a negative error code
627 * \warning Using of this function might be dangerous in the sense
628 * of compatibility reasons. The prototype might be freely
629 * changed in future.
631 int _snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name,
632 snd_config_t *root, snd_config_t *conf,
633 snd_pcm_stream_t stream, int mode)
635 snd_config_iterator_t i, next;
636 int err;
637 snd_pcm_t *spcm;
638 snd_config_t *slave = NULL, *sconf;
639 snd_pcm_format_t sformat;
640 snd_config_for_each(i, next, conf) {
641 snd_config_t *n = snd_config_iterator_entry(i);
642 const char *id;
643 if (snd_config_get_id(n, &id) < 0)
644 continue;
645 if (snd_pcm_conf_generic_id(id))
646 continue;
647 if (strcmp(id, "slave") == 0) {
648 slave = n;
649 continue;
651 SNDERR("Unknown field %s", id);
652 return -EINVAL;
654 if (!slave) {
655 SNDERR("slave is not defined");
656 return -EINVAL;
658 err = snd_pcm_slave_conf(root, slave, &sconf, 1,
659 SND_PCM_HW_PARAM_FORMAT, SCONF_MANDATORY, &sformat);
660 if (err < 0)
661 return err;
662 if (snd_pcm_format_linear(sformat) != 1 &&
663 sformat != SND_PCM_FORMAT_IMA_ADPCM) {
664 snd_config_delete(sconf);
665 SNDERR("invalid slave format");
666 return -EINVAL;
668 err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
669 snd_config_delete(sconf);
670 if (err < 0)
671 return err;
672 err = snd_pcm_adpcm_open(pcmp, name, sformat, spcm, 1);
673 if (err < 0)
674 snd_pcm_close(spcm);
675 return err;
677 #ifndef DOC_HIDDEN
678 SND_DLSYM_BUILD_VERSION(_snd_pcm_adpcm_open, SND_PCM_DLSYM_VERSION);
679 #endif