使用opensl 的BufferQueueAudioPlayer对wav文件的播放

创建音频引擎之后,读取wav文件到内存,然后使用BufferQueueAudioPlayer进行播放。

这里在读取wav文件的时候需要对wav文件的前44个类似头信息进行解析,然后在进行播放的时候,在创建BufferQueueAudioPlayer的时候需要配置音源的时候需要用到,要不然是不能正常播放wav文件的。

 SLDataFormat_PCM format_pcm = {
     SL_DATAFORMAT_PCM,                    //数据格式定义
     1, 
     SL_SAMPLINGRATE_8,                    //采样率(hz)
        SL_PCMSAMPLEFORMAT_FIXED_16,    //采样格式
        SL_PCMSAMPLEFORMAT_FIXED_16,    //
        SL_SPEAKER_FRONT_CENTER,        //声道相关
        SL_BYTEORDER_LITTLEENDIAN        //块的字节顺序 从16--32位
 };

其中数据格式定义可选:

#define SL_DATAFORMAT_MIME        ((SLuint32) 0x00000001)
#define SL_DATAFORMAT_PCM        ((SLuint32) 0x00000002)
#define SL_DATAFORMAT_RESERVED3    ((SLuint32) 0x00000003)
#define SL_DATAFORMAT_PCM_EX    ((SLuint32) 0x00000004)

这里重点是采样率,如果设置的采用率与读取的wav文件内的采用率不同的话,声音是不能正常播放的,下面是sl提供的采用率:

#define SL_SAMPLINGRATE_8          ((SLuint32) 8000000)
#define SL_SAMPLINGRATE_11_025     ((SLuint32) 11025000)
#define SL_SAMPLINGRATE_12         ((SLuint32) 12000000)
#define SL_SAMPLINGRATE_16         ((SLuint32) 16000000)
#define SL_SAMPLINGRATE_22_05      ((SLuint32) 22050000)
#define SL_SAMPLINGRATE_24         ((SLuint32) 24000000)
#define SL_SAMPLINGRATE_32         ((SLuint32) 32000000)
#define SL_SAMPLINGRATE_44_1       ((SLuint32) 44100000)
#define SL_SAMPLINGRATE_48         ((SLuint32) 48000000)
#define SL_SAMPLINGRATE_64         ((SLuint32) 64000000)
#define SL_SAMPLINGRATE_88_2       ((SLuint32) 88200000)
#define SL_SAMPLINGRATE_96         ((SLuint32) 96000000)
#define SL_SAMPLINGRATE_192        ((SLuint32) 192000000)

虽然sl支持的采样率很多,但通常用到的也就是 8000000 和 44100000 这两个。

第四个参数是采样格式,sl列举下面几个:

#define SL_PCMSAMPLEFORMAT_FIXED_8     ((SLuint16) 0x0008)
#define SL_PCMSAMPLEFORMAT_FIXED_16    ((SLuint16) 0x0010)
#define SL_PCMSAMPLEFORMAT_FIXED_20    ((SLuint16) 0x0014)
#define SL_PCMSAMPLEFORMAT_FIXED_24    ((SLuint16) 0x0018)
#define SL_PCMSAMPLEFORMAT_FIXED_28    ((SLuint16) 0x001C)
#define SL_PCMSAMPLEFORMAT_FIXED_32    ((SLuint16) 0x0020)
#define SL_PCMSAMPLEFORMAT_FIXED_64    ((SLuint16) 0x0040)

第五个参数同上。

第六个参数,应该属于声道相关的,研究的很浅,sl给列举的也不少:

#define SL_SPEAKER_FRONT_LEFT                  ((SLuint32) 0x00000001)
#define SL_SPEAKER_FRONT_RIGHT                 ((SLuint32) 0x00000002)
#define SL_SPEAKER_FRONT_CENTER                ((SLuint32) 0x00000004)
#define SL_SPEAKER_LOW_FREQUENCY               ((SLuint32) 0x00000008)
#define SL_SPEAKER_BACK_LEFT                   ((SLuint32) 0x00000010)
#define SL_SPEAKER_BACK_RIGHT                  ((SLuint32) 0x00000020)
#define SL_SPEAKER_FRONT_LEFT_OF_CENTER        ((SLuint32) 0x00000040)
#define SL_SPEAKER_FRONT_RIGHT_OF_CENTER       ((SLuint32) 0x00000080)
#define SL_SPEAKER_BACK_CENTER                 ((SLuint32) 0x00000100)
#define SL_SPEAKER_SIDE_LEFT                   ((SLuint32) 0x00000200)
#define SL_SPEAKER_SIDE_RIGHT                  ((SLuint32) 0x00000400)
#define SL_SPEAKER_TOP_CENTER                  ((SLuint32) 0x00000800)
#define SL_SPEAKER_TOP_FRONT_LEFT              ((SLuint32) 0x00001000)
#define SL_SPEAKER_TOP_FRONT_CENTER            ((SLuint32) 0x00002000)
#define SL_SPEAKER_TOP_FRONT_RIGHT             ((SLuint32) 0x00004000)
#define SL_SPEAKER_TOP_BACK_LEFT               ((SLuint32) 0x00008000)
#define SL_SPEAKER_TOP_BACK_CENTER             ((SLuint32) 0x00010000)
#define SL_SPEAKER_TOP_BACK_RIGHT              ((SLuint32) 0x00020000)

第七个参数:

#define SL_BYTEORDER_BIGENDIAN                ((SLuint32) 0x00000001)
#define SL_BYTEORDER_LITTLEENDIAN            ((SLuint32) 0x00000002)

音源配置成功后设置播放状态,使用内存进行播放。

sl提供的接口是

SLresult (*Enqueue) (
SLBufferQueueItf self,  //创建的BufferQueueAudioPlayer
const void *pBuffer,    //读取wave文件的buffer  
SLuint32 size,      //buffer大小
SLboolean isLastBuffer  //是否最后(暂时没用过)
);

实际用法:

SLresult result;
        result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize);
        if (SL_RESULT_SUCCESS != result) {
            return JNI_FALSE;
        }

在使用BufferQueueAudioPlayer进行播放的时候,我试图去频繁的获取播放的状态

SLresult (*GetPlayState) (
SLPlayItf self,
SLuint32 *pState
);

的时候,貌似获取的都是playing 而在一个wav文件播放结束的时候,还是没有出现我所期待的stopped,暂时还不知道什么原因。

原文地址:https://www.cnblogs.com/wainiwann/p/3064992.html