ffmpeg解析pcm文件进行播放

news/2024/9/22 21:36:25/

初始化音频子系统是使用 SDL 播放音频之前的一个必要步骤。这确保了 SDL 能够正确地配置和使用音频硬件。如果你不进行初始化,试图使用音频功能可能会导致未定义的行为或错误。

为什么需要初始化音频子系统?
1.资源分配:
SDL 需要为音频设备分配资源,比如设置缓冲区大小、采样率等。
初始化确保 SDL 可以适当地配置音频设备。
2.设备兼容性:
不同的操作系统和硬件平台有不同的音频设备驱动程序。
初始化过程确保 SDL 使用正确的驱动程序与音频硬件通信。
3.状态设置:
初始化过程中可以设置音频输出的基本参数,如通道数、采样率、格式等。
这些设置对于播放音频是必需的。
4.错误检测:
初始化时 SDL 会尝试检测并报告任何潜在的问题,如音频设备不可用或驱动程序错误。

//初始化Audio子系统if(SDL_Init(SDL_INIT_AUDIO)){qDebug() << "SDL_Init error" << SDL_GetError();return;}
#include "playthread.h"
#include <SDL2/SDL.h>
#include <QDebug>
#include <QFile>#define FILENAME "D:/ffmpeg/ffm.pcm"
#define SAMPLE_RATE 44100
#define SAMPLE_FORMAT AUDIO_S16LSB
#define SAMPLE_SIZE (SAMPLE_FORMAT & 0xFF)//== SDL_AUDIO_BITSIZE() = 16;
#define CHANNELS 2//缓冲区样本数量
#define SAMPLES 1024
//每个样本占用多少字节
#define BYTES_PER_SAMPLE ((SAMPLE_SIZE * CHANNELS)/8) // 4
//文件缓冲区大小
#define BUFFER_SIZE BYTES_PER_SAMPLE * SAMPLES//4096typedef struct
{int len = 0;int pullLen = 0;char* data = nullptr;
}AudioBuffer;
//音频参数SDL_AudioSpec spec;//采样率spec.freq = SAMPLE_RATE;//采集格式(s16le)spec.format = AUDIO_S16LSB;//小端读取//声道数spec.channels = CHANNELS;//音频缓冲区的样本数量(这个值必须是2的幂)spec.samples = 1024;//回调spec.callback = pull_audio_data;//传递给回调函数的参数AudioBuffer buffer;spec.userdata = &buffer;//打开设备if(SDL_OpenAudio(&spec,nullptr)){qDebug() << "SDL 0penAudio error" << SDL_GetError();//清楚所有子系统SDL_Quit();return;}//打开文件QFile file(FILENAME);if(!(file.open(QFile::ReadOnly))){qDebug() << "file open error" << FILENAME;//关闭设备SDL_CloseAudio();//清除所有子系统SDL_Quit();return;}//开始播放(0是取消暂停) -- 开始后会一直调用回调函数SDL_PauseAudio(0);//存放从文件中读取的数据char data[BUFFER_SIZE];while(!isInterruptionRequested()){//只要从文件中读取的音频数据,还没有填充完毕,就跳过if(buffer.len > 0) continue;buffer.len = file.read(data,BUFFER_SIZE);if(buffer.len <= 0){//剩余的样本数量int samples = buffer.pullLen / BYTES_PER_SAMPLE;int ms = samples * 1000 / SAMPLE_RATE;qDebug() << ms;break;}//读取到了文件数据buffer.data = data;}//关闭文件file.close();//关闭设备SDL_CloseAudio();//清除所有子系统SDL_Quit();

当进行传参并进行设置回调函数后,线程就会不停歇的进行调用回调函数,知道线程结束

//等待音视频设备回调(会回调多次)
void pull_audio_data(void *userdata,//需要往stream中填充PCM数据Uint8 *stream,//希望填充的大小(samples *format *channels / 8)int len)
{//清空streamSDL_memset(stream,0,len);AudioBuffer* buffer = (AudioBuffer*)userdata;//如果bufferLen的长度为0说明还没有准备好if(buffer->len <= 0) return;//取len、bufferLen的最小值(防止指针越界)buffer->pullLen = (len > buffer->len) ? buffer->len : len;//填充数据进行播放SDL_MixAudio(stream,(Uint8*)buffer->data,buffer->pullLen,SDL_MIX_MAXVOLUME);buffer->data += buffer->pullLen;buffer->len -= buffer->pullLen;
}

http://www.ppmy.cn/news/1500082.html

相关文章

Oracle对比两表数据的不一致

MINUS 基本语法如下 [SQL 语句 1] MINUS [SQL 语句 2];举个例子&#xff1a; select 1 from dual minus select 2 from dual--运行结果 1-------------------------------- select 2 from dual minus select 1 from dual--运行结果 2所以&#xff0c;如果想找所有不一致的&a…

springboot3-web-questions-分析

系列文章目录 文章目录 目录 系列文章目录 文章目录 前言 一、问题案例 1、maven项目compile时候出现告警warn 2、java文件打包然后在命令行中运行java会找不到主类 3、程序找不到数据库驱动和配置实例 4、springboot和mybatis-plus版本不兼容导致 5、springboot项目启动的解释…

足浴行业押金原路退回怎么开通?

一手机版和电脑版差别 手机版押金管理的优点&#xff1a; 1. 便携性&#xff1a;管理人员可以随时随地通过手机查看和处理押金相关事务&#xff0c;不受地点限制。例如&#xff0c;当不在店内时&#xff0c;仍能及时了解押金的收支情况&#xff0c;对突发问题进行处理。 2. 实…

【电源专题】结合锂电池相关资料和华为手机聊聊锂离子电池使用条件限制

在文章:【电源专题】锂电池的特点和工作原理 中我们讲到了一些关于锂电池种类和特点、工作原理等。但是对于锂离子电池使用条件限制却没有介绍,本文基于手机产商 锂离子电池使用条件-电池性能和应用介绍 | 华为官网 (huawei.com)提供的介绍文档再次深入学习锂离子电池的一些特…

麒麟桌面操作系统上配置Samba

原文链接&#xff1a;麒麟桌面操作系统上配置Samba Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于在麒麟桌面操作系统上配置Samba的文章。Samba是一种免费的软件&#xff0c;实现了SMB/CIFS网络协议&#xff0c;使得Linux和Windows系统之间可以共享文件和打印机…

Python学习计划——7.2数据可视化

数据可视化是数据分析的重要组成部分&#xff0c;通过图表和图形将数据直观地展示出来&#xff0c;帮助我们发现数据中的模式和趋势。Python中常用的数据可视化库有matplotlib和seaborn。以下是对这些库的详细讲解及可运行的Python案例。 1. matplotlib 库 matplotlib 是一个…

华为网络模拟器eNSP安装部署教程

eNSP是图形化网络仿真平台&#xff0c;该平台通过对真实网络设备的仿真模拟&#xff0c;帮助广大ICT从业者和客户快速熟悉华为数通系列产品&#xff0c;了解并掌握相关产品的操作和配置、提升对企业ICT网络的规划、建设、运维能力&#xff0c;从而帮助企业构建更高效&#xff0…

【Hot100】LeetCode—416. 分割等和子集

目录 题目1- 思路2- 实现⭐152. 乘积最大子数组——题解思路 3- ACM 实现 题目 原题连接&#xff1a;416. 分割等和子集 1- 思路 理解为背包问题 思路&#xff1a; 能否将均分的子集理解为一个背包&#xff0c;比如对于 [1,5,11,5]&#xff0c;判断能否凑齐背包为 11 的容量…