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 #define SHIFT 11
0028 #define BITS (1<<SHIFT)
0029 #define R_MASK (BITS-1)
0030
0031
0032
0033
0034
0035 struct rate_channel {
0036 signed short last_S1;
0037 signed short last_S2;
0038 };
0039
0040 typedef void (*rate_f)(struct snd_pcm_plugin *plugin,
0041 const struct snd_pcm_plugin_channel *src_channels,
0042 struct snd_pcm_plugin_channel *dst_channels,
0043 int src_frames, int dst_frames);
0044
0045 struct rate_priv {
0046 unsigned int pitch;
0047 unsigned int pos;
0048 rate_f func;
0049 snd_pcm_sframes_t old_src_frames, old_dst_frames;
0050 struct rate_channel channels[];
0051 };
0052
0053 static void rate_init(struct snd_pcm_plugin *plugin)
0054 {
0055 unsigned int channel;
0056 struct rate_priv *data = (struct rate_priv *)plugin->extra_data;
0057 data->pos = 0;
0058 for (channel = 0; channel < plugin->src_format.channels; channel++) {
0059 data->channels[channel].last_S1 = 0;
0060 data->channels[channel].last_S2 = 0;
0061 }
0062 }
0063
0064 static void resample_expand(struct snd_pcm_plugin *plugin,
0065 const struct snd_pcm_plugin_channel *src_channels,
0066 struct snd_pcm_plugin_channel *dst_channels,
0067 int src_frames, int dst_frames)
0068 {
0069 unsigned int pos = 0;
0070 signed int val;
0071 signed short S1, S2;
0072 signed short *src, *dst;
0073 unsigned int channel;
0074 int src_step, dst_step;
0075 int src_frames1, dst_frames1;
0076 struct rate_priv *data = (struct rate_priv *)plugin->extra_data;
0077 struct rate_channel *rchannels = data->channels;
0078
0079 for (channel = 0; channel < plugin->src_format.channels; channel++) {
0080 pos = data->pos;
0081 S1 = rchannels->last_S1;
0082 S2 = rchannels->last_S2;
0083 if (!src_channels[channel].enabled) {
0084 if (dst_channels[channel].wanted)
0085 snd_pcm_area_silence(&dst_channels[channel].area, 0, dst_frames, plugin->dst_format.format);
0086 dst_channels[channel].enabled = 0;
0087 continue;
0088 }
0089 dst_channels[channel].enabled = 1;
0090 src = (signed short *)src_channels[channel].area.addr +
0091 src_channels[channel].area.first / 8 / 2;
0092 dst = (signed short *)dst_channels[channel].area.addr +
0093 dst_channels[channel].area.first / 8 / 2;
0094 src_step = src_channels[channel].area.step / 8 / 2;
0095 dst_step = dst_channels[channel].area.step / 8 / 2;
0096 src_frames1 = src_frames;
0097 dst_frames1 = dst_frames;
0098 while (dst_frames1-- > 0) {
0099 if (pos & ~R_MASK) {
0100 pos &= R_MASK;
0101 S1 = S2;
0102 if (src_frames1-- > 0) {
0103 S2 = *src;
0104 src += src_step;
0105 }
0106 }
0107 val = S1 + ((S2 - S1) * (signed int)pos) / BITS;
0108 if (val < -32768)
0109 val = -32768;
0110 else if (val > 32767)
0111 val = 32767;
0112 *dst = val;
0113 dst += dst_step;
0114 pos += data->pitch;
0115 }
0116 rchannels->last_S1 = S1;
0117 rchannels->last_S2 = S2;
0118 rchannels++;
0119 }
0120 data->pos = pos;
0121 }
0122
0123 static void resample_shrink(struct snd_pcm_plugin *plugin,
0124 const struct snd_pcm_plugin_channel *src_channels,
0125 struct snd_pcm_plugin_channel *dst_channels,
0126 int src_frames, int dst_frames)
0127 {
0128 unsigned int pos = 0;
0129 signed int val;
0130 signed short S1, S2;
0131 signed short *src, *dst;
0132 unsigned int channel;
0133 int src_step, dst_step;
0134 int src_frames1, dst_frames1;
0135 struct rate_priv *data = (struct rate_priv *)plugin->extra_data;
0136 struct rate_channel *rchannels = data->channels;
0137
0138 for (channel = 0; channel < plugin->src_format.channels; ++channel) {
0139 pos = data->pos;
0140 S1 = rchannels->last_S1;
0141 S2 = rchannels->last_S2;
0142 if (!src_channels[channel].enabled) {
0143 if (dst_channels[channel].wanted)
0144 snd_pcm_area_silence(&dst_channels[channel].area, 0, dst_frames, plugin->dst_format.format);
0145 dst_channels[channel].enabled = 0;
0146 continue;
0147 }
0148 dst_channels[channel].enabled = 1;
0149 src = (signed short *)src_channels[channel].area.addr +
0150 src_channels[channel].area.first / 8 / 2;
0151 dst = (signed short *)dst_channels[channel].area.addr +
0152 dst_channels[channel].area.first / 8 / 2;
0153 src_step = src_channels[channel].area.step / 8 / 2;
0154 dst_step = dst_channels[channel].area.step / 8 / 2;
0155 src_frames1 = src_frames;
0156 dst_frames1 = dst_frames;
0157 while (dst_frames1 > 0) {
0158 S1 = S2;
0159 if (src_frames1-- > 0) {
0160 S2 = *src;
0161 src += src_step;
0162 }
0163 if (pos & ~R_MASK) {
0164 pos &= R_MASK;
0165 val = S1 + ((S2 - S1) * (signed int)pos) / BITS;
0166 if (val < -32768)
0167 val = -32768;
0168 else if (val > 32767)
0169 val = 32767;
0170 *dst = val;
0171 dst += dst_step;
0172 dst_frames1--;
0173 }
0174 pos += data->pitch;
0175 }
0176 rchannels->last_S1 = S1;
0177 rchannels->last_S2 = S2;
0178 rchannels++;
0179 }
0180 data->pos = pos;
0181 }
0182
0183 static snd_pcm_sframes_t rate_src_frames(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t frames)
0184 {
0185 struct rate_priv *data;
0186 snd_pcm_sframes_t res;
0187
0188 if (snd_BUG_ON(!plugin))
0189 return -ENXIO;
0190 if (frames == 0)
0191 return 0;
0192 data = (struct rate_priv *)plugin->extra_data;
0193 if (plugin->src_format.rate < plugin->dst_format.rate) {
0194 res = (((frames * data->pitch) + (BITS/2)) >> SHIFT);
0195 } else {
0196 res = DIV_ROUND_CLOSEST(frames << SHIFT, data->pitch);
0197 }
0198 if (data->old_src_frames > 0) {
0199 snd_pcm_sframes_t frames1 = frames, res1 = data->old_dst_frames;
0200 while (data->old_src_frames < frames1) {
0201 frames1 >>= 1;
0202 res1 <<= 1;
0203 }
0204 while (data->old_src_frames > frames1) {
0205 frames1 <<= 1;
0206 res1 >>= 1;
0207 }
0208 if (data->old_src_frames == frames1)
0209 return res1;
0210 }
0211 data->old_src_frames = frames;
0212 data->old_dst_frames = res;
0213 return res;
0214 }
0215
0216 static snd_pcm_sframes_t rate_dst_frames(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t frames)
0217 {
0218 struct rate_priv *data;
0219 snd_pcm_sframes_t res;
0220
0221 if (snd_BUG_ON(!plugin))
0222 return -ENXIO;
0223 if (frames == 0)
0224 return 0;
0225 data = (struct rate_priv *)plugin->extra_data;
0226 if (plugin->src_format.rate < plugin->dst_format.rate) {
0227 res = DIV_ROUND_CLOSEST(frames << SHIFT, data->pitch);
0228 } else {
0229 res = (((frames * data->pitch) + (BITS/2)) >> SHIFT);
0230 }
0231 if (data->old_dst_frames > 0) {
0232 snd_pcm_sframes_t frames1 = frames, res1 = data->old_src_frames;
0233 while (data->old_dst_frames < frames1) {
0234 frames1 >>= 1;
0235 res1 <<= 1;
0236 }
0237 while (data->old_dst_frames > frames1) {
0238 frames1 <<= 1;
0239 res1 >>= 1;
0240 }
0241 if (data->old_dst_frames == frames1)
0242 return res1;
0243 }
0244 data->old_dst_frames = frames;
0245 data->old_src_frames = res;
0246 return res;
0247 }
0248
0249 static snd_pcm_sframes_t rate_transfer(struct snd_pcm_plugin *plugin,
0250 const struct snd_pcm_plugin_channel *src_channels,
0251 struct snd_pcm_plugin_channel *dst_channels,
0252 snd_pcm_uframes_t frames)
0253 {
0254 snd_pcm_uframes_t dst_frames;
0255 struct rate_priv *data;
0256
0257 if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
0258 return -ENXIO;
0259 if (frames == 0)
0260 return 0;
0261 #ifdef CONFIG_SND_DEBUG
0262 {
0263 unsigned int channel;
0264 for (channel = 0; channel < plugin->src_format.channels; channel++) {
0265 if (snd_BUG_ON(src_channels[channel].area.first % 8 ||
0266 src_channels[channel].area.step % 8))
0267 return -ENXIO;
0268 if (snd_BUG_ON(dst_channels[channel].area.first % 8 ||
0269 dst_channels[channel].area.step % 8))
0270 return -ENXIO;
0271 }
0272 }
0273 #endif
0274
0275 dst_frames = rate_dst_frames(plugin, frames);
0276 if (dst_frames > dst_channels[0].frames)
0277 dst_frames = dst_channels[0].frames;
0278 data = (struct rate_priv *)plugin->extra_data;
0279 data->func(plugin, src_channels, dst_channels, frames, dst_frames);
0280 return dst_frames;
0281 }
0282
0283 static int rate_action(struct snd_pcm_plugin *plugin,
0284 enum snd_pcm_plugin_action action,
0285 unsigned long udata)
0286 {
0287 if (snd_BUG_ON(!plugin))
0288 return -ENXIO;
0289 switch (action) {
0290 case INIT:
0291 case PREPARE:
0292 rate_init(plugin);
0293 break;
0294 default:
0295 break;
0296 }
0297 return 0;
0298 }
0299
0300 int snd_pcm_plugin_build_rate(struct snd_pcm_substream *plug,
0301 struct snd_pcm_plugin_format *src_format,
0302 struct snd_pcm_plugin_format *dst_format,
0303 struct snd_pcm_plugin **r_plugin)
0304 {
0305 int err;
0306 struct rate_priv *data;
0307 struct snd_pcm_plugin *plugin;
0308
0309 if (snd_BUG_ON(!r_plugin))
0310 return -ENXIO;
0311 *r_plugin = NULL;
0312
0313 if (snd_BUG_ON(src_format->channels != dst_format->channels))
0314 return -ENXIO;
0315 if (snd_BUG_ON(src_format->channels <= 0))
0316 return -ENXIO;
0317 if (snd_BUG_ON(src_format->format != SNDRV_PCM_FORMAT_S16))
0318 return -ENXIO;
0319 if (snd_BUG_ON(dst_format->format != SNDRV_PCM_FORMAT_S16))
0320 return -ENXIO;
0321 if (snd_BUG_ON(src_format->rate == dst_format->rate))
0322 return -ENXIO;
0323
0324 err = snd_pcm_plugin_build(plug, "rate conversion",
0325 src_format, dst_format,
0326 struct_size(data, channels,
0327 src_format->channels),
0328 &plugin);
0329 if (err < 0)
0330 return err;
0331 data = (struct rate_priv *)plugin->extra_data;
0332 if (src_format->rate < dst_format->rate) {
0333 data->pitch = ((src_format->rate << SHIFT) + (dst_format->rate >> 1)) / dst_format->rate;
0334 data->func = resample_expand;
0335 } else {
0336 data->pitch = ((dst_format->rate << SHIFT) + (src_format->rate >> 1)) / src_format->rate;
0337 data->func = resample_shrink;
0338 }
0339 data->pos = 0;
0340 rate_init(plugin);
0341 data->old_src_frames = data->old_dst_frames = 0;
0342 plugin->transfer = rate_transfer;
0343 plugin->src_frames = rate_src_frames;
0344 plugin->dst_frames = rate_dst_frames;
0345 plugin->action = rate_action;
0346 *r_plugin = plugin;
0347 return 0;
0348 }