示范程序:录音
「CIOS音讯核心」当中,不论是语音活动侦测(Voice Activity Detection)、语音辨识(Speech Recognition)、录音、外部环境侦测或是声源位置探测,都是使用这个功能。
如果您需要自己处理全部的流程,要使用 「CIOS音讯核心」录音功能,需要处理五个主要的部分:
- 导流管的继承
- 选取音讯设备
- 设定音讯参数
- 启动音讯驱动介面
- 处理音讯串流程序
virtual bool Record (Conduit * conduit , CaDeviceIndex deviceId , int channelCount , CaSampleFormat sampleFormat , int sampleRate , int frameCount , CaStreamFlags streamFlags = 0 , int sleepInterval = 50 ) ;
参数 |
说明 |
conduit |
导
流管。 |
deviceId |
音讯设备编号。 |
channelCount |
声道数量。 |
sampleFormat |
取样格式。格式请参考《CaSampleFormat》。 |
sampleRate |
取样频率。「CIOS音讯核心」支持的范围为8000-192000,某些 音讯驱动介面可能不支持特定取样频率。 |
frameCount |
每次取样的数量,一般建议为0.1秒或0.2秒。 如果您的取样频率是44100或48000,那麽这个frameCount值一般建议为4410、8820 或是4800、9600。 |
streamFlags |
串流状态,一般为0,一般而言你不需要设定这个值,这是为某些特定音讯驱动
介面功能而给定的参数。 |
sleepInterval |
侦测播放状态的时间间隔,一般建议值为50~250微秒,尽可能不要太长。 |
使用示范
Core core ;MyOwnConduit * conduit = new MyOwnConduit () ;
...
core . Record ( conduit , 1 , 2 , cafInt16 , 44100 , 4410 , 0 , 100 ) ;
...
如果您需要无阻塞的录音方式,请参考《播放音讯档》当中的线绪实作方法。
导流管的继承
完整的继承处理 方式,请参考《导流管的继承处理》、 《LinearConduit》或是《BridgeConduit》。如果您只需要自行处理音讯数据,那麽导流管当中仅需处理两个函式,obtain函式只要留空白或是直接返回Complete即可:
virtual int put (void) = 0 ;
virtual void finish (ConduitDirection direction = NoDirection ,FinishCondition condition = Correct ) = 0 ;
put函式处理StreamIO Input,处理的方式大体如下:
int MyOwnConduit::put (void)
{
if ( ... condition is ready for audio input ... ) {
... copy your audio input into Input.Buffer ...
// example code in BridgeConduit.cpp : Buffer . put ( Input . Buffer , Input . Total ( ) ) ;
return Continue ;
}
if ( ... condition is audio input is completely empty ... ) {
return Complete ;
}
if ( ... condition has something unexpected ... ) {
return Abort ;
}
return Postpone ;
}
整个录音串流被结束时,Stream会主动呼叫finish。
void MyOwnConduit::finish (ConduitDirection direction,FinishCondition condition = Correct)
{
if ( InputDirection != direction ) return ;
... handle your own finishing conditions here ...
}
选取音讯设备
您需要透过取得DeviceInfo来得知音讯设备的细节,详 细的设定请参考《DeviceInfo》。CaPlay当中的示范程序
void ListInputDevices(void)
{
Core core ;
core . Initialize ( ) ;
for (int i=0;i<core.DeviceCount();i++) {
DeviceInfo * dev ;
dev = core.GetDeviceInfo((CaDeviceIndex)i) ;
if ( NULL != dev && dev->maxInputChannels>0) {
printf("%4d : %s\n",i,dev->name) ;
} ;
} ;
core . Terminate ( ) ;
}
一般而言,录音设备必须事先得知并取得编号,如果您没有设定音讯设备的话,系统会自动选用:
virtual CaDeviceIndex DefaultInputDevice (void) ;
这个函式所设定的录音设备。
由于某些作业系统底层音讯驱动程序实作的问题,这个录音设备不见得可以正常运作。由于「CIOS音讯核心」使用这些底层的音讯驱动程序,如果录音设备不能正常运作,在
「CIOS音讯核心」当中寻找解决途径一般是徒劳无功的。
设定音讯参数
设定音讯参数需要设定StreamParameters, 详细使用方法请见《StreamParameters》。一般而言,仅需要在宣告的时候,使用以下宣告即可设定音讯参数:
StreamParameters inputParameters ( deviceId , channelCount , sampleFormat ) ;
取样频率的设定,必须在设备打开的时候设定,请见《启动音讯驱动介面》这一部分。
启动音讯驱动介面
启动及停止音讯驱动介面,需要以下步骤:
Core core ;
...
core . Initialize ( ) ;
//////////////////////////////////////////////////////////////////////////// ... configure input paraments here ... //////////////////////////////////////////////////////////////////////////// rt = core . Open ( &stream , &inputParameters , NULL , sampleRate , frameCount , streamFlags , conduit ) ; if ( ( NoError != rt ) || ( NULL == stream ) ) correct = false ; //////////////////////////////////////////////////////////////////////////// if ( correct ) { rt = core . Start ( stream ) ; if ( NoError != rt ) correct = false ;
////////////////////////////////////////////////////////////////////////// ... handle your stream process here ... ////////////////////////////////////////////////////////////////////////// if ( correct && ( 0 != core.IsStopped ( stream ) ) ) core.Stop ( stream ) ; } core . Close ( stream ) ; core . Terminate ( ) ;
...
处理音讯串流程序
音讯串流启动以后,您需要侦测它是否被停止或是被启动,下面两个Core函式是您所需要的:
virtual CaError IsStopped (Stream * stream) ;
virtual CaError IsActive (Stream * stream) ;
示范:
while ( 1 == core . IsActive ( stream ) ) {
Timer :: Sleep ( sleepInterval ) ;
}
示范程序
/* Record specific device into conduit */
bool Core::Record ( Conduit * conduit ,
CaDeviceIndex deviceId ,
int channelCount ,
CaSampleFormat sampleFormat ,
int sampleRate ,
int frameCount ,
CaStreamFlags streamFlags ,
int sleepInterval )
{
if ( NULL == conduit ) return false ;
////////////////////////////////////////////////////////////////////////////
StreamParameters INSP ( deviceId , channelCount , sampleFormat ) ;
Stream * stream = NULL ;
CaError rt ;
bool correct = true ;
////////////////////////////////////////////////////////////////////////////
Initialize ( ) ;
////////////////////////////////////////////////////////////////////////////
INSP . suggestedLatency = GetDeviceInfo(deviceId)->defaultLowInputLatency ;
////////////////////////////////////////////////////////////////////////////
rt = Open ( &stream ,
&INSP ,
NULL ,
sampleRate ,
frameCount ,
streamFlags ,
conduit ) ;
if ( ( NoError != rt ) || ( NULL == stream ) ) correct = false ;
////////////////////////////////////////////////////////////////////////////
if ( correct ) {
rt = Start ( stream ) ;
if ( NoError != rt ) correct = false ;
////////////////////////////////////////////////////////////////////////////
while ( correct && ( 1 == IsActive ( stream ) ) ) {
Timer :: Sleep ( sleepInterval ) ;
} ;
//////////////////////////////////////////////////////////////////////////
if ( correct && ( 0 != IsStopped ( stream ) ) ) Stop ( stream ) ;
} ;
Close ( stream ) ;
Terminate ( ) ;
return correct ;
}