📄 route.c
字号:
/* * Attenuated route Plug-In * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org> * * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 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 Library General Public License for more details. * * You should have received a copy of the GNU Library 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 <sound/driver.h>#include <linux/slab.h>#include <linux/time.h>#include <sound/core.h>#include <sound/pcm.h>#include "pcm_plugin.h"/* The best possible hack to support missing optimization in gcc 2.7.2.3 */#if ROUTE_PLUGIN_RESOLUTION & (ROUTE_PLUGIN_RESOLUTION - 1) != 0#define div(a) a /= ROUTE_PLUGIN_RESOLUTION#elif ROUTE_PLUGIN_RESOLUTION == 16#define div(a) a >>= 4#else#error "Add some code here"#endiftypedef struct ttable_dst ttable_dst_t;typedef struct route_private_data route_t;typedef void (*route_channel_f)(snd_pcm_plugin_t *plugin, const snd_pcm_plugin_channel_t *src_channels, snd_pcm_plugin_channel_t *dst_channel, ttable_dst_t* ttable, snd_pcm_uframes_t frames);typedef struct { int channel; int as_int;#if ROUTE_PLUGIN_USE_FLOAT float as_float;#endif} ttable_src_t;struct ttable_dst { int att; /* Attenuated */ unsigned int nsrcs; ttable_src_t* srcs; route_channel_f func;};struct route_private_data { enum {R_UINT32=0, R_UINT64=1, R_FLOAT=2} sum_type; int get, put; int conv; int src_sample_size; ttable_dst_t ttable[0];};typedef union { u_int32_t as_uint32; u_int64_t as_uint64;#if ROUTE_PLUGIN_USE_FLOAT float as_float;#endif} sum_t;static void route_to_channel_from_zero(snd_pcm_plugin_t *plugin, const snd_pcm_plugin_channel_t *src_channels ATTRIBUTE_UNUSED, snd_pcm_plugin_channel_t *dst_channel, ttable_dst_t* ttable ATTRIBUTE_UNUSED, snd_pcm_uframes_t frames){ if (dst_channel->wanted) snd_pcm_area_silence(&dst_channel->area, 0, frames, plugin->dst_format.format); dst_channel->enabled = 0;}static void route_to_channel_from_one(snd_pcm_plugin_t *plugin, const snd_pcm_plugin_channel_t *src_channels, snd_pcm_plugin_channel_t *dst_channel, ttable_dst_t* ttable, snd_pcm_uframes_t frames){#define CONV_LABELS#include "plugin_ops.h"#undef CONV_LABELS route_t *data = (route_t *)plugin->extra_data; void *conv; const snd_pcm_plugin_channel_t *src_channel = NULL; unsigned int srcidx; char *src, *dst; int src_step, dst_step; for (srcidx = 0; srcidx < ttable->nsrcs; ++srcidx) { src_channel = &src_channels[ttable->srcs[srcidx].channel]; if (src_channel->area.addr != NULL) break; } if (srcidx == ttable->nsrcs) { route_to_channel_from_zero(plugin, src_channels, dst_channel, ttable, frames); return; } dst_channel->enabled = 1; conv = conv_labels[data->conv]; src = src_channel->area.addr + src_channel->area.first / 8; src_step = src_channel->area.step / 8; dst = dst_channel->area.addr + dst_channel->area.first / 8; dst_step = dst_channel->area.step / 8; while (frames-- > 0) { goto *conv;#define CONV_END after#include "plugin_ops.h"#undef CONV_END after: src += src_step; dst += dst_step; }}static void route_to_channel(snd_pcm_plugin_t *plugin, const snd_pcm_plugin_channel_t *src_channels, snd_pcm_plugin_channel_t *dst_channel, ttable_dst_t* ttable, snd_pcm_uframes_t frames){#define GET_U_LABELS#define PUT_U32_LABELS#include "plugin_ops.h"#undef GET_U_LABELS#undef PUT_U32_LABELS static void *zero_labels[3] = { &&zero_int32, &&zero_int64,#if ROUTE_PLUGIN_USE_FLOAT &&zero_float#endif }; /* sum_type att */ static void *add_labels[3 * 2] = { &&add_int32_noatt, &&add_int32_att, &&add_int64_noatt, &&add_int64_att,#if ROUTE_PLUGIN_USE_FLOAT &&add_float_noatt, &&add_float_att#endif }; /* sum_type att shift */ static void *norm_labels[3 * 2 * 4] = { NULL, &&norm_int32_8_noatt, &&norm_int32_16_noatt, &&norm_int32_24_noatt, NULL, &&norm_int32_8_att, &&norm_int32_16_att, &&norm_int32_24_att, &&norm_int64_0_noatt, &&norm_int64_8_noatt, &&norm_int64_16_noatt, &&norm_int64_24_noatt, &&norm_int64_0_att, &&norm_int64_8_att, &&norm_int64_16_att, &&norm_int64_24_att,#if ROUTE_PLUGIN_USE_FLOAT &&norm_float_0, &&norm_float_8, &&norm_float_16, &&norm_float_24, &&norm_float_0, &&norm_float_8, &&norm_float_16, &&norm_float_24,#endif }; route_t *data = (route_t *)plugin->extra_data; void *zero, *get, *add, *norm, *put_u32; int nsrcs = ttable->nsrcs; char *dst; int dst_step; char *srcs[nsrcs]; int src_steps[nsrcs]; ttable_src_t src_tt[nsrcs]; u_int32_t sample = 0; int srcidx, srcidx1 = 0; for (srcidx = 0; srcidx < nsrcs; ++srcidx) { const snd_pcm_plugin_channel_t *src_channel = &src_channels[ttable->srcs[srcidx].channel]; if (!src_channel->enabled) continue; srcs[srcidx1] = src_channel->area.addr + src_channel->area.first / 8; src_steps[srcidx1] = src_channel->area.step / 8; src_tt[srcidx1] = ttable->srcs[srcidx]; srcidx1++; } nsrcs = srcidx1; if (nsrcs == 0) { route_to_channel_from_zero(plugin, src_channels, dst_channel, ttable, frames); return; } else if (nsrcs == 1 && src_tt[0].as_int == ROUTE_PLUGIN_RESOLUTION) { route_to_channel_from_one(plugin, src_channels, dst_channel, ttable, frames); return; } dst_channel->enabled = 1; zero = zero_labels[data->sum_type]; get = get_u_labels[data->get]; add = add_labels[data->sum_type * 2 + ttable->att]; norm = norm_labels[data->sum_type * 8 + ttable->att * 4 + 4 - data->src_sample_size]; put_u32 = put_u32_labels[data->put]; dst = dst_channel->area.addr + dst_channel->area.first / 8; dst_step = dst_channel->area.step / 8; while (frames-- > 0) { ttable_src_t *ttp = src_tt; sum_t sum; /* Zero sum */ goto *zero; zero_int32: sum.as_uint32 = 0; goto zero_end; zero_int64: sum.as_uint64 = 0; goto zero_end;#if ROUTE_PLUGIN_USE_FLOAT zero_float: sum.as_float = 0.0; goto zero_end;#endif zero_end: for (srcidx = 0; srcidx < nsrcs; ++srcidx) { char *src = srcs[srcidx]; /* Get sample */ goto *get;#define GET_U_END after_get#include "plugin_ops.h"#undef GET_U_END after_get: /* Sum */ goto *add; add_int32_att: sum.as_uint32 += sample * ttp->as_int; goto after_sum; add_int32_noatt: if (ttp->as_int) sum.as_uint32 += sample; goto after_sum; add_int64_att: sum.as_uint64 += (u_int64_t) sample * ttp->as_int; goto after_sum; add_int64_noatt: if (ttp->as_int) sum.as_uint64 += sample; goto after_sum;#if ROUTE_PLUGIN_USE_FLOAT add_float_att: sum.as_float += sample * ttp->as_float; goto after_sum; add_float_noatt: if (ttp->as_int) sum.as_float += sample; goto after_sum;#endif after_sum: srcs[srcidx] += src_steps[srcidx]; ttp++; } /* Normalization */ goto *norm; norm_int32_8_att: sum.as_uint64 = sum.as_uint32; norm_int64_8_att: sum.as_uint64 <<= 8; norm_int64_0_att: div(sum.as_uint64); goto norm_int; norm_int32_16_att: sum.as_uint64 = sum.as_uint32; norm_int64_16_att: sum.as_uint64 <<= 16; div(sum.as_uint64); goto norm_int; norm_int32_24_att: sum.as_uint64 = sum.as_uint32; norm_int64_24_att:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -