2 * PCM Plug-In shared (kernel/library) code
3 * Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
4 * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Library General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <sound/driver.h>
28 #include <linux/slab.h>
29 #include <linux/time.h>
30 #include <linux/vmalloc.h>
31 #include <sound/core.h>
32 #include <sound/pcm.h>
33 #include <sound/pcm_params.h>
34 #include "pcm_plugin.h"
36 #define snd_pcm_plug_first(plug) ((plug)->runtime->oss.plugin_first)
37 #define snd_pcm_plug_last(plug) ((plug)->runtime->oss.plugin_last)
39 static int snd_pcm_plugin_src_channels_mask(snd_pcm_plugin_t *plugin,
43 bitset_t *vmask = plugin->src_vmask;
44 bitset_copy(vmask, dst_vmask, plugin->src_format.channels);
49 static int snd_pcm_plugin_dst_channels_mask(snd_pcm_plugin_t *plugin,
53 bitset_t *vmask = plugin->dst_vmask;
54 bitset_copy(vmask, src_vmask, plugin->dst_format.channels);
60 * because some cards might have rates "very close", we ignore
61 * all "resampling" requests within +-5%
63 static int rate_match(unsigned int src_rate, unsigned int dst_rate)
65 unsigned int low = (src_rate * 95) / 100;
66 unsigned int high = (src_rate * 105) / 100;
67 return dst_rate >= low && dst_rate <= high;
70 static int snd_pcm_plugin_alloc(snd_pcm_plugin_t *plugin, snd_pcm_uframes_t frames)
72 snd_pcm_plugin_format_t *format;
76 snd_pcm_plugin_channel_t *c;
78 if (plugin->stream == SNDRV_PCM_STREAM_PLAYBACK) {
79 format = &plugin->src_format;
81 format = &plugin->dst_format;
83 if ((width = snd_pcm_format_physical_width(format->format)) < 0)
85 size = frames * format->channels * width;
86 snd_assert((size % 8) == 0, return -ENXIO);
88 if (plugin->buf_frames < frames) {
91 plugin->buf = vmalloc(size);
92 plugin->buf_frames = frames;
95 plugin->buf_frames = 0;
98 c = plugin->buf_channels;
99 if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
100 for (channel = 0; channel < format->channels; channel++, c++) {
104 c->area.addr = plugin->buf;
105 c->area.first = channel * width;
106 c->area.step = format->channels * width;
108 } else if (plugin->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
109 snd_assert((size % format->channels) == 0,);
110 size /= format->channels;
111 for (channel = 0; channel < format->channels; channel++, c++) {
115 c->area.addr = plugin->buf + (channel * size);
117 c->area.step = width;
124 int snd_pcm_plug_alloc(snd_pcm_plug_t *plug, snd_pcm_uframes_t frames)
127 snd_assert(snd_pcm_plug_first(plug) != NULL, return -ENXIO);
128 if (snd_pcm_plug_stream(plug) == SNDRV_PCM_STREAM_PLAYBACK) {
129 snd_pcm_plugin_t *plugin = snd_pcm_plug_first(plug);
130 while (plugin->next) {
131 if (plugin->dst_frames)
132 frames = plugin->dst_frames(plugin, frames);
133 snd_assert(frames > 0, return -ENXIO);
134 plugin = plugin->next;
135 err = snd_pcm_plugin_alloc(plugin, frames);
140 snd_pcm_plugin_t *plugin = snd_pcm_plug_last(plug);
141 while (plugin->prev) {
142 if (plugin->src_frames)
143 frames = plugin->src_frames(plugin, frames);
144 snd_assert(frames > 0, return -ENXIO);
145 plugin = plugin->prev;
146 err = snd_pcm_plugin_alloc(plugin, frames);
155 snd_pcm_sframes_t snd_pcm_plugin_client_channels(snd_pcm_plugin_t *plugin,
156 snd_pcm_uframes_t frames,
157 snd_pcm_plugin_channel_t **channels)
159 *channels = plugin->buf_channels;
163 int snd_pcm_plugin_build(snd_pcm_plug_t *plug,
165 snd_pcm_plugin_format_t *src_format,
166 snd_pcm_plugin_format_t *dst_format,
168 snd_pcm_plugin_t **ret)
170 snd_pcm_plugin_t *plugin;
171 unsigned int channels;
173 snd_assert(plug != NULL, return -ENXIO);
174 snd_assert(src_format != NULL && dst_format != NULL, return -ENXIO);
175 plugin = (snd_pcm_plugin_t *)snd_kcalloc(sizeof(*plugin) + extra, GFP_KERNEL);
180 plugin->stream = snd_pcm_plug_stream(plug);
181 plugin->access = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
182 plugin->src_format = *src_format;
183 plugin->src_width = snd_pcm_format_physical_width(src_format->format);
184 snd_assert(plugin->src_width > 0, );
185 plugin->dst_format = *dst_format;
186 plugin->dst_width = snd_pcm_format_physical_width(dst_format->format);
187 snd_assert(plugin->dst_width > 0, );
188 if (plugin->stream == SNDRV_PCM_STREAM_PLAYBACK)
189 channels = src_format->channels;
191 channels = dst_format->channels;
192 plugin->buf_channels = snd_kcalloc(channels * sizeof(*plugin->buf_channels), GFP_KERNEL);
193 if (plugin->buf_channels == NULL) {
194 snd_pcm_plugin_free(plugin);
197 plugin->src_vmask = bitset_alloc(src_format->channels);
198 if (plugin->src_vmask == NULL) {
199 snd_pcm_plugin_free(plugin);
202 plugin->dst_vmask = bitset_alloc(dst_format->channels);
203 if (plugin->dst_vmask == NULL) {
204 snd_pcm_plugin_free(plugin);
207 plugin->client_channels = snd_pcm_plugin_client_channels;
208 plugin->src_channels_mask = snd_pcm_plugin_src_channels_mask;
209 plugin->dst_channels_mask = snd_pcm_plugin_dst_channels_mask;
214 int snd_pcm_plugin_free(snd_pcm_plugin_t *plugin)
218 if (plugin->private_free)
219 plugin->private_free(plugin);
220 if (plugin->buf_channels)
221 kfree(plugin->buf_channels);
224 if (plugin->src_vmask)
225 kfree(plugin->src_vmask);
226 if (plugin->dst_vmask)
227 kfree(plugin->dst_vmask);
232 snd_pcm_sframes_t snd_pcm_plug_client_size(snd_pcm_plug_t *plug, snd_pcm_uframes_t drv_frames)
234 snd_pcm_plugin_t *plugin, *plugin_prev, *plugin_next;
235 int stream = snd_pcm_plug_stream(plug);
237 snd_assert(plug != NULL, return -ENXIO);
240 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
241 plugin = snd_pcm_plug_last(plug);
242 while (plugin && drv_frames > 0) {
243 plugin_prev = plugin->prev;
244 if (plugin->src_frames)
245 drv_frames = plugin->src_frames(plugin, drv_frames);
246 plugin = plugin_prev;
248 } else if (stream == SNDRV_PCM_STREAM_CAPTURE) {
249 plugin = snd_pcm_plug_first(plug);
250 while (plugin && drv_frames > 0) {
251 plugin_next = plugin->next;
252 if (plugin->dst_frames)
253 drv_frames = plugin->dst_frames(plugin, drv_frames);
254 plugin = plugin_next;
261 snd_pcm_sframes_t snd_pcm_plug_slave_size(snd_pcm_plug_t *plug, snd_pcm_uframes_t clt_frames)
263 snd_pcm_plugin_t *plugin, *plugin_prev, *plugin_next;
264 snd_pcm_sframes_t frames;
265 int stream = snd_pcm_plug_stream(plug);
267 snd_assert(plug != NULL, return -ENXIO);
271 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
272 plugin = snd_pcm_plug_first(plug);
273 while (plugin && frames > 0) {
274 plugin_next = plugin->next;
275 if (plugin->dst_frames) {
276 frames = plugin->dst_frames(plugin, frames);
280 plugin = plugin_next;
282 } else if (stream == SNDRV_PCM_STREAM_CAPTURE) {
283 plugin = snd_pcm_plug_last(plug);
285 plugin_prev = plugin->prev;
286 if (plugin->src_frames) {
287 frames = plugin->src_frames(plugin, frames);
291 plugin = plugin_prev;
298 static int snd_pcm_plug_formats(snd_mask_t *mask, int format)
300 snd_mask_t formats = *mask;
301 u64 linfmts = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
302 SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE |
303 SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE |
304 SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_S24_LE |
305 SNDRV_PCM_FMTBIT_U24_BE | SNDRV_PCM_FMTBIT_S24_BE |
306 SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE |
307 SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE);
308 snd_mask_set(&formats, SNDRV_PCM_FORMAT_MU_LAW);
310 if (formats.bits[0] & (u32)linfmts)
311 formats.bits[0] |= (u32)linfmts;
312 if (formats.bits[1] & (u32)(linfmts >> 32))
313 formats.bits[1] |= (u32)(linfmts >> 32);
314 return snd_mask_test(&formats, format);
317 static int preferred_formats[] = {
318 SNDRV_PCM_FORMAT_S16_LE,
319 SNDRV_PCM_FORMAT_S16_BE,
320 SNDRV_PCM_FORMAT_U16_LE,
321 SNDRV_PCM_FORMAT_U16_BE,
322 SNDRV_PCM_FORMAT_S24_LE,
323 SNDRV_PCM_FORMAT_S24_BE,
324 SNDRV_PCM_FORMAT_U24_LE,
325 SNDRV_PCM_FORMAT_U24_BE,
326 SNDRV_PCM_FORMAT_S32_LE,
327 SNDRV_PCM_FORMAT_S32_BE,
328 SNDRV_PCM_FORMAT_U32_LE,
329 SNDRV_PCM_FORMAT_U32_BE,
334 int snd_pcm_plug_slave_format(int format, snd_mask_t *format_mask)
336 if (snd_mask_test(format_mask, format))
338 if (! snd_pcm_plug_formats(format_mask, format))
340 if (snd_pcm_format_linear(format)) {
341 int width = snd_pcm_format_width(format);
342 int unsignd = snd_pcm_format_unsigned(format);
343 int big = snd_pcm_format_big_endian(format);
345 int wid, width1=width;
347 for (wid = 0; wid < 4; ++wid) {
349 for (end = 0; end < 2; ++end) {
350 int sgn, unsignd1 = unsignd;
351 for (sgn = 0; sgn < 2; ++sgn) {
352 format1 = snd_pcm_build_linear_format(width1, unsignd1, big1);
354 snd_mask_test(format_mask, format1))
356 unsignd1 = !unsignd1;
372 case SNDRV_PCM_FORMAT_MU_LAW:
373 for (i = 0; i < sizeof(preferred_formats) / sizeof(preferred_formats[0]); ++i) {
374 int format1 = preferred_formats[i];
375 if (snd_mask_test(format_mask, format1))
384 int snd_pcm_plug_format_plugins(snd_pcm_plug_t *plug,
385 snd_pcm_hw_params_t *params,
386 snd_pcm_hw_params_t *slave_params)
388 snd_pcm_plugin_format_t tmpformat;
389 snd_pcm_plugin_format_t dstformat;
390 snd_pcm_plugin_format_t srcformat;
391 int src_access, dst_access;
392 snd_pcm_plugin_t *plugin = NULL;
394 int stream = snd_pcm_plug_stream(plug);
395 int slave_interleaved = (params_channels(slave_params) == 1 ||
396 params_access(slave_params) == SNDRV_PCM_ACCESS_RW_INTERLEAVED);
399 case SNDRV_PCM_STREAM_PLAYBACK:
400 dstformat.format = params_format(slave_params);
401 dstformat.rate = params_rate(slave_params);
402 dstformat.channels = params_channels(slave_params);
403 srcformat.format = params_format(params);
404 srcformat.rate = params_rate(params);
405 srcformat.channels = params_channels(params);
406 src_access = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
407 dst_access = (slave_interleaved ? SNDRV_PCM_ACCESS_RW_INTERLEAVED :
408 SNDRV_PCM_ACCESS_RW_NONINTERLEAVED);
410 case SNDRV_PCM_STREAM_CAPTURE:
411 dstformat.format = params_format(params);
412 dstformat.rate = params_rate(params);
413 dstformat.channels = params_channels(params);
414 srcformat.format = params_format(slave_params);
415 srcformat.rate = params_rate(slave_params);
416 srcformat.channels = params_channels(slave_params);
417 src_access = (slave_interleaved ? SNDRV_PCM_ACCESS_RW_INTERLEAVED :
418 SNDRV_PCM_ACCESS_RW_NONINTERLEAVED);
419 dst_access = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
425 tmpformat = srcformat;
427 pdprintf("srcformat: format=%i, rate=%i, channels=%i\n",
431 pdprintf("dstformat: format=%i, rate=%i, channels=%i\n",
436 /* Format change (linearization) */
437 if ((srcformat.format != dstformat.format ||
438 !rate_match(srcformat.rate, dstformat.rate) ||
439 srcformat.channels != dstformat.channels) &&
440 !snd_pcm_format_linear(srcformat.format)) {
441 if (snd_pcm_format_linear(dstformat.format))
442 tmpformat.format = dstformat.format;
444 tmpformat.format = SNDRV_PCM_FORMAT_S16;
445 first = plugin == NULL;
446 switch (srcformat.format) {
447 case SNDRV_PCM_FORMAT_MU_LAW:
448 err = snd_pcm_plugin_build_mulaw(plug,
449 &srcformat, &tmpformat,
455 pdprintf("format change: src=%i, dst=%i returns %i\n", srcformat.format, tmpformat.format, err);
458 err = snd_pcm_plugin_append(plugin);
460 snd_pcm_plugin_free(plugin);
463 srcformat = tmpformat;
464 src_access = dst_access;
467 /* channels reduction */
468 if (srcformat.channels > dstformat.channels) {
469 int sv = srcformat.channels;
470 int dv = dstformat.channels;
471 route_ttable_entry_t *ttable = snd_kcalloc(dv*sv*sizeof(*ttable), GFP_KERNEL);
475 if (sv == 2 && dv == 1) {
482 for (v = 0; v < dv; ++v)
483 ttable[v * sv + v] = FULL;
485 tmpformat.channels = dstformat.channels;
486 if (rate_match(srcformat.rate, dstformat.rate) &&
487 snd_pcm_format_linear(dstformat.format))
488 tmpformat.format = dstformat.format;
489 err = snd_pcm_plugin_build_route(plug,
490 &srcformat, &tmpformat,
493 pdprintf("channels reduction: src=%i, dst=%i returns %i\n", srcformat.channels, tmpformat.channels, err);
495 snd_pcm_plugin_free(plugin);
498 err = snd_pcm_plugin_append(plugin);
500 snd_pcm_plugin_free(plugin);
503 srcformat = tmpformat;
504 src_access = dst_access;
507 /* rate resampling */
508 if (!rate_match(srcformat.rate, dstformat.rate)) {
509 tmpformat.rate = dstformat.rate;
510 if (srcformat.channels == dstformat.channels &&
511 snd_pcm_format_linear(dstformat.format))
512 tmpformat.format = dstformat.format;
513 err = snd_pcm_plugin_build_rate(plug,
514 &srcformat, &tmpformat,
516 pdprintf("rate down resampling: src=%i, dst=%i returns %i\n", srcformat.rate, tmpformat.rate, err);
518 snd_pcm_plugin_free(plugin);
521 err = snd_pcm_plugin_append(plugin);
523 snd_pcm_plugin_free(plugin);
526 srcformat = tmpformat;
527 src_access = dst_access;
530 /* channels extension */
531 if (srcformat.channels < dstformat.channels) {
532 int sv = srcformat.channels;
533 int dv = dstformat.channels;
534 route_ttable_entry_t *ttable = snd_kcalloc(dv * sv * sizeof(*ttable), GFP_KERNEL);
540 for (v = 0; v < sv; ++v)
541 ttable[v * sv + v] = FULL;
545 /* Playback is spreaded on all channels */
547 for (vd = 0, vs = 0; vd < dv; ++vd) {
548 ttable[vd * sv + vs] = FULL;
555 tmpformat.channels = dstformat.channels;
556 if (snd_pcm_format_linear(dstformat.format))
557 tmpformat.format = dstformat.format;
558 err = snd_pcm_plugin_build_route(plug,
559 &srcformat, &tmpformat,
562 pdprintf("channels extension: src=%i, dst=%i returns %i\n", srcformat.channels, tmpformat.channels, err);
564 snd_pcm_plugin_free(plugin);
567 err = snd_pcm_plugin_append(plugin);
569 snd_pcm_plugin_free(plugin);
572 srcformat = tmpformat;
573 src_access = dst_access;
577 if (srcformat.format != dstformat.format) {
578 tmpformat.format = dstformat.format;
579 if (tmpformat.format == SNDRV_PCM_FORMAT_MU_LAW) {
580 err = snd_pcm_plugin_build_mulaw(plug,
581 &srcformat, &tmpformat,
584 else if (snd_pcm_format_linear(srcformat.format) &&
585 snd_pcm_format_linear(tmpformat.format)) {
586 err = snd_pcm_plugin_build_linear(plug,
587 &srcformat, &tmpformat,
592 pdprintf("format change: src=%i, dst=%i returns %i\n", srcformat.format, tmpformat.format, err);
595 err = snd_pcm_plugin_append(plugin);
597 snd_pcm_plugin_free(plugin);
600 srcformat = tmpformat;
601 src_access = dst_access;
605 if (src_access != dst_access) {
606 err = snd_pcm_plugin_build_copy(plug,
610 pdprintf("interleave change (copy: returns %i)\n", err);
613 err = snd_pcm_plugin_append(plugin);
615 snd_pcm_plugin_free(plugin);
623 snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(snd_pcm_plug_t *plug,
625 snd_pcm_uframes_t count,
626 snd_pcm_plugin_channel_t **channels)
628 snd_pcm_plugin_t *plugin;
629 snd_pcm_plugin_channel_t *v;
630 snd_pcm_plugin_format_t *format;
631 int width, nchannels, channel;
632 int stream = snd_pcm_plug_stream(plug);
634 snd_assert(buf != NULL, return -ENXIO);
635 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
636 plugin = snd_pcm_plug_first(plug);
637 format = &plugin->src_format;
639 plugin = snd_pcm_plug_last(plug);
640 format = &plugin->dst_format;
642 v = plugin->buf_channels;
644 if ((width = snd_pcm_format_physical_width(format->format)) < 0)
646 nchannels = format->channels;
647 snd_assert(plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || format->channels <= 1, return -ENXIO);
648 for (channel = 0; channel < nchannels; channel++, v++) {
651 v->wanted = (stream == SNDRV_PCM_STREAM_CAPTURE);
653 v->area.first = channel * width;
654 v->area.step = nchannels * width;
659 int snd_pcm_plug_playback_channels_mask(snd_pcm_plug_t *plug,
660 bitset_t *client_vmask)
662 snd_pcm_plugin_t *plugin = snd_pcm_plug_last(plug);
663 if (plugin == NULL) {
666 int schannels = plugin->dst_format.channels;
667 bitset_t bs[bitset_size(schannels)];
669 bitset_t *dstmask = bs;
671 bitset_one(dstmask, schannels);
672 if (plugin == NULL) {
673 bitset_and(client_vmask, dstmask, schannels);
677 err = plugin->src_channels_mask(plugin, dstmask, &srcmask);
681 if (plugin->prev == NULL)
683 plugin = plugin->prev;
685 bitset_and(client_vmask, dstmask, plugin->src_format.channels);
690 int snd_pcm_plug_capture_channels_mask(snd_pcm_plug_t *plug,
691 bitset_t *client_vmask)
693 snd_pcm_plugin_t *plugin = snd_pcm_plug_first(plug);
694 if (plugin == NULL) {
697 int schannels = plugin->src_format.channels;
698 bitset_t bs[bitset_size(schannels)];
699 bitset_t *srcmask = bs;
702 bitset_one(srcmask, schannels);
704 err = plugin->dst_channels_mask(plugin, srcmask, &dstmask);
708 if (plugin->next == NULL)
710 plugin = plugin->next;
712 bitset_and(client_vmask, srcmask, plugin->dst_format.channels);
717 static int snd_pcm_plug_playback_disable_useless_channels(snd_pcm_plug_t *plug,
718 snd_pcm_plugin_channel_t *src_channels)
720 snd_pcm_plugin_t *plugin = snd_pcm_plug_first(plug);
721 unsigned int nchannels = plugin->src_format.channels;
722 bitset_t bs[bitset_size(nchannels)];
723 bitset_t *srcmask = bs;
725 unsigned int channel;
726 for (channel = 0; channel < nchannels; channel++) {
727 if (src_channels[channel].enabled)
728 bitset_set(srcmask, channel);
730 bitset_reset(srcmask, channel);
732 err = snd_pcm_plug_playback_channels_mask(plug, srcmask);
735 for (channel = 0; channel < nchannels; channel++) {
736 if (!bitset_get(srcmask, channel))
737 src_channels[channel].enabled = 0;
742 static int snd_pcm_plug_capture_disable_useless_channels(snd_pcm_plug_t *plug,
743 snd_pcm_plugin_channel_t *src_channels,
744 snd_pcm_plugin_channel_t *client_channels)
746 snd_pcm_plugin_t *plugin = snd_pcm_plug_last(plug);
747 unsigned int nchannels = plugin->dst_format.channels;
748 bitset_t bs[bitset_size(nchannels)];
749 bitset_t *dstmask = bs;
752 unsigned int channel;
753 for (channel = 0; channel < nchannels; channel++) {
754 if (client_channels[channel].enabled)
755 bitset_set(dstmask, channel);
757 bitset_reset(dstmask, channel);
760 err = plugin->src_channels_mask(plugin, dstmask, &srcmask);
764 plugin = plugin->prev;
766 plugin = snd_pcm_plug_first(plug);
767 nchannels = plugin->src_format.channels;
768 for (channel = 0; channel < nchannels; channel++) {
769 if (!bitset_get(dstmask, channel))
770 src_channels[channel].enabled = 0;
775 snd_pcm_sframes_t snd_pcm_plug_write_transfer(snd_pcm_plug_t *plug, snd_pcm_plugin_channel_t *src_channels, snd_pcm_uframes_t size)
777 snd_pcm_plugin_t *plugin, *next;
778 snd_pcm_plugin_channel_t *dst_channels;
780 snd_pcm_sframes_t frames = size;
782 if ((err = snd_pcm_plug_playback_disable_useless_channels(plug, src_channels)) < 0)
785 plugin = snd_pcm_plug_first(plug);
786 while (plugin && frames > 0) {
787 if ((next = plugin->next) != NULL) {
788 snd_pcm_sframes_t frames1 = frames;
789 if (plugin->dst_frames)
790 frames1 = plugin->dst_frames(plugin, frames);
791 if ((err = next->client_channels(next, frames1, &dst_channels)) < 0) {
794 if (err != frames1) {
796 if (plugin->src_frames)
797 frames = plugin->src_frames(plugin, frames1);
801 pdprintf("write plugin: %s, %li\n", plugin->name, frames);
802 if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0)
804 src_channels = dst_channels;
807 return snd_pcm_plug_client_size(plug, frames);
810 snd_pcm_sframes_t snd_pcm_plug_read_transfer(snd_pcm_plug_t *plug, snd_pcm_plugin_channel_t *dst_channels_final, snd_pcm_uframes_t size)
812 snd_pcm_plugin_t *plugin, *next;
813 snd_pcm_plugin_channel_t *src_channels, *dst_channels;
814 snd_pcm_sframes_t frames = size;
817 frames = snd_pcm_plug_slave_size(plug, frames);
822 plugin = snd_pcm_plug_first(plug);
823 while (plugin && frames > 0) {
824 if ((next = plugin->next) != NULL) {
825 if ((err = plugin->client_channels(plugin, frames, &dst_channels)) < 0) {
830 if ((err = snd_pcm_plug_capture_disable_useless_channels(plug, dst_channels, dst_channels_final)) < 0)
834 dst_channels = dst_channels_final;
836 pdprintf("read plugin: %s, %li\n", plugin->name, frames);
837 if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0)
840 src_channels = dst_channels;
845 int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_area, size_t dst_offset,
846 size_t samples, int format)
848 /* FIXME: sub byte resolution and odd dst_offset */
850 unsigned int dst_step;
855 dst = dst_area->addr + (dst_area->first + dst_area->step * dst_offset) / 8;
856 width = snd_pcm_format_physical_width(format);
857 silence = snd_pcm_format_silence_64(format);
858 if (dst_area->step == (unsigned int) width) {
859 size_t dwords = samples * width / 64;
860 u_int64_t *dst64 = (u_int64_t *)dst;
862 samples -= dwords * 64 / width;
869 dst_step = dst_area->step / 8;
872 u_int8_t s0 = silence & 0xf0;
873 u_int8_t s1 = silence & 0x0f;
874 int dstbit = dst_area->first % 8;
875 int dstbit_step = dst_area->step % 8;
876 while (samples-- > 0) {
885 dstbit += dstbit_step;
894 u_int8_t sil = silence;
895 while (samples-- > 0) {
902 u_int16_t sil = silence;
903 while (samples-- > 0) {
904 *(u_int16_t*)dst = sil;
910 u_int32_t sil = silence;
911 while (samples-- > 0) {
912 *(u_int32_t*)dst = sil;
918 while (samples-- > 0) {
919 *(u_int64_t*)dst = silence;
930 int snd_pcm_area_copy(const snd_pcm_channel_area_t *src_area, size_t src_offset,
931 const snd_pcm_channel_area_t *dst_area, size_t dst_offset,
932 size_t samples, int format)
934 /* FIXME: sub byte resolution and odd dst_offset */
937 int src_step, dst_step;
938 src = src_area->addr + (src_area->first + src_area->step * src_offset) / 8;
940 return snd_pcm_area_silence(dst_area, dst_offset, samples, format);
941 dst = dst_area->addr + (dst_area->first + dst_area->step * dst_offset) / 8;
944 width = snd_pcm_format_physical_width(format);
945 if (src_area->step == (unsigned int) width &&
946 dst_area->step == (unsigned int) width) {
947 size_t bytes = samples * width / 8;
948 samples -= bytes * 8 / width;
949 memcpy(dst, src, bytes);
953 src_step = src_area->step / 8;
954 dst_step = dst_area->step / 8;
957 int srcbit = src_area->first % 8;
958 int srcbit_step = src_area->step % 8;
959 int dstbit = dst_area->first % 8;
960 int dstbit_step = dst_area->step % 8;
961 while (samples-- > 0) {
962 unsigned char srcval;
964 srcval = *src & 0x0f;
966 srcval = *src & 0xf0;
973 srcbit += srcbit_step;
979 dstbit += dstbit_step;
988 while (samples-- > 0) {
996 while (samples-- > 0) {
997 *(u_int16_t*)dst = *(u_int16_t*)src;
1004 while (samples-- > 0) {
1005 *(u_int32_t*)dst = *(u_int32_t*)src;
1012 while (samples-- > 0) {
1013 *(u_int64_t*)dst = *(u_int64_t*)src;