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动态缩减功能以下就来细致看看吧:整合好 ...
随机推荐
- 最新CoreData封装Demo
1.创建CoreData文件 2. 3. 4. UploadCoreDataAPI.h // // UploadCoreDataAPI.h // dsafsda // // Created by 冯敏 ...
- 腾讯大讲堂 微信红包系统设计 & 优化
http://djt.qq.com/article/view/1349 编者按:经过2014年一年的酝酿,2015微信红包总量创下历史新高,峰值1400万次/秒,8.1亿次每分钟,微信红包收发达10. ...
- magento登陆
magento判断用户登录 Magento 登陆之后返回登录之前的页面 magento 在登陆后一般会自动跳转到 My Account 页面 但是经常会有需求 就是登陆自动跳转到 之前的页面里面 工具 ...
- 【Algorithm】冒泡排序
一. 算法描述 冒泡排序思想:依次比较相邻的数据,将小数据放在前,大数据放在后:即第一趟先比较第1个和第2个数,大数在后,小数在前,再比较第2个数与第3个数,大数在后,小数在前,以此类推则将最大的数& ...
- Fragment使用具体解释
fragment是Google在3.0版本号中推出的新功能,如今已经增加到V4包中,假设要使用V4兼容包中的Fragment须要将Activity换成FragmentActivity,调用的getSu ...
- Desugar Scala(17) -- Option和for,以及脑子里发生的事情
欢迎关注我的新博客地址:http://cuipengfei.me/blog/2014/08/30/options-for/ Scala里的forkeyword是个非常有趣的东西. 能够用来把多层嵌套f ...
- hdu 4223 Dynamic Programming? (dp)
//连续的和的绝对值最小 # include <stdio.h> # include <string.h> # include <algorithm> # incl ...
- stm8时钟
为使系统快速启动,复位后时钟控制器自动使用HSI的8分频(HSI/8)做为主时钟(2M).其原因为HSI的稳定时间短,而8分频可保证系统在较差的VDD条件下安全启动.一旦主时钟源稳定,用户程序可将主时 ...
- 另辟蹊径 直取通州的“墨迹天气”APP应用的成功故事
一个天气应用,曾被认为是要挑战国家气象局,网站也莫名其妙地被封,两个合伙人先后离开.创始人金犁是如何把这么一款工具类应用做到人所共知的? 采访 | 郑江波 翟文婷 文 | 翟文婷 出生时间:1982年 ...
- 纯干货,Spring-data-jpa详解(转)
本篇进行Spring-data-jpa的介绍,几乎涵盖该框架的所有方面,在日常的开发当中,基本上能满足所有需求.这里不讲解JPA和Spring-data-jpa单独使用,所有的内容都是在和Spring ...