关键数据结构之帧结构:mad_herder和mad_frame

一个MP3帧由帧头和帧数据构成。Madlib分别填充mad_herdermad_frame这两个结构,然后进行解码。mad_herder里包含mp3数据的描述信息,这个结构在frame.h头文件中定义:

struct mad_header { enum mad_layer layer; /* audio layer (1, 2, or 3) */ enum mad_mode mode; /* channel mode (see above) */ int mode_extension; /* additional mode info */ enum mad_emphasis emphasis; /* de-emphasis to use (see above) */ unsigned long bitrate; /* stream bitrate (bps) */ unsigned int samplerate; /* sampling frequency (Hz) */ unsigned short crc_check; /* frame CRC accumulator */ unsigned short crc_target; /* final target CRC checksum */ int flags; /* flags (see below) */ int private_bits; /* private bits (see below) */ mad_timer_t duration; /* audio playing time of frame */ };

layer成员的类型是enum mad_layer,这个枚举类型有3个取值(123),分别对应MPEG音频的123层;mode成员描述音频的声道数和立体声类型,取值为MAD_MODE_SINGLE_CHANNEL(单声道)、MAD_MODE_DUAL_CHANNEL(双声道)、MAD_MODE_JOINT_STEREO(联合立体声)、MAD_MODE_STEREO(普通立体声);接下来的比特率、采样率、CRC校验、播放时间等信息直接来自mp3帧。

mad_frame包含一个帧头(mad_herder)和一帧中的采样数据。该结构同样定义于frame.h头文件中:

struct mad_frame { struct mad_header header; /* MPEG audio header */ int options; /* decoding options (from stream) */ mad_fixed_t sbsample[2][36][32]; /* synthesis subband filter samples */ mad_fixed_t (*overlap)[2][32][18]; /* Layer III block overlap data */ };

static enum mad_flow output(void *data, struct mad_header const *header, struct mad_pcm *pcm) { unsigned int nchannels, nsamples; mad_fixed_t const *left_ch, *right_ch; /* pcm->samplerate contains the sampling frequency */ nchannels = pcm->channels; nsamples = pcm->length; left_ch = pcm->samples[0]; right_ch = pcm->samples[1]; while (nsamples--) { signed int sample; /* output sample(s) in 16-bit signed little-endian PCM */ sample = scale(*left_ch++); putchar((sample >> 0) & 0xff);//输出低8位 putchar((sample >> 8) & 0xff);//输出高8位 if (nchannels == 2) { sample = scale(*right_ch++); putchar((sample >> 0) & 0xff);//输出低8位 putchar((sample >> 8) & 0xff);//输出高8位 } }

 

其中的option字段来自mad_stream结构,sbsample[2][36][32]中保存的就是从mp3文件中取得的采样数据:2个声道,每声道36个采样(可播放26ms的音频,每秒帧速率大约为38fps);overlap指针成我员不了解它的用途,希望有高手不吝赐教!

Madlib每次解码循环结束时解码完成一个帧,将1152PCM采样数据保存在数组里传递给output回调函数作输出前的处理。压缩包里的参考示例minimad.c中的output回调函数只是简单地将PCM数据在屏幕上打印显示:

 

 

你可能感兴趣的:(数据结构,Stream,struct,header,layer,output)