📄 dts_parser.cpp
字号:
#include <math.h>
#include <stdio.h>
#include "dts_parser.h"
#include "dts_header.h"
#include "dts_tables.h"
#include "dts_tables_huffman.h"
#include "dts_tables_quantization.h"
#include "dts_tables_adpcm.h"
#include "dts_tables_fir.h"
#include "dts_tables_vq.h"
#define DTS_MODE_MONO 0
#define DTS_MODE_CHANNEL 1
#define DTS_MODE_STEREO 2
#define DTS_MODE_STEREO_SUMDIFF 3
#define DTS_MODE_STEREO_TOTAL 4
#define DTS_MODE_3F 5
#define DTS_MODE_2F1R 6
#define DTS_MODE_3F1R 7
#define DTS_MODE_2F2R 8
#define DTS_MODE_3F2R 9
static const int dts_order[NCHANNELS] = { CH_C, CH_L, CH_R, CH_SL, CH_SR, CH_LFE };
static const int amode2mask_tbl[] =
{
MODE_MONO,
MODE_STEREO,
MODE_STEREO,
MODE_STEREO,
MODE_STEREO,
MODE_3_0,
MODE_2_1,
MODE_3_1,
MODE_2_2,
MODE_3_2
};
static const int amode2rel_tbl[] =
{
NO_RELATION,
NO_RELATION,
NO_RELATION,
RELATION_SUMDIFF,
RELATION_DOLBY,
NO_RELATION,
NO_RELATION,
NO_RELATION,
NO_RELATION,
NO_RELATION,
};
inline int
decode_blockcode(int code, int levels, int *values)
{
int i;
int offset = (levels - 1) >> 1;
for (i = 0; i < 4; i++)
{
values[i] = (code % levels) - offset;
code /= levels;
}
if (code == 0)
return 1;
else
{
fprintf (stderr, "ERROR: block code look-up failed\n");
return 0;
}
}
///////////////////////////////////////////////////////////////////////////////
// DTSParser
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Init
DTSParser::DTSParser()
{
init_cosmod();
samples.allocate(DTS_NCHANNELS, DTS_MAX_SAMPLES);
reset();
}
void
DTSParser::init_cosmod()
{
int i, j, k;
for (j=0,k=0;k<16;k++)
for (i=0;i<16;i++)
cos_mod[j++] = cos((2*i+1)*(2*k+1)*M_PI/64);
for (k=0;k<16;k++)
for (i=0;i<16;i++)
cos_mod[j++] = cos((i)*(2*k+1)*M_PI/32);
for (k=0;k<16;k++)
cos_mod[j++] = 0.25/(2*cos((2*k+1)*M_PI/128));
for (k=0;k<16;k++)
cos_mod[j++] = -0.25/(2.0*sin((2*k+1)*M_PI/128));
}
///////////////////////////////////////////////////////////////////////////////
// FrameParser overrides
const HeaderParser *
DTSParser::header_parser() const
{
return &dts_header;
}
void
DTSParser::reset()
{
spk = spk_unknown;
frame_size = 0;
nsamples = 0;
frame_type = 0;
samples_deficit = 0;
crc_present = 0;
sample_blocks = 0;
amode = 0;
sample_rate = 0;
bit_rate = 0;
memset(subband_samples_hist, 0, sizeof(subband_samples_hist));
memset(subband_fir_hist, 0, sizeof(subband_fir_hist));
memset(subband_fir_noidea, 0, sizeof(subband_fir_noidea));
memset(lfe_data, 0, sizeof(lfe_data));
}
bool
DTSParser::parse_frame(uint8_t *frame, size_t size)
{
HeaderInfo hinfo;
if (!dts_header.parse_header(frame, &hinfo))
return false;
if (hinfo.frame_size > size)
return false;
spk = hinfo.spk;
spk.format = FORMAT_LINEAR;
frame_size = hinfo.frame_size;
nsamples = hinfo.nsamples;
bs_type = hinfo.bs_type;
bs.set_ptr(frame, bs_type);
if (!parse_frame_header())
return false;
// 8 samples per subsubframe and per subband
for (int i = 0; i < sample_blocks / 8; i++)
{
// Sanity check
if (current_subframe >= subframes)
return false;
// Read subframe header
if (!current_subsubframe)
if (!parse_subframe_header())
return false;
// Read subsubframe
if (!parse_subsubframe())
return false;
// Update state
current_subsubframe++;
if (current_subsubframe >= subsubframes)
{
current_subsubframe = 0;
current_subframe++;
}
// Read subframe footer
if (current_subframe >= subframes)
if (!parse_subframe_footer())
return false;
}
return true;
}
size_t
DTSParser::stream_info(char *buf, size_t size) const
{
char info[1024];
char *stream = "???";
switch (bs_type)
{
case BITSTREAM_16BE: stream = "16bit BE"; break;
case BITSTREAM_16LE: stream = "16bit LE"; break;
case BITSTREAM_14BE: stream = "14bit BE"; break;
case BITSTREAM_14LE: stream = "14bit LE"; break;
}
size_t len = sprintf(info,
"DTS\n"
"speakers: %s\n"
"sample rate: %iHz\n"
"bitrate: %ikbps\n"
"stream: %s\n"
"frame size: %i bytes\n"
"nsamples: %i\n"
"amode: %i\n"
"%s"
"\0",
spk.mode_text(),
spk.sample_rate,
dts_bit_rates[bit_rate] / 1000,
stream,
frame_size,
nsamples,
amode,
crc_present? "CRC protected\n": "No CRC"
);
if (len + 1 > size) len = size - 1;
memcpy(buf, info, len + 1);
buf[len] = 0;
return len;
}
size_t
DTSParser::frame_info(char *buf, size_t size) const
{
if (buf && size) buf[0] = 0;
return 0;
}
///////////////////////////////////////////////////////////////////////////////
// FRAME HEADER
///////////////////////////////////////////////////////////////////////////////
bool
DTSParser::parse_frame_header()
{
int i, j;
static const float adj_table[] = { 1.0, 1.1250, 1.2500, 1.4375 };
/////////////////////////////////////////////////////////
// Skip sync
bs.get(32);
/////////////////////////////////////////////////////////
// Frame header
frame_type = bs.get(1);
samples_deficit = bs.get(5) + 1;
crc_present = bs.get(1);
sample_blocks = bs.get(7) + 1;
frame_size = bs.get(14) + 1;
amode = bs.get(6);
sample_rate = bs.get(4);
bit_rate = bs.get(5);
downmix = bs.get(1);
dynrange = bs.get(1);
timestamp = bs.get(1);
aux_data = bs.get(1);
hdcd = bs.get(1);
ext_descr = bs.get(3);
ext_coding = bs.get(1);
aspf = bs.get(1);
lfe = bs.get(2);
predictor_history = bs.get(1);
if (crc_present)
{
// todo: check CRC
header_crc = bs.get(16);
}
multirate_inter = bs.get(1);
version = bs.get(4);
copy_history = bs.get(2);
source_pcm_res = bs.get(3);
front_sum = bs.get(1);
surround_sum = bs.get(1);
dialog_norm = bs.get(4);
/////////////////////////////////////////////////////////
// Primary audio coding header
subframes = bs.get(4) + 1;
prim_channels = bs.get(3) + 1;
for (i = 0; i < prim_channels; i++)
{
subband_activity[i] = bs.get(5) + 2;
if (subband_activity[i] > DTS_SUBBANDS)
subband_activity[i] = DTS_SUBBANDS;
}
for (i = 0; i < prim_channels; i++)
{
vq_start_subband[i] = bs.get(5) + 1;
if (vq_start_subband[i] > DTS_SUBBANDS)
vq_start_subband[i] = DTS_SUBBANDS;
}
for (i = 0; i < prim_channels; i++)
joint_intensity[i] = bs.get(3);
for (i = 0; i < prim_channels; i++)
transient_huffman[i] = bs.get(2);
for (i = 0; i < prim_channels; i++)
scalefactor_huffman[i] = bs.get(3);
for (i = 0; i < prim_channels; i++)
{
bitalloc_huffman[i] = bs.get(3);
// if (bitalloc_huffman[i] == 7) bailout
}
// Get codebooks quantization indexes
for (i = 0; i < prim_channels; i++)
{
quant_index_huffman[i][0] = 0; // Not transmitted
quant_index_huffman[i][1] = bs.get(1);
}
for (j = 2; j < 6; j++)
for (i = 0; i < prim_channels; i++)
quant_index_huffman[i][j] = bs.get(2);
for (j = 6; j < 11; j++)
for (i = 0; i < prim_channels; i++)
quant_index_huffman[i][j] = bs.get(3);
for (j = 11; j < 27; j++)
for (i = 0; i < prim_channels; i++)
quant_index_huffman[i][j] = 0; // Not transmitted
// Get scale factor adjustment
for (j = 0; j < 11; j++)
for (i = 0; i < prim_channels; i++)
scalefactor_adj[i][j] = 1;
for (i = 0; i < prim_channels; i++)
if (quant_index_huffman[i][1] == 0)
scalefactor_adj[i][1] = adj_table[bs.get(2)];
for (j = 2; j < 6; j++)
for (i = 0; i < prim_channels; i++)
if (quant_index_huffman[i][j] < 3)
scalefactor_adj[i][j] = adj_table[bs.get(2)];
for (j = 6; j < 11; j++)
for (i = 0; i < prim_channels; i++)
if (quant_index_huffman[i][j] < 7)
scalefactor_adj[i][j] = adj_table[bs.get(2)];
if (crc_present)
{
// todo: audio header CRC check
bs.get(16);
}
/////////////////////////////////////////////////////////
// Some initializations
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -