xref: /linux/sound/core/oss/copy.c (revision c17ee635fd3a482b2ad2bf5e269755c2eae5f25e)
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