项目地址https://gitee.com/fahati-champion-and-runner-up/sdl_audio_test
项目目的
这是一个基于 SDL2 的音频测试项目,支持音频的录制、播放和保存。项目可以生成测试音频、录制麦克风输入,并将音频数据保存为 PCM 文件,同时支持直接播放录音和调用系统工具播放。适合音频开发、设备调试和 SDL2 学习参考。
环境需求与运行
1. 安装 SDL2 开发库
Ubuntu/Debian 系统可执行:
sudo apt-get install libsdl2-dev
2. 克隆本项目代码
git clone git@gitee.com:fahati-champion-and-runner-up/sdl_audio_test.git
cd test_sdl
3. 编译项目
./build.sh
关键代码解读
1. 生成测试音频
作用:生成5秒的双声道440Hz正弦波音频数据,存入buffer。
void generateTestAudio(std::vector<Uint8>& buffer) {
// ...参数设置...
buffer.resize(numSamples * channels * bytesPerSample);
Sint16* samples = reinterpret_cast<Sint16*>(buffer.data());
// 生成A4音符的正弦波
for (int i = 0; i < numSamples; i++) {
double value = 0.5 * sin(2.0 * M_PI * freq * i / sampleRate);
Sint16 sample = static_cast<Sint16>(value * 32767);
for (int c = 0; c < channels; c++) {
samples[i * channels + c] = sample;
}
}
}
2. 播放音频数据
作用:用SDL回调方式将内存中的音频数据推送到声卡播放。
void playAudio(const std::vector<Uint8>& data, int freq, int channels, SDL_AudioFormat format) {
// ...PlaybackData结构体...
spec.callback = [](void* userdata, Uint8* stream, int len) {
// 从数据缓冲区复制音频数据到输出流
// 不足部分用静音填充
};
// 打开音频设备,播放音频
SDL_OpenAudio(&spec, nullptr);
SDL_PauseAudio(0);
SDL_Delay(durationMs + 500);
SDL_PauseAudio(1);
SDL_CloseAudio();
}
3. 录音回调
作用:每当录音设备有新数据时,将其追加到audioBuffer,并判断是否达到录音时长。
void audioCaptureCallback(void* userdata, Uint8* stream, int len) {
if (isRecording) {
std::lock_guard<std::mutex> lock(audioMutex);
std::copy(stream, stream + len, std::back_inserter(audioBuffer));
// 检查录音时长,超时则停止
}
}
4. 主流程 main
- 初始化SDL音频系统,枚举并打印可用的播放和录音设备。
- 测试1:生成测试音频并播放,保存为generated_audio.pcm。
- 测试2:尝试打开录音设备,录制5秒音频到audioBuffer,保存为recorded_audio.pcm。
- 测试3:播放刚刚录制的音频。
- 测试4:提示如何用
aplay
命令行工具播放录音文件。
5. 线程安全与状态控制
- 使用
std::mutex
保护音频缓冲区,防止多线程访问冲突。 - 用
std::atomic<bool> isRecording
控制录音状态。
总结:
本程序实现了音频的生成、播放、录制、保存和回放,适合用于SDL音频接口的测试和学习。