ALSA lib-ext plugin
External Plugin: Filter-Type Plugin
The filter-type plugin is a plugin to convert the PCM signals from the input and feeds to the output. Thus, this plugin always needs a slave PCM as its output.
The plugin can modify the format and the channels of the input/output PCM. It can not modify the sample rate (because of simplicity reason).
The following fields have to be filled in extplug record before calling snd_pcm_extplug_create() : version, name, callback. Otherfields are optional and should be initialized with zero.
The constant SND_PCM_EXTPLUG_VERSION must be passed to the version field for the version check in alsa-lib. A non-NULL ASCII string has to be passed to the name field. The callback field contains the table of callback functions for this plugin (defined as snd_pcm_extplug_callback_t).
The driver can set an arbitrary value (pointer) to private_data field to refer its own data in the callbacks.
The rest fields are filled by snd_pcm_extplug_create(). The pcm field is the resultant PCM handle. The others are the current status of the PCM.
The callback functions in snd_pcm_extplug_callback_t define the real behavior of the driver. At least, transfer callback must be given. This callback is called at each time certain size of data block is transfered to the slave PCM. Other callbacks are optional.
The close callback is called when the PCM is closed. If the plugin allocates private resources, this is the place to release them again. The hw_params and hw_free callbacks are called at snd_pcm_hw_params() and snd_pcm_hw_free() API calls, respectively. The last, dump callback, is called for printing the information of the given plugin.
The init callback is called when the PCM is at prepare state or any initialization is issued. Use this callback to reset the PCM instance to a sane initial state.
The hw_params constraints can be defined via either snd_pcm_extplug_set_param_minmax() and snd_pcm_extplug_set_param_list() functions after callingsnd_pcm_extplug_create(). The former defines the minimal and maximal acceptable values for the given hw_params parameter (SND_PCM_EXTPLUG_HW_XXX). This function can't be used for the format parameter. The latter function specifies the available parameter values as the list. As mentioned above, the rate can't be changed. Only changeable parameters are sample format and channels.
To define the constraints of the slave PCM configuration, use either snd_pcm_extplug_set_slave_param_minmax() and snd_pcm_extplug_set_slave_param_list(). The arguments are as same as former functions.
To clear the parameter constraints, call snd_pcm_extplug_params_reset() function.
When using snd_pcm_extplug_set_param_*() or snd_pcm_extplug_set_slave_param_*() for any parameter. This parameter is no longer linked between the client and slave PCM. Therefore it could differ and the extplug has to support conversion between all valid parameter configurations. To keep the client and slave parameter linkedsnd_pcm_extplug_set_param_link() can be used for the corresponding parameter. For example if the extplug does not support channel nor format conversion the supported client parameters can be limited with snd_pcm_extplug_set_param_*() and afterwards #snd_pcm_extplug_set_param_link(ext, SND_PCM_EXTPLUG_HW_FORMAT, 1) and #snd_pcm_extplug_set_param_link(ext, SND_PCM_EXTPLUG_HW_CHANNELS, 1) should be called to keep the client and slave parameters the same.
参考pcm_speex.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <alsa/asoundlib.h>
#include <alsa/pcm_external.h> struct ctx_parms {
int frames;
int enable_dump;
FILE *dump_fp;
float gain;
}; typedef struct {
snd_pcm_extplug_t ext;
struct ctx_parms parms;
short *buf;
short *outbuf;
unsigned int filled;
unsigned int processed;
}snd_pcm_fellowext_t; static inline void *area_addr(const snd_pcm_channel_area_t *area, snd_pcm_uframes_t offset)
{
unsigned int bitofs = area->first + area->step * offset;
return (char *)area->addr + bitofs / ;
} static void process(snd_pcm_fellowext_t *ctx)
{
int frames = ctx->parms.frames;
short *inbuf = ctx->buf;
short *outbuf= ctx->outbuf;
int channels= ctx->ext.channels;
int ch_idx = , frame_idx = ;
for (frame_idx = ; frame_idx < frames; frame_idx++)
{
for (ch_idx = ; ch_idx < channels; ch_idx++)
{
outbuf[frame_idx * channels + ch_idx] = (short)((float)inbuf[frame_idx * channels + ch_idx] * ctx->parms.gain);
}
}
} static snd_pcm_sframes_t fellowext_transfer(snd_pcm_extplug_t *ext, const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset, const snd_pcm_channel_area_t *src_areas, snd_pcm_uframes_t src_offset, snd_pcm_uframes_t size)
{
snd_pcm_fellowext_t *ctx = (snd_pcm_fellowext_t *)ext;
short *src = area_addr(src_areas, src_offset);
short *dst = area_addr(dst_areas, dst_offset);
unsigned int count = size;
int channels = ctx->ext.channels;
int bytes_per_frame = * channels; while (count > ) {
unsigned int chunk;
if (ctx->filled + count > ctx->parms.frames)
chunk = ctx->parms.frames - ctx->filled;
else
chunk = count;
if (ctx->processed)
memcpy(dst, ctx->outbuf + ctx->filled * channels, chunk * bytes_per_frame);
else
memset(dst, , chunk * bytes_per_frame);
if (ctx->parms.enable_dump)
fwrite(dst, , chunk * bytes_per_frame, ctx->parms.dump_fp);
dst += chunk * channels; memcpy(ctx->buf + ctx->filled * channels, src, chunk * bytes_per_frame);
ctx->filled += chunk;
if (ctx->filled == ctx->parms.frames) {
process(ctx);
ctx->processed = ;
ctx->filled = 0;
}
src += chunk * channels;
count -= chunk;
}
return size;
} static int fellowext_init(snd_pcm_extplug_t *ext)
{
snd_pcm_fellowext_t *ctx = (snd_pcm_fellowext_t *)ext;
int channels = ctx->ext.channels; ctx->filled = ;
ctx->processed = ;
if (!ctx->buf) {
ctx->buf = malloc(ctx->parms.frames * * channels);
if (!ctx->buf)
return -ENOMEM;
}
memset (ctx->buf, , ctx->parms.frames * * channels);
if (!ctx->outbuf) {
ctx->outbuf = malloc(ctx->parms.frames * * channels);
if (!ctx->outbuf)
return -ENOMEM;
}
memset (ctx->outbuf, , ctx->parms.frames * * channels);
return ;
} static int fellowext_close(snd_pcm_extplug_t *ext)
{
snd_pcm_fellowext_t *ctx = (snd_pcm_fellowext_t *)ext;
if (ctx->parms.enable_dump)
fclose(ctx->parms.dump_fp);
if (ctx->buf) {
free(ctx->buf);
ctx->buf = NULL;
}
if (ctx->outbuf) {
free(ctx->outbuf);
ctx->outbuf = NULL;
}
return ;
} static const snd_pcm_extplug_callback_t fellowext_callback = {
.transfer = fellowext_transfer,
.init = fellowext_init,
.close = fellowext_close,
}; static int get_bool_parm(snd_config_t *n, const char *id, const char *str, int *val_ret)
{
int val;
if (strcmp(id, str))
return ;
val = snd_config_get_bool(n);
if (val < ) {
SNDERR("Invalid value for %s", id );
return val;
}
*val_ret = val;
return ;
} static int get_int_parm(snd_config_t *n, const char *id, const char *str, int *val_ret)
{
long val;
int err;
if (strcmp(id, str))
return ;
err = snd_config_get_integer(n, &val);
if (err < ) {
SNDERR("Invalid value for %s", id );
return err;
}
*val_ret = val;
return ;
} static int get_float_parm(snd_config_t *n, const char *id, const char *str, float *val_ret)
{
double val;
int err;
if (strcmp(id, str))
return ;
err = snd_config_get_ireal(n, &val);
if (err < ) {
SNDERR("Invalid value for %s", id );
return err;
}
*val_ret = val;
return ;
}
SND_PCM_PLUGIN_DEFINE_FUNC(fellowext)
{
snd_config_iterator_t i, next;
snd_pcm_fellowext_t *ctx;
snd_config_t *sconf = NULL;
int err;
struct ctx_parms parms = {
.frames = ,
.enable_dump = ,
.dump_fp = NULL,
.gain = 0.5,
}; snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id;
if (snd_config_get_id(n, &id) < )
continue;
if (strcmp(id, "comment") == || strcmp(id, "type") == )
continue;
if (strcmp(id, "slave") == ) {
sconf = n;
continue;
}
err = get_int_parm(n, id, "frames", &parms.frames);
if (err)
goto ok;
err = get_bool_parm(n, id, "enable_dump", &parms.enable_dump);
if (err)
goto ok;
err = get_float_parm(n, id, "gain", &parms.gain);
if (err)
goto ok; SNDERR("Unknown field %s", id);
return -EINVAL;
ok:
if (err < )
return err;
}
if (!sconf) {
SNDERR("No slave configuration for fellowext pcm");
return -EINVAL;
}
if (parms.enable_dump)
parms.dump_fp = fopen("extplug.pcm", "wb");
ctx = calloc(, sizeof(*ctx));
if (!ctx)
return -ENOMEM;
ctx->ext.version = SND_PCM_EXTPLUG_VERSION;
ctx->ext.name = "Fellow Ext Plugin";
ctx->ext.callback = &fellowext_callback;
ctx->ext.private_data = ctx;
ctx->parms = parms;
err = snd_pcm_extplug_create(&ctx->ext, name, root, sconf, stream, mode);
if (err < ) {
free(ctx);
return err;
}
snd_pcm_extplug_set_param(&ctx->ext, SND_PCM_EXTPLUG_HW_CHANNELS, );
snd_pcm_extplug_set_slave_param(&ctx->ext, SND_PCM_EXTPLUG_HW_CHANNELS, );
snd_pcm_extplug_set_param(&ctx->ext, SND_PCM_EXTPLUG_HW_FORMAT, SND_PCM_FORMAT_S16);
snd_pcm_extplug_set_slave_param(&ctx->ext, SND_PCM_EXTPLUG_HW_FORMAT, SND_PCM_FORMAT_S16);
*pcmp = ctx->ext.pcm;
return ;
}
SND_PCM_PLUGIN_SYMBOL(fellowext);
Makefile:
ALSA_INC_PATH=/home/fellow/alsa-lib-1.2./output/usr/include
ALSA_LIB_PATH=/usr/lib/i386-linux-gnu export LD_LIBRARY_PATH=${ALSA_LIB_PATH}:$LD_LIBRARY_PATH
export CC=gcc
export CFLAGS=-I${ALSA_INC_PATH}
export LDFLAGS=-L{ALSA_LIB_PATH} -lasound
SOURCE=pcm_fellowext.c
TARGET=libasound_module_pcm_fellowext.so
all:
${CC} ${SOURCE} ${CFLAGS} ${LDFLAGS} -shared -fPIC -DPIC -Wall -Werror -o ${TARGET}
将libasound_module_pcm_fellowext.so copy到/usr/lib/alsa-lib
在home目录下新建.asoundrc
pcm.myout {
type fellow
slavepcm "default"
dumpfile "fellowdump.pcm"
}
pcm.out1 {
type plug
slave.pcm myout
}
pcm.out {
type plug
slave.pcm "default"
}
pcm.myext {
type fellowext
enable_dump
slave {
pcm out1
}
}
执行命令:aplay -D myext xxx.wav
ALSA lib-ext plugin的更多相关文章
- jmeter的dubbo压测,依赖jar包要放到执行机的lib/ext下
对于jmeter的dubbo压测场景的master-slave结构: 即master的jmeter进行任务的下发和报告的生成,slave进行任务的执行 因为dubbo压测需要依赖很多三方jar包,那么 ...
- ALSA lib编译
http://blog.sina.com.cn/s/blog_7d7e9d0f0101lqlp.html alsa lib: #!bin/sh rm -rf ./output/* mkdir -p ...
- ALSA lib基本概念
1.channel 通道,即我们熟知的声道数.左/右声道,5.1channel等等 2.sample A sample is a single value that describes the amp ...
- ALSA lib调用实例
1. Display Some PCM Types and Formats 2. Opening PCM Device and Setting Parameters /* This example o ...
- ALSA 学习小记
对于playback snd_pcm_begin snd_pcm_commit, 貌似 commit给的frame才会使得alsa去把数据填充 转自 http://magodo.github.io/ ...
- Jmeter plugin jp@gc - PerfMon Metrics Collector
Jmeter由于是开源工具,所以目前有很多插件可以供使用,最简单的方法是先把Plugin Manager安装了 下载地址:https://jmeter-plugins.org/wiki/Plugins ...
- 转:JMeter监控内存及CPU ——plugin插件监控被测系统资源方法
JMeter监控内存及CPU ——plugin插件监控被测系统资源方法 jmeter中也可以监控服务器的CPU和内存使用情况,但是需要安装一些插件还需要在被监测服务器上开启服务. 1.需要的插件准备 ...
- Spring整合JUnit4进行AOP单元测试的时候,报:"C:\Program Files\Java\jdk1.8.0_191\bin\java.exe" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2018.3\lib\idea_rt.jar=64
错误代码 "C:\Program Files\Java\jdk1.8.0_191\bin\java.exe" -ea -Didea.test.cyclic.buffer.size= ...
- Jmeter-12-如何使用Plugin Manager
1. 搜索 Jmeter plugin 并找到plugin manager 下载jar文件 2. 放到jmeter/lib/ext下面, 重启jmeter 3. 找到选项-> Plugin ma ...
随机推荐
- Win环境下安装vue及运行vue开发的前端项目
vue安装及配置 首先下载node.js要求版本在8.9以上 官网:https://nodejs.org/zh-cn/ 下载完可检查在windows任务命令行里输入node -v 使用淘 ...
- OpenLayers 6 学习笔记
这个是真的学习笔记!不是教程 转载请声明:https://www.cnblogs.com/onsummer/p/12159366.html 基于openlayers 6.x api不太好查,就基于腾讯 ...
- R12客户表结构分析
客户表/联系人/PARTY关联 HZ_PARTIES 客户账户表 HZ_CUST_ACCOUNTS 例子: select hp.party_number --客户注册标识 ...
- RequestFacade对象获取请求头时忽略大小写
也许在Controller层 在RequestFacde文件中getHeader函数逻辑实现如下所示: public String getHeader(String name) { if(this.r ...
- JS事件流、DOM事件流、IE事件处理、跨浏览器事件处理、事件对象与类型
事件的移除 removeEventListener() 第二个参数需要指定要移除的事件句柄,不能是匿名函数,因为无法识别 想要移除成功,那么三个参数必须跟addEventListener中的三个完全一 ...
- 回炉重造之重读Windows核心编程-006-线程
线程也是有两部分组成的: 线程的内核对象,操作系统用来管理线程和统计线程信息的地方. 线程堆栈,用于维护现场在执行代码的时候用到的所有函数参数和局部变量. 进程是线程的容器,如果进程中有一个以上的线程 ...
- OHEM论文笔记
目录 引言 Fast R-CNN设计思路 一.动机 二.现有方案hard negative mining 及其窘境 hard negative mining实现 窘境 设计思路 OHEM步骤: 反向传 ...
- Django复制记录的方法
最近的Django项目中有复制记录的需求.数据库里有一张名为Party的表,记录用户创建的party,现在要让用户能够复制一个新的party.本身非常简单的一个功能,但运行的时候出错了.我以为是复制过 ...
- 哈尔滨工业大学(深圳)本科毕业设计(论文)LaTeX模板:hitszthesis
目录 本篇文章的主要内容如下: 目录 引言 Why hitszthesis? 下载方式 编译方式简介 模板说明文档(用户手册) 毕业论文撰写样例 后记 引言 去年发布过哈深本科毕业设计(论文)的LaT ...
- python3-cookbook笔记:第四章 迭代器与生成器
python3-cookbook中每个小节以问题.解决方案和讨论三个部分探讨了Python3在某类问题中的最优解决方式,或者说是探讨Python3本身的数据结构.函数.类等特性在某类问题上如何更好地使 ...