本来音频模块不属于我的,但为了团队,为了更好的工作,更重要的是为了自己,看看吧,可我之前对音频处理这一块几乎没接触过,一片空白,怎么办呢,没办法,我只有把手册从头到尾关于音频的好好的整理了一下,由于CSDN特性即难插图片,所以省略了图表说明,希望对从事Hi35XX系列的同志们有所帮助。。。。。
我这干的是苦力活,即把手册整理(copy)了一下,万事都是这样子开始的。。。。。。。
我们需要处理的是:1.音频输入-》编码-》网络传输出去。2、网络获取音频数据-》解码-》输出。
AUDIO模块包括音频输入、音频输出、音频编码、音频解码四个子模块。音频输入和输出模块通过对 Hi3520/Hi3515芯片SIO设备的控制实现相应的音频输入输出功能;音频编码和解码模块则提供对 ADPCM、G726、G711、AMR格式的音频编解码功能。
一、重要概念
声音
能量波,有频率有振幅,频率高低就是音调,振幅大小就是音量;采样率是对频率采样,采样精度是对幅度采样,人耳能听到的频率范围是200-20KHz。
CODEC
音频压缩CO+解压缩DEC,CODEC就是多媒体数字信号编解码器,主要负责DAC和ADC。不管是音频加速器好,还是I/O控制器好,他们输入输出的都是纯数字信号,我们要使用声卡上的Line Out插孔输出信号的话,信号就必须经过声卡上的CODEC的转换处理。可以说,声卡模拟输入输出的品质和CODEC的转换品质有着重大的关系,音频加速器或I/O控制器决定了声卡内部数字信号的质量,而CODEC则决定了模拟输入输出的好坏。
SIO及 AI、AO设备
音频输入输出接口 SIO(Sonic Input/Output),用于和片外 Audio CODEC芯片连接,完成音乐(语音)的播放及录制。Hi3520芯片提供3个 SIO接口,Hi3515芯片提供 2个 SIO接口,依次标示为 SIO0、SIO1、SIO2。每个 SIO接口都能同时提供音频输入和音频输出功能(但由于芯片管脚的限制,各个 SIO支持的情况是不一样的)。
SIO0 能同时提供音频输入和输出功能,SIO1能提供音频输入功能; Hi3520相对
Hi3515 而言,增加了 SIO1的输出功能和 SIO2的输入功能,但这两者是复用关系,即只能选择其中一种功能,并且芯片管脚也是复用的。
软件 SDK将音频输入和输出功能分别用 AI和 AO两个模块来管理,AI和 AO又按照 SIO序号来区分不同的 SIO接口。例如 SIO0的输入接口称为 AI0设备,SIO0的输出接口称为 AO0设备,SIO1的输入接口称为 AI1设备。
音频接口时序
SIO接口支持标准的I2S接口时序模式(I2S只处理音频),并提供灵活的配置以支持与多种 AUDIO CODEC 对接。详细的时序支持情况请参考《Hi3520/Hi3515 H.264编解码处理器用户指南》。
用户需要对 I2S协议以及对接的 CODEC时序支持情况有足够了解,这里只简单介绍下 Hi3520/Hi3515 I2S接口时序的几个特性:
− 按照标准 I2S协议,总是先传送 MSB(高位),后传送 LSB(低位),即按照从高位到低位的顺序传输串行数据。
− Hi3520/Hi3515 SIO支持扩展的多路接收的 I2S接口时序,对接 CODEC的时序支持情况、时钟、位宽等配置必须与 Hi3520/Hi3515的配置保持一致,否则可能采集不到正确的数据。
− Hi3520/Hi3515 SIO支持I2S主模式和 I2S从模式,主模式即 SIO提供时钟,从模式即 CODEC提供时钟;主模式时 SIO提供的时钟供输入和输出共同使用,而从模式时的输入输出可以分别由外围 CODEC提供时钟。
AI、AO通道
标准的I2S协议只有左右声道这两个通道的概念,Hi3520/Hi3515 SIO同时能够支持多路复用的接收模式,最大支持 16bit 16 通道的 I2S数据接收。SIO本身并不关心具体的通道分布,通道由软件 SDK来管理;根据输入和输出的不同,分为 AI通道和 AO通道,通道又隶属于设备,例如 AiDev0下可支持多个通道 AiChn0、AiChn1、…、AiChn16,具体支持的通道个数由用户根据对接时序要求来做相应的配置。
AI、AO通道排列
必须理解对接 CODEC通道和 AI、AO通道的对应关系,才能从正确的通道获取数据。
Hi3520/Hi3515 SIO在一个帧同步时钟内,最大能接收16bit%16chn=256bit的音频串行数据;如图 9-2 (图片太大,不便输出)所示,通道的排列顺序与 SIO取数据的顺序一致,即从高位到低位排列;SIO实际取的数据多少由配置的通道路数和采样精度决定。
音频帧结构体
typedef struct hiAUDIO_FRAME_S
{
AUDIO_BIT_WIDTH_E enBitwidth; //音频采样精度
AUDIO_SOUND_MODE_E enSoundmode; //音频声道模式。
HI_U8 aData[MAX_AUDIO_FRAME_LEN*2]; //实际音频帧数据
HI_U64 u64TimeStamp; //音频帧时间戳。以μs为单位
HI_U32 u32Seq; //音频帧序号
HI_U32 u32Len; //音频帧长度。以 byte为单位。
}AUDIO_FRAME_S;
A. u32Len(音频帧长度)指单个声道的数据长度。
B. 单声道数据直接存放,采样点数为 ptnum,长度为 len;立体声数据按左右声道分开存放,先存放采样点为 ptnum、长度为 len 的左声道数据,然后存放采样点为ptnum,长度为 len的右声道数据。
二、API参考
1.音频输入
频输入(AI)主要实现配置及启用音频输入设备、获取音频帧数据等功能。
1.设置/获取 AI 设备属性
HI_S32 HI_MPI_AI_SetPubAttr(AUDIO_DEV AudioDevId,const AIO_ATTR_S *pstAttr);
HI_S32 HI_MPI_AI_GetPubAttr(AUDIO_DEV AudioDevId, AIO_ATTR_S*pstAttr);
A.音频输入设备的属性决定了输入数据的格式,输入设备属性包括 SIO工作模式、采样率、采样精度、buffer大小、每帧的采样点数、扩展标志、时钟选择和通道数目。
− 工作模式
SIO输入输出目前支持 I2S主模式和 I2S从模式。
− 采样率
采样率指一秒中内的采样点数,采样率越高表明失真度越小,处理的数据量也就随之增加。主模式下 AI支持 8k~48k的采样率,一般来说语音使用 8k采样率,音频使用 32k或以上的采样率;在从模式下,采样率由 codec芯片决定。
− 采样精度
采样精度指某个通道的采样点数据宽度,同时决定整个设备的通道分布。采样位宽可以设置为 8bit、16bit和 32bit。
− buffer大小
buffer大小以帧为单位,每帧的采样点数和采样精度决定帧长,buffer大小设置当前能容纳帧的个数。
− 扩展标志
扩展标志表明在 8bit采样精度的条件下是否需要对 8bit数据进行 8bit到 16bit带符号扩展,扩展后获取的数据就为 16bit,以满足编码器需求。在设置非 8bit采样精度的情况下,此标志是无效的。
− 通道数目
通道数目指当前 SIO设备的 AI功能支持的最大通道数目,需与对接的 AUDIO CODEC的配置保持一致;支持 2路、4路、8路和 16路。
− 时钟选择
AUDIO CODEC 提供时钟(即 I2S从模式)时,如果能提供独立的 AD和 DA功能信号(即 RCK/RFS/XCK/XFS),那么将此项配置为 0,否则配置为 1。
B.在设置属性之前需要保证 AI处于非启用状态,如果处于启用状态则需要首先禁用AI设备。
C.同一 SIO下的 AI和 AO设备的主从模式、时钟选择应该一致,否则设置属性时会返回错误。
D.在从模式下,采样率的设置不起作用。
E. AI 必须和 AD配合起来才能正常工作,用户必须清楚 AD采集的数据分布和通道的关系才能从正确的通道取得数据。
E.获取的属性为前一次配置的属性。
F. 如果从来没有配置过属性,则返回属性未配置的错误。
定义音频输入输出设备属性结构体:
typedef struct hiAIO_ATTR_S
{
AUDIO_SAMPLE_RATE_E enSamplerate; //音频采样率(从模式下,此参数不起作用)
AUDIO_BIT_WIDTH_E enBitwidth; //音频采样精度(从模式下,此参数必须和音频 AD/DA的采样精度匹配)。
AIO_MODE_E enWorkmode; //音频输入输出工作模式。
AUDIO_SOUND_MODE_E enSoundmode; //音频声道模式。
HI_U32 u32EXFlag; // 8bit到16bit扩展标志(8bit精度时有效)。
HI_U32 u32FrmNum ; //缓存帧数目
HI_U32 u32PtNumPerFrm; //每帧的采样点个数。
HI_U32 u32ChnCnt; //支持的最大通道数目。
HI_U32 u32ClkSel; //时钟选择。
}AIO_ATTR_S;
定义音频采样率:
typedef enum hiAUDIO_SAMPLE_RATE_E
{
AUDIO_SAMPLE_RATE_8000 =8000, // 8kHz采样率
AUDIO_SAMPLE_RATE_11025 =11025, /* 11.025kHz sampling rate */
AUDIO_SAMPLE_RATE_16000 =16000, /* 16kHz sampling rate */
AUDIO_SAMPLE_RATE_22050 =22050, /* 22.050kHz sampling rate */
AUDIO_SAMPLE_RATE_24000 =24000, /* 24kHz sampling rate */
AUDIO_SAMPLE_RATE_32000 =32000, /* 32kHz sampling rate */
AUDIO_SAMPLE_RATE_44100 =44100, /* 44.1kHz sampling rate */
AUDIO_SAMPLE_RATE_48000 =48000, /* 48kHz sampling rate */
}AUDIO_SAMPLE_RATE_E;
定义音频采样精度:
typedef enum hiAUDIO_BIT_WIDTH_E
{
AUDIO_BIT_WIDTH_8 =0, //采样精度为 8bit位宽
AUDIO_BIT_WIDTH_16 =1, /* 16bit/sample */
AUDIO_BIT_WIDTH_32 =2, /* 32bit/sample */
AUDIO_BIT_WIDTH_BUTT,
}AUDIO_BIT_WIDTH_E;
定义音频输入输出设备工作模式:
typedef enum hiAIO_MODE_E
{
AIO_MODE_I2S_MASTER = 0, // I2S主模式
AIO_MODE_I2S_SLAVE = 1, // I2S从模式
AIO_MODE_PCM_SLAVE_STD, // PCM从模式(标准协议)
AIO_MODE_PCM_SLAVE_NSTD, // PCM从模式(非标准协议)
AIO_MODE_BUTT
}AIO_MODE_E;
定义音频声道模式:
typedef enum hiAIO_SOUND_MODE_E
{
AUDIO_SOUND_MODE_MOMO =0, //单声道momo
AUDIO_SOUND_MODE_STEREO =1, //双声道stereo
AUDIO_SOUND_MODE_BUTT
}AUDIO_SOUND_MODE_E;
2.启用/禁用 AI 设备
HI_S32 HI_MPI_AI_Enable(AUDIO_DEV AudioDevId);
HI_S32 HI_MPI_AI_Disable(AUDIO_DEV AudioDevId);
A. 必须在启用前配置 AI设备属性,否则返回属性未配置错误。
B. 如果 AI设备已经处于运行状态,则直接返回成功
C.如果 AI设备已经处于非运行状态,则直接返回成功。
D. 禁用 AI设备前必须先禁用该设备下已启用的所有 AI通道。
3.启用/禁用AI通道
HI_S32 HI_MPI_AI_EnableChn(AUDIO_DEV AudioDevId, AI_CHN AiChn);
HI_S32 HI_MPI_AI_DisableChn(AUDIO_DEV AudioDevId, AI_CHN AiChn);
A. 启用 AI通道前,必须先启用其所属的 AI设备,否则返回设备未启动的错误码。
4.启用/禁用指定 AI 及 AO的回声抵消功能
HI_S32 HI_MPI_AI_EnableAec(AUDIO_DEV AiDevId, AI_CHN AiChn, AUDIO_DEV AoDevId, AO_CHN AoChn);
HI_S32 HI_MPI_AI_DisableAec(AUDIO_DEV AiDevId, AI_CHN AiChn);
A. 启用回声抵消前必须先启用相对应的 AI设备。
B. 成功启用回声抵消需要具备一定条件:单声道模式,采样率为 8kHz,采样精度为16bit,帧长为 80 或 160个采样点,且 AI和 AO帧长必须相同。以上条件 AI和AO都必须满足(但实际上本接口只检查 AI的属性)。
C. 多次启用相同 AI、AO的回声抵消,则返回成功。
5.启用/禁用 AI 重采样
HI_S32 HI_MPI_AI_EnableReSmp(AUDIO_DEV AudioDevId,
AI_CHN AiChn,AUDIO_RESAMPLE_ATTR_S *pstAttr);
HI_S32 HI_MPI_AI_DisableReSmp(AUDIO_DEV AudioDevId, AI_CHN AiChn);
A. 在启用 AI通道之后,绑定 AI通道之前,调用此接口启用重采样功能。
B. 如果启用 AI重采样功能,则在 AI通道输出音频原始数据之前,内部将会先执行重采样处理,处理完后的数据再输出给绑定的 AO或 AENC。
C. 音频重采样属性包含以下项:
− u32InPointNum:输入音频帧的每帧采样点个数。
− enInSampleRate:输入音频帧的采样率。
− enReSampleType:重采样类型,支持 2到1倍、4到 1倍的重采样,例如32kHz降采样到 8kHz或 16kHz降采样到 8kHz。
D. 重采样处理后音频帧的每帧采样点数目会发生变化,调用 HI_MPI_AI_SetPubAttr接口时,音频公共属性中的 32PtNumPerFrm项应该配置为重采样之前的值,本接口中重采样属性中的 u32InPointNum项也配置为重采样之前的值。例如 AI从 32K到 8K重采样,重采样完成后输出给 AO或 AENC的每帧采样点个数将会是重采样前的四分之一,如果期望输出的采样点数为 320,那么公共属性中的 u32PtNumPerFrm项则应配置为 320%4=1280,重采样属性中的 u32InPointNum项也配置成相同值。
E. 不允许重复启用重采样功能,即在再次启用之前需要先将其禁用。
F.不再使用 AI重采样功能的话,应该调用此接口将其禁用。
定义音频重采样属性配置结构体:
typedef struct hiAUDIO_RESAMPLE_ATTR_S
{
HI_U32 u32InPointNum; //输入的每帧采样点个数
AUDIO_SAMPLE_RATE_E enInSampleRate; //输入的采样率
AUDIO_RESAMPLE_TYPE_E enReSampleType; //重采样类型
} AUDIO_RESAMPLE_ATTR_S;
6.获取音频输入通道号对应的设备文件句柄
HI_S32 HI_MPI_AI_GetFd(AUDIO_DEV AudioDevId ,AI_CHN AiChn)
2.音频输出
音频输出(AO)主要实现启用音频输出设备、发送音频帧到输出通道等功能。
3.视频编码
音频编码主要实现创建编码通道、发送音频帧编码及获取编码码流等功能。
1.创建/销毁音频编码通道
HI_S32 HI_MPI_AENC_CreateChn(AENC_CHN AeChn, const AENC_CHN_ATTR_S
*pstAttr);
HI_S32 HI_MPI_AENC_DestroyChn(AENC_CHN AeChn);
A. 协议类型指定该通道的编码协议,目前支持 G711、G726、ADPCM和 AMR 和AAC,具体内容如表 9-1所示。
B. 表 9-1中列举的编解码协议只支持16bit线性 PCM音频数据处理,如果输入的是8bit采样精度的数据,AENC内部会将其扩展为 16bit;另外,使用 Hi3520 AI时,建议将扩展标志置为 1,使得 AI数据由 8bit自动扩展到 16bit。
C. 海思语音帧结构如表 9-4所示。
D. 音频编码的部分属性需要与输入的音频数据属性相匹配,例如采样率、帧长(每帧采样点数目)等。
E. buffer大小以帧为单位,取值范围是[1, MAX_AUDIO_FRAME_NUM]。
F. 在通道闲置时才能使用此接口,如果通道已经被创建,则返回通道已经创建的错误。
G.先创建完编码通道,再调用此接口,否则返回通道未创建。
H. 如果正在获取/释放码流或者发送帧时销毁该通道,则会返回失败。
定义音频编码通道属性结构体:
typedef struct hiAENC_CHN_ATTR_S
{
PAYLOAD_TYPE_E enType; //音频编码协议类型:为一个枚举类型
HI_U32 u32BufSize; //音频编码缓存大小,以帧为单位
HI_VOID *pValue; //具体协议属性指针
}AENC_CHN_ATTR_S;
定义 ADPCM编解码协议类型
typedef enumhiADPCM_TYPE_E
{
ADPCM_TYPE_DVI4 = 0, // 32kbit/s ADPCM(DVI4)
ADPCM_TYPE_IMA, // 32kbit/s ADPCM(IMA)
ADPCM_TYPE_BUTT,
}ADPCM_TYPE_E;
2.绑定编码通道与输入通道
HI_S32 HI_MPI_AENC_BindAi(AENC_CHN AeChn, AUDIO_DEV AudioDevId, AI_CHN AiChn,AUDIO);
3.获取/释放音频编码码流
HI_S32 HI_MPI_AENC_GetStream(AENC_CHN AeChn, AUDIO_STREAM_S*pstStream ,
HI_U32 u32BlockFlag);
HI_S32 HI_MPI_AENC_ReleaseStream(AENC_CHN AeChn, const AUDIO_STREAM_S
*pstStream);
A. 必须创建通道后才可能获取码流,否则直接返回失败,如果在获取码流过程中销毁通道则会立刻返回失败。
B. 支持阻塞或非阻塞方式获取码流,并且支持标准的 select系统调用。
C. 当阻塞方式获取码流时,如果音频数据 Buffer空则此接口调用会被阻塞,直至Buffer中有新的数据或销毁 AENC 通道。
D. 直接获取 AI原始音频数据的方法:创建一路AENC通道,编码协议类型设置为PT_LPCM,绑定AI通道后,从此AENC通道获取的音频数据即 AI原始数据。
E.码流最好能够在使用完之后立即释放,如果不及时释放,会导致编码过程阻塞等待码流释放。
F. 释放的码流必须是从该通道获取的码流,不得对码流信息结构体进行任何修改,否则会导致码流不能释放,使此码流 buffer丢失,甚至导致程序异常。
G. 释放码流时必须保证通道已经被创建,否则直接返回失败,如果在释放码流过程中销毁通道则会立刻返回失败。
定义音频码流结构体:
typedef struct hiAUDIO_STREAM_S
{
HI_U8 *pStream; //音频码流数据指针
HI_U32 u32Len; //音频码流长度。以 byte为单位。
HI_U64 u64TimeStamp; //音频码流时间戳。
HI_U32 u32Seq; //音频码流序号。
}AUDIO_STREAM_S;
4.音频解码
音频解码主要实现创建解码通道、发送音频码流解码及获取解码后音频帧等功能。
1.创建/销毁音频解码通道
HI_S32 HI_MPI_ADEC_CreateChn(ADEC_CHN AdChn, ADEC_CHN_ATTR_S *pstAttr);
HI_S32 HI_MPI_ADEC_DestroyChn(ADEC_CHN AdChn);
A. 协议类型指定了该通道的解码协议,目前支持 G711、G726、ADPCM和 AMR 和AAC。各种音频编解码协议的详细说明请参见“9.3.3 音频编码”。)
B. 音频解码的部分属性需要与输出设备属性相匹配,例如采样率、帧长(每帧采样点数目)等。
C. buffer大小以帧为单位,取值范围是[0, MAX_AUDIO_FRAME_NUM]。
D. 在通道未创建前(或销毁后)才能使用此接口,如果通道已经被创建,则返回通道已经创建。
定义解码通道属性结构体:
typedef struct hiADEC_CH_ATTR_S
{
PAYLOAD_TYPE_E enType; //音频解码协议类型
HI_U32 u32BufSize; //音频解码缓存大小
ADEC_MODE_E enMode; //解码方式
HI_VOID *pValue; //具体协议属性指针
}ADEC_CHN_ATTR_S;
定义解码方式:
typedef enum hiADEC_MODE_E
{
ADEC_MODE_PACK = 0, // pack模式解码
ADEC_MODE_STREAM , // stream模式解码。
ADEC_MODE_BUTT
}ADEC_MODE_E;
注:
pack模式用于用户确认当前码流包为一帧数据编码结果的情况下,解码器会直接进行对其解码,如果不是一帧,解码器会出错。这种模式的效率比较高,在使用AENC模块编码的码流包如果没有破坏,均可以使用此方式解码。
stream模式用于用户不能确认当前码流包是不是一帧数据的情况下,解码器需要对码流进行判断并缓存,此工作方式的效率低下,一般用于读文件码流送解码或者不确定码流包边界的情况。当然由于语音编码码流长度固定,很容易确定在码流中的帧边界,推荐使用 pack 模式解码。
2.向音频解码通道发送码流
HI_S32 HI_MPI_ADEC_SendStream(ADEC_CHN AdChn, const AUDIO_STREAM_S *pstStream, HI_U32 u32BlockFlag);
A. 创建解码通道时可以指定解码方式为 pack方式或 stream方式。
B. 发送数据时必须保证通道已经被创建,否则直接返回失败,如果在送数据过程中销毁通道则会立刻返回失败。
C. 支持阻塞或非阻塞方式发送码流。
D. 当阻塞方式发送码流时,如果音频数据 Buffer满则此接口调用会被阻塞,直至取走音频数据或销毁 ADEC通道。
F. 确保发送给 ADEC通道的码流数据的正确性,否则可能引起解码器异常退出。
定义音频码流结构体:
typedef struct hiAUDIO_STREAM_S
{
HI_U8 *pStream; //音频码流数据指针
HI_U32 u32Len; //音频码流长度。以 byte为单位
HI_U64 u64TimeStamp; //音频码流时间戳
HI_U32 u32Seq; //音频码流序号
}AUDIO_STREAM_S;
3.清除 ADEC通道中当前的音频数据缓存
HI_S32 HI_MPI_ADEC_ClearChnBuf(ADEC_CHN AdChn);
A. 要求解码通道已经被创建,如果通道未被创建则返回通道不存在错误码。
B. 使用本接口时,不建议使用流式解码。使用流式解码进行清除缓存操作时,用户需要确保清除完缓存后,发送给解码器的数据必须是完整的一帧码流,否则可能导致解码器不能正常工作。
C. 无论是否使用流式解码,都要确保送数据解码的操作和清除缓存的操作之间的同步。