Chinaunix首页 | 论坛 | 博客
  • 博客访问: 365425
  • 博文数量: 242
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 1134
  • 用 户 组: 普通用户
  • 注册时间: 2012-10-20 10:53
文章分类

全部博文(242)

文章存档

2015年(1)

2014年(10)

2013年(18)

2012年(213)

分类:

2012-11-07 10:41:10

原文地址:SDL下播放声音文件 作者:iARM


SDL在默认情况下,只支持WAV格式,如果要播放其他格式的文件我们可以采用SDL_mixer,它支持WAV,MP3,MIDI,OGG,MOD,如果要支持更多的文件格式,我们就不得不采用其他库了. 一. SDL 下播放WAV 格式的声音文件. 1 步骤: (1) 打开WAV文件,将WAV文件中的声音数据全部拷贝到内存. ...
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 len ) {
            amount = len;
        }
        //convert original sound data from wav file to destnation format
        SDL_MixAudio(stream, &sounds.data[sounds.dpos], amount, SDL_MIX_MAXVOLUME);
        sounds.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 =
    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 =
        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)
阅读(422) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~