162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Linear conversion Plug-In 362306a36Sopenharmony_ci * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org> 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * This library is free software; you can redistribute it and/or modify 762306a36Sopenharmony_ci * it under the terms of the GNU Library General Public License as 862306a36Sopenharmony_ci * published by the Free Software Foundation; either version 2 of 962306a36Sopenharmony_ci * the License, or (at your option) any later version. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * This program is distributed in the hope that it will be useful, 1262306a36Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 1362306a36Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1462306a36Sopenharmony_ci * GNU Library General Public License for more details. 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * You should have received a copy of the GNU Library General Public 1762306a36Sopenharmony_ci * License along with this library; if not, write to the Free Software 1862306a36Sopenharmony_ci * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci */ 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include <linux/time.h> 2362306a36Sopenharmony_ci#include <sound/core.h> 2462306a36Sopenharmony_ci#include <sound/pcm.h> 2562306a36Sopenharmony_ci#include "pcm_plugin.h" 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic snd_pcm_sframes_t copy_transfer(struct snd_pcm_plugin *plugin, 2862306a36Sopenharmony_ci const struct snd_pcm_plugin_channel *src_channels, 2962306a36Sopenharmony_ci struct snd_pcm_plugin_channel *dst_channels, 3062306a36Sopenharmony_ci snd_pcm_uframes_t frames) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci unsigned int channel; 3362306a36Sopenharmony_ci unsigned int nchannels; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci if (snd_BUG_ON(!plugin || !src_channels || !dst_channels)) 3662306a36Sopenharmony_ci return -ENXIO; 3762306a36Sopenharmony_ci if (frames == 0) 3862306a36Sopenharmony_ci return 0; 3962306a36Sopenharmony_ci nchannels = plugin->src_format.channels; 4062306a36Sopenharmony_ci for (channel = 0; channel < nchannels; channel++) { 4162306a36Sopenharmony_ci if (snd_BUG_ON(src_channels->area.first % 8 || 4262306a36Sopenharmony_ci src_channels->area.step % 8)) 4362306a36Sopenharmony_ci return -ENXIO; 4462306a36Sopenharmony_ci if (snd_BUG_ON(dst_channels->area.first % 8 || 4562306a36Sopenharmony_ci dst_channels->area.step % 8)) 4662306a36Sopenharmony_ci return -ENXIO; 4762306a36Sopenharmony_ci if (!src_channels->enabled) { 4862306a36Sopenharmony_ci if (dst_channels->wanted) 4962306a36Sopenharmony_ci snd_pcm_area_silence(&dst_channels->area, 0, frames, plugin->dst_format.format); 5062306a36Sopenharmony_ci dst_channels->enabled = 0; 5162306a36Sopenharmony_ci continue; 5262306a36Sopenharmony_ci } 5362306a36Sopenharmony_ci dst_channels->enabled = 1; 5462306a36Sopenharmony_ci snd_pcm_area_copy(&src_channels->area, 0, &dst_channels->area, 0, frames, plugin->src_format.format); 5562306a36Sopenharmony_ci src_channels++; 5662306a36Sopenharmony_ci dst_channels++; 5762306a36Sopenharmony_ci } 5862306a36Sopenharmony_ci return frames; 5962306a36Sopenharmony_ci} 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ciint snd_pcm_plugin_build_copy(struct snd_pcm_substream *plug, 6262306a36Sopenharmony_ci struct snd_pcm_plugin_format *src_format, 6362306a36Sopenharmony_ci struct snd_pcm_plugin_format *dst_format, 6462306a36Sopenharmony_ci struct snd_pcm_plugin **r_plugin) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci int err; 6762306a36Sopenharmony_ci struct snd_pcm_plugin *plugin; 6862306a36Sopenharmony_ci int width; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci if (snd_BUG_ON(!r_plugin)) 7162306a36Sopenharmony_ci return -ENXIO; 7262306a36Sopenharmony_ci *r_plugin = NULL; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci if (snd_BUG_ON(src_format->format != dst_format->format)) 7562306a36Sopenharmony_ci return -ENXIO; 7662306a36Sopenharmony_ci if (snd_BUG_ON(src_format->rate != dst_format->rate)) 7762306a36Sopenharmony_ci return -ENXIO; 7862306a36Sopenharmony_ci if (snd_BUG_ON(src_format->channels != dst_format->channels)) 7962306a36Sopenharmony_ci return -ENXIO; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci width = snd_pcm_format_physical_width(src_format->format); 8262306a36Sopenharmony_ci if (snd_BUG_ON(width <= 0)) 8362306a36Sopenharmony_ci return -ENXIO; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci err = snd_pcm_plugin_build(plug, "copy", src_format, dst_format, 8662306a36Sopenharmony_ci 0, &plugin); 8762306a36Sopenharmony_ci if (err < 0) 8862306a36Sopenharmony_ci return err; 8962306a36Sopenharmony_ci plugin->transfer = copy_transfer; 9062306a36Sopenharmony_ci *r_plugin = plugin; 9162306a36Sopenharmony_ci return 0; 9262306a36Sopenharmony_ci} 93