【目的】Windows平台 PCM裸流录制
【方案】使用RtAudio进行音频采集录制。RtAudio是一个跨平台(Linux,MacOS,Windows)的实时音频输入/输出的通用API,大大简化了开发人员与计算机音频硬件交互的过程。更多详细功能可以参考RtAudio的主页介绍,地址附在参考资料
【实践】
1.RtAudio编译
(1)源码下载,可以直接clone Master分支或者在RtAudio主页下载提供好的版本压缩包
(2)使用cmake进行编译
我使用的cmake版本是cmake-3.19.2-win32-x86,使用cmake-gui工具,设置源码路径以及构建路径,如下:
然后执行Configure进行配置,我这里配置的Win32版本
最后generate生成即可
(3)使用VS打开工程生成你想要Debug或者Release版本的库
2.打开工程找到record项目
(1)生成可执行文件,将动态库放到同级目录下
(2)看代码,做了详细备注
int main( int argc, char *argv[] )
{
unsigned int channels, fs, bufferFrames, device = 0, offset = 0;
double time = 2.0;//默认录制2秒
FILE *fd;
/*
argc[1]:声道数
argc[2]:采样频率
argc[3]:录制时长
argc[4]:设备ID(0-(getDeviceCount()-1))
argc[5]:设备的第一个通道索引,默认为0
*/
// minimal command-line checking
if ( argc < 3 || argc > 6 ) usage();
RtAudio adc;//RtAudio对象声明
if ( adc.getDeviceCount() < 1 ) {//设备数量检测
std::cout << "\nNo audio devices found!\n";
exit( 1 );
}
channels = (unsigned int) atoi( argv[1] );
fs = (unsigned int) atoi( argv[2] );
if ( argc > 3 )
time = (double) atof( argv[3] );
if ( argc > 4 )
device = (unsigned int) atoi( argv[4] );
if ( argc > 5 )
offset = (unsigned int) atoi( argv[5] );
// Let RtAudio print messages to stderr.
adc.showWarnings( true );
// Set our stream parameters for input only.
bufferFrames = 512;
RtAudio::StreamParameters iParams;//音频流声明以及初始化
if ( device == 0 )
iParams.deviceId = adc.getDefaultInputDevice();
else
iParams.deviceId = device;
iParams.nChannels = channels;
iParams.firstChannel = offset;
InputData data;//音频输入存储
data.buffer = 0;
try {
adc.openStream( NULL, &iParams, FORMAT, fs, &bufferFrames, &input, (void *)&data );//RtAudio用来使用指定参数打开流的方法
}
catch ( RtAudioError& e ) {
std::cout << '\n' << e.getMessage() << '\n' << std::endl;
goto cleanup;
}
data.bufferBytes = bufferFrames * channels * sizeof( MY_TYPE );
data.totalFrames = (unsigned long) (fs * time);
data.frameCounter = 0;
data.channels = channels;
unsigned long totalBytes;
totalBytes = data.totalFrames * channels * sizeof( MY_TYPE );
// Allocate the entire data buffer before starting stream.
data.buffer = (MY_TYPE*) malloc( totalBytes );
if ( data.buffer == 0 ) {
std::cout << "Memory allocation error ... quitting!\n";
goto cleanup;
}
try {
adc.startStream();//启动流
}
catch ( RtAudioError& e ) {
std::cout << '\n' << e.getMessage() << '\n' << std::endl;
goto cleanup;
}
std::cout << "\nRecording for " << time << " seconds ... writing file 'record.raw' (buffer frames = " << bufferFrames << ")." << std::endl;
while ( adc.isStreamRunning() ) {
SLEEP( 100 ); // wake every 100 ms to check if we're done
}
// Now write the entire data to the file.
fd = fopen( "record.raw", "wb" );
fwrite( data.buffer, sizeof( MY_TYPE ), data.totalFrames * channels, fd );
fclose( fd );
cleanup:
if ( adc.isStreamOpen() ) adc.closeStream();//关闭流
if ( data.buffer ) free( data.buffer );//垃圾回收
return 0;
}
(3)设置采样频率,声道数以及想要的采样时长就可以拿到裸流数据
以44.1K采样,双声道,16位为例,10秒钟的裸流码率为172.3K/s
【总结】RtAudio在Windows上可以很好的实现音频采集与录制,实际业务中往往需要对裸流数据进行编码来适应不同的网络状况,后续就是使用不同的编码器对裸流数据进行编码比较。
【参考资料】
【1】RtAudio主页:http://www.music.mcgill.ca/~gary/rtaudio/