📄 layer3.c
字号:
MAD_F_MLA(hi, lo, X[2], (*s)[2]);
MAD_F_MLA(hi, lo, X[3], (*s)[3]);
MAD_F_MLA(hi, lo, X[4], (*s)[4]);
MAD_F_MLA(hi, lo, X[5], (*s)[5]);
yptr[i + 0] = MAD_F_MLZ(hi, lo);
yptr[5 - i] = -yptr[i + 0];
++s;
MAD_F_ML0(hi, lo, X[0], (*s)[0]);
MAD_F_MLA(hi, lo, X[1], (*s)[1]);
MAD_F_MLA(hi, lo, X[2], (*s)[2]);
MAD_F_MLA(hi, lo, X[3], (*s)[3]);
MAD_F_MLA(hi, lo, X[4], (*s)[4]);
MAD_F_MLA(hi, lo, X[5], (*s)[5]);
yptr[ i + 6] = MAD_F_MLZ(hi, lo);
yptr[11 - i] = yptr[i + 6];
++s;
}
yptr += 12;
X += 6;
}
/* windowing, overlapping and concatenation */
yptr = &y[0];
wptr = &window_s[0];
for (i = 0; i < 6; ++i) {
z[i + 0] = 0;
z[i + 6] = mad_f_mul(yptr[ 0 + 0], wptr[0]);
MAD_F_ML0(hi, lo, yptr[ 0 + 6], wptr[6]);
MAD_F_MLA(hi, lo, yptr[12 + 0], wptr[0]);
z[i + 12] = MAD_F_MLZ(hi, lo);
MAD_F_ML0(hi, lo, yptr[12 + 6], wptr[6]);
MAD_F_MLA(hi, lo, yptr[24 + 0], wptr[0]);
z[i + 18] = MAD_F_MLZ(hi, lo);
z[i + 24] = mad_f_mul(yptr[24 + 6], wptr[6]);
z[i + 30] = 0;
++yptr;
++wptr;
}
}
/*
* NAME: III_overlap()
* DESCRIPTION: perform overlap-add of windowed IMDCT outputs
*/
static
void III_overlap(mad_fixed_t const output[36], mad_fixed_t overlap[18],
mad_fixed_t sample[18][32], unsigned int sb)
{
unsigned int i;
# if defined(ASO_INTERLEAVE2)
{
register mad_fixed_t tmp1, tmp2;
tmp1 = overlap[0];
tmp2 = overlap[1];
for (i = 0; i < 16; i += 2) {
sample[i + 0][sb] = output[i + 0] + tmp1;
overlap[i + 0] = output[i + 0 + 18];
tmp1 = overlap[i + 2];
sample[i + 1][sb] = output[i + 1] + tmp2;
overlap[i + 1] = output[i + 1 + 18];
tmp2 = overlap[i + 3];
}
sample[16][sb] = output[16] + tmp1;
overlap[16] = output[16 + 18];
sample[17][sb] = output[17] + tmp2;
overlap[17] = output[17 + 18];
}
# elif 0
for (i = 0; i < 18; i += 2) {
sample[i + 0][sb] = output[i + 0] + overlap[i + 0];
overlap[i + 0] = output[i + 0 + 18];
sample[i + 1][sb] = output[i + 1] + overlap[i + 1];
overlap[i + 1] = output[i + 1 + 18];
}
# else
for (i = 0; i < 18; ++i) {
sample[i][sb] = output[i] + overlap[i];
overlap[i] = output[i + 18];
}
# endif
}
/*
* NAME: III_overlap_z()
* DESCRIPTION: perform "overlap-add" of zero IMDCT outputs
*/
static inline
void III_overlap_z(mad_fixed_t overlap[18],
mad_fixed_t sample[18][32], unsigned int sb)
{
unsigned int i;
# if defined(ASO_INTERLEAVE2)
{
register mad_fixed_t tmp1, tmp2;
tmp1 = overlap[0];
tmp2 = overlap[1];
for (i = 0; i < 16; i += 2) {
sample[i + 0][sb] = tmp1;
overlap[i + 0] = 0;
tmp1 = overlap[i + 2];
sample[i + 1][sb] = tmp2;
overlap[i + 1] = 0;
tmp2 = overlap[i + 3];
}
sample[16][sb] = tmp1;
overlap[16] = 0;
sample[17][sb] = tmp2;
overlap[17] = 0;
}
# else
for (i = 0; i < 18; ++i) {
sample[i][sb] = overlap[i];
overlap[i] = 0;
}
# endif
}
/*
* NAME: III_freqinver()
* DESCRIPTION: perform subband frequency inversion for odd sample lines
*/
static
void III_freqinver(mad_fixed_t sample[18][32], unsigned int sb)
{
unsigned int i;
# if 1 || defined(ASO_INTERLEAVE1) || defined(ASO_INTERLEAVE2)
{
register mad_fixed_t tmp1, tmp2;
tmp1 = sample[1][sb];
tmp2 = sample[3][sb];
for (i = 1; i < 13; i += 4) {
sample[i + 0][sb] = -tmp1;
tmp1 = sample[i + 4][sb];
sample[i + 2][sb] = -tmp2;
tmp2 = sample[i + 6][sb];
}
sample[13][sb] = -tmp1;
tmp1 = sample[17][sb];
sample[15][sb] = -tmp2;
sample[17][sb] = -tmp1;
}
# else
for (i = 1; i < 18; i += 2)
sample[i][sb] = -sample[i][sb];
# endif
}
/*
* NAME: III_decode()
* DESCRIPTION: decode frame main_data
*/
static
enum mad_error III_decode(struct mad_bitptr *ptr, struct mad_frame *frame,
struct sideinfo *si, unsigned int nch)
{
struct mad_header *header = &frame->header;
unsigned int sfreqi, ngr, gr;
{
unsigned int sfreq;
sfreq = header->samplerate;
if (header->flags & MAD_FLAG_MPEG_2_5_EXT)
sfreq *= 2;
/* 48000 => 0, 44100 => 1, 32000 => 2,
24000 => 3, 22050 => 4, 16000 => 5 */
sfreqi = ((sfreq >> 7) & 0x000f) +
((sfreq >> 15) & 0x0001) - 8;
if (header->flags & MAD_FLAG_MPEG_2_5_EXT)
sfreqi += 3;
}
/* scalefactors, Huffman decoding, requantization */
ngr = (header->flags & MAD_FLAG_LSF_EXT) ? 1 : 2;
for (gr = 0; gr < ngr; ++gr) {
struct granule *granule = &si->gr[gr];
unsigned char const *sfbwidth[2];
mad_fixed_t xr[2][576];
unsigned int ch;
enum mad_error error;
for (ch = 0; ch < nch; ++ch) {
struct channel *channel = &granule->ch[ch];
unsigned int part2_length;
sfbwidth[ch] = sfbwidth_table[sfreqi].l;
if (channel->block_type == 2) {
sfbwidth[ch] = (channel->flags & mixed_block_flag) ?
sfbwidth_table[sfreqi].m : sfbwidth_table[sfreqi].s;
}
if (header->flags & MAD_FLAG_LSF_EXT) {
part2_length = III_scalefactors_lsf(ptr, channel,
ch == 0 ? 0 : &si->gr[1].ch[1],
header->mode_extension);
}
else {
part2_length = III_scalefactors(ptr, channel, &si->gr[0].ch[ch],
gr == 0 ? 0 : si->scfsi[ch]);
}
error = III_huffdecode(ptr, xr[ch], channel, sfbwidth[ch], part2_length);
if (error)
return error;
}
/* joint stereo processing */
if (header->mode == MAD_MODE_JOINT_STEREO && header->mode_extension) {
error = III_stereo(xr, granule, header, sfbwidth[0]);
if (error)
return error;
}
/* reordering, alias reduction, IMDCT, overlap-add, frequency inversion */
for (ch = 0; ch < nch; ++ch) {
struct channel const *channel = &granule->ch[ch];
mad_fixed_t (*sample)[32] = &frame->sbsample[ch][18 * gr];
unsigned int sb, l, i, sblimit;
mad_fixed_t output[36];
if (channel->block_type == 2) {
III_reorder(xr[ch], channel, sfbwidth[ch]);
# if !defined(OPT_STRICT)
/*
* According to ISO/IEC 11172-3, "Alias reduction is not applied for
* granules with block_type == 2 (short block)." However, other
* sources suggest alias reduction should indeed be performed on the
* lower two subbands of mixed blocks. Most other implementations do
* this, so by default we will too.
*/
if (channel->flags & mixed_block_flag)
III_aliasreduce(xr[ch], 36);
# endif
}
else
III_aliasreduce(xr[ch], 576);
l = 0;
/* subbands 0-1 */
if (channel->block_type != 2 || (channel->flags & mixed_block_flag)) {
unsigned int block_type;
block_type = channel->block_type;
if (channel->flags & mixed_block_flag)
block_type = 0;
/* long blocks */
for (sb = 0; sb < 2; ++sb, l += 18) {
III_imdct_l(&xr[ch][l], output, block_type);
III_overlap(output, (*frame->overlap)[ch][sb], sample, sb);
}
}
else {
/* short blocks */
for (sb = 0; sb < 2; ++sb, l += 18) {
III_imdct_s(&xr[ch][l], output);
III_overlap(output, (*frame->overlap)[ch][sb], sample, sb);
}
}
III_freqinver(sample, 1);
/* (nonzero) subbands 2-31 */
i = 576;
while (i > 36 && xr[ch][i - 1] == 0)
--i;
sblimit = 32 - (576 - i) / 18;
if (channel->block_type != 2) {
/* long blocks */
for (sb = 2; sb < sblimit; ++sb, l += 18) {
III_imdct_l(&xr[ch][l], output, channel->block_type);
III_overlap(output, (*frame->overlap)[ch][sb], sample, sb);
if (sb & 1)
III_freqinver(sample, sb);
}
}
else {
/* short blocks */
for (sb = 2; sb < sblimit; ++sb, l += 18) {
III_imdct_s(&xr[ch][l], output);
III_overlap(output, (*frame->overlap)[ch][sb], sample, sb);
if (sb & 1)
III_freqinver(sample, sb);
}
}
/* remaining (zero) subbands */
for (sb = sblimit; sb < 32; ++sb) {
III_overlap_z((*frame->overlap)[ch][sb], sample, sb);
if (sb & 1)
III_freqinver(sample, sb);
}
}
}
return MAD_ERROR_NONE;
}
/*
* NAME: layer->III()
* DESCRIPTION: decode a single Layer III frame
*/
int mad_layer_III(struct mad_stream *stream, struct mad_frame *frame)
{
struct mad_header *header = &frame->header;
unsigned int nch, priv_bitlen, next_md_begin = 0;
unsigned int si_len, data_bitlen, md_len;
unsigned int frame_space, frame_used, frame_free;
struct mad_bitptr ptr;
struct sideinfo si;
enum mad_error error;
int result = 0;
/* allocate Layer III dynamic structures */
if (stream->main_data == 0) {
stream->main_data = malloc(MAD_BUFFER_MDLEN);
if (stream->main_data == 0) {
stream->error = MAD_ERROR_NOMEM;
return -1;
}
}
if (frame->overlap == 0) {
frame->overlap = calloc(2 * 32 * 18, sizeof(mad_fixed_t));
if (frame->overlap == 0) {
stream->error = MAD_ERROR_NOMEM;
return -1;
}
}
nch = MAD_NCHANNELS(header);
si_len = (header->flags & MAD_FLAG_LSF_EXT) ?
(nch == 1 ? 9 : 17) : (nch == 1 ? 17 : 32);
/* check frame sanity */
if (stream->next_frame - mad_bit_nextbyte(&stream->ptr) <
(signed int) si_len) {
stream->error = MAD_ERROR_BADFRAMELEN;
stream->md_len = 0;
return -1;
}
/* check CRC word */
if (header->flags & MAD_FLAG_PROTECTION) {
header->crc_check =
mad_bit_crc(stream->ptr, si_len * CHAR_BIT, header->crc_check);
if (header->crc_check != header->crc_target &&
!(frame->options & MAD_OPTION_IGNORECRC)) {
stream->error = MAD_ERROR_BADCRC;
result = -1;
}
}
/* decode frame side information */
error = III_sideinfo(&stream->ptr, nch, header->flags & MAD_FLAG_LSF_EXT,
&si, &data_bitlen, &priv_bitlen);
if (error && result == 0) {
stream->error = error;
result = -1;
}
header->flags |= priv_bitlen;
header->private_bits |= si.private_bits;
/* find main_data of next frame */
{
struct mad_bitptr peek;
unsigned long header;
mad_bit_init(&peek, stream->next_frame);
header = mad_bit_read(&peek, 32);
if ((header & 0xffe60000L) /* syncword | layer */ == 0xffe20000L) {
if (!(header & 0x00010000L)) /* protection_bit */
mad_bit_skip(&peek, 16); /* crc_check */
next_md_begin =
mad_bit_read(&peek, (header & 0x00080000L) /* ID */ ? 9 : 8);
}
mad_bit_finish(&peek);
}
/* find main_data of this frame */
frame_space = stream->next_frame - mad_bit_nextbyte(&stream->ptr);
if (next_md_begin > si.main_data_begin + frame_space)
next_md_begin = 0;
md_len = si.main_data_begin + frame_space - next_md_begin;
frame_used = 0;
if (si.main_data_begin == 0) {
ptr = stream->ptr;
stream->md_len = 0;
frame_used = md_len;
}
else {
if (si.main_data_begin > stream->md_len) {
if (result == 0) {
stream->error = MAD_ERROR_BADDATAPTR;
result = -1;
}
}
else {
mad_bit_init(&ptr,
*stream->main_data + stream->md_len - si.main_data_begin);
if (md_len > si.main_data_begin) {
assert(stream->md_len + md_len -
si.main_data_begin <= MAD_BUFFER_MDLEN);
memcpy(*stream->main_data + stream->md_len,
mad_bit_nextbyte(&stream->ptr),
frame_used = md_len - si.main_data_begin);
stream->md_len += frame_used;
}
}
}
frame_free = frame_space - frame_used;
/* decode main_data */
if (result == 0) {
error = III_decode(&ptr, frame, &si, nch);
if (error) {
stream->error = error;
result = -1;
}
/* desig
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -