sdl播放pcm文件

来源:互联网 发布:离散数学教材推荐 知乎 编辑:程序博客网 时间:2024/06/02 05:30

参考:最简单的视音频播放示例9:SDL2播放PCM

用到的数据结构和函数

1. SDL_Init

int SDLCALL SDL_Init(Uint32 flags)  

初始化SDL,播放音频时flags为SDL_INIT_AUDIO | SDL_INIT_TIMER;
2. SDL_AudioSpec

类型 字段 备注 int freq 音频采样率 SDL_AudioFormat format audio data format Uint8 channels 声道数 Uint8 silence audio buffer silence value (calculated) Uint16 samples audio buffer size in samples (power of 2) Uint32 size audio buffer size in bytes (calculated) SDL_AudioCallback callback 数据回调函数 void* userdata a pointer that is passed to callback (otherwise ignored by SDL)

其中回调函数的格式如下所示:


void (SDLCALL * SDL_AudioCallback) (void *userdata, Uint8 * stream, int len);

其中userdata为SDL_OpenAudio参数desired中的值;stream为填充缓冲器的地址;len为缓冲区长度;
3. SDL_OpenAudio

int SDL_OpenAudio(SDL_AudioSpec* desired,                  SDL_AudioSpec* obtained)

desired:期望的音频参数;obtained:实际音频设备的参数;

4. SDL_PauseAudio

void SDL_PauseAudio(int pause_on);

pause_on为0表示播放,非0表示暂停;

5. SDL_Delay

void SDL_Delay(Uint32 ms);

等待ms毫秒。
6. SDL_MixAudio

void SDL_MixAudio(Uint8*       dst,                  const Uint8* src,                  Uint32       len,                  int          volume);

音频混音函数,如果需要同时播放多段音频,只需回调函数中依次调用SDL_MixAudio即可。

步骤

  1. 初始化sdl;
  2. 填充SDL_AudioSpec结构体, 并调用SDL_OpenAudio函数;
  3. 开始播放,调用SDL_PauseAudio;
  4. 等待播放完成;

测试demo

#include <iostream>#include "SDL/SDL.h"typedef struct AudioInfoContext{    FILE *fd;    char buffer[4096];    bool isFileReadEnd;}AudioInfoContext;void readAudioData(void *userdata, Uint8 * stream,                                    int len){    AudioInfoContext *pAudioCtx = (AudioInfoContext*)userdata;    memset(stream, 0, len);    if(len > 4096)    {        len = 4096;    }    int ret = fread(pAudioCtx->buffer, 1, len, pAudioCtx->fd);    if(ret < len){        pAudioCtx->isFileReadEnd = true;    }    len = len > ret ? ret:len;    SDL_MixAudio(stream,(uint8_t*)pAudioCtx->buffer,len,SDL_MIX_MAXVOLUME);}#undef mainint main() {    if(SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER)) {        std::cout <<  "Could not initialize SDL , msg:" << SDL_GetError() << std::endl;        return -1;    }    std::string pcmFile = "/Users/skl/Downloads/pcm16k.pcm";    AudioInfoContext audioCtx;    audioCtx.fd = fopen(pcmFile.c_str(), "rb");    if(!audioCtx.fd)    {        std::cout << "open pcm file fail" << std::endl;        return -1;    }    audioCtx.isFileReadEnd = false;    SDL_AudioSpec audioSpec;    audioSpec.freq = 16000;    audioSpec.format = AUDIO_S16SYS;    audioSpec.channels = 1;    audioSpec.silence = 0;    audioSpec.samples = 1024;    audioSpec.callback = readAudioData;    audioSpec.userdata = (void*)&audioCtx;    if(SDL_OpenAudio(&audioSpec, NULL) < 0)    {        std::cout << "can't open audio, msg:" <<  SDL_GetError() << std::endl;        return -1;    }    SDL_PauseAudio(0);    while(1){        if(!audioCtx.isFileReadEnd)            SDL_Delay(1);        else            break;    }    fclose(audioCtx.fd);    std::cout << "play end" << std::endl;    return 0;}
0 0