1 // SPDX-License-Identifier: LGPL-2.0+ 2 /* 3 * Linear conversion Plug-In 4 * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org> 5 */ 6 7 #include <linux/time.h> 8 #include <sound/core.h> 9 #include <sound/pcm.h> 10 #include "pcm_plugin.h" 11 12 static snd_pcm_sframes_t copy_transfer(struct snd_pcm_plugin *plugin, 13 const struct snd_pcm_plugin_channel *src_channels, 14 struct snd_pcm_plugin_channel *dst_channels, 15 snd_pcm_uframes_t frames) 16 { 17 unsigned int channel; 18 unsigned int nchannels; 19 20 if (snd_BUG_ON(!plugin || !src_channels || !dst_channels)) 21 return -ENXIO; 22 if (frames == 0) 23 return 0; 24 nchannels = plugin->src_format.channels; 25 for (channel = 0; channel < nchannels; channel++) { 26 if (snd_BUG_ON(src_channels->area.first % 8 || 27 src_channels->area.step % 8)) 28 return -ENXIO; 29 if (snd_BUG_ON(dst_channels->area.first % 8 || 30 dst_channels->area.step % 8)) 31 return -ENXIO; 32 if (!src_channels->enabled) { 33 if (dst_channels->wanted) 34 snd_pcm_area_silence(&dst_channels->area, 0, frames, plugin->dst_format.format); 35 dst_channels->enabled = 0; 36 continue; 37 } 38 dst_channels->enabled = 1; 39 snd_pcm_area_copy(&src_channels->area, 0, &dst_channels->area, 0, frames, plugin->src_format.format); 40 src_channels++; 41 dst_channels++; 42 } 43 return frames; 44 } 45 46 int snd_pcm_plugin_build_copy(struct snd_pcm_substream *plug, 47 struct snd_pcm_plugin_format *src_format, 48 struct snd_pcm_plugin_format *dst_format, 49 struct snd_pcm_plugin **r_plugin) 50 { 51 int err; 52 struct snd_pcm_plugin *plugin; 53 int width; 54 55 if (snd_BUG_ON(!r_plugin)) 56 return -ENXIO; 57 *r_plugin = NULL; 58 59 if (snd_BUG_ON(src_format->format != dst_format->format)) 60 return -ENXIO; 61 if (snd_BUG_ON(src_format->rate != dst_format->rate)) 62 return -ENXIO; 63 if (snd_BUG_ON(src_format->channels != dst_format->channels)) 64 return -ENXIO; 65 66 width = snd_pcm_format_physical_width(src_format->format); 67 if (snd_BUG_ON(width <= 0)) 68 return -ENXIO; 69 70 err = snd_pcm_plugin_build(plug, "copy", src_format, dst_format, 71 0, &plugin); 72 if (err < 0) 73 return err; 74 plugin->transfer = copy_transfer; 75 *r_plugin = plugin; 76 return 0; 77 } 78