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)