百灵鸟 (lark) 是一个免费、轻量、功能强大的软件音频DSP。它提供了一种灵活可扩展的方法来设计效能高、空间占用小、延时低的音频路由,让您可以像搭积木一样构建音频系统。
百灵鸟 是由一个基础的动态库liblark.so
,各种可选的块(动态加载库)例如libblkmixer.so
,和一个可选的可执行调试工具lkdb
组成。基于 百灵鸟,您可以很容易地创建您想实现的既可以简单又可以复杂的音频路由,实时启动/停止任意一个路由,或者实时设定/获取任意块的参数。
由于 百灵鸟 依赖于klogging库,您首先需要安装klogging。访问 https://gitee.com/wksuper/klogging 以安装之。另一种方式是,此仓库已经包含了预编译好的libklogging.so
,它会随着 百灵鸟 的安装而一起安装。
安装 百灵鸟 到您的Linux机器。
cd lark-release
sudo ./install.sh
sudo ldconfig
当您不需要 百灵鸟 时,您可以使用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 libblkpaplayback.so
***************** ****************** ************* ************** ******************* ******************
* * * *0-->0* *0-------->0* *0---->0* * * *
* filereader_0 *0-->0* deinterleave_0 *1-->1* *1---+ * mixer_0 * * interleave_0 *0--->0* paplayback_0 *
* * * * * * | +-->1* * +->1* * * *
***************** ****************** * * | | ************** | ******************* ******************
* gain_0 * | | |
***************** ****************** * * | | ************** |
* * * * * * +-|-->0* *0--+
* filereader_1 *0-->0* deinterleave_0 *0-->2* *2-----+ * mixer_1 *
* * * *1-->3* *3-------->1* *
***************** ****************** ************* **************
运行例2之前,需要先安装 PortAudio 库。
sudo apt install libportaudio2
运行例2:
x86_64-linux-gnu/bin/larkexample2
如果没错误的话,两个音乐文件应该开始混合播放输出了。
开启另一个shell,在里面您可以通过lkdb
调节他们的音量增益。
$ lkdb status # 显示百灵鸟状态
RouteA is RUNNING, 319 frames processed OK, 0 error 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
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
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
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
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
blkgain_0
(I00) <-- lnk_1 48000Hz S16_LE 1ch 960samples/frame
(I01) <-- lnk_2 48000Hz S16_LE 1ch 960samples/frame
(I02) <-- lnk_4 48000Hz S16_LE 1ch 960samples/frame
(I03) <-- lnk_5 48000Hz S16_LE 1ch 960samples/frame
(O00) --> lnk_6 48000Hz S16_LE 1ch 960samples/frame
(O01) --> lnk_7 48000Hz S16_LE 1ch 960samples/frame
(O02) --> lnk_8 48000Hz S16_LE 1ch 960samples/frame
(O03) --> lnk_9 48000Hz S16_LE 1ch 960samples/frame
blkpaplayback_0
(I00) <-- lnk_12 48000Hz S16_LE 2ch 960samples/frame
No fifo
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_0 1 2 0.5 # pacificrim-48000_16_2.pcm左声道的输出音量变低
lkdb setparam RouteA blkgain_0 1 3 0.5 # pacificrim-48000_16_2.pcm右声道的输出音量变低
lkdb setparam RouteA blkgain_0 1 2 0.0 # pacificrim-48000_16_2.pcm左声道的输出静音
lkdb setparam RouteA blkgain_0 1 3 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_0 1 2 1.0 # pacificrim-48000_16_2.pcm左声道的输出音量恢复
lkdb setparam RouteA blkgain_0 1 3 1.0 # pacificrim-48000_16_2.pcm右声道的输出音量恢复
这个例子的源代码在此: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
*duplicator_0*0<--0* dummybf_0 *0<--0* speexpreprocessor_0 * * align_0 * **********0*******
* * * *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 # 显示百灵鸟状态
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.dylib libblkformatdapter.dylib libblkdeinterleave.dylib libblkmixer.dylib libblksoxeffect.dylib libblkinterleave.dylib libblkfilewriter.dylib
******************* ********************** ********************* ************** *************************** ******************* *******************
* * * * * * * *0-->0* blksoxeffect_highpass_0 *0-->0* * * *
* * * * * *0-->0* * *************************** * * * *
* blkfilereader_0 *0-->0* blkformatadapter_0 *0-->0* blkdeinterleave_0 * * blkmixer_0 * * blkinterleave_0 *0-->0* blkfilewriter_0 *
* * * * * *1-->1* * *************************** * * * (stdout) *
* * * * * * * *1-->0* blksoxeffect_lowpass_0 *0-->1* * * *
******************* ********************** ********************* ************** *************************** ******************* *******************
运行例7之前需要先安装 SoX 库和 ffmpeg 。
brew install sox
brew install ffmpeg
运行例7:
x86_64-apple-darwin/bin/larkexample7 | ffplay -i pipe:0 -f s32le -ar 48000 -ac 2 -autoexit
如果没错误的话,播放应该开始了。同时在ffplay的播放画面上,音频频谱正在被实时绘制如下:
在另一个shell里,
lkdb status # 显示百灵鸟状态,找到高通/低通滤波器的块名称分别为'blksoxeffect_highpass_0'/'blksoxeffect_lowpass_0'
lkdb setparam RouteA blksoxeffect_highpass_0 0 800 # 只有高于800Hz的音乐信号输出到左喇叭
音频频谱实时绘制如下:
贴士:在ffplay的音频频谱中,红色代表左声道,绿色代表右声道。如果在某个时刻点某个频率显示为灰色,则表示左右声道在那个时刻的那个频率上能量均等。
lkdb setparam RouteA blksoxeffect_lowpass_0 0 800 # 只有低于800Hz的音乐信号输出到右喇叭
音频频谱实时绘制如下:
ffplay频谱颜色的实时变化验证了集成在 百灵鸟 路由里的sox效果器在实时生效。
这个例子的源代码在此:larkexample7.cpp。
作者的博客文章:<我的工程师爸爸-音频应用DIY系列>通过一系列小故事展示了利用 百灵鸟 来编程解决生活中遇到的音频问题。
lkdb
实时调试当 百灵鸟 在一个进程里运行时,调试工具lkdb
可以跟它通信,从 百灵鸟 获取信息,向 百灵鸟 发送命令。
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 --
除了以上例子中显示的实时打印状态、设定参数功能之外,lkdb
还可以操作音频路由、抓取路由快照、改变日志等级、设定音频数据转储等。
lkdb
跑一个跟例1一样的路由在一个shell里,
x86_64-linux-gnu/bin/larkexample0 # 运行百灵鸟
在另一个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。
lkdb
抓取例3路由的快照当例3运行时,
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以获取更多信息。
在您的进程里调用 百灵鸟 的API来实现您的路由。样例已经列出。参考用户手册以获取更多信息。
Q1: “块”是什么?“端点”是什么?“链接”是什么?“路由”是什么?
A: 一个“块”就是一个软件DSP处理单元。它从一个动态加载库里被创建,并被 百灵鸟 路由所管理。它接受最多32路输入(即输入端点)数据,处理它们,把处理后的数据填入输出端点(最多32路输出)。 通常情况,一个端点代表一个声道音频,然而一个端点也可以运载多声道。例如“interleave”块的一个输出端点就可以运载多声道。 一个“链接”连接一个块的一个输出端点(作为源)至另一个块的一个输入端点(作为汇)。 一个“路由”是一个由多个块连接成的链条(或者图)。
Q2: 在一个机器上,我可以同时运行几个 百灵鸟 实例?在一个 百灵鸟 中,我可以创建几个路由?在一个路由中,我可以创建多少个块?多少个first块?多少个last块?
A: 在一个机器上,只有一个进程被容许创建一个 百灵鸟 实例。也就是说,一个机器运行一个 百灵鸟 实例。lkdb
会跟这个唯一的 百灵鸟 实例通信。在一个 百灵鸟 中,最多可以创建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。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
1. 开源生态
2. 协作、人、软件
3. 评估模型