• SDL2 播放音频数据(PCM)


    1.简介

    这里以常用的视频原始数据PCM数据为例,展示音频的播放。

    SDL播放音频的流程如下:

    • 初始化音频子系统:SDL_Init()。
    • 设置音频参数:SDL_AudioSpec。
    • 设置回调函数:SDL_AudioCallback。
    • 打开音频设备:SDL_OpenAudio()。
    • 打开pcm文件,读取数据。
    • 开始播放:SDL_PauseAudio()。

    2.使用的数据结构以及方法介绍

    SDL_AudioSpec:

    1. typedef struct SDL_AudioSpec {
    2. int freq; // 音频采样率
    3. SDL_AudioFormat format; // 音频数据格式
    4. Uint8 channels; // 声道数: 1 单声道, 2 立体声
    5. Uint8 silence; // 设置静音的值,因为声音采样是有符号的,所以0当然就是这个值
    6. Uint16 samples; // 音频缓冲区中的采样个数,要求必须是2的n次,这个决定了回调len的长度,len=samples*chn*位宽(单位是字节)
    7. Uint16 padding; // 考虑到兼容性的一个参数
    8. Uint32 size; // 音频缓冲区的大小,以字节为单位
    9. SDL_AudioCallback callback; // 填充音频缓冲区的回调函数
    10. void *userdata; // 用户自定义的数据
    11. } SDL_AudioSpec;

    SDL_AudioCallback回调:

    • userdata:SDL_AudioSpec结构中的用户自定义数据,一般情况下可以不用。
    • stream:该指针指向需要填充的音频缓冲区。
    • len:音频缓冲区的大小(以字节为单位)。
    1. typedef void (SDLCALL * SDL_AudioCallback) (void *userdata, Uint8 * stream,
    2. int len);

    播放音频数据:

    1. // 当pause_on设置为0的时候即可开始播放音频数据。设置为1的时候,将会播放静音的值。
    2. void SDLCALL SDL_PauseAudio(int pause_on)

    混音函数:

    • dst:目标数据,这里传入音频缓冲区指针 stream;
    • src:音频数据,这里传入我们读出的 PCM 数据;
    • len:音频数据长度,这里传入音频缓冲区大小 len;
    • volume:音量,范围 0~128,这里我们传入 SDL_MIX_MAXVOLUME,注意此参数并不会修改硬件音量;
    1. extern DECLSPEC void SDLCALL SDL_MixAudio(Uint8 * dst, const Uint8 * src,
    2. Uint32 len, int volume);

    3.代码示例

    1. #include
    2. #include
    3. static Uint8 *audio_chunk;
    4. static Uint32 audio_len;
    5. static Uint8 *audio_pos;
    6. void fill_audio(void *udata, Uint8 *stream, int len)
    7. {
    8. //SDL 2.0
    9. SDL_memset(stream, 0, len);
    10. if (audio_len == 0) /* Only play if we have data left */
    11. return;
    12. len = (len > audio_len ? audio_len : len); /* Mix as much data as possible */
    13. SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME);
    14. audio_pos += len;
    15. audio_len -= len;
    16. }
    17. #undef main
    18. int main(int argc, char* argv[])
    19. {
    20. //Init
    21. if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER))
    22. {
    23. printf("Could not initialize SDL - %s\n", SDL_GetError());
    24. return -1;
    25. }
    26. //SDL_AudioSpec
    27. SDL_AudioSpec wanted_spec;
    28. wanted_spec.freq = 44100;
    29. wanted_spec.format = AUDIO_S16SYS;
    30. wanted_spec.channels = 2;
    31. wanted_spec.silence = 0;
    32. wanted_spec.samples = 1024;
    33. wanted_spec.callback = fill_audio;
    34. //打开音频设备
    35. if (SDL_OpenAudio(&wanted_spec, NULL) < 0)
    36. {
    37. printf("can't open audio.\n");
    38. return -1;
    39. }
    40. FILE *fp = fopen("./test.pcm", "rb+");
    41. if (fp == NULL)
    42. {
    43. printf("cannot open this file\n");
    44. return -1;
    45. }
    46. //For YUV420P
    47. int pcm_buffer_size = 4096;
    48. char *pcm_buffer = (char *)malloc(pcm_buffer_size);
    49. int data_count = 0;
    50. while (1)
    51. {
    52. if (fread(pcm_buffer, 1, pcm_buffer_size, fp) != pcm_buffer_size)
    53. {
    54. // Loop
    55. fseek(fp, 0, SEEK_SET);
    56. fread(pcm_buffer, 1, pcm_buffer_size, fp);
    57. data_count = 0;
    58. }
    59. printf("Now Playing %10d Bytes data.\n", data_count);
    60. data_count += pcm_buffer_size;
    61. //Set audio buffer (PCM data)
    62. audio_chunk = (Uint8 *)pcm_buffer;
    63. //Audio buffer length
    64. audio_len = pcm_buffer_size;
    65. audio_pos = audio_chunk;
    66. //Play
    67. SDL_PauseAudio(0);
    68. while (audio_len > 0)//Wait until finish
    69. SDL_Delay(1);
    70. }
    71. fclose(fp);
    72. SDL_CloseAudio();
    73. SDL_Quit();
    74. return 0;
    75. }

    4.相关推荐

    [总结]FFMPEG视音频编解码零基础学习方法_零基础ffmpeg 雷霄骅-CSDN博客

    FFmpeg 音频解码(秒懂)-CSDN博客

    SDL2 播放视频文件(MP4)-CSDN博客

    SDL2 播放音频(MP4)-CSDN博客

  • 相关阅读:
    音频处理:Acon Digital Acoustica Premium Mac
    【1】DDR---容量计算
    4个实用小工具安利,你不看看吗
    广州华锐互动:VR互动教学平台如何赋能职业院校?
    jvm类加载机制,双亲委派机制,juc
    日志pattern
    MongoDB权限控制
    解决:Typora上传图片后本地显示不出来
    Zookeeper3.7.1分布式安装部署
    Windows内核--CreateProcess的内核实现 (3)
  • 原文地址:https://blog.csdn.net/wzz953200463/article/details/134419782