SDL播放wav格式的音樂

#include "stdafx.h"
#include<stdlib.h>
#include<stdio.h>
#include<SDL.h>
#include<SDL_config.h>
static SDL_AudioSpec spec;
static Uint8 *sound = NULL;
static Uint32 soundlen = 0;

static int posindex = 0;
static Uint32 positions[64];

static void quit(int rc) 
{
    SDL_Quit();
    exit(rc);
}

/*
_pos:userdata的數據
stream:需要填充的流
len:相應stream的大小

簡單來說就是將音頻在內存中的地址複製給stream,SDL會播放stream中對應地址的數據
*/
void SDLCALL fillerup(void *_pos, Uint8 *stream, int len)
{

    Uint32 pos = *((Uint32*)_pos);

    Uint8 *waveptr;
    int waveleft;

    /*設置當前聲音指針
    聲音指針+當前播放的位置
    */
    waveptr = sound + pos;

    //剩餘聲音數據   聲音數據長度-當前播放的位置   
    waveleft = soundlen - pos;

    /* 如果剩餘數據<需要的長度 */
    while (waveleft <= len)
    {
        //拷貝剩餘數據到音頻緩衝區  
        SDL_memcpy(stream,waveptr,waveleft);

        //音頻緩衝區stream指針後移  
        stream += waveleft;
        len -= waveleft;

        //拷貝玩剩餘數據  
        //waveptr指向 聲音數據開頭    
        waveptr = sound;

        //長度等於len
        waveleft = soundlen;
        pos = 0;
    }

    SDL_memcpy(stream, waveptr, len);
    pos += len;
    *((Uint32*)_pos) = pos;

}

static int done = 0;

void poked(int sig) 
{
    done = 1;
}

static void iteration()
{
    SDL_Event e;
    SDL_AudioDeviceID dev;

    //獲取當前等待的事件
    while (SDL_PollEvent(&e)) 
    {
        if (e.type == SDL_QUIT) 
        {
            done = 1;
        }
        else if (e.type==SDL_AUDIODEVICEADDED)//音頻添加
        {
            const char *name = SDL_GetAudioDeviceName(e.adevice.which, 0);
            SDL_Log("new %s audio device :%s\n",e.adevice.iscapture?"capture":"output",name);

            if (!e.adevice.iscapture)
            {
                positions[posindex] = 0;

                spec.userdata = &positions[posindex++];

                spec.callback = fillerup;

                dev = SDL_OpenAudioDevice(name, 0, &spec, NULL, 0);

                if (!dev)
                {
                    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "can not open '%s':%s\n",name, SDL_GetError());
                }
                else
                {
                    SDL_Log("opened '%s' as %u \n", name, (unsigned int)dev);

                    //循環播放音樂
                    SDL_PauseAudioDevice(dev, 0);

                    SDL_OpenAudio(&spec,NULL);
                }

            }
            else if (e.type==SDL_AUDIODEVICEREMOVED)//音頻移除
            {
                dev = (SDL_AudioDeviceID)e.adevice.which;
                SDL_Log("%s device %u removed.\n", e.adevice.iscapture ? "capture" : "output", (unsigned int)dev);

                //關閉音頻設備
                SDL_CloseAudioDevice(dev);
            }
        }

    }

}


/**
音頻播放的步驟
1.初始化SDL模塊,這裏是要播放音樂,所有初始化SDL_INIT_AUDIO和視頻模塊
2.創建窗口
3.加載音頻
4.播放音頻
5.視頻音頻
6.退出SDL
*/

int main(int argc, char* argv[])
{
    int i;
    char filename[4096];

    //設置顯示application 的log信息
    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);


    //設置sdl要初始化的模塊
    if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO)<0) 
    {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,"couldn't initialize SDL:%s\n",SDL_GetError());
        return 1;
    }

    //創建窗口
    //SDL_MinimizeWindow(SDL_CreateWindow("test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0));

    //獲取文件名
    if (argc > 1)
    {
        SDL_strlcpy(filename, argv[1], sizeof(filename));
    }
    else
    {
        SDL_strlcpy(filename, "sample.wav", sizeof(filename));
        //SDL_strlcpy(filename, "Now.mp3", sizeof(filename));
    }



    /**
     將音頻文件加載到內存中
     filename:文件名
     spec:音頻的規格
     sound:音頻的句柄
     soundlen:音頻文件的長度
    */
    if (SDL_LoadWAV(filename, &spec, &sound, &soundlen) == NULL)
    {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,"cound't load %s:%s \n",filename,SDL_GetError());
        quit(1);
    }


    SDL_Log("available audio drivers");


    //打印音頻設備
    for (i = 0; i < SDL_GetNumAudioDrivers(); i++)
    {
        SDL_Log("%i:%s", i, SDL_GetAudioDriver(i));
    }

    //查看當前使用的音頻設備
    SDL_Log("Using audio driver:%s\n", SDL_GetCurrentAudioDriver());


    while (!done)
    {
        SDL_Delay(100);
        iteration();
    }

    //釋放音頻內存
    SDL_FreeWAV(sound);

    //退出sdl
    SDL_Quit();


    system("pause");
    return 0;
}

我這裏只是將官網給出的例子添加了註釋,方便大家理解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章