zoukankan      html  css  js  c++  java
  • 【秒懂音视频开发】11_播放WAV

    对于WAV文件来说,可以直接使用ffplay命令播放,而且不用像PCM那样增加额外的参数。因为WAV的文件头中已经包含了相关的音频参数信息。

    ffplay in.wav
    

    接下来演示一下如何使用SDL播放WAV文件。

    初始化子系统

    // 初始化Audio子系统
    if (SDL_Init(SDL_INIT_AUDIO)) {
        qDebug() << "SDL_Init error:" << SDL_GetError();
        return;
    }
    

    加载WAV文件

    // 存放WAV的PCM数据和数据长度
    typedef struct {
        Uint32 len = 0;
        int pullLen = 0;
        Uint8 *data = nullptr;
    } AudioBuffer;
    
    // WAV中的PCM数据
    Uint8 *data;
    // WAV中的PCM数据大小(字节)
    Uint32 len;
    // 音频参数
    SDL_AudioSpec spec;
    
    // 加载wav文件
    if (!SDL_LoadWAV(FILENAME, &spec, &data, &len)) {
        qDebug() << "SDL_LoadWAV error:" << SDL_GetError();
        // 清除所有的子系统
        SDL_Quit();
        return;
    }
    
    // 回调
    spec.callback = pull_audio_data;
    // 传递给回调函数的userdata
    AudioBuffer buffer;
    buffer.len = len;
    buffer.data = data;
    spec.userdata = &buffer;
    

    如果想要轻松加载MP3、Ogg、FLAC等格式的音频文件,可以使用第三方库:SDL_mixer

    打开音频设备

    // 打开设备
    if (SDL_OpenAudio(&spec, nullptr)) {
        qDebug() << "SDL_OpenAudio error:" << SDL_GetError();
        // 释放文件数据
        SDL_FreeWAV(data);
        // 清除所有的子系统
        SDL_Quit();
        return;
    }
    

    开始播放

    // 开始播放(0是取消暂停)
    SDL_PauseAudio(0);
    
    while (!isInterruptionRequested()) {
        if (buffer.len > 0) continue;
        // 每一个样本的大小
        int size = spec.channels * SDL_AUDIO_BITSIZE(spec.format) / 8;
        // 最后一次播放的样本数量
        int samples = buffer.pullLen / size;
        // 最后一次播放的时长
        int ms = samples * 1000 / spec.freq;
        SDL_Delay(ms);
        break;
    }
    

    回调函数

    // 等待音频设备回调(会回调多次)
    void pull_audio_data(void *userdata,
                         // 需要往stream中填充PCM数据
                         Uint8 *stream,
                         // 希望填充的大小(samples * format * channels / 8)
                         int len
                        ) {
        // 清空stream
        SDL_memset(stream, 0, len);
    
        AudioBuffer *buffer = (AudioBuffer *) userdata;
    
        // 文件数据还没准备好
        if (buffer->len <= 0) return;
    
        // 取len、bufferLen的最小值
        buffer->pullLen = (len > (int) buffer->len) ? buffer->len : len;
    
        // 填充数据
        SDL_MixAudio(stream,
                     buffer->data,
                     buffer->pullLen,
                     SDL_MIX_MAXVOLUME);
        buffer->data += buffer->pullLen;
        buffer->len -= buffer->pullLen;
    }
    

    释放资源

    // 释放WAV文件数据
    SDL_FreeWAV(data);
    
    // 关闭设备
    SDL_CloseAudio();
    
    // 清除所有的子系统
    SDL_Quit();
    
  • 相关阅读:
    UI自动化定位控件添加醒目标识
    Web自动化测试代码优化方案之定位、操作
    面试常用英文关键字知多少
    Linux常用命令必知必会
    Jenkins自动化UI测试Tomcat报错“The web application [/jenkins] appears to have started a thread named”解决办法
    appium API元素定位方法汇总
    Jmeter参数化方法
    python学习-文件读写整理
    python学习_模块化示例
    python学习-python webdriver API(转载)
  • 原文地址:https://www.cnblogs.com/mjios/p/14582322.html
Copyright © 2011-2022 走看看