OSDN Git Service

Lot of cleanings with the help of gcc3
[android-x86/external-alsa-lib.git] / src / pcm / pcm_adpcm.c
1 /*
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>
6  *
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.
10  *
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.
15  *
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.
20  *
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.
24  *
25  */
26   
27 /*
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.
31
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.
35
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.
41
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.
45
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.
48  */
49
50 #include <byteswap.h>
51 #include "pcm_local.h"
52 #include "pcm_plugin.h"
53
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,
59                         unsigned int getputidx,
60                         snd_pcm_adpcm_state_t *states);
61
62 typedef struct {
63         /* This field need to be the first */
64         snd_pcm_plugin_t plug;
65         unsigned int getput_idx;
66         adpcm_f func;
67         snd_pcm_format_t sformat;
68         snd_pcm_adpcm_state_t *states;
69 } snd_pcm_adpcm_t;
70
71 /* First table lookup for Ima-ADPCM quantizer */
72 static char IndexAdjust[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
73
74 /* Second table lookup for Ima-ADPCM quantizer */
75 static short StepSize[89] = {
76         7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
77         19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
78         50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
79         130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
80         337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
81         876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
82         2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
83         5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
84         15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
85 };
86
87 static char adpcm_encoder(int sl, snd_pcm_adpcm_state_t * state)
88 {
89         short diff;             /* Difference between sl and predicted sample */
90         short pred_diff;        /* Predicted difference to next sample */
91
92         unsigned char sign;     /* sign of diff */
93         short step;             /* holds previous StepSize value */
94         unsigned char adjust_idx;       /* Index to IndexAdjust lookup table */
95
96         int i;
97
98         /* Compute difference to previous predicted value */
99         diff = sl - state->pred_val;
100         sign = (diff < 0) ? 0x8 : 0x0;
101         if (sign) {
102                 diff = -diff;
103         }
104
105         /*
106          * This code *approximately* computes:
107          *    adjust_idx = diff * 4 / step;
108          *    pred_diff = (adjust_idx + 0.5) * step / 4;
109          *
110          * But in shift step bits are dropped. The net result of this is
111          * that even if you have fast mul/div hardware you cannot put it to
112          * good use since the fixup would be too expensive.
113          */
114
115         step = StepSize[state->step_idx];
116
117         /* Divide and clamp */
118         pred_diff = step >> 3;
119         for (adjust_idx = 0, i = 0x4; i; i >>= 1, step >>= 1) {
120                 if (diff >= step) {
121                         adjust_idx |= i;
122                         diff -= step;
123                         pred_diff += step;
124                 }
125         }
126
127         /* Update and clamp previous predicted value */
128         state->pred_val += sign ? -pred_diff : pred_diff;
129
130         if (state->pred_val > 32767) {
131                 state->pred_val = 32767;
132         } else if (state->pred_val < -32768) {
133                 state->pred_val = -32768;
134         }
135
136         /* Update and clamp StepSize lookup table index */
137         state->step_idx += IndexAdjust[adjust_idx];
138
139         if (state->step_idx < 0) {
140                 state->step_idx = 0;
141         } else if (state->step_idx > 88) {
142                 state->step_idx = 88;
143         }
144         return (sign | adjust_idx);
145 }
146
147
148 static int adpcm_decoder(unsigned char code, snd_pcm_adpcm_state_t * state)
149 {
150         short pred_diff;        /* Predicted difference to next sample */
151         short step;             /* holds previous StepSize value */
152         char sign;
153
154         int i;
155
156         /* Separate sign and magnitude */
157         sign = code & 0x8;
158         code &= 0x7;
159
160         /*
161          * Computes pred_diff = (code + 0.5) * step / 4,
162          * but see comment in adpcm_coder.
163          */
164
165         step = StepSize[state->step_idx];
166
167         /* Compute difference and new predicted value */
168         pred_diff = step >> 3;
169         for (i = 0x4; i; i >>= 1, step >>= 1) {
170                 if (code & i) {
171                         pred_diff += step;
172                 }
173         }
174         state->pred_val += (sign) ? -pred_diff : pred_diff;
175
176         /* Clamp output value */
177         if (state->pred_val > 32767) {
178                 state->pred_val = 32767;
179         } else if (state->pred_val < -32768) {
180                 state->pred_val = -32768;
181         }
182
183         /* Find new StepSize index value */
184         state->step_idx += IndexAdjust[code];
185
186         if (state->step_idx < 0) {
187                 state->step_idx = 0;
188         } else if (state->step_idx > 88) {
189                 state->step_idx = 88;
190         }
191         return (state->pred_val);
192 }
193
194 void snd_pcm_adpcm_decode(const snd_pcm_channel_area_t *dst_areas,
195                           snd_pcm_uframes_t dst_offset,
196                           const snd_pcm_channel_area_t *src_areas,
197                           snd_pcm_uframes_t src_offset,
198                           unsigned int channels, snd_pcm_uframes_t frames,
199                           unsigned int putidx,
200                           snd_pcm_adpcm_state_t *states)
201 {
202 #define PUT16_LABELS
203 #include "plugin_ops.h"
204 #undef PUT16_LABELS
205         void *put = put16_labels[putidx];
206         unsigned int channel;
207         for (channel = 0; channel < channels; ++channel, ++states) {
208                 const char *src;
209                 int srcbit;
210                 char *dst;
211                 int src_step, srcbit_step, dst_step;
212                 snd_pcm_uframes_t frames1;
213                 const snd_pcm_channel_area_t *src_area = &src_areas[channel];
214                 const snd_pcm_channel_area_t *dst_area = &dst_areas[channel];
215                 srcbit = src_area->first + src_area->step * src_offset;
216                 src = (const char *) src_area->addr + srcbit / 8;
217                 srcbit %= 8;
218                 src_step = src_area->step / 8;
219                 srcbit_step = src_area->step % 8;
220                 dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
221                 dst_step = snd_pcm_channel_area_step(dst_area);
222                 frames1 = frames;
223                 while (frames1-- > 0) {
224                         int16_t sample;
225                         unsigned char v;
226                         if (srcbit)
227                                 v = *src & 0x0f;
228                         else
229                                 v = (*src >> 4) & 0x0f;
230                         sample = adpcm_decoder(v, states);
231                         goto *put;
232 #define PUT16_END after
233 #include "plugin_ops.h"
234 #undef PUT16_END
235                 after:
236                         src += src_step;
237                         srcbit += srcbit_step;
238                         if (srcbit == 8) {
239                                 src++;
240                                 srcbit = 0;
241                         }
242                         dst += dst_step;
243                 }
244         }
245 }
246
247 void snd_pcm_adpcm_encode(const snd_pcm_channel_area_t *dst_areas,
248                           snd_pcm_uframes_t dst_offset,
249                           const snd_pcm_channel_area_t *src_areas,
250                           snd_pcm_uframes_t src_offset,
251                           unsigned int channels, snd_pcm_uframes_t frames,
252                           unsigned int getidx,
253                           snd_pcm_adpcm_state_t *states)
254 {
255 #define GET16_LABELS
256 #include "plugin_ops.h"
257 #undef GET16_LABELS
258         void *get = get16_labels[getidx];
259         unsigned int channel;
260         int16_t sample = 0;
261         for (channel = 0; channel < channels; ++channel, ++states) {
262                 const char *src;
263                 char *dst;
264                 int dstbit;
265                 int src_step, dst_step, dstbit_step;
266                 snd_pcm_uframes_t frames1;
267                 const snd_pcm_channel_area_t *src_area = &src_areas[channel];
268                 const snd_pcm_channel_area_t *dst_area = &dst_areas[channel];
269                 src = snd_pcm_channel_area_addr(src_area, src_offset);
270                 src_step = snd_pcm_channel_area_step(src_area);
271                 dstbit = dst_area->first + dst_area->step * dst_offset;
272                 dst = (char *) dst_area->addr + dstbit / 8;
273                 dstbit %= 8;
274                 dst_step = dst_area->step / 8;
275                 dstbit_step = dst_area->step % 8;
276                 frames1 = frames;
277                 while (frames1-- > 0) {
278                         int v;
279                         goto *get;
280 #define GET16_END after
281 #include "plugin_ops.h"
282 #undef GET16_END
283                 after:
284                         v = adpcm_encoder(sample, states);
285                         if (dstbit)
286                                 *dst = (*dst & 0xf0) | v;
287                         else
288                                 *dst = (*dst & 0x0f) | (v << 4);
289                         src += src_step;
290                         dst += dst_step;
291                         dstbit += dstbit_step;
292                         if (dstbit == 8) {
293                                 dst++;
294                                 dstbit = 0;
295                         }
296                 }
297         }
298 }
299
300 static int snd_pcm_adpcm_hw_refine_cprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
301 {
302         snd_pcm_adpcm_t *adpcm = pcm->private_data;
303         int err;
304         snd_pcm_access_mask_t access_mask = { SND_PCM_ACCBIT_SHM };
305         err = _snd_pcm_hw_param_set_mask(params, SND_PCM_HW_PARAM_ACCESS,
306                                          &access_mask);
307         if (err < 0)
308                 return err;
309         if (adpcm->sformat == SND_PCM_FORMAT_IMA_ADPCM) {
310                 snd_pcm_format_mask_t format_mask = { SND_PCM_FMTBIT_LINEAR };
311                 err = _snd_pcm_hw_param_set_mask(params, SND_PCM_HW_PARAM_FORMAT,
312                                                  &format_mask);
313         } else {
314                 err = _snd_pcm_hw_params_set_format(params,
315                                                    SND_PCM_FORMAT_IMA_ADPCM);
316         }
317         if (err < 0)
318                 return err;
319         err = _snd_pcm_hw_params_set_subformat(params,
320                                                SND_PCM_SUBFORMAT_STD);
321         if (err < 0)
322                 return err;
323         params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
324         return 0;
325 }
326
327 static int snd_pcm_adpcm_hw_refine_sprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *sparams)
328 {
329         snd_pcm_adpcm_t *adpcm = pcm->private_data;
330         snd_pcm_access_mask_t saccess_mask = { SND_PCM_ACCBIT_MMAP };
331         _snd_pcm_hw_params_any(sparams);
332         _snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
333                                    &saccess_mask);
334         _snd_pcm_hw_params_set_format(sparams, adpcm->sformat);
335         _snd_pcm_hw_params_set_subformat(sparams, SND_PCM_SUBFORMAT_STD);
336         return 0;
337 }
338
339 static int snd_pcm_adpcm_hw_refine_schange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
340                                             snd_pcm_hw_params_t *sparams)
341 {
342         int err;
343         unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
344                               SND_PCM_HW_PARBIT_RATE |
345                               SND_PCM_HW_PARBIT_PERIOD_SIZE |
346                               SND_PCM_HW_PARBIT_BUFFER_SIZE |
347                               SND_PCM_HW_PARBIT_PERIODS |
348                               SND_PCM_HW_PARBIT_PERIOD_TIME |
349                               SND_PCM_HW_PARBIT_BUFFER_TIME |
350                               SND_PCM_HW_PARBIT_TICK_TIME);
351         err = _snd_pcm_hw_params_refine(sparams, links, params);
352         if (err < 0)
353                 return err;
354         return 0;
355 }
356         
357 static int snd_pcm_adpcm_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
358                                             snd_pcm_hw_params_t *sparams)
359 {
360         int err;
361         unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
362                               SND_PCM_HW_PARBIT_RATE |
363                               SND_PCM_HW_PARBIT_PERIOD_SIZE |
364                               SND_PCM_HW_PARBIT_BUFFER_SIZE |
365                               SND_PCM_HW_PARBIT_PERIODS |
366                               SND_PCM_HW_PARBIT_PERIOD_TIME |
367                               SND_PCM_HW_PARBIT_BUFFER_TIME |
368                               SND_PCM_HW_PARBIT_TICK_TIME);
369         err = _snd_pcm_hw_params_refine(params, links, sparams);
370         if (err < 0)
371                 return err;
372         return 0;
373 }
374
375 static int snd_pcm_adpcm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
376 {
377         return snd_pcm_hw_refine_slave(pcm, params,
378                                        snd_pcm_adpcm_hw_refine_cprepare,
379                                        snd_pcm_adpcm_hw_refine_cchange,
380                                        snd_pcm_adpcm_hw_refine_sprepare,
381                                        snd_pcm_adpcm_hw_refine_schange,
382                                        snd_pcm_plugin_hw_refine_slave);
383 }
384
385 static int snd_pcm_adpcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
386 {
387         snd_pcm_adpcm_t *adpcm = pcm->private_data;
388         int err = snd_pcm_hw_params_slave(pcm, params,
389                                           snd_pcm_adpcm_hw_refine_cchange,
390                                           snd_pcm_adpcm_hw_refine_sprepare,
391                                           snd_pcm_adpcm_hw_refine_schange,
392                                           snd_pcm_plugin_hw_params_slave);
393         if (err < 0)
394                 return err;
395
396
397         if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
398                 if (adpcm->sformat == SND_PCM_FORMAT_IMA_ADPCM) {
399                         adpcm->getput_idx = snd_pcm_linear_get_index(snd_pcm_hw_params_get_format(params), SND_PCM_FORMAT_S16);
400                         adpcm->func = snd_pcm_adpcm_encode;
401                 } else {
402                         adpcm->getput_idx = snd_pcm_linear_put_index(SND_PCM_FORMAT_S16, adpcm->sformat);
403                         adpcm->func = snd_pcm_adpcm_decode;
404                 }
405         } else {
406                 if (adpcm->sformat == SND_PCM_FORMAT_IMA_ADPCM) {
407                         adpcm->getput_idx = snd_pcm_linear_put_index(SND_PCM_FORMAT_S16, snd_pcm_hw_params_get_format(params));
408                         adpcm->func = snd_pcm_adpcm_decode;
409                 } else {
410                         adpcm->getput_idx = snd_pcm_linear_get_index(adpcm->sformat, SND_PCM_FORMAT_S16);
411                         adpcm->func = snd_pcm_adpcm_encode;
412                 }
413         }
414         assert(!adpcm->states);
415         adpcm->states = malloc(adpcm->plug.slave->channels * sizeof(*adpcm->states));
416         return 0;
417 }
418
419 static int snd_pcm_adpcm_hw_free(snd_pcm_t *pcm)
420 {
421         snd_pcm_adpcm_t *adpcm = pcm->private_data;
422         if (adpcm->states) {
423                 free(adpcm->states);
424                 adpcm->states = 0;
425         }
426         return snd_pcm_hw_free(adpcm->plug.slave);
427 }
428
429 static int snd_pcm_adpcm_init(snd_pcm_t *pcm)
430 {
431         snd_pcm_adpcm_t *adpcm = pcm->private_data;
432         unsigned int k;
433         for (k = 0; k < pcm->channels; ++k) {
434                 adpcm->states[k].pred_val = 0;
435                 adpcm->states[k].step_idx = 0;
436         }
437         return 0;
438 }
439
440 static snd_pcm_uframes_t
441 snd_pcm_adpcm_write_areas(snd_pcm_t *pcm,
442                           const snd_pcm_channel_area_t *areas,
443                           snd_pcm_uframes_t offset,
444                           snd_pcm_uframes_t size,
445                           const snd_pcm_channel_area_t *slave_areas,
446                           snd_pcm_uframes_t slave_offset,
447                           snd_pcm_uframes_t *slave_sizep)
448 {
449         snd_pcm_adpcm_t *adpcm = pcm->private_data;
450         if (size > *slave_sizep)
451                 size = *slave_sizep;
452         adpcm->func(slave_areas, slave_offset,
453                     areas, offset, 
454                     pcm->channels, size,
455                     adpcm->getput_idx, adpcm->states);
456         *slave_sizep = size;
457         return size;
458 }
459
460 static snd_pcm_uframes_t
461 snd_pcm_adpcm_read_areas(snd_pcm_t *pcm,
462                          const snd_pcm_channel_area_t *areas,
463                          snd_pcm_uframes_t offset,
464                          snd_pcm_uframes_t size,
465                          const snd_pcm_channel_area_t *slave_areas,
466                          snd_pcm_uframes_t slave_offset,
467                          snd_pcm_uframes_t *slave_sizep)
468 {
469         snd_pcm_adpcm_t *adpcm = pcm->private_data;
470         if (size > *slave_sizep)
471                 size = *slave_sizep;
472         adpcm->func(areas, offset, 
473                     slave_areas, slave_offset,
474                     pcm->channels, size,
475                     adpcm->getput_idx, adpcm->states);
476         *slave_sizep = size;
477         return size;
478 }
479
480 static void snd_pcm_adpcm_dump(snd_pcm_t *pcm, snd_output_t *out)
481 {
482         snd_pcm_adpcm_t *adpcm = pcm->private_data;
483         snd_output_printf(out, "Ima-ADPCM conversion PCM (%s)\n", 
484                 snd_pcm_format_name(adpcm->sformat));
485         if (pcm->setup) {
486                 snd_output_printf(out, "Its setup is:\n");
487                 snd_pcm_dump_setup(pcm, out);
488         }
489         snd_output_printf(out, "Slave: ");
490         snd_pcm_dump(adpcm->plug.slave, out);
491 }
492
493 snd_pcm_ops_t snd_pcm_adpcm_ops = {
494         close: snd_pcm_plugin_close,
495         info: snd_pcm_plugin_info,
496         hw_refine: snd_pcm_adpcm_hw_refine,
497         hw_params: snd_pcm_adpcm_hw_params,
498         hw_free: snd_pcm_adpcm_hw_free,
499         sw_params: snd_pcm_plugin_sw_params,
500         channel_info: snd_pcm_plugin_channel_info,
501         dump: snd_pcm_adpcm_dump,
502         nonblock: snd_pcm_plugin_nonblock,
503         async: snd_pcm_plugin_async,
504         mmap: snd_pcm_plugin_mmap,
505         munmap: snd_pcm_plugin_munmap,
506 };
507
508 int snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sformat, snd_pcm_t *slave, int close_slave)
509 {
510         snd_pcm_t *pcm;
511         snd_pcm_adpcm_t *adpcm;
512         assert(pcmp && slave);
513         if (snd_pcm_format_linear(sformat) != 1 &&
514             sformat != SND_PCM_FORMAT_IMA_ADPCM)
515                 return -EINVAL;
516         adpcm = calloc(1, sizeof(snd_pcm_adpcm_t));
517         if (!adpcm) {
518                 return -ENOMEM;
519         }
520         adpcm->sformat = sformat;
521         adpcm->plug.read = snd_pcm_adpcm_read_areas;
522         adpcm->plug.write = snd_pcm_adpcm_write_areas;
523         adpcm->plug.init = snd_pcm_adpcm_init;
524         adpcm->plug.slave = slave;
525         adpcm->plug.close_slave = close_slave;
526
527         pcm = calloc(1, sizeof(snd_pcm_t));
528         if (!pcm) {
529                 free(adpcm);
530                 return -ENOMEM;
531         }
532         if (name)
533                 pcm->name = strdup(name);
534         pcm->type = SND_PCM_TYPE_ADPCM;
535         pcm->stream = slave->stream;
536         pcm->mode = slave->mode;
537         pcm->ops = &snd_pcm_adpcm_ops;
538         pcm->op_arg = pcm;
539         pcm->fast_ops = &snd_pcm_plugin_fast_ops;
540         pcm->fast_op_arg = pcm;
541         pcm->private_data = adpcm;
542         pcm->poll_fd = slave->poll_fd;
543         pcm->hw_ptr = &adpcm->plug.hw_ptr;
544         pcm->appl_ptr = &adpcm->plug.appl_ptr;
545         *pcmp = pcm;
546
547         return 0;
548 }
549
550 int _snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name,
551                          snd_config_t *conf, 
552                          snd_pcm_stream_t stream, int mode)
553 {
554         snd_config_iterator_t i, next;
555         const char *sname = NULL;
556         int err;
557         snd_pcm_t *spcm;
558         snd_config_t *slave = NULL;
559         snd_pcm_format_t sformat;
560         snd_config_for_each(i, next, conf) {
561                 snd_config_t *n = snd_config_iterator_entry(i);
562                 const char *id = snd_config_get_id(n);
563                 if (strcmp(id, "comment") == 0)
564                         continue;
565                 if (strcmp(id, "type") == 0)
566                         continue;
567                 if (strcmp(id, "slave") == 0) {
568                         slave = n;
569                         continue;
570                 }
571                 SNDERR("Unknown field %s", id);
572                 return -EINVAL;
573         }
574         if (!slave) {
575                 SNDERR("slave is not defined");
576                 return -EINVAL;
577         }
578         err = snd_pcm_slave_conf(slave, &sname, 1,
579                                  SND_PCM_HW_PARAM_FORMAT, 1, &sformat);
580         if (err < 0)
581                 return err;
582         if (snd_pcm_format_linear(sformat) != 1 &&
583             sformat != SND_PCM_FORMAT_IMA_ADPCM) {
584                 SNDERR("invalid slave format");
585                 return -EINVAL;
586         }
587         /* This is needed cause snd_config_update may destroy config */
588         sname = strdup(sname);
589         if (!sname)
590                 return  -ENOMEM;
591         err = snd_pcm_open(&spcm, sname, stream, mode);
592         free((void *) sname);
593         if (err < 0)
594                 return err;
595         err = snd_pcm_adpcm_open(pcmp, name, sformat, spcm, 1);
596         if (err < 0)
597                 snd_pcm_close(spcm);
598         return err;
599 }
600                                 
601