修复kaldi中的在线语音识别的bug
当我们运行kaldi的online目录下的online-gmm-decode-faster的时候程序会显示PortAudio failed to open the default stream错误信息(kaldi的在线识别倚赖于portaudio库,这个库的作用可以理解为操作系统声音模块相关API的一个的封装。提供一个更加友好的编程接口,而且是跨平台的)。在使用portaudio之前必须要打开一个输出流或者输入流或者同时打开输入输出流。详细的了解请移步portaudio的官方文档。之所以出现这个bug是因为打开默认的输入流失败。我想portaudio是没有问题的因为V19的版本还比较稳定。而且这个问题出现处的代码与kaldi的其他代码没有联系。最有可能就是portaudio安装的不正确或者是编译设置不正确。出于这样的动机我决定重新安装portaudio。下面是详细的步骤。
- portaudio的安装
- kaldi代码的修改
- Makfile的修改
- 常见错误
portaudio的安装
- 安装之前请先安装ALSA这个API,关于portaudio 的安装官方文档里有说就是先configure一下再make就成了。configure后会出现ALSA-------yes,如果是no那就请你先安装ALSA。在Makefile里在CFLAGS里面加上 -fPIC。可以将头文件库文件安装到指定的路径。就这样也可以如果你以后不是经常在这个库上作开发的话。生成的库在lib/.libs/下面。bin里面有一些测试程序。可以运行一个看看有没有问题。paex_record是一个录音的程序运行一下看看有没有错误。将pa_ringbuffer.c 改为pa_ringbuffer.cc 然后再将pa_ringbuffer.h,pa_ringbuffer.cc,pa_memorybarrier.h这三个文件考到src/online下。
kaldi代码的修改
将online下的online-audio-source.cc打开,定位到OnlinePaSource这个函数,我们要修改这个函数,错误就在这里。改成这个样子。
54 using namespace std;
55
56 // Note this will work for 32bit integers but not for 64bit.
57 // For 64bit integers even double wouldn't work
58 // You would ahve to use something like
59 // int64 rb_bits = 0; while (rb_size != 0) {++rb_bits; rb_size >>= 1;}
60 // it would be much faster than two logs of FP numbers (even floats), too,
61 // but I dont have the time to test it.
62 float f = Log(static_cast<float>(rb_size)) / Log(static_cast<float>(2));
63 int32 rb_bits = static_cast<int32>(ceil(f));
64 if (rb_bits > 30) // ok, this limit is somewhat arbitrary
65 throw invalid_argument("PortAudio ring buffer too large!");
66 rb_size_ = 1 << rb_bits;
67 ring_buffer_ = new char[rb_size_];
68 ring_buffer_size_t rbs = PaUtil_InitializeRingBuffer(
69 &pa_ringbuf_, sizeof(SampleType),
70 rb_size_ / sizeof(SampleType), ring_buffer_);
71 if (rbs != 0)
72 throw runtime_error("Unexpected PortAudio ring buffer init error");
73 /*
74 *Begin: the code block is newly added to fix the bug:
75 * */
76 PaStreamParameters inputParameters,outputParameters;
77
78 PaError paerr = Pa_Initialize();
79 if (paerr != paNoError)
80 throw runtime_error("PortAudio initialization error");
81
82 inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
83 if (inputParameters.device == paNoDevice) {
84 throw runtime_error("no device avilable");
85 }
86
87 inputParameters.channelCount = 1; /* stereo input */
88 inputParameters.sampleFormat = paInt16;
89 inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
90 inputParameters.hostApiSpecificStreamInfo = NULL;
91
92
93
94 /*
95 *End: the code block is newly added to fix the bug:
96 * */
97
98 // Monophone, 16-bit input hardcoded
99 KALDI_ASSERT(sizeof(SampleType) == 2 &&
100 "The current OnlinePaSource code assumes 16-bit input");
101
102 paerr=Pa_OpenStream(
103 &pa_stream_,
104 &inputParameters,
105 NULL, /* &outputParameters, */
106 sample_rate_,
107 0,
108 paNoFlag, /* we won't output out of range samples so don't bother clipping them */
109 PaCallback,
110 this );
111 // paerr = Pa_OpenDefaultStream(&pa_stream_, 1, 0, paInt16, sample_rate_, 0,
112 // PaCallback, this);
113 if (paerr != paNoError)
114 throw runtime_error("PortAudio failed to open the default stream steve");
115 }
Makfile的修改
打开online下的Makefile
EXTRA_CXXFLAGS += -Wno-sign-compare -fPIC -I/你portaudio安装的地方/portaudio/include
14 #ifeq ($(UNAME), Linux)
15 #ifneq "$(wildcard ../../tools/portaudio/install/lib/libportaudio.a)" ""
16 # EXTRA_LDLIBS = ../../tools/portaudio/install/lib/libportaudio.a
17 # else
18 EXTRA_LDLIBS =/home/xiao/temp/portaudio/lib/.libs/libportaudio.a
19 # endif
20 # ifneq ($(wildcard ../../tools/portaudio/install/include/pa_linux_alsa.h),)
21 EXTRA_LDLIBS += -lasound -lrt
22 # else
23 # EXTRA_LDLIBS += -lrt
24 # endif
25 # ifneq ($(wildcard ../../tools/portaudio/install/include/pa_jack.h),)
26 # EXTRA_LDLIBS += -ljack
27 # endif
28 #endif
将一些判断语句注释掉,将你的libportaudio.a的静态库添加进来。
在OBJFILES这个变量后面添加pa_ringbuffer.o
onlinebin 下的makefile也作相应的修改
将online下的.so,.o文件删除再make ext
常见错误
一。
/usr/bin/ld: kaldi-online.a(pa_ringbuffer.o): relocation R_X86_64_PC32 against symbol `PaUtil_FlushRingBuffer’ can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: 错误的值
在编译的时候添加 -fPIC
出现最多的就是这个错误,还有一些忘记了。就写到这吧。希望对遇到相同问题的人有所帮助。