SDL播放PCM

简介: SDL播放PCM
//
// Created by simp on 2021/7/7.
//
#include <stdio.h>
#include <SDL.h>
//每次读取2帧数据,以1024个采样点一帧 2通道16bit采样点为例
#define  PCM_BUFFER_SIZE (1024*2*2*2)
//音频PCM数据缓存
static Uint8 *s_audio_buf = NULL;
//目前读取的位置
static Uint8 *s_audio_pos = NULL;
//缓存结束位置
static Uint8 *s_audio_end = NULL;
//音频设备回调函数
void fill_audio_pcm(void *userdata, Uint8 *stream, int len) {
    //SDL_AudioCallback
    //userdata:SDL_AudioSpec 结构中的用户自定义数据,一般情况下可以不用。
    //stream:该指针指向需要填充的音频缓冲区
    //len:音频缓冲区的大小(以字节为单位)1024*2*2
    SDL_memset(stream, 0, len);
    if (s_audio_pos >= s_audio_end)//数据读取完毕
    {
        printf("read complete\n");
        return;
    }
    //数据够了就读取预设的长度,数据不够就只读部分(不够的时候剩多少就读多少)
    int remain_buffer_len = s_audio_end - s_audio_pos;
    len = (len < remain_buffer_len) ? len : remain_buffer_len;
    //拷贝数据到stream并调整音量
    SDL_MixAudio(stream, s_audio_pos, len, SDL_MIX_MAXVOLUME / 8);
    printf("len=%d\n", len);
    s_audio_pos += len;//移动缓存指针
}
//提取PCM文件
//ffmpeg -i input.mp4 -t20 -codec:a pcm_s16le -ar 44100 -ac 2  -f s16le 44100_16bit_2ch.pcm
//测试pcm
//ffplay -ar 44100 -ac2 -f s16le 44100_16bit_2ch.pcm
#undef main
int main(int argc, char *argv[]) {
    int ret = -1;
    FILE *audio_fd = NULL;
    SDL_AudioSpec spec;
//    C:\Users\simp\CLionProjects\SDLaction\cmake-build-debug\44100_16bit_2ch.pcm
    const char *path = "44100_16bit_2ch.pcm";
    size_t read_buffer_len = 0;
    //SDL_initialize
    if (SDL_Init(SDL_INIT_AUDIO)) {//确认设备是否支持AUDIO
        fprintf(stderr, "Could not initalize SDL -%s\n", SDL_GetError());
        return ret;
    }
    //打开PCM文件
    audio_fd = fopen(path, "rb");
    if (!audio_fd) {
        fprintf(stderr, "Failed to open pcm file!\n");
        goto _FAIL;
    }
    s_audio_buf = (uint8_t *) malloc(PCM_BUFFER_SIZE);
    //音频参数设置SDL_AudioSpec
    spec.freq = 44100;//采样频率
    spec.format = AUDIO_S16SYS;//采样点格式 音频数据格式
    spec.channels = 2;//声道数:1单声道 2立体声
    spec.silence = 0;//设置静音的值,因为声音采样是有符号的,所以0当然就是这个值
    spec.samples = 1024;//23.2ms -> 46.4ms每次读取的采样数量,多久产生一次回调和samples  音频缓冲区中的采样个数,要求必须是2的n次方
    spec.callback = fill_audio_pcm;//回调函数
    spec.userdata = NULL;
//    打开音频设备
    if (SDL_OpenAudio(&spec, NULL)) {
        fprintf(stderr, "Failed to open audio device,%s\n", SDL_GetError());
        goto _FAIL;
    }
    //play audio
    SDL_PauseAudio(0);//当pause_on为0的时候即可开始播放音频数据。设置为1的时候,将会播放静音的值。
    int data_count = 0;
    while (1) {
        //从文件读取PCM数据
        read_buffer_len = fread(s_audio_buf, 1, PCM_BUFFER_SIZE, audio_fd);
        if (read_buffer_len == 0) {
            break;
        }
        data_count += read_buffer_len;//统计读取数据总字节数
        printf("now playing %10d bytes data.\n", data_count);
        s_audio_end = s_audio_buf + read_buffer_len;//更新buffer的结束位置
        s_audio_pos = s_audio_buf;//更新buffer的起始位置
//        the main thread wait for a moment
        while (s_audio_pos<s_audio_end) {
            SDL_Delay(10);//等待PCM数据消耗
        }
    }
    printf("play PCM finish\n");
    //关闭音频设备
    SDL_CloseAudio();
_FAIL:
    //release some resources
    if (s_audio_buf)free(s_audio_buf);
    if (audio_fd)fclose(audio_fd);
    SDL_Quit();
    return 0;
}
目录
相关文章
|
2月前
|
C语言 C++ 内存技术
SDL基础使用06 (SDL播放pcm文件)
如何使用SDL库在C和C++中播放PCM音频文件,包括初始化SDL音频、设置音频参数、读取PCM数据、播放音频以及资源释放的完整流程。
3445 1
|
内存技术
音频格式G711转PCM的代码
音频格式G711转PCM的代码
297 0
|
存储 缓存 内存技术
SDL开发笔记(二):音频基础介绍、使用SDL播放音频
SDL开发笔记(二):音频基础介绍、使用SDL播放音频
SDL开发笔记(二):音频基础介绍、使用SDL播放音频
|
缓存 编解码 API
FFmpeg开发笔记(八):ffmpeg解码音频并使用SDL同步音频播放
FFmpeg开发笔记(八):ffmpeg解码音频并使用SDL同步音频播放
FFmpeg开发笔记(八):ffmpeg解码音频并使用SDL同步音频播放
|
存储 编解码 缓存
FFmpeg 开发(03):FFmpeg + OpenSLES 实现音频解码播放
本文将利用 FFmpeg 对一个 Mp4 文件的音频流进行解码,然后使用 libswresample 将解码后的 PCM 音频数据转换为目标格式的数据,最后利用 OpenSLES 进行播放。
543 0
FFmpeg 开发(03):FFmpeg + OpenSLES 实现音频解码播放
|
内存技术
【音视频连载-008】基础学习篇-SDL 播放 PCM 音频文件(下)
接上篇 SDL 播放 PCM 音频文件,已经实现了 推 的模式去播放,接下来看看 拉 的模式如何实现。
219 0
【音视频连载-008】基础学习篇-SDL 播放 PCM 音频文件(下)
|
消息中间件 vr&ar 数据格式
【音视频连载-007】基础学习篇-SDL 播放 PCM 音频文件(上)
在前面的文章中已经能够利用 SDL 去播放 YUV 视频文件了,接下来要通过 SDL 去播放 PCM 音频文件。
588 0
【音视频连载-007】基础学习篇-SDL 播放 PCM 音频文件(上)
|
消息中间件
【音视频连载-006】基础学习篇-SDL 播放 YUV 视频文件
在前面的文章中,我们已经能够加载 YUV 帧并显示了,那是把一张图片转换成 YUV 帧得到的素材。 如果是一个 YUV 视频文件的话,那就是很多 YUV 帧连续在一起,既然能展示一帧,那肯定可以连续展示多帧。 接下来就要这样的操作。
249 0
【音视频连载-006】基础学习篇-SDL 播放 YUV 视频文件
|
内存技术 C++ 缓存
XAudio2播放PCM
XAudio2     是一个跨平台的API,在Xbox 360及Windows中得到支持。在Xbox 360上, XAudio2作为一个静态库编译到游戏可执行文件中。在Windows上,XAudio2提供一个动态链接库(DLL)。
1505 0
|
异构计算 编解码 算法
32.FFmpeg+OpenGLES+OpenSLES播放器实现(六.FFmpeg音视频解码)
项目源码FFmpeg开发文档 解码分为软解码和硬解码,那么什么是软解码和硬解码,二者有什么区别?简单来说,在于是否使用CPU进行解码,最初视频解码都是通过CPU进行的,那时候视频分辨率较低,CPU完全可以胜任解码的工作,但是随着高清视频的出现,使用CPU进行解码的压力越来越大 软解码 使用CPU进行解码,所以就很容易造成CPU负载过大。
2748 0