智能机器人(11):声音操作
声音操作主要涉及audio-common这个stack,包括:
audio_capture,记录从microphone记录音频并发布音频消息到/audio这个topic;audio_play,监听/audio并输出音频到speaker;audio_common_msgs,消息定义;sound_play,播放音频文件或者合成语音;最常用到audio_capture和audio_play这两个package。
1、硬件
1.1、验证声卡
$ cat /proc/asound/cards
0 [AudioPCI ]: ENS1371 – Ensoniq AudioPCI
———————Ensoniq AudioPCI ENS1371 at 0x2080, irq 16
如果必要设置下默认的声卡序号:
$ asoundconf set-default-card 0
2、驱动
2.1、安装相应版本驱动
$ sudo apt-get install ros-hydro-audio-common
2.2、测试
验证gstreamer在ALSA下工作正常,可以采集音频、播放音频:
$ gst-launch-0.10 alsasrc ! audioconvert ! audioresample ! alsasink
3、测试
3.1、audio_capture:采集音频
$ roslaunch audio_capture capture.launch
这产生/audio这个topic,查看下数据:
$ rostopic hz /audio
如果要保存文件,是:
$ roslaunch audio_capture capture_to_file.launch
这个是mp3格式的,要用sox播放需要先转换成wav格式:
$ lame –decode out1.mp3 outwav1.wav
$ play outwav1.wav
如果要直接播放,需要下载解码器:
$ sudo apt-get install libsox-fmt-mp3
>>>这个通常是run在远程机器上。
3.2、audio_play:播放音频
$ roslaunch audio_play play.launch
这样是个应声虫,microphone接收到啥,speaker就播放啥。
>>>这个通常是run在本地机器上。
3.3、sound_play:播放声音
$ rosrun sound_play soundplay_node.py
注意这个node是必需要首先加载的,多出了/robotsound这个topic。
>>>这个通常是run在远程机器上。
3.4、然后直接播放需要合成的音频:
$ rosrun sound_play say.py “hello world”
或者播放音频文件:
$ rosrun sound_play play.py /opt/ros/hydro/share/sound_play/sounds/say-beep.wav
要注意这个是全路径。
如果需要即时停止所有音频:
$ rosrun sound_play shutup.py
>>>这个通常是run在本地机器上。
4、源代码方式
这个部分是不必要的。如果需要,先卸载前述驱动包
$ sudo apt-get removeros-hydro-audio-common
安装最新代码
$ cd ~/catkin_ws/src
$ git clone https://github.com/ros-drivers/audio_common.git
$ rosdep install audio_common
#All required rosdeps installed successfully
$ cd ~/catkin_ws
$ catkin_make
如果出错:
$ sudo apt-get install libgstreamer0.10-dev libgstreamer-plugins-base0.10-dev
上面这个0.10是ubuntu12.04的默认版本,如果提示需要1.0:
sudo add-apt-repository ppa:gstreamer-developers/ppa
sudo apt-get update
sudo apt-get install gstreamer1.0*
此路不通ppa源不可用:
sudo apt-get install ubuntu-restricted-extras
这个市浩大的一堆,慢慢下。
catkin_make后要更新
$ source ~/catkin_ws/devel/setup.bash
5、建立声音接口
建立一个node,利用sound_play作为wrapper来控制声音。注意用node给robotsound这个topic发消息,而不是建立消息。
这里把这个node命名为yak_node,用来处理SoundClient()和sound_play。SoundClient要注意避免超载报错,其参数可以是wav的文件名或者要合成语音的文本。
需要把所有音频资料防止同一个路径下,而且注意只支持wav和ogg格式的音频。
用户的音频采用yak形式publishe到yak这个topic,而yak_node这个node同样是subscribe到yak这个topic。
#!/usr/bin/env python
import roslib; roslib.load_manifest(‘sound_yak’)
import rospy, os, sys
from sound_play.msg import SoundRequest
from sound_play.libsoundplay import SoundClient
from sound_yak.msg import yak_cmd
# directory with sound assets – change as needed
soundAssets = ‘/home/shiloh/devel/audio_assets/’
# duration of yak throttle
throttle = 3 # seconds
def sound_translator(data):
#segmentation fault if too many sound commands given in short period
print data
global allow_yak
if rospy.Time.now() <= allow_yak: # Throttles yak to avoid
print(“Sound throttled”) # SoundClient segfault
return
# when to reallow yak
allow_yak = rospy.Time.now() + rospy.Duration.from_sec(throttle)
#process yak commands requires full path names for sound assets
if data.cmd == “wav”:
soundhandle.playWave(soundAssets + data.param)
if data.cmd == “say”:
soundhandle.say(data.param)
def yak_init():
rospy.init_node(‘yak_node’, anonymous = True)
global allow_yak
allow_yak = rospy.Time.now()
rospy.Subscriber(‘yak’, yak_cmd, sound_translator)
rospy.spin()
if __name__ == ‘__main__’:
soundhandle = SoundClient()
rospy.sleep(1)
yak_init()
6、launch脚本
示例launch文件:
<launch>
<node name=”soundplay_node” pkg=”sound_play” type=”soundplay_node.py”/>
</launch>
7、sox瑞士军刀
http://ymkimit.blogspot.com/2014/07/recording-sound-detecting-silence.html#!/2014/07/recording-sound-detecting-silence.html
http://sox.sourceforge.net/sox.html
http://linux.die.net/man/1/rec
http://bbs.chinaunix.net/thread-2005749-1-1.html
http://blog.csdn.net/lijin6249/article/details/51955206
set AUDIODRIVER=oss
rec -t wav -r 16000 -b 16 -c 1 aa.wav silence 1 0.3 1% 1 0.3 1%
自适应记录语音
rec rec.wav silence 1 0.5 1% 1 1.0 3%
rec -t wav -r 16000 -b 16 -c 1 rec.wav silence 1 0.1 1% 1 2.0 3% is OKAY
sox -d -e u-law –endian little -b 8 -c 1 -r 8000 -t ul bb.wav silence 1 0.3 1% 1 0.3 1%
-t ossdsp 输入音频源
-w 采样位深w16位b8位
-r 44100 采样频率
-c 2 声道2
/dev/dsp 输入
-t raw 生数据
>>>效果器
效果器主要是声音滤波、频率转换、和声、混响、移相、音量等功能,可以只用一个也可以联合使用。
重低音:
play file.wav bass -20
play file.wav bass +20
bass是给输出结果加上低音效果,-20是低限值,+20是高限值。值愈低,声音愈低,反之则值愈高,声音愈浑厚。
混频器:
play 1234567890.wav mixer 0.3,0.5,0.8,0.6
mixer效果器,它通过混合或者减少音轨从而减少音轨数,或者通过复制音轨而增加音轨数。0.3是从输入声道的左边到输出声道左边的音量值,0.5是从输入声道的左边到输
出声道右边的音量值,0.8是从输入声道的右边到输出声道左边的音量值,0.6是从输入声道的右边到输出声道右边的音量值。不过对于单声道无效。
节拍器:
play 1234567890.wav tempo -q 0.8 82 20 16
0.8设置新节拍相对于老节拍的比率,82设置所选算法要划分音频的片段大小,单位毫秒,20是音频长度,依靠它来搜索以寻找重叠点,16是重叠长度。
颤动器:
play 1234567890.wav tremolo 3.5 60
3.5是颤音频率,单位是赫兹Hz,60是深度百分比,具体来说就是”颤”到多长或深。
回响器:
play 1234567890.wav echo 0.8 0.88 60 0.4
听起来就象用两个乐器演奏同一个样本一样,0.8是输入音量,0.88是输出音量,60是延迟单位是毫秒,0.4是相对于输入音量的衰减值。
如果延迟时间变长,听起来更象在山顶上的露天演唱会。假如延迟很短,听起来象(金属的)机器人的表演。回响可以多个,echo 0.8 0.9 1000 0.3 1800 0.25;这种回响分对称回声和不对称回声。
和声器:
play 1234567890.wav chorus 0.7 0.9 55 0.4 0.25 2 -t
55是延迟,0.4是衰减,0.25是调制速度,单位Hz,2是调制深度,典型的延迟在40毫秒(40ms)到60毫秒(60ms),调制速度最好在0.25Hz附近,调制深度2毫秒左右(2ms)。-t使用三
角函数调制,上面的延迟时间有点短,输出有点过载。
play 1234567890.wav chorus 0.6 0.9 50 0.4 0.25 2 -t 60 0.32 0.4 1.3 -s
-s,表示正弦波调制。
play 1234567890.wav chorus 0.5 0.9 50 0.4 0.25 2 -t 60 0.32 0.4 2.3 -t 40 0.3 0.3 1.3 -s
这采用了三部和声
缩展器:
让它在低音部分不要那样小声,而在高音部分不要那样刺耳,允许信号动态地压缩或扩展。
play 1234567890.wav compand 0.3,1 6:-70,-60,-20 -5 -90 0.2 0.3是起音时间(指的是生因忽然变大的时间),1是衰减时间,起 音时间应该比衰减时间短,因为我们的耳朵对忽然变大的声音比对忽然柔和哦的声音更敏感。6:-70是缩展器转换函数表,单位是dB,它跟音频信号的最大幅值有关联,它的意思是很柔软的声音(-70dB以下)仍然保留不变,这将防止缩展器在在乐章转换时从静默忽然飙升音量。但是在-60dB到0dB(最大音量)的声音将被提高,原始音频60dB的动态范围将被压缩成20dB,这样频宽足以享受音乐同时有可以不受路上噪音的影响。这就是-60和-20的意思。-5是额外增益,用来避免削波,-90表示初始化音量从几乎静默开始,这样对于削波现象将有很好的抑制作用。0.2秒是的延迟使得缩展器对于声音的忽然升高有很好的抑制作用。
取得戏剧性效果:
1、将回放速率改为原先的2倍,这个是参数越大速度越慢:
play 1234567890.wav stretch 0.5
2、改变回放调子和节拍,这个语速越快越逗:
play 1234567890.wav speed 2
3、升高样本1个短调(100音分),这个声调正的越高越儿童脆否则越老人:
play 1234567890.wav pitch 100
play 1234567890.wav pitch 300 speed 2 stretch 0.5
余响器:
play 1234567890.wav reverb 1 100 100
1是输出音量,600是余响时间,180是延迟时间,延迟时间最好是余响时间的1/4到1/2。只考虑了一面墙的情形,如果还要考虑在多加一面墙,为 reverb 1 600 180 200,依次累加。
pitch 300 speed 2 stretch 2 echo 1 1 100 0.2
pitch 300 speed 1.5 stretch 1 echo 1 1 100 0.2
./web2.sh –voice_name=xiaorong “pitch 100 speed 1 stretch 1 echo 1 1 20 0.4”