A Little Fool

Fool For Free.

博客园 首页 新随笔 联系 订阅 管理

SDL 声音库 (SoundBank)

 

    本系列教程来自Dev Hub

英文原文地址: http://www.sdltutorials.com/sdl-soundbank/


在这附加的教程里,我们将会增加一个声音库用于加载我们所有的声音。并且,我们通过ID来播放这些文件,不管我们什么时候想要。这个教程只会涉及到声音,没有音乐,对于你来说这是一个非常基本的教程,仅仅让这声音处理的事情完成了。有很多东西可以被加到这个类里,通道,组等等,但是在这里我们只处理基本事情。我们这个教程将会基于我先前的SDL Events 教程。所以,使用这些项目文件如果你想要下面的例子正常工作的话。


 第一件你要去做的事情是从 SDL website下载SDL mixer。那里也有我主页上提供的SDL库。确保include文件和SDL的inlcude文件在同一个目录下。lib目录和SDL的lib文件在同一目录下,使得事情变得简单。


通过打开你的项目来开始吧,然后进入到linker设置。吧SDL_mixer加在SDLmain以后,就像:

mingw32
SDLmain
SDL_mixer
SDL

如果你不记得在哪里去找这些设置,你可以去看看第一个教程,温习一下链接设置。如果你有一个.lib的文件,而不是.a的文件,通过browse按钮去找到库文件。


仅仅在一个小方注意一下声音。SDL_mixer把任何在内存里声音都当成是数据块(chunk)。数据块(chunk)包含了频率数据。SDL_mixer的好处是,由来它处理这些数据,并把它发送到音频输出,那意味着SDL_mixer做了所有这些困难的工作。所以所有我们要做的事情只需要加载我们的数据。比如从一个WAV文件里,然后将它发送到SDL_mixer去播放。

 

首先,创建两个新文件,CSoundBank.h和CSoundBank.cpp。先打开头文件:

#ifndef _CSOUNDBANK_H_
    
#define _CSOUNDBANK_H_

#include 
<SDL.h>
#include 
<SDL_mixer.h>
#include 
<vector>

class CSoundBank {
    
public:
        
static CSoundBank           SoundControl;

        std::vector
<Mix_Chunk*>     SoundList;

    
public:
        CSoundBank();

        
int OnLoad(char* File);

        
void OnCleanup();

    
public:
        
void Play(int ID);
};

#endif

 

 我们先有了一个静态的控制对象,这让我们能在程序的任何位置增加声音和播放声音。想象一下这个东西就像是增加/播放声音的主控件。然后我们有了我们的SoundList,这是一个SDL_mixer声音的列表。现在,一个Mix_Chunk的对象包含了需要去播放一个声音的信息。我们接下来要做的事情是加载一个wav文件到Mix_Chunk对象里。想象一下,声音就像SDL_Surface。那么,我们有了一些加载,清除,和播放声音的的基本功能了。很简单吧。

接下来,打开CSoundBank.cpp:

#include "CSoundBank.h"

CSoundBank CSoundBank::SoundControl;

CSoundBank::CSoundBank() {
}

int CSoundBank::OnLoad(char* File) {
    Mix_Chunk
* TempSound = NULL;

    
if((TempSound = Mix_LoadWAV(File)) == NULL) {
        
return -1;
    }

    SoundList.push_back(TempSound);

    
return (SoundList.size() - 1);
}

void CSoundBank::OnCleanup() {
    
for(int i = 0;i < SoundList.size();i++) {
        Mix_FreeChunk(SoundList[i]);
    }

    SoundList.clear();
}

void CSoundBank::Play(int ID) {
    
if(ID < 0 || ID >= SoundList.size()) return;
    
if(SoundList[ID] == NULL) return;

    Mix_PlayChannel(
-1, SoundList[ID], 0);
}



这些东西也是非常直观的。我们有一个静态控件,我们空的构造函数,并且还有我们的加载函数。我们基本上能够让声音文件被加载,并且尝试通过Mix_LoadWAV加载到Mix_Chunk对象里。 注意,我先是创建一个临时对象,然后把它扔到列表里。在快接近函数结束的地方,我返回最后被插入声音的ID。因此,例如,我加载了SoundA和SoundB:

int SoundA = CSoundBank::SoundControl.OnLoad("sounda.wav");
int SoundB = CSoundBank::SoundControl.OnLoad("soundb.wav");

 

用来播放这个声音的ID会被OnLoad函数返回。

OK,接下来我们有cleanup函数,它遍历这个列表并且释放声音数据块。就像SDL_FreeSurface一样简单吧。

 

最后,我们有了真正播放声音的Play函数。我们先传一个ID(从Load函数得到的返回值)给Play函数。我们做一小点边界测试,确保ID是有效的。然后,试着去播放声音。Mix_PlayChannel有三个参数:

第一个参数指定要播放的通道,-1代表使用第一个可用的通道。

第二个参数指定要播放的数据块。

最后一个参数指定要播放多长的时间。-1代表无限。

 

我们这个类里没有做大量的关于通道的工作,但是这个类很容被修改,增加功能。基本的,通道允许你修改特定声音的设定。例如,你可以设置音量和偏移在第一个通道上,因此任何在那个通道上播放的声音都有同样的效果。

 

现在那么让我们做一点小小的测试。打开CApp.h,并且加上头文件,然后加上一些变量和函数到CApp类里:

#include "CSoundBank.h"

//

class CApp {
    
public:
        
int SoundA;
        
int SoundB;

        
//… other code

    
public:
        
void OnKeyDown(SDLKey sym, SDLMod mod, Uint16 unicode);
};


 

现在,打开CApp_Init.cpp,要是我们能够加载一些声音:

if((SoundA = CSoundBank::SoundControl.OnLoad("sounda.wav")) == -1) {
    
return false;
}

if((SoundB = CSoundBank::SoundControl.OnLoad("soundb.wav")) == -1) {
    
return false;
}


现在,为了能让我们按下一个按键是发出声音,打开CApp_OnEvent.cpp,然后增加下面的函数:

void CApp::OnKeyDown(SDLKey sym, SDLMod mod, Uint16 unicode) {
    
if(sym == SDLK_1) {
        CSoundBank::SoundControl.Play(SoundA);
    }

    
if(sym == SDLK_2) {
        CSoundBank::SoundControl.Play(SoundB);
    }
}


 

我们还没有完成,我们必须做一点点事情去启动SDL_mixer。这就像是启动SDL一样,但是我们需要的是去启动SDL_mixer去访问声音。打开CApp_Init.cpp并且加入下面的代码,在SDL_Init下面一点的地方。

if(Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 24096< 0) {
    
return false;
}

 

Mix_OpenAudio简单的初始话SDL_Mixer。 这个函数接受4个参数。第一个参数用来指定频率,44100通常是一个比较好的频率。但是你依据的WAV文件,你也许要变更频率。另一个通用的频率是22050。我不想谈论过的关于频率的细节,让它在那里,除非你真的需要改变它。下一个参数是格式(format),最好是不要管它除非你有很多关于声音的知识(基本上是采样的大小,8位或16位)。再下一个参数是通道数,1 代表单声道,2代表立体声。注意,这里的通道和以前我在其地方谈的通道是不一样的。这里的通道,其实是声音的输出数目。想象一下,他就像是你有的音箱数目。两个音箱,两个通道。最后一个参数是用来设置声音的大小。除非你真的知道怎么做,最好不要去管它。


为了让代码整洁,当我们完成时我们需要确保我们停止了SDL_mixer的服务,就像是释放任何我们加载的声音。

所以打开CApp_OnCleanup.cpp,然后加入下面的代码:

 

CSoundBank::SoundControl.OnCleanup();

Mix_CloseAudio();


 

我们完成了!试着去编译,并且按下1 和 2 键去听一些声音。如果你需要一些WAV文件,下载下面的项目文件去获取它们。

SDL 声音库 (SoundBank) - 课程文件:
Win32: Zip, Rar
Linux: Tar (Thanks Gaten)

posted on 2009-03-22 00:19  HenryRead  阅读(2635)  评论(1编辑  收藏  举报