PortAudio 是采集和播放音频的开源库,可以用于Linux和windows,在windows下依赖DirectX库(Directshow):用于驱动声卡,所以必须安装DirectX sdk库。
安装DirectX sdk库参考:
http://blog.sina.com.cn/s/blog_b5c2c06f01016cu5.html
portaudioV19的安装集合包 下载地址:
http://download.csdn.net/detail/yanmy2012/4655561
编译方式:
参考http://portaudio.com/docs/v19-doxydocs/compile_windows.html
http://portaudio.com/docs/v19-doxydocs/pages.html 还有其他的编译方式
由于V19 相对于V18改了非常多的地方,所以只编译V19的库,例程只有较新的才能在V19中编译通过,有些会显示找不到类型和函数申明。
编译过程
下面列出的步骤来建立PortAudio成一个dll和lib文件。得到的DLL文件可能包含所有五个目前的win32 PortAudio的API:MME,DirectSound的,WASAPI,WDM / KS和ASIO,根据下面的步骤9中
设置的预处理器定义。
,PortAudio可以被编译使用Visual C + + Express版是由微软免费提供。如果你有一个C + +开发环境,只需下载并安装。这些指令已经成功观察到使用Visual Studio 2010和。
1)PortAudio为Windows需要的文件dsound.h的和dsconf.h。下载并安装DirectX SDK 获得这些文件。如果你安装了DirectX SDK!的DirectSound的库和头文件的自动加到 Visual C + +中。
如果你得到一个错误说缺少dsound.h,或dsconf.h的,你可以添加这些路径。或者,您可以复制dsound.h和dsconf.h,到portaudio \。还应该有一个名为“dsound.lib”C:\Program Files
\Microsoft SDKs\Windows\v6.0A\Lib文件.
2)支持ASIO,下载ASIO SDK在http://www.steinberg.net/en/company/developer.html。 SDK是免费的,但您将需要与斯坦伯格建立一个开发者帐号,所以我提供了下载文件,这个也是从网
上收回来的。复制整个ASIOSDK2的到src文件夹\ hostapi \ ASIO \。重命名它,从ASIOSDK2到ASIOSDK。
3)如果您的Visual Studio 6.0,7.0(VC.NET/2001)或7.1(VC.2003),打开portaudio.dsp并转换如果需要的话。
4)如果你有Visual Studio 2005中的Visual C + + 2008 Express Edition或Visual Studio 2010中,双击portaudio.sln的文件位于在build \ MSVC \。这样做将打开Visual Studio或
Visual C + +。点击“Finish”如果出现一个向导。sln文件中包含四种配置:Win32和Win64的发布和调试的变种。
对于Visual Studio 2005中的Visual C + + 2008 Express版或Visual Studio 2010中
5)打开项目 - > portaudio“属性”,在树视图中选择“配置属性”。
6)选择“配置”中的“配置”组合框。选择“所有平台”
7)设置几个选项:
C / C + + - >优化 - >省略框架指针= YES
C / C + + - >代码生成 - >运行时库/ MT
可选:C / C + + - >代码生成 - >浮点模型=快速
注:对于大多数用户来说,它是没有必要显式地设置结构成员对齐,默认情况下应该正常工作。然而,一些语言要求,例如,4 -字节对齐。如果您有portaudio.h结构的成员没有被正确读取
或写入的问题,可能有必要显式地设置这个值由C / C + + - >代码生成- >结构成员对齐,将其设置为一个适当的值(四是共同的价值)。如果你的编译器是可配置的,你应该确保它被设置
为使用相同的结构成员对齐值所使用的PortAudio构建。
当你设置完这些参数后点击“确定”。
预处理器定义
由于预处理器定义是不同的,每个配置和平台,你需要编辑这些单独为每个配置/平台组合,你想修改的“配置”和“平台”组合框。
8)为了抑制的PortAudio运行调试控制台输出项目 - >属性 - >配置属性 - > C / C + + - >预处理器。在该领域的预处理器定义“,找到PA_ENABLE_DEBUG_OUTPUT并删除它。控制台将不输
出调试信息。
9)你需要明确地定义你想使用的音频API的预处理器定义。对于Windows提供的API定义是:
PA_USE_ASIO [[BR]] PA_USE_DS(DirectSound的)[[BR]] PA_USE_WMME(MME)[[BR]] PA_USE_WASAPI [[BR]] PA_USE_WDMKS [[BR]] PA_USE_SKELETON
对于每个这样的,值为0表示不应列入这个API的支持。值1表示应该包括这个API的支持。
设置预处理器定义时,build是配置每个平台的过程。按照这些说明build你感兴趣的每一个配置/平台组合
10)从“生成”菜单上单击“生成” - >“生成解决方案”。对于32位编译的dll文件创建的这个过程(portaudio_x86.dll)中可以找到的目录生成\ MSVC \ WIN32 \发布。64位编译的DLL文
件被称为portaudio_x64.dll,被发现在目录中生成\ MSVC \ X64 \发布。
11)现在,任何项目需要portaudio可以与portaudio_x86.lib(或_x64),包括您可能要添加/删除一些DLL 相关的头(portaudio.h,和/或pa_asio.h,pa_x86_plain_converters.h),入口
点。现在,这6个项目是不是从portaudio.h:
最后会生成portaudio_x86.lib和portaudio_x86.dll,各两个分别是Debug和Release的,不同配置下使用不同dll和lib
安装完之后就是测试,源代码文件夹test文件夹下有测试代码,由于V19 相对于V18改了非常多的地方,所以只编译V19的库,例程只有较新的才能在V19中编译通过,有些会显示找不到类型和函数申明。
patest_record.c代码,运行过程中会有5秒的嘟嘟声(由的算法产生的float点型级别的声波),这样就证明了已经安装成功
#include
#include
#include "portaudio.h"
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (1024)
#define NUM_SECONDS (5)
#define NUM_CHANNELS (2)
#define DITHER_FLAG (0)
#if 1
#define PA_SAMPLE_TYPE paFloat32
typedef float SAMPLE;
#define SAMPLE_SILENCE (0.0f)
#define PRINTF_S_FORMAT "%.8f"
#elif 1
#define PA_SAMPLE_TYPE paInt16
typedef short SAMPLE;
#define SAMPLE_SILENCE (0)
#define PRINTF_S_FORMAT "%d"
#elif 0
#define PA_SAMPLE_TYPE paInt8
typedef char SAMPLE;
#define SAMPLE_SILENCE (0)
#define PRINTF_S_FORMAT "%d"
#else
#define PA_SAMPLE_TYPE paUInt8
typedef unsigned char SAMPLE;
#define SAMPLE_SILENCE (128)
#define PRINTF_S_FORMAT "%d"
#endif
typedef struct
{
int frameIndex;
int maxFrameIndex;
SAMPLE *recordedSamples;
}
paTestData;
static int recordCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
const SAMPLE *rptr = (const SAMPLE*)inputBuffer;
SAMPLE *wptr = &data->recordedSamples[data->frameIndex * NUM_CHANNELS];
long framesToCalc;
long i;
int finished;
unsigned long framesLeft = data->maxFrameIndex - data->frameIndex;
(void) outputBuffer;
(void) timeInfo;
(void) statusFlags;
(void) userData;
if( framesLeft < framesPerBuffer )
{
framesToCalc = framesLeft;
finished = paComplete;
}
else
{
framesToCalc = framesPerBuffer;
finished = paContinue;
}
if( inputBuffer == NULL )
{
for( i=0; i
{
*wptr++ = SAMPLE_SILENCE;
if( NUM_CHANNELS == 2 ) *wptr++ = SAMPLE_SILENCE;
}
}
else
{
for( i=0; i
{
*wptr++ = *rptr++;
if( NUM_CHANNELS == 2 ) *wptr++ = *rptr++;
}
}
data->frameIndex += framesToCalc;
return finished;
}
static int playCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
SAMPLE *rptr = &data->recordedSamples[data->frameIndex * NUM_CHANNELS];
SAMPLE *wptr = (SAMPLE*)outputBuffer;
unsigned int i;
int finished;
unsigned int framesLeft = data->maxFrameIndex - data->frameIndex;
(void) inputBuffer;
(void) timeInfo;
(void) statusFlags;
(void) userData;
if( framesLeft < framesPerBuffer )
{
for( i=0; i
{
*wptr++ = *rptr++;
if( NUM_CHANNELS == 2 ) *wptr++ = *rptr++;
}
for( ; i
{
*wptr++ = 0;
if( NUM_CHANNELS == 2 ) *wptr++ = 0;
}
data->frameIndex += framesLeft;
finished = paComplete;
}
else
{
for( i=0; i
{
*wptr++ = *rptr++;
if( NUM_CHANNELS == 2 ) *wptr++ = *rptr++;
}
data->frameIndex += framesPerBuffer;
finished = paContinue;
}
return finished;
}
int main(void);
int main(void)
{
PaStreamParameters inputParameters,
outputParameters;
PaStream* stream;
PaError err = paNoError;
paTestData data;
int i;
int totalFrames;
int numSamples;
int numBytes;
SAMPLE max, val;
double average;
printf("patest_record.c\n"); fflush(stdout);
data.maxFrameIndex = totalFrames = NUM_SECONDS * SAMPLE_RATE;
data.frameIndex = 0;
numSamples = totalFrames * NUM_CHANNELS;
numBytes = numSamples * sizeof(SAMPLE);
data.recordedSamples = (SAMPLE *) malloc( numBytes );
if( data.recordedSamples == NULL )
{
printf("Could not allocate record array.\n");
goto done;
}
for( i=0; i
err = Pa_Initialize();
if( err != paNoError ) goto done;
inputParameters.device = Pa_GetDefaultInputDevice();
inputParameters.channelCount = 2;
inputParameters.sampleFormat = PA_SAMPLE_TYPE;
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream(
&stream,
&inputParameters,
NULL,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff,
recordCallback,
&data );
if( err != paNoError ) goto done;
err = Pa_StartStream( stream );
if( err != paNoError ) goto done;
printf("Now recording!!\n"); fflush(stdout);
while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
{
Pa_Sleep(1000);
printf("index = %d\n", data.frameIndex ); fflush(stdout);
}
if( err < 0 ) goto done;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto done;
max = 0;
average = 0.0;
for( i=0; i
{
val = data.recordedSamples[i];
if( val < 0 ) val = -val;
if( val > max )
{
max = val;
}
average += val;
}
average = average / (double)numSamples;
printf("sample max amplitude = "PRINTF_S_FORMAT"\n", max );
printf("sample average = %lf\n", average );
#if 0
{
FILE *fid;
fid = fopen("recorded.raw", "wb");
if( fid == NULL )
{
printf("Could not open file.");
}
else
{
fwrite( data.recordedSamples, NUM_CHANNELS * sizeof(SAMPLE), totalFrames, fid );
fclose( fid );
printf("Wrote data to 'recorded.raw'\n");
}
}
#endif
data.frameIndex = 0;
outputParameters.device = Pa_GetDefaultOutputDevice();
outputParameters.channelCount = 2;
outputParameters.sampleFormat = PA_SAMPLE_TYPE;
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
printf("Begin playback.\n"); fflush(stdout);
err = Pa_OpenStream(
&stream,
NULL,
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff,
playCallback,
&data );
if( err != paNoError ) goto done;
if( stream )
{
err = Pa_StartStream( stream );
if( err != paNoError ) goto done;
printf("Waiting for playback to finish.\n"); fflush(stdout);
while( ( err = Pa_IsStreamActive( stream ) ) == 1 ) Pa_Sleep(100);
if( err < 0 ) goto done;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto done;
printf("Done.\n"); fflush(stdout);
}
done:
Pa_Terminate();
if( data.recordedSamples )
free( data.recordedSamples );
if( err != paNoError )
{
fprintf( stderr, "An error occured while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
err = 1;
}
return err;
}