PortAudio详解(2015年12月1日更新)

PortAudio详解

整理者:赤子玄心

QQ:280604597

Email:280604597@qq.com

大家有什么不明白的地方,或者想要详细了解的地方可以联系我,我会认真回复的

1   简介

PortAudio是一个免费、跨平台、开源的音频I/O库。看到I/O可能就想到了文件,但是PortAudio操作的I/O不是文件,而是音频设备。它能够简化C/C++的音频程序的设计实现,能够运行在Windows、Macintosh OS X和UNIX之上(Linux的各种版本也不在话下)。使用PortAudio可以在不同的平台上迁移应用程序,比如你可以把你基于PortAudio的应用程序发展一个Android版本啊。

PortAudio的API非常简单,通过一个一个简单的回调函数或者阻塞的读/写接口来录制或者播放声音。PortAudio自带了很多示例程序,比如播放正弦波形的音频信号,处理音频输入,录制回放音频,列举音频设备。

 

PortAudio使用的是自己定义的License,关键点在于:

1、允许在你的项目或程序中免费使用PortAudio,商业软件也是免费使用的。

2、可以不开源你的源码。

3、禁止删除PortAudio中的版权信息。

4、如果你修复了PortAudio中的bug,请通知社区。

5、如果你的程序因为PortAudio而崩溃,我们不负任何责任。

 

PortAudio的最新版本是V19。本文讨论的就是该版本。

2   PortAudio V19库编译

2.1 准备

PortAudio官网:

http://www.portaudio.com/

 

PortAudio库API英文详解:

http://www.portaudio.com/docs/v19-doxydocs/portaudio_8h.html#a443ad16338191af364e3be988014cbbe

 

DirectX SDK下载:

http://www.microsoft.com/en-us/download/details.aspx?id=6812

 

PortAudio下载:

http://portaudio.com/docs/v19-doxydocs/compile_windows.html

 

ASIO SDK下载:

http://download.csdn.net/detail/linyiqinggood/6778175

 

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

2.2 编译方式

Windows编译参考http://portaudio.com/docs/v19-doxydocs/compile_windows.html

其他的编译方式http://portaudio.com/docs/v19-doxydocs/pages.html

 

由于V19 相对于V18改了非常多的地方,所以只编译V19的库,例程只有较新的才能在V19中编译通过,有些会显示找不到类型和函数申明。

2.3 编译过程

下面列出的步骤来建立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

PA_USE_DS(DirectSound的)

PA_USE_WMME(MME)

PA_USE_WASAPI

PA_USE_WDMKS

PA_USE_SKELETON

对于每个这样的,值为0表示不应列入这个API的支持。值1表示应该包括这个API的支持。

设置预处理器定义时,build是配置每个平台的过程。按照这些说明build你感兴趣的每一个配置/平台组合。

以上宏在“项目—〉属性—〉配置属性—〉C/C++—〉预处理器—〉预处理器定义”中定义的。

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 "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;

}

 

 

3   函数库

3.1 函数模板(未完成)

函数名称

xxx

头文件

#include "PortAudio.h"

库文件

#pragma comment(lib, "PortAudio_x86.lib或PortAudio_x64.lib")

函数功能

函数主要功能说明。

函数声明

类型 函数名 (

类型 参数1,

类型 参数2,

……

);

函数参数

参数1,[输入|输出|输入&输出]:

参数说明。

参数2,[输入|输出|输入&输出]:

参数说明。

……

返回值

返回值1:返回值说明。

返回值2:返回值说明。

……

错误码

EXXXX:错误码说明。

EXXXX:错误码说明。

……

线程安全

是 或 否 或 未知,表示此函数多线程调用是否会产生影响

原子操作

是 或 否 或 未知,表示此函数是否是单一操作,不是多个步骤的组合

其他说明

……

……

 

 

3.2 Pa_Initialize(未完成)

函数名称

Pa_Initialize

头文件

#include "PortAudio.h"

库文件

#pragma comment(lib, "PortAudio_x86.lib或PortAudio_x64.lib")

函数功能

初始化PortAudio库。

函数声明

PaError Pa_Initialize (

void

);

函数参数

返回值

paNoError枚举(0x0000):成功。

其他:失败,返回值就是错误码,调用Pa_GetErrorText()函数查看错误码对应的错误信息。

错误码

EXXXX:错误码说明。

EXXXX:错误码说明。

……

线程安全

是 或 否 或 未知,表示此函数多线程调用是否会产生影响

原子操作

是 或 否 或 未知,表示此函数是否是单一操作,不是多个步骤的组合

其他说明

使用PortAudio函数库之前必须调用本函数初始化。

本函数初始化的内部数据结构,并准备底层主机的API使用。除了Pa_GetVersion(),Pa_GetVersionText(),和Pa_GetErrorText()时,该功能必须使用任何其他PortAudio API函数之前调用。

如果本函数被调用多次,每一次成功的调用必须有相应调用Pa_Terminate()函数相匹配。调用Pa_Initialize的对()/ Pa_Terminate()可能会重叠,并且不要求完全嵌套。

如果本函数返回失败,不需要调用Pa_Terminate()函数来销毁。

 

 

3.3 Pa_Terminate(未完成)

函数名称

Pa_Terminate

头文件

#include "PortAudio.h"

库文件

#pragma comment(lib, "PortAudio_x86.lib或PortAudio_x64.lib")

函数功能

销毁已经初始化的PortAudio库。

函数声明

PaError Pa_Terminate (

void

);

函数参数

返回值

paNoError枚举(0x0000):成功。

其他:失败,返回值就是错误码,调用Pa_GetErrorText()函数查看错误码对应的错误信息。

错误码

paNotInitialized枚举(-10000):没有初始化PortAudio库。

EXXXX:错误码说明。

……

线程安全

是 或 否 或 未知,表示此函数多线程调用是否会产生影响

原子操作

是 或 否 或 未知,表示此函数是否是单一操作,不是多个步骤的组合

其他说明

本函数会销毁由PortAudio库分配的所有资源。

本函数必须在程序退出之前被调用,否则可能会导致严重的资源泄漏,如录音设备或播放设备不可用,除非重新启动操作系统。

 

 

3.4 Pa_GetErrorText(未完成)

函数名称

Pa_GetErrorText

头文件

#include "PortAudio.h"

库文件

#pragma comment(lib, "PortAudio_x86.lib或PortAudio_x64.lib")

函数功能

根据指定的错误码获取对应的错误信息字符串。

函数声明

const char * Pa_GetErrorText (

PaError errorCode

);

函数参数

errorCode,[输入]:

存放错误码的值。

返回值

错误信息字符串的内存指针。

错误码

线程安全

是 或 否 或 未知,表示此函数多线程调用是否会产生影响

原子操作

是 或 否 或 未知,表示此函数是否是单一操作,不是多个步骤的组合

其他说明

如果指定的错误码是不存在的,返回的错误信息字符串为"Invalid error code (value greater than zero)"。

 

 

3.5 Pa_GetVersion(未完成)

函数名称

Pa_GetVersion

头文件

#include "PortAudio.h"

库文件

#pragma comment(lib, "PortAudio_x86.lib或PortAudio_x64.lib")

函数功能

以整数方式获取当前程序正在使用的PortAudio库的版本号,例如:1900。

函数声明

int Pa_GetVersion (

void

);

函数参数

返回值

PortAudio库的版本号的整数。

错误码

线程安全

是 或 否 或 未知,表示此函数多线程调用是否会产生影响

原子操作

是 或 否 或 未知,表示此函数是否是单一操作,不是多个步骤的组合

其他说明

 

 

 

3.6 Pa_GetVersionText(未完成)

函数名称

Pa_GetVersionText

头文件

#include "PortAudio.h"

库文件

#pragma comment(lib, "PortAudio_x86.lib或PortAudio_x64.lib")

函数功能

以信息字符串方式获取当前程序正在使用的PortAudio库的版本号,例如:"PortAudio V19-devel 13 October 2002"。

函数声明

int Pa_GetVersionText (

void

);

函数参数

返回值

PortAudio库的版本号的信息字符串的内存指针。

错误码

线程安全

是 或 否 或 未知,表示此函数多线程调用是否会产生影响

原子操作

是 或 否 或 未知,表示此函数是否是单一操作,不是多个步骤的组合

其他说明

获取到信息字符串所占用的内存由Pa_Terminate()函数自动释放,不需要手动释放,否则会出现未知错误。

 

 

3.7 Pa_GetDeviceCount(未完成)

函数名称

Pa_GetDeviceCount

头文件

#include "PortAudio.h"

库文件

#pragma comment(lib, "PortAudio_x86.lib或PortAudio_x64.lib")

函数功能

获取可用的音频设备的数量。

函数声明

PaDeviceIndex Pa_GetDeviceCount (

void

);

函数参数

返回值

大于等于0:成功,可用的音频设备的数量。

小于0:失败,返回值就是错误码,调用Pa_GetErrorText()函数查看错误码对应的错误信息。

错误码

EXXXX:错误码说明。

EXXXX:错误码说明。

……

线程安全

是 或 否 或 未知,表示此函数多线程调用是否会产生影响

原子操作

是 或 否 或 未知,表示此函数是否是单一操作,不是多个步骤的组合

其他说明

 

 

 

3.8 Pa_GetDeviceInfo(未完成)

函数名称

Pa_GetDeviceInfo

头文件

#include "PortAudio.h"

库文件

#pragma comment(lib, "PortAudio_x86.lib或PortAudio_x64.lib")

函数功能

根据音频设备的索引号获取音频设备的相关信息。

函数声明

const PaDeviceInfo * Pa_GetDeviceInfo (

PaDeviceIndex device

);

函数参数

device,[输入]:

存放音频设备的索引号。

音频设备的索引号范围从0开始,到Pa_GetDeviceCount()函数返回的音频设备的数量减一。

返回值

NULL:失败,音频设备的索引号超出范围。

其他:音频设备信息结构体的内存指针。

错误码

EXXXX:错误码说明。

EXXXX:错误码说明。

……

线程安全

是 或 否 或 未知,表示此函数多线程调用是否会产生影响

原子操作

是 或 否 或 未知,表示此函数是否是单一操作,不是多个步骤的组合

其他说明

获取到音频设备信息结构体所占用的内存由Pa_Terminate()函数自动释放,不需要手动释放,否则会出现未知错误。

如果不知道该用哪个音频输入设备,可以调用Pa_GetDefaultInputDevice()函数获取默认的音频输入设备。

如果不知道该用哪个音频输出设备,可以调用Pa_GetDefaultOutputDevice()函数获取默认的音频输出设备。

 

 

3.9 Pa_GetDefaultInputDevice(未完成)

函数名称

Pa_GetDefaultInputDevice

头文件

#include "PortAudio.h"

库文件

#pragma comment(lib, "PortAudio_x86.lib或PortAudio_x64.lib")

函数功能

获取操作系统中默认的音频输入设备。

函数声明

PaDeviceIndex Pa_GetDefaultInputDevice (

void

);

函数参数

返回值

paNoDevice宏(-1):没有音频输入设备。

大于等于0:音频输入设备的索引号。

错误码

线程安全

是 或 否 或 未知,表示此函数多线程调用是否会产生影响

原子操作

是 或 否 或 未知,表示此函数是否是单一操作,不是多个步骤的组合

其他说明

 

 

 

3.10  Pa_GetDefaultOutputDevice(未完成)

函数名称

Pa_GetDefaultOutputDevice

头文件

#include "PortAudio.h"

库文件

#pragma comment(lib, "PortAudio_x86.lib或PortAudio_x64.lib")

函数功能

获取操作系统中默认的音频输入设备。

函数声明

PaDeviceIndex Pa_GetDefaultOutputDevice (

void

);

函数参数

返回值

paNoDevice宏(-1):没有音频输出设备。

大于等于0:音频输出设备的索引号。

错误码

线程安全

是 或 否 或 未知,表示此函数多线程调用是否会产生影响

原子操作

是 或 否 或 未知,表示此函数是否是单一操作,不是多个步骤的组合

其他说明

 

 

 

3.11  Pa_OpenStream(未完成)

函数名称

Pa_OpenStream

头文件

#include "PortAudio.h"

库文件

#pragma comment(lib, "PortAudio_x86.lib或PortAudio_x64.lib")

函数功能

使用指定的音频输入输出设备打开一个音频流句柄,用于 音频输入 或 音频输出 或 音频输入输出。

函数声明

PaError Pa_OpenStream (

PaStream ** stream,

const PaStreamParameters * inputParameters,

const PaStreamParameters * outputParameters,

double sampleRate,

unsigned long framesPerBuffer,

PaStreamFlags streamFlags,

PaStreamCallback * streamCallback,

void * userData

);

函数参数

stream,[输出]:

存放用于存放音频流句柄的指针变量的内存指针。

存放音频流句柄的变量类型为PaStream *。

inputParameters,[输入]:

outputParameters,[输入|输出|输入&输出]:

参数说明。

sampleRate,[输入|输出|输入&输出]:

参数说明。

framesPerBuffer,[输入|输出|输入&输出]:

参数说明。

streamFlags,[输入|输出|输入&输出]:

参数说明。

streamCallback,[输入|输出|输入&输出]:

参数说明。

userData,[输入|输出|输入&输出]:

参数说明。

返回值

paNoError枚举(0x0000):成功。

其他:失败,返回值就是错误码,调用Pa_GetErrorText()函数查看错误码对应的错误信息。

错误码

EXXXX:错误码说明。

EXXXX:错误码说明。

……

线程安全

是 或 否 或 未知,表示此函数多线程调用是否会产生影响

原子操作

是 或 否 或 未知,表示此函数是否是单一操作,不是多个步骤的组合

其他说明

……

……

 

 

3.12  Pa_OpenDefaultStream(未完成)

函数名称

Pa_OpenDefaultStream

头文件

#include "PortAudio.h"

库文件

#pragma comment(lib, "PortAudio_x86.lib或PortAudio_x64.lib")

函数功能

使用操作系统默认的音频输入输出设备打开一个音频流句柄,用于 音频输入 或 音频输出 或 音频输入输出。

函数声明

PaError Pa_OpenDefaultStream (

PaStream ** stream,

int numInputChannels,

int numOutputChannels,

PaSampleFormat sampleFormat,

double sampleRate,

unsigned long framesPerBuffer,

PaStreamCallback * streamCallback,

void * userData

);

函数参数

stream,[输入]:

存放用于存放音频流句柄的指针变量的内存指针。

存放音频流句柄的变量类型为PaStream *。

numInputChannels,[输入]:

存放音频流的音频输入声道个数,为0表示不需要音频输入,为1表示单声道,为2表示双声道立体声。

numOutputChannels,[输入]:

存放音频流的音频输出声道个数,为0表示不需要音频输出,为1表示单声道,为2表示双声道立体声。

sampleFormat,[输入]:

存放音频流的采样位数和采样格式。可以为(选一至一个):

paFloat32宏(0x0001):用一个32位有符号浮点型存储每个音频数据块。音频数据范围最高为1.0,最低为-1.0。

paInt32宏(0x0002):用一个32位有符号整型存储每个音频数据块。音频数据范围最高为2147483647,最低为-2147483648。

paInt24宏(0x0004):用一个24位有符号整型存储每个音频数据块。音频数据范围最高为8388607,最低为-8388608。

paInt16宏(0x0008):用一个16位有符号整型存储每个音频数据块。音频数据范围最高为32767,最低为-32768。

paInt8宏(0x0010):用一个8位有符号整型存储每个音频数据块。音频数据范围最高为127,最低为-128。

paUInt8宏(0x0020):用一个8位无符号整型存储每个音频数据块。音频数据范围最高为255,最低为0。

paCustomFormat宏(0x10000):

paNonInterleaved宏(0x80000000):

sampleRate,[输入]:

存放音频的采样频率,单位赫兹。一般可以为:8000、11025、22050、44100。

framesPerBuffer,[输入]:

存放当每次处理完音频数据时,在音频数据输入输出缓存中存放的每个声道的音频数据块个数。

音频数据输入输出缓存在音频数据处理回调函数中使用,如果不采用回调函数方式,本参数无意义。

streamCallback,[输入]:

存放音频数据处理回调函数的内存指针,表示采用回调函数方式进行音频输入数据采样,或播放音频数据。

音频数据处理回调函数是程序自己定义的,且会一直在另外一个独立的新线程中自动被调用执行。参考PaStreamCallback

如果不采用回调函数方式,本参数就填NULL。

 

回调函数调用条件:

如果要打开的音频流只需要音频输入,那么每次当音频输入数据采样完毕,就会自动调用一次音频数据处理回调函数。

如果要打开的音频流只需要音频输出,那么每次当音频输出数据播放完毕,就会自动调用一次音频数据处理回调函数。

如果要打开的音频流需要音频输入和音频输出,那么每次当音频输入数据采样完毕,就会自动调用一次音频数据处理回调函数。因为采样速度和播放速度是一样的,所以就只调用一次音频数据处理回调函数。

userData,[输入]:

存放音频数据处理回调函数被调用时,传递给该函数的一个程序自定义参数。

返回值

paNoError枚举(0x0000):成功。

其他:失败,返回值就是错误码,调用Pa_GetErrorText()函数查看错误码对应的错误信息。

错误码

EXXXX:错误码说明。

EXXXX:错误码说明。

……

线程安全

是 或 否 或 未知,表示此函数多线程调用是否会产生影响

原子操作

是 或 否 或 未知,表示此函数是否是单一操作,不是多个步骤的组合

其他说明

打开音频流句柄后,需要调用Pa_StartStream()函数,才能让音频流句柄开始处理音频数据。

如果不采用回调函数方式,可以调用Pa_ReadStream()函数或Pa_WriteStream()函数处理音频数据。

 

 

3.13  Pa_CloseStream(未完成)

函数名称

Pa_CloseStream

头文件

#include "PortAudio.h"

库文件

#pragma comment(lib, "PortAudio_x86.lib或PortAudio_x64.lib")

函数功能

关闭一个已经打开的音频流句柄。

函数声明

PaError Pa_CloseStream (

PaStream * stream

);

函数参数

stream,[输入]:

存放音频流句柄。

返回值

paNoError枚举(0x0000):成功。

其他:失败,返回值就是错误码,调用Pa_GetErrorText()函数查看错误码对应的错误信息。

错误码

EXXXX:错误码说明。

EXXXX:错误码说明。

……

线程安全

是 或 否 或 未知,表示此函数多线程调用是否会产生影响

原子操作

是 或 否 或 未知,表示此函数是否是单一操作,不是多个步骤的组合

其他说明

……

……

 

 

3.14  PaStreamCallback(未完成)

函数名称

PaStreamCallback

头文件

#include "PortAudio.h"

库文件

#pragma comment(lib, "PortAudio_x86.lib或PortAudio_x64.lib")

函数功能

音频数据处理回调函数。

函数声明

int PaStreamCallback (

const void * input,

void * output,

unsigned long frameCount,

const PaStreamCallbackTimeInfo * timeInfo,

PaStreamCallbackFlags statusFlags,

void * userData

)

函数参数

input,[输入]:

存放音频数据输入缓存的内存指针,也就是音频设备采样到的音频数据。

音频数据输入缓存的长度计算方法(单位字节):声道个数×每个声道的音频数据块个数×采样位数÷8。

output,[输出]:

存放音频数据输出缓存的内存指针,也就是需要音频设备播放的音频数据。

音频数据输出缓存的长度计算方法(单位字节):声道个数×每个声道的音频数据块个数×采样位数÷8

frameCount,[输入]:

存放音频数据输入输出缓存中存放的每个声道的音频数据块个数。

timeInfo,[输入|输出|输入&输出]:

参数说明。

statusFlags,[输入|输出|输入&输出]:

参数说明。

userData,[输入&输出]:

存放程序自定义参数。

返回值

返回值1:返回值说明。

返回值2:返回值说明。

……

错误码

EXXXX:错误码说明。

EXXXX:错误码说明。

……

线程安全

是 或 否 或 未知,表示此函数多线程调用是否会产生影响

原子操作

是 或 否 或 未知,表示此函数是否是单一操作,不是多个步骤的组合

其他说明

音频数据输入输出缓存的内存格式:

 

第一个字节

第二个字节

第三个字节

第四个字节

……

单声道

8位采样量化

采样1

采样2

采样3

采样4

……

声道0

声道0

声道0

声道0

……

 

 

 

 

 

 

双声道

8位采样量化

采样1

采样2

……

声道0(左)

声道1(右)

声道0(左)

声道1(右)

……

 

 

 

 

 

 

单声道

16位采样量化

采样1

采样2

……

声道0

(低位字节)

声道0

(高位字节)

声道0

(低位字节)

声道0

(高位字节)

……

 

 

 

 

 

 

双声道

16位采样量化

采样1

……

声道0(左)

(低位字节)

声道0(右)

(高位字节)

声道1(左)

(低位字节)

声道1(右)

(高位字节)

……

就是这样的。

 

 

3.15  Pa_StartStream(未完成)

函数名称

Pa_StartStream

头文件

#include "PortAudio.h"

库文件

#pragma comment(lib, "PortAudio_x86.lib或PortAudio_x64.lib")

函数功能

让一个已经打开的音频流句柄开始处理音频数据。

函数声明

类型 函数名 (

类型 参数1,

类型 参数2,

……

);

函数参数

参数1,[输入|输出|输入&输出]:

参数说明。

参数2,[输入|输出|输入&输出]:

参数说明。

……

返回值

返回值1:返回值说明。

返回值2:返回值说明。

……

错误码

EXXXX:错误码说明。

EXXXX:错误码说明。

……

线程安全

是 或 否 或 未知,表示此函数多线程调用是否会产生影响

原子操作

是 或 否 或 未知,表示此函数是否是单一操作,不是多个步骤的组合

其他说明

停止处理音频数据需要调用Pa_StopStream()函数。

 

 

3.16  Pa_StopStream(未完成)

函数名称

Pa_StopStream

头文件

#include "PortAudio.h"

库文件

#pragma comment(lib, "PortAudio_x86.lib或PortAudio_x64.lib")

函数功能

让一个已经打开的音频流句柄停止处理音频数据。

函数声明

类型 函数名 (

类型 参数1,

类型 参数2,

……

);

函数参数

参数1,[输入|输出|输入&输出]:

参数说明。

参数2,[输入|输出|输入&输出]:

参数说明。

……

返回值

返回值1:返回值说明。

返回值2:返回值说明。

……

错误码

EXXXX:错误码说明。

EXXXX:错误码说明。

……

线程安全

是 或 否 或 未知,表示此函数多线程调用是否会产生影响

原子操作

是 或 否 或 未知,表示此函数是否是单一操作,不是多个步骤的组合

其他说明

……

……

 

 

3.17  Pa_ReadStream(未完成)

函数名称

Pa_ReadStream

头文件

#include "PortAudio.h"

库文件

#pragma comment(lib, "PortAudio_x86.lib或PortAudio_x64.lib")

函数功能

从一个已经打开并开始处理音频数据的音频流句柄,阻塞采集指定长度的音频数据。

函数声明

PaError Pa_ReadStream (

PaStream * stream,

void * buffer,

unsigned long frames

);

函数参数

stream,[输入]:

存放音频流句柄。

buffer,[输出]:

存放音频数据输入缓存的内存指针,也就是音频设备采样到的音频数据。

frames,[输入]:

存放音频数据输入缓存中存放的每个声道的音频数据块个数。

音频数据输入缓存的长度计算方法(单位字节):声道个数×每个声道的音频数据块个数×采样位数÷8。

返回值

paNoError枚举(0x0000):成功。

其他:失败,返回值就是错误码,调用Pa_GetErrorText()函数查看错误码对应的错误信息。

错误码

EXXXX:错误码说明。

EXXXX:错误码说明。

……

线程安全

是 或 否 或 未知,表示此函数多线程调用是否会产生影响

原子操作

是 或 否 或 未知,表示此函数是否是单一操作,不是多个步骤的组合

其他说明

……

……

 

 

3.18  Pa_WriteStream(未完成)

函数名称

Pa_WriteStream

头文件

#include "PortAudio.h"

库文件

#pragma comment(lib, "PortAudio_x86.lib或PortAudio_x64.lib")

函数功能

从一个已经打开并开始处理音频数据的音频流句柄,阻塞播放指定长度的音频数据。

函数声明

PaError Pa_WriteStream (

PaStream * stream,

const void * buffer,

unsigned long frames

);

函数参数

stream,[输入]:

存放音频流句柄。

buffer,[输入]:

存放音频数据输出缓存的内存指针,也就是音频设备采样到的音频数据。

frames,[输入]:

存放音频数据输出缓存中存放的每个声道的音频数据块个数。

音频数据输出缓存的长度计算方法(单位字节):声道个数×每个声道的音频数据块个数×采样位数÷8。

返回值

paNoError枚举(0x0000):成功。

其他:失败,返回值就是错误码,调用Pa_GetErrorText()函数查看错误码对应的错误信息。

错误码

EXXXX:错误码说明。

EXXXX:错误码说明。

……

线程安全

是 或 否 或 未知,表示此函数多线程调用是否会产生影响

原子操作

是 或 否 或 未知,表示此函数是否是单一操作,不是多个步骤的组合

其他说明

……

……

 

 

4   结构体库

4.1 结构体模板(未完成)

结构体名称

xxx

头文件

#include "PortAudio.h"

结构体称呼

结构体的中文称呼。

结构体说明

结构体主要用途说明。

相关函数

Func1()、Func2()、Func3()…

结构体声明

struct xxx

{

类型  成员变量1;

类型  成员变量2;

……

};

成员变量

成员变量1

成员变量说明。

成员变量2

成员变量说明。

……

其他说明

……

……

 

 

4.2 PaDeviceInfo(未完成)

结构体名称

PaDeviceInfo

头文件

#include <xxx.h>

#include <xxx.h>

结构体说明

音频设备信息结构体,用于存放音频设备的相关信息。

相关函数

Pa_GetDeviceInfo()、Func2()、Func3()…

结构体声明

typedef struct PaDeviceInfo

{

int structVersion;

const char * name;

PaHostApiIndex hostApi; /**< note this is a host API index, not a type id*/

   

int maxInputChannels;

int maxOutputChannels;

 

/** Default latency values for interactive performance. */

PaTime defaultLowInputLatency;

PaTime defaultLowOutputLatency;

/** Default latency values for robust non-interactive applications (eg. playing sound files). */

PaTime defaultHighInputLatency;

PaTime defaultHighOutputLatency;

 

double defaultSampleRate;

} PaDeviceInfo;

成员变量

structVersion

存放本结构体的版本号,一直为2。

name

存放音频设备的名称字符串的内存指针,例如: "Microsoft 声音映射器 - Input", "Speakers (Realtek HD Audio output)"。

hostApi

note this is a host API index, not a type id.

maxInputChannels

存放音频设备的最大音频输入声道个数,为0表示本设备不支持音频输入。

maxOutputChannels

存放音频设备的最大音频输出声道个数,为0表示本设备不支持音频输出。

defaultLowInputLatency

Default latency values for interactive performance.

defaultLowOutputLatency

成员变量说明。

defaultHighInputLatency

Default latency values for robust non-interactive applications (eg. playing sound files).

defaultHighOutputLatency

成员变量说明。

defaultSampleRate

存放音频设备的默认采样频率,单位Hz赫兹。

其他说明

 

 

 

4.3 PaStreamParameters(未完成)

结构体名称

PaStreamParameters

头文件

#include "PortAudio.h"

结构体说明

结构体主要用途说明。

相关函数

Pa_OpenStream()、Func2()、Func3()…

结构体声明

typedef struct PaStreamParameters

{

    /** A valid device index in the range 0 to (Pa_GetDeviceCount()-1)

     specifying the device to be used or the special constant

     paUseHostApiSpecificDeviceSpecification which indicates that the actual

     device(s) to use are specified in hostApiSpecificStreamInfo.

     This field must not be set to paNoDevice.

    */

    PaDeviceIndex device;

   

    /** The number of channels of sound to be delivered to the

     stream callback or accessed by Pa_ReadStream() or Pa_WriteStream().

     It can range from 1 to the value of maxInputChannels in the

     PaDeviceInfo record for the device specified by the device parameter.

    */

    int channelCount;

 

    /** The sample format of the buffer provided to the stream callback,

     a_ReadStream() or Pa_WriteStream(). It may be any of the formats described

     by the PaSampleFormat enumeration.

    */

    PaSampleFormat sampleFormat;

 

    /** The desired latency in seconds. Where practical, implementations should

     configure their latency based on these parameters, otherwise they may

     choose the closest viable latency instead. Unless the suggested latency

     is greater than the absolute upper limit for the device implementations

     should round the suggestedLatency up to the next practical value - ie to

     provide an equal or higher latency than suggestedLatency wherever possible.

     Actual latency values for an open stream may be retrieved using the

     inputLatency and outputLatency fields of the PaStreamInfo structure

     returned by Pa_GetStreamInfo().

     @see default*Latency in PaDeviceInfo, *Latency in PaStreamInfo

    */

    PaTime suggestedLatency;

 

    /** An optional pointer to a host api specific data structure

     containing additional information for device setup and/or stream processing.

     hostApiSpecificStreamInfo is never required for correct operation,

     if not used it should be set to NULL.

    */

    void *hostApiSpecificStreamInfo;

 

} PaStreamParameters;

成员变量

device

成员变量说明。

channelCount

成员变量说明。

sampleFormat

成员变量说明。

suggestedLatency

成员变量说明。

hostApiSpecificStreamInfo

成员变量说明。

其他说明

……

……

 

 

 

 

posted @ 2015-12-01 19:33  赤勇玄心行天道  阅读(14484)  评论(2编辑  收藏  举报