• SDL 声音库 (SoundBank)


    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)

  • 相关阅读:
    4 种高可用 RocketMQ 集群搭建方案!
    Spring @Autowired 注解自动注入流程是怎么样?
    AQS 自定义同步锁,挺难的!
    PyCharm爬虫实例:使用Scrapy抓取网页特定内容、数据采集与数据预处理--biaobiao88
    Ubuntu中安装Hadoop出现的问题
    Win10系统FF新推荐弹窗的卸载方法
    Sublime Text 中文乱码(解决)
    JProfiler的安装
    稀疏数组
    算法基础<一>
  • 原文地址:https://www.cnblogs.com/Henrya2/p/1418535.html
Copyright © 2020-2023  润新知