0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include <linux/time.h>
0023 #include <sound/core.h>
0024 #include <sound/pcm.h>
0025 #include "pcm_plugin.h"
0026
0027 static void zero_areas(struct snd_pcm_plugin_channel *dvp, int ndsts,
0028 snd_pcm_uframes_t frames, snd_pcm_format_t format)
0029 {
0030 int dst = 0;
0031 for (; dst < ndsts; ++dst) {
0032 if (dvp->wanted)
0033 snd_pcm_area_silence(&dvp->area, 0, frames, format);
0034 dvp->enabled = 0;
0035 dvp++;
0036 }
0037 }
0038
0039 static inline void copy_area(const struct snd_pcm_plugin_channel *src_channel,
0040 struct snd_pcm_plugin_channel *dst_channel,
0041 snd_pcm_uframes_t frames, snd_pcm_format_t format)
0042 {
0043 dst_channel->enabled = 1;
0044 snd_pcm_area_copy(&src_channel->area, 0, &dst_channel->area, 0, frames, format);
0045 }
0046
0047 static snd_pcm_sframes_t route_transfer(struct snd_pcm_plugin *plugin,
0048 const struct snd_pcm_plugin_channel *src_channels,
0049 struct snd_pcm_plugin_channel *dst_channels,
0050 snd_pcm_uframes_t frames)
0051 {
0052 int nsrcs, ndsts, dst;
0053 struct snd_pcm_plugin_channel *dvp;
0054 snd_pcm_format_t format;
0055
0056 if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
0057 return -ENXIO;
0058 if (frames == 0)
0059 return 0;
0060 if (frames > dst_channels[0].frames)
0061 frames = dst_channels[0].frames;
0062
0063 nsrcs = plugin->src_format.channels;
0064 ndsts = plugin->dst_format.channels;
0065
0066 format = plugin->dst_format.format;
0067 dvp = dst_channels;
0068 if (nsrcs <= 1) {
0069
0070 for (dst = 0; dst < ndsts; ++dst) {
0071 copy_area(src_channels, dvp, frames, format);
0072 dvp++;
0073 }
0074 return frames;
0075 }
0076
0077 for (dst = 0; dst < ndsts && dst < nsrcs; ++dst) {
0078 copy_area(src_channels, dvp, frames, format);
0079 dvp++;
0080 src_channels++;
0081 }
0082 if (dst < ndsts)
0083 zero_areas(dvp, ndsts - dst, frames, format);
0084 return frames;
0085 }
0086
0087 int snd_pcm_plugin_build_route(struct snd_pcm_substream *plug,
0088 struct snd_pcm_plugin_format *src_format,
0089 struct snd_pcm_plugin_format *dst_format,
0090 struct snd_pcm_plugin **r_plugin)
0091 {
0092 struct snd_pcm_plugin *plugin;
0093 int err;
0094
0095 if (snd_BUG_ON(!r_plugin))
0096 return -ENXIO;
0097 *r_plugin = NULL;
0098 if (snd_BUG_ON(src_format->rate != dst_format->rate))
0099 return -ENXIO;
0100 if (snd_BUG_ON(src_format->format != dst_format->format))
0101 return -ENXIO;
0102
0103 err = snd_pcm_plugin_build(plug, "route conversion",
0104 src_format, dst_format, 0, &plugin);
0105 if (err < 0)
0106 return err;
0107
0108 plugin->transfer = route_transfer;
0109 *r_plugin = plugin;
0110 return 0;
0111 }