Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2092765
  • 博文数量: 413
  • 博客积分: 10926
  • 博客等级: 上将
  • 技术积分: 3862
  • 用 户 组: 普通用户
  • 注册时间: 2006-01-09 18:14
文章分类

全部博文(413)

文章存档

2015年(5)

2014年(1)

2013年(5)

2012年(6)

2011年(138)

2010年(85)

2009年(42)

2008年(46)

2007年(26)

2006年(59)

分类: LINUX

2006-04-13 14:20:01

SDL在默认情况下,只支持WAV格式,如果要播放其他格式的文件我们可以采用SDL_mixer,它支持WAV,MP3,MIDI,OGG,MOD,如果要支持更多的文件格式,我们就不得不采用其他库了.
一. SDL 下播放WAV 格式的声音文件.
1 步骤:
    (1) 打开WAV文件,将WAV文件中的声音数据全部拷贝到内存.
    (2) 设置播放参数(采样率,比特数,声道),分配内存,将(1)中获得的数据转换成前面设置格式,将转换后的数据保存到所分配的内存中.
    (3) 关闭声音文件.
    (4) 打开声音设备,并设置参数,这里的参数跟(2)中设置的播放参数一致,并设置回掉函数,回调函数用于在播放每一帧数据之前,对其进行处理.
    (5) 开始播放
    (6) 播放完成后释放(2)中所分配的内存.
    (7) 关闭声音设备.
2 example:

#define NUM_SOUNDS 2
struct sample {
    Uint8 *data;
    Uint32 dpos;
    Uint32 dlen;
} sounds[NUM_SOUNDS];

//this is callback function,it is executed in separate thread.
void mixaudio(void *unused, Uint8 *stream, int len)
{
    int i;
    Uint32 amount;

    for ( i=0; i         amount = (sounds[i].dlen-sounds[i].dpos);
        if ( amount > len ) {
            amount = len;
        }

        //convert original sound data from wav file to destnation format
        SDL_MixAudio(stream, &sounds[i].data[sounds[i].dpos], amount, SDL_MIX_MAXVOLUME);
        sounds[i].dpos += amount;
    }
}

int Open_Audio()
{
    SDL_AudioSpec fmt;

    //open audio device and set properties
    fmt.freq = 22050;
    fmt.format = AUDIO_S16;
    fmt.channels = 2;
    fmt.samples = 512;
    fmt.callback = mixaudio;
    fmt.userdata = NULL;

    if ( SDL_OpenAudio(&fmt, NULL) < 0 )
    {
        debug("无法打开音频: %s\n", SDL_GetError());
        return -1;
    }

    //begin play
    SDL_PauseAudio(0);
}

void PlaySound(char *file)
{
        int index;
        SDL_AudioSpec wave;
        Uint8 *data;
        Uint32 dlen;
        SDL_AudioCVT cvt;

        //find an empty sound port
        for ( index=0; index         {
                if ( sounds[index].dpos == sounds[index].dlen )
                {
                    break;
                }
        }
        if ( index == NUM_SOUNDS )
                return;


        //load wav file, and copy sound data to buffer
        if ( SDL_LoadWAV(file, &wave, &data, &dlen) == NULL )
        {
                debug("call SDL_LoadWAV failed\n");
                return;
        }
        //build audio convertion struct
        SDL_BuildAudioCVT(&cvt, wave.format, wave.channels, wave.freq,
                            AUDIO_S16,   2,             22050);
        //build cvt.buf, and copy sound data to this buffer,then free sound data buffer
        cvt.buf = (Uint8 *)malloc(dlen*cvt.len_mult);
        memcpy(cvt.buf, data, dlen);
        cvt.len = dlen;
        SDL_ConvertAudio(&cvt);
        SDL_FreeWAV(data);


        //free history sound buffer,it is equal to cvt.buf
        if ( sounds[index].data )
        {
                free(sounds[index].data);
        }


        //protect resource which will be used in thread mixaudio
        SDL_LockAudio();
        sounds[index].data = cvt.buf;
        sounds[index].dlen = cvt.len_cvt;
        sounds[index].dpos = 0;
        SDL_UnlockAudio();

        //open audio to play
        Open_Audio();
}


播放时,调用函数PlaySound()即可,如:
PlaySound("test.wav);

注意:
  (1) 由于回调函数是在一个独立的线程中执行的,所以要注意保护资源,本例中的SDL_LockAudio,SDL_UnlockAudio正是起这样的作用
  (2) 由于SDL一次将WAV文件中全部数据都拷贝到内存中,所以这种播放方式只适合较小的WAV文件的播放.


                                           (...continued)
阅读(5672) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~