📄 decode.cpp
字号:
/*
* Copyright (C) Aaron Holtzman - May 1999
*
* This file is part of ac3dec, a free Dolby AC-3 stream decoder.
*
* ac3dec is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* ac3dec is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#define AC3
#define BIT
#include "../global.h"
#include "ac3.h"
#include "bitstream.h"
void bit_allocate(uint_16 fscod, bsi_t *bsi, audblk_t *audblk);
static audblk_t audblk;
static bsi_t bsi;
static syncinfo_t syncinfo;
// the floating point samples for one audblk
static stream_samples_t samples;
// the integer samples for the entire frame (with enough space for 2 ch out)
// if this size change, be sure to change the size when muting
static sint_16 s16_samples[2 * 6 * 256];
// storage for the syncframe
#define BUFFER_MAX_SIZE 4096
static uint_8 buffer[BUFFER_MAX_SIZE];
static sint_32 buffer_size;
uint_32 decode_buffer_syncframe(syncinfo_t *syncinfo, uint_8 **start, uint_8 *end)
{
uint_8 *cur = *start;
uint_16 syncword = syncinfo->syncword;
uint_32 ret = 0;
// find an ac3 sync frame
resync:
while(syncword != 0x0b77)
{
if(cur >= end)
goto done;
syncword = (syncword << 8) + *cur++;
}
// need the next 3 bytes to decide how big the frame is
while(buffer_size < 3)
{
if(cur >= end)
goto done;
buffer[buffer_size++] = *cur++;
}
parse_syncinfo(syncinfo, buffer);
if (syncinfo->frame_size==0) // CRITICAL CONDITION
goto done;
while(buffer_size < syncinfo->frame_size * 2 - 2)
{
if(cur >= end)
goto done;
buffer[buffer_size++] = *cur++;
}
// check the crc over the entire frame
crc_init();
crc_process_frame(buffer, syncinfo->frame_size * 2 - 2);
if(!crc_validate())
{
syncword = 0xffff;
buffer_size = 0;
goto resync;
}
// if we got to this point, we found a valid ac3 frame to decode
bitstream_init(buffer);
// get rid of the syncinfo struct as we already parsed it
bitstream_get(24);
// reset the syncword for next time
syncword = 0xffff;
buffer_size = 0;
ret = 1;
done:
syncinfo->syncword = syncword;
*start = cur;
return ret;
}
void decode_mute(void)
{
// mute the frame
memset(s16_samples, 0, sizeof(sint_16) * 256 * 2 * 6);
error_flag = 0;
}
void ac3_init(ac3_config_t *config)
{
memcpy(&ac3_config, config, sizeof(ac3_config_t));
imdct_init();
sanity_check_init(&syncinfo, &bsi, &audblk);
}
sint_32 ac3_decode_data(uint_8 *data_start, int size)
{
uint_8 *data_end = data_start + size;
uint_32 i, j=0;
while (decode_buffer_syncframe(&syncinfo, &data_start, data_end))
{
if (error_flag)
{
decode_mute();
continue;
}
parse_bsi(&bsi);
for (i=0; i<6; i++)
{
// Initialize freq/time sample storage
memset(samples, 0, sizeof(float) * 256 * (bsi.nfchans + bsi.lfeon));
// Extract most of the audblk info from the bitstream
// minus the mantissas
parse_audblk(&bsi, &audblk);
// Take the differential exponent data and turn it into
// absolute exponents
exponent_unpack(&bsi, &audblk);
if(error_flag)
goto error;
// Figure out how many bits per mantissa
bit_allocate(syncinfo.fscod, &bsi, &audblk);
// Extract the mantissas from the stream and
// generate floating point frequency coefficients
coeff_unpack(&bsi, &audblk, samples);
if(error_flag)
goto error;
if(bsi.acmod == 0x2)
rematrix(&audblk, samples);
// Convert the frequency samples into time samples
imdct(&bsi, &audblk, samples);
// Downmix into the requested number of channels
// and convert floating point to sint_16
downmix(&bsi, samples, &s16_samples[i * 512]);
sanity_check(&syncinfo, &bsi, &audblk);
if(error_flag)
goto error;
}
memcpy(&AC3Dec_Buffer[j*6144], s16_samples, 6144);
j++;
error:
;
}
return j*6144;
}
void InitialAC3()
{
error_flag = 0;
lfsr_state = 1;
buffer_size = 0;
ac3_config.num_output_ch = 2;
ac3_config.flags = 0;
ac3_init(&ac3_config);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -