同步操作将从 王揆/lark-release 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
lark是一个免费、轻量、功能强大的软件音频DSP。它提供了一种灵活可扩展的方法来设计效能高、空间占用小、延时低的音频路由,让您可以像搭积木一样构建音频系统。 主要特性(至v0.10版本):
lark是由一个基础的动态库liblark.so
,各种可选的块(动态加载库)例如libblkmixer.so
,和一个可选的可执行调试工具lkdb
组成。基于 lark,您可以很容易地创建您想实现的既可以简单又可以复杂的音频路由,实时启动/停止任意一个路由,或者实时设定/获取任意块的参数。
由于 lark 依赖于klogging库,您首先需要安装klogging。访问 https://gitee.com/wksuper/klogging 以安装之。另一种方式是,此仓库已经包含了预编译好的libklogging.so
,它会随着lark的安装而一起安装。
安装 lark 到您的Linux机器。
$ cd lark-release
$ sudo ./install.sh
$ sudo ldconfig
当您不需要 lark 时,您可以使用sudo ./uninstall.sh
来移除它。
运行音频路由。
RouteA
libblkfilereader.so libblkalsaplayback.so
******************* ******************
* * * *
* filereader_0 *0--->0* alsaplayback_0 *
* * * *
******************* ******************
$ x86_64-linux-gnu/bin/larkexample1
如果没错误的话,音乐文件应该开始播放了。
这个例子的源代码在此:larkexample1.cpp。
RouteA
libblkfilereader.so libblkdeinterleave.so libblkgain.so libblkmixer.so libblkinterleave.so libblkalsaplayback.so
***************** ****************** ************* ************** ******************* ******************
* * * *0-->0* *0-------->0* *0---->0* * * *
* filereader_0 *0-->0* deinterleave_0 *1-->1* gain_0 *1---+ * mixer_0 * * interleave_0 *0--->0* alsaplayback_0 *
* * * * * * | +-->1* * +->1* * * *
***************** ****************** ************* | | ************** | ******************* ******************
| | |
***************** ****************** ************* | | ************** |
* * * * * * +-|-->0* *0--+
* filereader_1 *0-->0* deinterleave_0 *0-->0* gain_1 *0-----+ * mixer_1 *
* * * *1-->1* *1-------->1* *
***************** ****************** ************* **************
$ x86_64-linux-gnu/bin/larkexample2
如果没错误的话,两个音乐文件应该开始混合播放输出了。
这个例子的源代码在此:larkexample2.cpp。
**************** ****************** ***************
RouteA * * * * * *
* filereader_0 *0--->0* alsaplayback_0 *0--->0* streamout_0 *
* * * * * *
**************** ****************** ********|******
v
========================================================================================================================================================[FIFO]=====
|
************** ************** ************* *********************** ****************** *********** ***************** *****v********
* * * * * * * * * * * * * * * *
* dummykwd_0 *0<--0* * * * * *0<--0* deinterleave_0 *0<--0* *0<--0* alsacapture_0 * * streamin_0 *
* * * * * * * *1<--1* * * * * * * *
************** * * * * * * ****************** * * ***************** ******0*******
* * * * * * * * v
* mixer_1 *0<--0* dummybf_0 *0<--0* speexpreprocessor_0 * * align_0 * **********0*******
*(duplicator)* * *1<--1* (aec, denoise, ...) * * * RouteB * deinterleave_1 *
* * * * * * * * ********0**1******
* * * * * * * * v v
**************** * * * * * * * * *********** **********0**1******
* * * * * * * *16<------------------------1* * * *0<---0* *
* filewriter_0 *0<--1* * * * * * * *1<--0* mixer_0 *1<---1* speexresampler_0 *
* * * * * * * * * * * * * *
**************** ************** ************* *********************** *********** *********** ********************
运行例3之前,需要先安装speex库。
$ sudo apt install libspeexdsp-dev
运行例3:
# 两个参数指的是alsa playback pcm name和capture pcm name。
# 它们随着机器的不同而不同。
$ x86_64-linux-gnu/bin/larkexample3 plughw:0,0 plughw:0,0
如果没错误的话,播放和录音应该同时开始了。
录到的声音文件存放在./cap-16000_16_1.pcm
。
这个例子的源代码在此:larkexample3.cpp。
RouteA
libblkfilereader.so libblkformatdapter.so libblksoundtouch.so libblkpaplayback.so
**************** ******************* **************** ****************
* * * * * * * *
* filereader_0 *0--->0* formatadapter_0 *0--->0* soundtouch_0 *0--->0* paplayback_0 *
* * * * * * * *
**************** ******************* **************** ****************
运行例5之前需要先安装 SoundTouch 库和 PortAudio 库。
$ sudo apt install libsoundtouch-dev
$ sudo apt install libportaudio2
运行例5:
$ x86_64-linux-gnu/bin/larkexample5
如果没错误的话,播放应该开始了。
在另一个shell里,
$ lkdb status # 显示lark状态
$ lkdb setparam RouteA blksoundtouch_0 1 0.6 # 音调变低
$ lkdb setparam RouteA blksoundtouch_0 1 1.8 # 音调变高
$ lkdb setparam RouteA blksoundtouch_0 1 1.0 # 音调变正常
$ lkdb setparam RouteA blksoundtouch_0 2 0.5 # 节拍变慢
$ lkdb setparam RouteA blksoundtouch_0 2 2.0 # 节拍变块
$ lkdb setparam RouteA blksoundtouch_0 2 1.0 # 节拍变正常
$ lkdb setparam RouteA blksoundtouch_0 3 2.2 # 播放速率变快
$ lkdb setparam RouteA blksoundtouch_0 3 0.4 # 播放速率变慢
$ lkdb setparam RouteA blksoundtouch_0 3 1.0 # 播放速率变正常
这个例子的源代码在此:larkexample5.cpp。
RouteA
libblkfilereader.so libblkformatdapter.so libblkdeinterleave.so libblkmixer.so libblksoxeffect.so libblkinterleave.so libblkpaplayback.so
**************** ******************* ****************** *********** *************** **************** ****************
* * * * * * * * * soxeffect_0 * * * * *
* * * * * *0-->0* *0-->0* (highpass) *0-->0* * * *
* * * * * * * * *************** * * * *
* filereader_0 *0-->0* formatadapter_0 *0-->0* deinterleave_0 * * mixer_0 * * interleave_0 *0-->0* paplayback_0 *
* * * * * * * * *************** * * * *
* * * * * *1-->1* *0-->0* soxeffect_1 *0-->1* * * *
* * * * * * * * * (lowpass) * * * * *
**************** ******************* ****************** *********** *************** **************** ****************
运行例7之前需要先安装 SoX 库和 PortAudio 库。
$ sudo apt install libsox-dev
$ sudo apt install libportaudio2
运行例7:
$ x86_64-linux-gnu/bin/larkexample7
如果没错误的话,播放应该开始了。
在另一个shell里,
$ lkdb status # 显示lark状态
$ lkdb setparam RouteA blksoxeffect_0 0 400 # 只有高于400Hz的音乐信号输出到左喇叭
$ lkdb setparam RouteA blksoxeffect_1 0 400 # 只有低于400Hz的音乐信号输出到右喇叭
这个例子的源代码在此:larkexample7.cpp。
作者的博客文章:<我的工程师爸爸-音频应用DIY系列>通过一系列小故事展示了利用lark来编程解决生活中遇到的音频问题。
lkdb
实时调试当 lark 在一个进程里运行时,调试工具lkdb
可以跟它通信,从 lark 获取信息,向 lark 发送命令。
Usage:
lkdb status [--dot]
- Print the lark running status
- Print dot code if enabled '--dot' option
lkdb newroute ROUTENAME
- Create a named route
lkdb newblock ROUTENAME SOLIB ISFIRST ISLAST [ARGS]
- Create a block on the route from the dynamic load library
lkdb newlink ROUTENAME RATE FORMAT CHNUM FRAMESIZEINSAMPLES SRCBLKNAME SRCBLKOUTEPIDX SINKBLKNAME SINKBLKINEPIDX
- Create a link to link the source block and sink block on the route
lkdb start ROUTENAME
- Start the route
lkdb stop ROUTENAME
- Stop the route
lkdb setparam ROUTENAME BLOCKNAME PARAMID [PARAMS]
- Set parameter to the block in the route
lkdb getparam ROUTENAME BLOCKNAME PARAMID
- Get parameter from the block in the route
lkdb delete ROUTENAME LINKNAME
- Delete the link from the route
lkdb delete ROUTENAME BLOCKNAME
- Delete the block and associated link(s) from the route
lkdb delete ROUTENAME !
- Delete the entire route
lkdb loglevel LEVEL
- Set the logging LEVEL: 0=off 1=fatal 2=error 3=warning 4=info(default) 5=debug 6=verbose
lkdb setdump DIRECTORY
- Enable dumping log & data when DIRECTORY is a valid path
- Disable dumping log & data when DIRECTORY is --
举个例子,当例2运行时,在另外一个shell里,您可以通过lkdb
调节例2的音量。
$ lkdb status # 显示lark状态
RouteA is RUNNING, 625 frames processed OK, 0 error frame
blkfilereader_0
(O00) --> lnk_0 48000Hz S16_LE 2ch 960samples/frame
blkdeinterleave_0
(I00) <-- lnk_0 48000Hz S16_LE 2ch 960samples/frame
(O00) --> lnk_1 48000Hz S16_LE 1ch 960samples/frame
(O01) --> lnk_2 48000Hz S16_LE 1ch 960samples/frame
blkfilereader_1
(O00) --> lnk_3 48000Hz S16_LE 2ch 960samples/frame
blkdeinterleave_1
(I01) <-- lnk_3 48000Hz S16_LE 2ch 960samples/frame
(O00) --> lnk_4 48000Hz S16_LE 1ch 960samples/frame
(O01) --> lnk_5 48000Hz S16_LE 1ch 960samples/frame
blkgain_0
(I00) <-- lnk_1 48000Hz S16_LE 1ch 960samples/frame
(I01) <-- lnk_2 48000Hz S16_LE 1ch 960samples/frame
(O00) --> lnk_6 48000Hz S16_LE 1ch 960samples/frame
(O01) --> lnk_7 48000Hz S16_LE 1ch 960samples/frame
blkgain_1
(I00) <-- lnk_4 48000Hz S16_LE 1ch 960samples/frame
(I01) <-- lnk_5 48000Hz S16_LE 1ch 960samples/frame
(O00) --> lnk_8 48000Hz S16_LE 1ch 960samples/frame
(O01) --> lnk_9 48000Hz S16_LE 1ch 960samples/frame
blkmixer_0
(I00) <-- lnk_6 48000Hz S16_LE 1ch 960samples/frame
(I01) <-- lnk_8 48000Hz S16_LE 1ch 960samples/frame
(O00) --> lnk_10 48000Hz S16_LE 1ch 960samples/frame
blkmixer_1
(I00) <-- lnk_7 48000Hz S16_LE 1ch 960samples/frame
(I01) <-- lnk_9 48000Hz S16_LE 1ch 960samples/frame
(O00) --> lnk_11 48000Hz S16_LE 1ch 960samples/frame
blkinterleave_0
(I00) <-- lnk_10 48000Hz S16_LE 1ch 960samples/frame
(I01) <-- lnk_11 48000Hz S16_LE 1ch 960samples/frame
(O00) --> lnk_12 48000Hz S16_LE 2ch 960samples/frame
blkalsaplayback_0
(I00) <-- lnk_12 48000Hz S16_LE 2ch 960samples/frame
$ lkdb setparam RouteA blkgain_0 1 0 0.5 # kanr-48000_16_2.pcm左声道的输出音量变低
$ lkdb setparam RouteA blkgain_0 1 1 0.5 # kanr-48000_16_2.pcm右声道的输出音量变低
$ lkdb setparam RouteA blkgain_0 1 0 0.0 # kanr-48000_16_2.pcm左声道的输出静音
$ lkdb setparam RouteA blkgain_0 1 1 0.0 # kanr-48000_16_2.pcm右声道的输出静音
$ lkdb setparam RouteA blkgain_1 1 0 0.5 # pacificrim-48000_16_2.pcm左声道的输出音量变低
$ lkdb setparam RouteA blkgain_1 1 1 0.5 # pacificrim-48000_16_2.pcm右声道的输出音量变低
$ lkdb setparam RouteA blkgain_1 1 0 0.0 # pacificrim-48000_16_2.pcm左声道的输出静音
$ lkdb setparam RouteA blkgain_1 1 1 0.0 # pacificrim-48000_16_2.pcm右声道的输出静音
$ lkdb setparam RouteA blkgain_0 1 0 1.0 # kanr-48000_16_2.pcm左声道的输出音量恢复
$ lkdb setparam RouteA blkgain_0 1 1 1.0 # kanr-48000_16_2.pcm右声道的输出音量恢复
$ lkdb setparam RouteA blkgain_1 1 0 1.0 # pacificrim-48000_16_2.pcm左声道的输出音量恢复
$ lkdb setparam RouteA blkgain_1 1 1 1.0 # pacificrim-48000_16_2.pcm右声道的输出音量恢复
再举个例子,当例3运行时,在另外一个shell里,您可以通过lkdb
抓取路由快照。
$ lkdb status --dot | dot -Tpng -o larkexample3.png
路由快照会被存成文件larkexample3.png
。
注意:这个功能需要graphviz(dot)先安装到您的机器。
$ sudo apt install graphviz
在您的脑海中设计好路由。那些预编译好的块(像gain, mixer等)可以直接使用。如果您想要客制化的块,您可以自行编译动态库。 BlkPassthrough.cpp是一个块源码的例子。 参考MANUAL.md - 4 Build Your Own Block以获取更多信息。
如果只是尝试为目的,lkdb
就可以做了。
例如,想要运行跟例1一样的路由,您也可以使用lkdb
来创建路由,启动/停止路由,删除路由。
在一个shell里,
$ x86_64-linux-gnu/bin/larkexample0 # 运行lark
在另一个shell里,
$ lkdb newroute RouteA
Created RouteA
$ lkdb newblock RouteA libblkfilereader.so true false examples/kanr-48000_16_2.pcm
Created blkfilereader_0 from libblkfilereader.so on RouteA
$ lkdb newblock RouteA libblkalsaplayback.so false true
Created blkalsaplayback_0 from libblkalsaplayback.so on RouteA
$ lkdb newlink RouteA 48000 S16_LE 2 960 blkfilereader_0 0 blkalsaplayback_0 0
Created lnk_0 on RouteA
$ lkdb start RouteA # 音乐播放应该开始了
Started RouteA
$ lkdb stop RouteA
Stopped RouteA
$ lkdb delete RouteA !
Deleted RouteA
这个例子的源代码在此:larkexample0.cpp。
要应用在真实产品中,您需要在您的进程里调用 lark 的API来创建您自己的音频路由。样例已经列出。参考用户手册以获取更多信息。
Q1: “块”是什么?“端点”是什么?“链接”是什么?“路由”是什么?
A: 一个“块”就是一个软件DSP处理单元。它从一个动态加载库里被创建,并被 lark 路由所管理。它接受最多32路输入(即输入端点)数据,处理它们,把处理后的数据填入输出端点(最多32路输出)。 通常情况,一个端点代表一个声道音频,然而一个端点也可以运载多声道。例如“interleave”块的一个输出端点就可以运载多声道。 一个“链接”连接一个块的一个输出端点(作为源)至另一个块的一个输入端点(作为汇)。 一个“路由”是一个由多个块连接成的链条(或者图)。
Q2: 在一个机器上,我可以同时运行几个 lark 实例?在一个 lark 中,我可以创建几个路由?在一个路由中,我可以创建多少个块?多少个first块?多少个last块?
A: 在一个机器上,只有一个进程被容许创建一个 lark 实例。也就是说,一个机器运行一个 lark 实例。lkdb
会跟这个唯一的 lark 实例通信。在一个 lark 中,最多可以创建26个路由,它们的名字需要被手动指定为"RouteA", "RouteB", ..., "RouteZ"。对于每个路由,名字是需要的,并且应该固定为"Route#"(大小写敏感),这里“#”代表[A-Z]。
在一个路由里,创建块没有数量限制。所有从一个路由里创建出来的块/链接都属于这个路由,也就是意味着它们的资源是被这个路由统一管理。
同样,创建first块和last块也没有数量限制。
Q3: 什么是“first块”?什么是“last块”?
A: 在一个路由里,至少需要创建一个“first块”和一个“last块”,这些块在创建的时候,都有“first”标志和“last”标志被各自指定。 这样的话,路由就可以知道从哪些块开始处理,到哪些块结束处理。从first块到last块之间,所有的块应该要被连接起来,不要有切断。只有所有连接都完整了,路由才可以启动。如果路由中间有切断,这是被容许的,但是路由就无法运行。如果您强制运行,路由将会进入BROKEN_RUNNING状态,直到切断被再接起来。
Q4: “多路由”跟“单路由多first块”有何不同?如果我有多路输入作为first块,我要如何在“多路由”和“单路由多first块”之间做选择?
A: 一个路由用一个线程处理数据。通常情况,“单路由多first块”可以工作地很好。在这种情况下,多输入以同样的步伐提供数据帧,并且它们不应该被相互阻塞。例如,一个输入是alsacapture,一个输入是filereader。 需要用到“多路由”的场景是,当多个输入放在一个路由里运行会有机会相互阻塞时,那么它们就应该被分离到多个路由。例如,一个输入alsacapture,一个输入是echo-reference。
lkdb status --dot
当有多个路由时的画图问题lkdb status --dot
能够画出路由之间的FIFO连接lkdb status --dot
输出的last block名字标签错误lkdb status --dot
命令来输出dot代码,以把路由图形快照画出来。x86_64-apple-darwin/bin/larkexample4
和x86_64-apple-darwin/bin/larkexample5
可以正常运行了README.md
拆分成了README.md(英语)和README-cn.md(简体中文)此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。