一、 参考文章
攻城狮百里
https://blog.csdn.net/weixin_52622200/article/details/131306315
二、 使用FFmpeg将mp3文件转成PCM文件命令
ffmpeg -i xxx.mp3 -f s16le xxx.pcm
三、 main函数
SDL播放PCM原理,SDL播放音频过程中,会不断触发回调函数,我们只要在回调函数中不断将PCM数据拷贝到回调函数指定的地址中即可实现音频播放
main.c
#include <iostream>
#include <fstream>
#include <thread>
extern "C" {
#include "SDL.h"
}
using namespace std;
//全局数据区,PCM文件内容
char pcmBuffer[100 * 1024 * 1024];
int audioPosition = 0;
int audioLength = 0;
//音频回调函数
void AudioCallback(void* userdata, Uint8* stream, int length);
int main(int argc,char* argv[])
{
//SDL初始化
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0)
{
cout << "sdl init failed" << endl;
}
else
{
cout << "sdl init succes" << endl;
}
//创建窗口
SDL_Window* pWindow = SDL_CreateWindow("sdl播放器", 100, 100, 1600, 900, SDL_WINDOW_RESIZABLE);
//打开音频设备
SDL_AudioSpec desired;
desired.freq = 44100;
desired.format = AUDIO_S16SYS;
desired.channels = 2;
desired.samples = 1024;
desired.silence = 0;
desired.callback = AudioCallback;
SDL_OpenAudio(&desired, NULL);
//读取PCM文件到内存
fstream fileStream;
fileStream.open("D:/myfile/project/ttt/audio/moonlight.pcm", ios::in | ios::binary);
if (!fileStream.is_open())
{
cout << "PCM文件打开失败" << endl;
}
fileStream.read(pcmBuffer, 100 * 1024 * 1024);
int readLength = fileStream.gcount();
cout << "pcmLength:" << readLength << endl;
audioLength = readLength;
fileStream.close();
//开始播放
SDL_PauseAudio(0);
while (true)
{
chrono::seconds delay(1);
this_thread::sleep_for(delay);
}
//关闭音频设备
SDL_CloseAudio();
return 0;
}
//音频回调函数
void AudioCallback(void* userdata, Uint8* stream, int length)
{
SDL_memset(stream, 0, length);
if (audioLength == 0)return;
length = (length > audioLength ? audioLength : length);
SDL_MixAudio(stream, (Uint8*)pcmBuffer + audioPosition, length, SDL_MIX_MAXVOLUME);
audioPosition += length;
audioLength -= length;
}