首先看源码:
typedef struct SDL_AudioSpec {
int freq; /**< DSP frequency -- samples per second */
Uint16 format; /**< Audio data format */
Uint8 channels; /**< Number of channels: 1 mono, 2 stereo */
Uint8 silence; /**< Audio buffer silence value (calculated) */
Uint16 samples; /**< Audio buffer size in samples (power of 2) */
Uint16 padding; /**< Necessary for some compile environments */
Uint32 size; /**< Audio buffer size in bytes (calculated) */
/**
* This function is called when the audio device needs more data.
*
* @param[out] stream A pointer to the audio data buffer
* @param[in] len The length of the audio buffer in bytes.
*
* Once the callback returns, the buffer will no longer be valid.
* Stereo samples are stored in a LRLRLR ordering.
*/
void (SDLCALL *callback)(void *userdata, Uint8 *stream, int len);
void *userdata;
} SDL_AudioSpec;
SDL_AudioSpec结构体是用来描述某些音频数据的格式。 结构体中的变量都会被SDL_OpenAudio()函数用到,想要用SDL处理音频数据,必须搞懂这些基础的东西。
freq 指定了每秒向音频设备发送的sample数。常用的值为:11025,22050,44100。值越高质量越好。
format 指定了每个sample元素的大小和类型。可能取值如下:
AUDIO_U8 | unsigned 8-bit samples. |
AUDIO_S8 | signed 8-bit samples. |
AUDIO_U16 or AUDIO_U16LSB | 并非所有硬件都支持(unsigned 16-bit little-endian) |
AUDIO_S16 or AUDIO_S16LSB | 并非所有硬件都支持 (signed 16-bit little-endian) |
AUDIO_U16MSB | 并非所有硬件都支持 (unsigned 16-bit big-endian) |
AUDIO_S16MSB | 并非所有硬件都支持 (signed 16-bit big-endian) |
int32 support | |
AUDIO_S32 or AUDIO_S32LSB | 32-bit integer samples |
AUDIO_S32MSB | as above, but big-endian byte order |
float32 support | |
AUDIO_F32 or AUDIO_F32LSB | 32-bit floating point samples |
AUDIO_F32MSB | as above, but big-endian byte order |
本地音频字节序 | |
AUDIO_U16SYS | AUDIO_U16LSB or AUDIO_U16MSB 取决于硬件CPU字节序 |
AUDIO_S16SYS | AUDIO_S16LSB or AUDIO_S16MSB 取决于硬件CPU字节序 |
AUDIO_S32SYS | AUDIO_S32LSB or AUDIO_S32MSB 取决于硬件CPU字节序 |
AUDIO_F32SYS | AUDIO_F32LSB or AUDIO_F32MSB 取决于硬件CPU字节序 |
channels 指定了声音的通道数:1(单声道)2(立体声)。
samples 这个值表示音频缓存区的大小(以sample计)。一个sample是一段大小为 format * channels 的音频数据。
size 这个值表示音频缓存区的大小(以byte计)。
silence 设置静音的值。
padding 考虑到兼容性的一个参数。
callback 是获取音频数据后的回调函数,可以作解码获取的音频码流及输出到设备的操作。例如:
void audio_callback(void *userdata, Uint8 *stream, int len){
AVCodecContext *aCodecCtx = (AVCodecContext *) userdata;
int len1, audio_size;
static uint8_t audio_buf[(MAX_AUDIO_FRAME_SIZE * 3) / 2];
static unsigned int audio_buf_size = 0;
static unsigned int audio_buf_index = 0;
SDL_memset(stream, 0, len);
printf("audio_callback len=%d \n", len);
//向设备发送长度为len的数据
while(len > 0){
//缓冲区中无数据
if(audio_buf_index >= audio_buf_size){
//从packet中解码数据
audio_size = audio_decode_frame(aCodecCtx, audio_buf, audio_buf_size);
printf("audio_decode_frame finish audio_size=%d \n", audio_size);
if(audio_size < 0){//没有解码到数据或者出错,填充0
audio_buf_size = 1024;
memset(audio_buf, 0, audio_buf_size);
}else{
audio_buf_size = audio_size;
}
audio_buf_index = 0;
}
len1 = audio_buf_size - audio_buf_index;
if(len1 > len)
len1 = len;
SDL_MixAudio(stream, audio_buf + audio_buf_index, len, SDL_MIX_MAXVOLUME);
len -= len1;
stream += len1;
audio_buf_index += len1;
}
}
关于callback的参数:
userdata | 程序特定的参数,保存在SDL_AudioSpec结构体中 |
stream | 指向缓存区的指针,这个缓存区将被这个回调函数填满 |
len | 上面缓存区的大小(字节数) |