summaryrefslogtreecommitdiffstats
path: root/alsa-lib/src/pcm/pcm_rate_linear.c
diff options
context:
space:
mode:
Diffstat (limited to 'alsa-lib/src/pcm/pcm_rate_linear.c')
-rw-r--r--alsa-lib/src/pcm/pcm_rate_linear.c435
1 files changed, 0 insertions, 435 deletions
diff --git a/alsa-lib/src/pcm/pcm_rate_linear.c b/alsa-lib/src/pcm/pcm_rate_linear.c
deleted file mode 100644
index 20e119b..0000000
--- a/alsa-lib/src/pcm/pcm_rate_linear.c
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * Linear rate converter plugin
- *
- * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
- * 2004 by Jaroslav Kysela <perex@perex.cz>
- * 2006 by Takashi Iwai <tiwai@suse.de>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <inttypes.h>
-#include <byteswap.h>
-#include "pcm_local.h"
-#include "pcm_plugin.h"
-#include "pcm_rate.h"
-
-#include "plugin_ops.h"
-
-
-/* LINEAR_DIV needs to be large enough to handle resampling from 192000 -> 8000 */
-#define LINEAR_DIV_SHIFT 19
-#define LINEAR_DIV (1<<LINEAR_DIV_SHIFT)
-
-struct rate_linear {
- unsigned int get_idx;
- unsigned int put_idx;
- unsigned int pitch;
- unsigned int pitch_shift; /* for expand interpolation */
- unsigned int channels;
- int16_t *old_sample;
- void (*func)(struct rate_linear *rate,
- const snd_pcm_channel_area_t *dst_areas,
- snd_pcm_uframes_t dst_offset, unsigned int dst_frames,
- const snd_pcm_channel_area_t *src_areas,
- snd_pcm_uframes_t src_offset, unsigned int src_frames);
-};
-
-static snd_pcm_uframes_t input_frames(void *obj, snd_pcm_uframes_t frames)
-{
- struct rate_linear *rate = obj;
- if (frames == 0)
- return 0;
- /* Round toward zero */
- return muldiv_near(frames, LINEAR_DIV, rate->pitch);
-}
-
-static snd_pcm_uframes_t output_frames(void *obj, snd_pcm_uframes_t frames)
-{
- struct rate_linear *rate = obj;
- if (frames == 0)
- return 0;
- /* Round toward zero */
- return muldiv_near(frames, rate->pitch, LINEAR_DIV);
-}
-
-static void linear_expand(struct rate_linear *rate,
- const snd_pcm_channel_area_t *dst_areas,
- snd_pcm_uframes_t dst_offset, unsigned int dst_frames,
- const snd_pcm_channel_area_t *src_areas,
- snd_pcm_uframes_t src_offset, unsigned int src_frames)
-{
-#define GET16_LABELS
-#define PUT16_LABELS
-#include "plugin_ops.h"
-#undef GET16_LABELS
-#undef PUT16_LABELS
- void *get = get16_labels[rate->get_idx];
- void *put = put16_labels[rate->put_idx];
- unsigned int get_threshold = rate->pitch;
- unsigned int channel;
- unsigned int src_frames1;
- unsigned int dst_frames1;
- int16_t sample = 0;
- unsigned int pos;
-
- for (channel = 0; channel < rate->channels; ++channel) {
- const snd_pcm_channel_area_t *src_area = &src_areas[channel];
- const snd_pcm_channel_area_t *dst_area = &dst_areas[channel];
- const char *src;
- char *dst;
- int src_step, dst_step;
- int16_t old_sample = 0;
- int16_t new_sample;
- int old_weight, new_weight;
- src = snd_pcm_channel_area_addr(src_area, src_offset);
- dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
- src_step = snd_pcm_channel_area_step(src_area);
- dst_step = snd_pcm_channel_area_step(dst_area);
- src_frames1 = 0;
- dst_frames1 = 0;
- new_sample = rate->old_sample[channel];
- pos = get_threshold;
- while (dst_frames1 < dst_frames) {
- if (pos >= get_threshold) {
- pos -= get_threshold;
- old_sample = new_sample;
- if (src_frames1 < src_frames) {
- goto *get;
-#define GET16_END after_get
-#include "plugin_ops.h"
-#undef GET16_END
- after_get:
- new_sample = sample;
- }
- }
- new_weight = (pos << (16 - rate->pitch_shift)) / (get_threshold >> rate->pitch_shift);
- old_weight = 0x10000 - new_weight;
- sample = (old_sample * old_weight + new_sample * new_weight) >> 16;
- goto *put;
-#define PUT16_END after_put
-#include "plugin_ops.h"
-#undef PUT16_END
- after_put:
- dst += dst_step;
- dst_frames1++;
- pos += LINEAR_DIV;
- if (pos >= get_threshold) {
- src += src_step;
- src_frames1++;
- }
- }
- rate->old_sample[channel] = new_sample;
- }
-}
-
-/* optimized version for S16 format */
-static void linear_expand_s16(struct rate_linear *rate,
- const snd_pcm_channel_area_t *dst_areas,
- snd_pcm_uframes_t dst_offset, unsigned int dst_frames,
- const snd_pcm_channel_area_t *src_areas,
- snd_pcm_uframes_t src_offset, unsigned int src_frames)
-{
- unsigned int channel;
- unsigned int src_frames1;
- unsigned int dst_frames1;
- unsigned int get_threshold = rate->pitch;
- unsigned int pos;
-
- for (channel = 0; channel < rate->channels; ++channel) {
- const snd_pcm_channel_area_t *src_area = &src_areas[channel];
- const snd_pcm_channel_area_t *dst_area = &dst_areas[channel];
- const int16_t *src;
- int16_t *dst;
- int src_step, dst_step;
- int16_t old_sample = 0;
- int16_t new_sample;
- int old_weight, new_weight;
- src = snd_pcm_channel_area_addr(src_area, src_offset);
- dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
- src_step = snd_pcm_channel_area_step(src_area) >> 1;
- dst_step = snd_pcm_channel_area_step(dst_area) >> 1;
- src_frames1 = 0;
- dst_frames1 = 0;
- new_sample = rate->old_sample[channel];
- pos = get_threshold;
- while (dst_frames1 < dst_frames) {
- if (pos >= get_threshold) {
- pos -= get_threshold;
- old_sample = new_sample;
- if (src_frames1 < src_frames)
- new_sample = *src;
- }
- new_weight = (pos << (16 - rate->pitch_shift)) / (get_threshold >> rate->pitch_shift);
- old_weight = 0x10000 - new_weight;
- *dst = (old_sample * old_weight + new_sample * new_weight) >> 16;
- dst += dst_step;
- dst_frames1++;
- pos += LINEAR_DIV;
- if (pos >= get_threshold) {
- src += src_step;
- src_frames1++;
- }
- }
- rate->old_sample[channel] = new_sample;
- }
-}
-
-static void linear_shrink(struct rate_linear *rate,
- const snd_pcm_channel_area_t *dst_areas,
- snd_pcm_uframes_t dst_offset, unsigned int dst_frames,
- const snd_pcm_channel_area_t *src_areas,
- snd_pcm_uframes_t src_offset, unsigned int src_frames)
-{
-#define GET16_LABELS
-#define PUT16_LABELS
-#include "plugin_ops.h"
-#undef GET16_LABELS
-#undef PUT16_LABELS
- void *get = get16_labels[rate->get_idx];
- void *put = put16_labels[rate->put_idx];
- unsigned int get_increment = rate->pitch;
- unsigned int channel;
- unsigned int src_frames1;
- unsigned int dst_frames1;
- int16_t sample = 0;
- unsigned int pos;
-
- for (channel = 0; channel < rate->channels; ++channel) {
- const snd_pcm_channel_area_t *src_area = &src_areas[channel];
- const snd_pcm_channel_area_t *dst_area = &dst_areas[channel];
- const char *src;
- char *dst;
- int src_step, dst_step;
- int16_t old_sample = 0;
- int16_t new_sample = 0;
- int old_weight, new_weight;
- pos = LINEAR_DIV - get_increment; /* Force first sample to be copied */
- src = snd_pcm_channel_area_addr(src_area, src_offset);
- dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
- src_step = snd_pcm_channel_area_step(src_area);
- dst_step = snd_pcm_channel_area_step(dst_area);
- src_frames1 = 0;
- dst_frames1 = 0;
- while (src_frames1 < src_frames) {
-
- goto *get;
-#define GET16_END after_get
-#include "plugin_ops.h"
-#undef GET16_END
- after_get:
- new_sample = sample;
- src += src_step;
- src_frames1++;
- pos += get_increment;
- if (pos >= LINEAR_DIV) {
- pos -= LINEAR_DIV;
- old_weight = (pos << (32 - LINEAR_DIV_SHIFT)) / (get_increment >> (LINEAR_DIV_SHIFT - 16));
- new_weight = 0x10000 - old_weight;
- sample = (old_sample * old_weight + new_sample * new_weight) >> 16;
- goto *put;
-#define PUT16_END after_put
-#include "plugin_ops.h"
-#undef PUT16_END
- after_put:
- dst += dst_step;
- dst_frames1++;
- if (CHECK_SANITY(dst_frames1 > dst_frames)) {
- SNDERR("dst_frames overflow");
- break;
- }
- }
- old_sample = new_sample;
- }
- }
-}
-
-/* optimized version for S16 format */
-static void linear_shrink_s16(struct rate_linear *rate,
- const snd_pcm_channel_area_t *dst_areas,
- snd_pcm_uframes_t dst_offset, unsigned int dst_frames,
- const snd_pcm_channel_area_t *src_areas,
- snd_pcm_uframes_t src_offset, unsigned int src_frames)
-{
- unsigned int get_increment = rate->pitch;
- unsigned int channel;
- unsigned int src_frames1;
- unsigned int dst_frames1;
- unsigned int pos = 0;
-
- for (channel = 0; channel < rate->channels; ++channel) {
- const snd_pcm_channel_area_t *src_area = &src_areas[channel];
- const snd_pcm_channel_area_t *dst_area = &dst_areas[channel];
- const int16_t *src;
- int16_t *dst;
- int src_step, dst_step;
- int16_t old_sample = 0;
- int16_t new_sample = 0;
- int old_weight, new_weight;
- pos = LINEAR_DIV - get_increment; /* Force first sample to be copied */
- src = snd_pcm_channel_area_addr(src_area, src_offset);
- dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
- src_step = snd_pcm_channel_area_step(src_area) >> 1;
- dst_step = snd_pcm_channel_area_step(dst_area) >> 1 ;
- src_frames1 = 0;
- dst_frames1 = 0;
- while (src_frames1 < src_frames) {
-
- new_sample = *src;
- src += src_step;
- src_frames1++;
- pos += get_increment;
- if (pos >= LINEAR_DIV) {
- pos -= LINEAR_DIV;
- old_weight = (pos << (32 - LINEAR_DIV_SHIFT)) / (get_increment >> (LINEAR_DIV_SHIFT - 16));
- new_weight = 0x10000 - old_weight;
- *dst = (old_sample * old_weight + new_sample * new_weight) >> 16;
- dst += dst_step;
- dst_frames1++;
- if (CHECK_SANITY(dst_frames1 > dst_frames)) {
- SNDERR("dst_frames overflow");
- break;
- }
- }
- old_sample = new_sample;
- }
- }
-}
-
-static void linear_convert(void *obj,
- const snd_pcm_channel_area_t *dst_areas,
- snd_pcm_uframes_t dst_offset, unsigned int dst_frames,
- const snd_pcm_channel_area_t *src_areas,
- snd_pcm_uframes_t src_offset, unsigned int src_frames)
-{
- struct rate_linear *rate = obj;
- rate->func(rate, dst_areas, dst_offset, dst_frames,
- src_areas, src_offset, src_frames);
-}
-
-static void linear_free(void *obj)
-{
- struct rate_linear *rate = obj;
-
- free(rate->old_sample);
- rate->old_sample = NULL;
-}
-
-static int linear_init(void *obj, snd_pcm_rate_info_t *info)
-{
- struct rate_linear *rate = obj;
-
- rate->get_idx = snd_pcm_linear_get_index(info->in.format, SND_PCM_FORMAT_S16);
- rate->put_idx = snd_pcm_linear_put_index(SND_PCM_FORMAT_S16, info->out.format);
- if (info->in.rate < info->out.rate) {
- if (info->in.format == info->out.format && info->in.format == SND_PCM_FORMAT_S16)
- rate->func = linear_expand_s16;
- else
- rate->func = linear_expand;
- /* pitch is get_threshold */
- } else {
- if (info->in.format == info->out.format && info->in.format == SND_PCM_FORMAT_S16)
- rate->func = linear_shrink_s16;
- else
- rate->func = linear_shrink;
- /* pitch is get_increment */
- }
- rate->pitch = (((u_int64_t)info->out.rate * LINEAR_DIV) +
- (info->in.rate / 2)) / info->in.rate;
- rate->channels = info->channels;
-
- free(rate->old_sample);
- rate->old_sample = malloc(sizeof(*rate->old_sample) * rate->channels);
- if (! rate->old_sample)
- return -ENOMEM;
-
- return 0;
-}
-
-static int linear_adjust_pitch(void *obj, snd_pcm_rate_info_t *info)
-{
- struct rate_linear *rate = obj;
- snd_pcm_uframes_t cframes;
-
- rate->pitch = (((u_int64_t)info->out.period_size * LINEAR_DIV) +
- (info->in.period_size/2) ) / info->in.period_size;
-
- cframes = input_frames(rate, info->out.period_size);
- while (cframes != info->in.period_size) {
- snd_pcm_uframes_t cframes_new;
- if (cframes > info->in.period_size)
- rate->pitch++;
- else
- rate->pitch--;
- cframes_new = input_frames(rate, info->out.period_size);
- if ((cframes > info->in.period_size && cframes_new < info->in.period_size) ||
- (cframes < info->in.period_size && cframes_new > info->in.period_size)) {
- SNDERR("invalid pcm period_size %ld -> %ld",
- info->in.period_size, info->out.period_size);
- return -EIO;
- }
- cframes = cframes_new;
- }
- if (rate->pitch >= LINEAR_DIV) {
- /* shift for expand linear interpolation */
- rate->pitch_shift = 0;
- while ((rate->pitch >> rate->pitch_shift) >= (1 << 16))
- rate->pitch_shift++;
- }
- return 0;
-}
-
-static void linear_reset(void *obj)
-{
- struct rate_linear *rate = obj;
-
- /* for expand */
- if (rate->old_sample)
- memset(rate->old_sample, 0, sizeof(*rate->old_sample) * rate->channels);
-}
-
-static void linear_close(void *obj)
-{
- free(obj);
-}
-
-static const snd_pcm_rate_ops_t linear_ops = {
- .close = linear_close,
- .init = linear_init,
- .free = linear_free,
- .reset = linear_reset,
- .adjust_pitch = linear_adjust_pitch,
- .convert = linear_convert,
- .input_frames = input_frames,
- .output_frames = output_frames,
-};
-
-int SND_PCM_RATE_PLUGIN_ENTRY(linear) (unsigned int version, void **objp, snd_pcm_rate_ops_t *ops)
-{
- struct rate_linear *rate;
-
- if (version != SND_PCM_RATE_PLUGIN_VERSION) {
- SNDERR("Invalid plugin version %x\n", version);
- return -EINVAL;
- }
-
- rate = calloc(1, sizeof(*rate));
- if (! rate)
- return -ENOMEM;
-
- *objp = rate;
- *ops = linear_ops;
- return 0;
-}