Beginning SDL 2.0(6) 音频渲染及wav播放
前面几篇关于SDL的文章介绍的是以画面为主,这里介绍下SDL中针对音频播放提供的机制,以及如何应用。
对于音频而言,有几个概念需要事先了解下,采样率、声道数、量化位数,如果你不清楚的话,麻烦先了解下这几本参数的概念。
常用的采样率有8kHz(语音、电话)、48kHz(电视),声道数常用的是双声道或5.1声道,量化位数8bit或16bit。
SDL提供了音频设备、音频输入/输出的控制机制。
比较常规的做法是先创建音频设备,然后按照你的实际需求进行音频输入输出。
由于音频处理相对简单,这里仅在一个cpp中实现所有wav播放的功能。
工程创建
为了演示期间,我们在vs10中创建控制台程序,并包含SDL头文件和库的路径。,工程名为3_wav_play。我从网上下了一个wav音频,名字为“congtouzailai.wav”。(音量比较大的,播放的时候注意下)
wav文件加载
SDL提供了SDL_LoadWAV函数,用于加载wav文件,加载的代码如下:
SDL_AudioSpec wav_spec;
Uint32 wav_length;
Uint8 *wav_buffer; /* Load the WAV */
if (SDL_LoadWAV("congtouzailai.wav", &wav_spec, &wav_buffer, &wav_length) == NULL)
{
fprintf(stderr, "Could not open test.wav: %s\n", SDL_GetError());
return -;
}
函数调用成功之后,就可以获得wav文件中的音频参数,比如采样率、声道数、量化位数等,其中原始的音频数据(PCM)存储在wav_buffer中,长度为wav_length。
创建回调参数上下文
struct AudioPlayContext
{
Uint8 * data; // pcm buffer
int offset; // current read pos
int data_len; // left data length
bool is_exit; // is audio play buffer empty?
};
提供这个参数,只是为了提供数据从主函数到回调函数传递参数的机制。
创建音频设备
AudioPlayContext context;
context.data = wav_buffer;
context.offset = ;
context.data_len = wav_length;
context.is_exit = false; // open audio device
SDL_AudioSpec want, have; want = wav_spec;
want.callback = MyAudioCallback; // you wrote this function elsewhere.
want.userdata = &context; if (SDL_OpenAudio(&want, &have) < )
{
printf("Failed to open audio: %s\n", SDL_GetError());
return -;
} if (have.format != want.format)
printf("We didn't get Float32 audio format.\n");
这里最主要的结构体SDL_AudioSpec的初始化,这里的回调函数MyAudioCallback,提供了向播放设备写入音频数据的方式。
播放音频数据
在主线程中,我们启动播放,并等待当前wav文件播放完成。代码如下
SDL_PauseAudio(); // start audio playing.
// wait for the end
while(!context.is_exit)
{
SDL_Delay();
}
在回调函数中我们需要将数据填充到音频设备的播放缓冲中,并设置是否播放完成的标志位,代码如下
void MyAudioCallback(void* userdata, Uint8* stream, int len)
{
AudioPlayContext * context = reinterpret_cast<AudioPlayContext *>(userdata);
int copy_len = __min(len, context->data_len);
memcpy(stream, context->data+context->offset, copy_len);
context->data_len -= copy_len;
context->offset += copy_len;
if (context->data_len <= )
{
context->is_exit = true;
} if (copy_len < len)
{
memset(stream+copy_len, , len-copy_len);
}
}
反初始化操作
程序退出时,别忘记释放wav文件加载时的数据。
SDL_CloseAudio();
/* Do stuff with the WAV data, and then... */
SDL_FreeWAV(wav_buffer);
SDL_Quit();
上面几个合并在一起就是最简单的wav文件播放器。
相关代码可以从我的git下载,url如下:https://git.oschina.net/Tocy/SampleCode.git,位于TocySDL2VisualTutorial目录下。
Beginning SDL 2.0(6) 音频渲染及wav播放的更多相关文章
- Beginning SDL 2.0(4) YUV加载及渲染
本文主要内容是基于的“Beginning SDL 2.0(3) SDL介绍及BMP渲染”(以下简称BS3)基础上,将BMP加载及渲染修改为YUV420或I420的原始视频格式.阅读完本部分内容相信你可 ...
- Beginning SDL 2.0(3) SDL介绍及BMP渲染
SDL是一个跨平台的多媒体库.为了实现跨平台,SDL提供了一个简单的界面库抽象,比如提供了SDL_Window用于表示窗口句柄,SDL_Surface.SDL_Texture.SDL_Renderer ...
- Beginning SDL 2.0(5) 基于MFC和SDL的YuvPlayer
本文是在“Beginning SDL 2.0(4) YUV加载及渲染”(以下简称BS4)基础上做的功能完善,如果你对之间介绍的内容了解不多,麻烦先阅读之前的内容. 本文主要介绍如何完成一个基于MFC和 ...
- Beginning SDL 2.0(2) TwinklebearDev SDL 2.0 Tutorial
本文整理并简要介绍了TwinklebearDev SDL 2.0 Tutorial相关内容(以下简称TDSDLTutorial). 这是作为我学习并了解SDL2.0功能一篇学习总结. TDSDLTut ...
- Beginning SDL 2.0(1) SDL功能简介
原文链接为 http://wiki.libsdl.org/Introduction. 由于近期整理音视频可视化的技术,发现好久不更新的SDL发布了2.0版本,以前也没有过于关注,这里准备尝试下.了解S ...
- Android下基于PCM的音频渲染
环境准备 请按照我之前的文章-Android下基于SDL的位图渲染,安装必要的开发环境. 实践篇 这里主要参考Beginning SDL 2.0(6) 音频渲染及wav播放,只不过将源从WAV文件改成 ...
- (转)在SDL工程中让SDL_ttf渲染汉字
有时候在关于SDL的博文中看到一些评论,说SDL对中文的支持不佳,因为当程序涉及中文时总是输出乱码. 照我个人观点,这里面很多都是误解.下面就根据我在windows下使用SDL的情况,说说我的观点. ...
- vue2.0 之文本渲染-v-html、v-text
vue2.0 之文本渲染-v-html.v-text 1.index.html代码 <!DOCTYPE html> <html> <head> <meta c ...
- COCOS2DX 3.0 优化提升渲染速度 Auto-batching
COCOS2DX 3.0 优化提升渲染速度 Auto-batching 近期在看COCOS2DX 3.0的Auto-batching合批与Auto Culling动态缩减功能以下就来细致看看吧:整合好 ...
随机推荐
- web安全之渗透测试
本次渗透测试使用工具列表如下: 漏洞扫描器 (主机/Web) 绿盟RAS漏洞扫描器 商用 端口扫描器 NMAP 开源 网络抓包 Fiddler 开源 暴力破解工具 Hydra 开源 数据库注入工具 S ...
- 【RS】Matrix Factorization Techniques for Recommender Systems - 推荐系统的矩阵分解技术
[论文标题]Matrix Factorization Techniques for Recommender Systems(2009,Published by the IEEE Computer So ...
- 【转】细说UI线程和Windows消息队列
在Windows应用程序中,窗体是由一种称为“UI线程(User Interface Thread)”的特殊类型的线程创建的. 首先,UI线程是一种“线程”,所以它具有一个线程应该具有的所有特征,比如 ...
- 简单的zip压缩和解压缩
其实像这样的php拓展很多,只是项目中没怎么用到: <?php $zip = new ZipArchive(); $filename = "./test112.zip"; / ...
- 【Android】Android动态加载Jar、APK的实现
本文介绍Android中动态加载Jar.APK的实现.而主要用到的就是DexClassLoader这个类.大家都知道Android和普通的Java虚拟机有差别,它只能加载经过处理的dex文件.而加载这 ...
- Android中ViewPager实现滑动条及与Fragment结合的实例教程
ViewPager类主要被用来实现可滑动的视图功能,这里我们就来共同学习Android中ViewPager实现滑动条及与Fragment结合的实例教程,需要的朋友可以参考下 自主实现滑动指示条先上一个 ...
- Python——验证码识别 Pillow + tesseract-ocr
至于安装教程在这里不再重复说了,可以参考博客,网上有大把的教程 https://blog.csdn.net/testcs_dn/article/details/78697730 要是别的验证码是如下类 ...
- AR模型与数据平稳性之间的关系
作者:桂. 时间:2017-12-19 21:39:08 链接:http://www.cnblogs.com/xingshansi/p/8068021.html 前言 前几天碰到一个序列分析的问题, ...
- Vue(四):实例化第一个Vue应用
实例化语法 var vm = new Vue({ // 选项 }) Vue 构造器中的内容 <!DOCTYPE html> <html> <head> <me ...
- Oozie workflow工作流action间参数传递实现
假设workflow里有两个action节点,shell和hive,hive需要用到shell节点里的值,shell脚本如下 #!/bin/sh day=`date '+%Y%m%d%H'` echo ...