audio/mp3: Move L3_Stereo to Go

This commit is contained in:
Hajime Hoshi 2017-06-15 01:54:25 +09:00
parent 9e002e3e52
commit 53c2c5d810
3 changed files with 148 additions and 140 deletions

View File

@ -28,6 +28,152 @@ import (
"unsafe" "unsafe"
) )
type sfBandIndices struct {
l [23]int
s [14]int
}
var (
is_ratios = [6]float32{0.000000, 0.267949, 0.577350, 1.000000, 1.732051, 3.732051}
g_sf_band_indices = [3]sfBandIndices{
{
l: [...]int{0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 52, 62, 74, 90, 110, 134, 162, 196, 238, 288, 342, 418, 576},
s: [...]int{0, 4, 8, 12, 16, 22, 30, 40, 52, 66, 84, 106, 136, 192},
},
{
l: [...]int{0, 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 60, 72, 88, 106, 128, 156, 190, 230, 276, 330, 384, 576},
s: [...]int{0, 4, 8, 12, 16, 22, 28, 38, 50, 64, 80, 100, 126, 192},
},
{
l: [...]int{0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 54, 66, 82, 102, 126, 156, 194, 240, 296, 364, 448, 550, 576},
s: [...]int{0, 4, 8, 12, 16, 22, 30, 42, 58, 78, 104, 138, 180, 192},
},
}
)
func stereoProcessIntensityLong(gr int, sfb int) {
is_ratio_l := float32(0)
is_ratio_r := float32(0)
/* Check that((is_pos[sfb]=scalefac) != 7) => no intensity stereo */
is_pos := C.g_main_data.scalefac_l[gr][0][sfb]
if is_pos != 7 {
sfreq := C.g_frame_header.sampling_frequency /* Setup sampling freq index */
sfb_start := g_sf_band_indices[sfreq].l[sfb]
sfb_stop := g_sf_band_indices[sfreq].l[sfb+1]
if is_pos == 6 { /* tan((6*PI)/12 = PI/2) needs special treatment! */
is_ratio_l = 1.0
is_ratio_r = 0.0
} else {
is_ratio_l = is_ratios[is_pos] / (1.0 + is_ratios[is_pos])
is_ratio_r = 1.0 / (1.0 + is_ratios[is_pos])
}
/* Now decode all samples in this scale factor band */
for i := sfb_start; i < sfb_stop; i++ {
C.g_main_data.is[gr][0][i] *= C.float(is_ratio_l)
C.g_main_data.is[gr][1][i] *= C.float(is_ratio_r)
}
}
}
func stereoProcessIntensityShort(gr int, sfb int) {
is_ratio_l := float32(0)
is_ratio_r := float32(0)
sfreq := C.g_frame_header.sampling_frequency /* Setup sampling freq index */
/* The window length */
win_len := g_sf_band_indices[sfreq].s[sfb+1] - g_sf_band_indices[sfreq].s[sfb]
/* The three windows within the band has different scalefactors */
for win := 0; win < 3; win++ {
/* Check that((is_pos[sfb]=scalefac) != 7) => no intensity stereo */
is_pos := C.g_main_data.scalefac_s[gr][0][sfb][win]
if is_pos != 7 {
sfb_start := g_sf_band_indices[sfreq].s[sfb]*3 + win_len*win
sfb_stop := sfb_start + win_len
if is_pos == 6 { /* tan((6*PI)/12 = PI/2) needs special treatment! */
is_ratio_l = 1.0
is_ratio_r = 0.0
} else {
is_ratio_l = is_ratios[is_pos] / (1.0 + is_ratios[is_pos])
is_ratio_r = 1.0 / (1.0 + is_ratios[is_pos])
}
/* Now decode all samples in this scale factor band */
for i := sfb_start; i < sfb_stop; i++ {
// https://github.com/technosaurus/PDMP3/issues/3
C.g_main_data.is[gr][0][i] *= C.float(is_ratio_l)
C.g_main_data.is[gr][1][i] *= C.float(is_ratio_r)
}
}
}
}
//export L3_Stereo
func L3_Stereo(gr C.unsigned) {
/* Do nothing if joint stereo is not enabled */
if (C.g_frame_header.mode != 1) || (C.g_frame_header.mode_extension == 0) {
return
}
/* Do Middle/Side("normal") stereo processing */
if (C.g_frame_header.mode_extension & 0x2) != 0 {
/* Determine how many frequency lines to transform */
i := 0
if C.g_side_info.count1[gr][0] > C.g_side_info.count1[gr][1] {
i = 1
}
max_pos := int(C.g_side_info.count1[gr][i])
/* Do the actual processing */
const invSqrt2 = math.Sqrt2 / 2
for i := 0; i < max_pos; i++ {
left := (C.g_main_data.is[gr][0][i] + C.g_main_data.is[gr][1][i]) * invSqrt2
right := (C.g_main_data.is[gr][0][i] - C.g_main_data.is[gr][1][i]) * invSqrt2
C.g_main_data.is[gr][0][i] = left
C.g_main_data.is[gr][1][i] = right
}
}
/* Do intensity stereo processing */
if (C.g_frame_header.mode_extension & 0x1) != 0 {
/* Setup sampling frequency index */
sfreq := C.g_frame_header.sampling_frequency
/* First band that is intensity stereo encoded is first band scale factor
* band on or above count1 frequency line. N.B.: Intensity stereo coding is
* only done for higher subbands, but logic is here for lower subbands. */
/* Determine type of block to process */
if (C.g_side_info.win_switch_flag[gr][0] == 1) &&
(C.g_side_info.block_type[gr][0] == 2) { /* Short blocks */
/* Check if the first two subbands
*(=2*18 samples = 8 long or 3 short sfb's) uses long blocks */
if C.g_side_info.mixed_block_flag[gr][0] != 0 { /* 2 longbl. sb first */
for sfb := 0; sfb < 8; sfb++ { /* First process 8 sfb's at start */
/* Is this scale factor band above count1 for the right channel? */
if C.unsigned(g_sf_band_indices[sfreq].l[sfb]) >= C.g_side_info.count1[gr][1] {
stereoProcessIntensityLong(int(gr), int(sfb))
}
}
/* And next the remaining bands which uses short blocks */
for sfb := 3; sfb < 12; sfb++ {
/* Is this scale factor band above count1 for the right channel? */
if C.unsigned(g_sf_band_indices[sfreq].s[sfb])*3 >= C.g_side_info.count1[gr][1] {
stereoProcessIntensityShort(int(gr), int(sfb)) /* intensity stereo processing */
}
}
} else { /* Only short blocks */
for sfb := 0; sfb < 12; sfb++ {
/* Is this scale factor band above count1 for the right channel? */
if C.unsigned(g_sf_band_indices[sfreq].s[sfb])*3 >= C.g_side_info.count1[gr][1] {
stereoProcessIntensityShort(int(gr), int(sfb)) /* intensity stereo processing */
}
}
}
} else { /* Only long blocks */
for sfb := 0; sfb < 21; sfb++ {
/* Is this scale factor band above count1 for the right channel? */
if C.unsigned(g_sf_band_indices[sfreq].l[sfb]) >= C.g_side_info.count1[gr][1] {
/* Perform the intensity stereo processing */
stereoProcessIntensityLong(int(gr), int(sfb))
}
}
}
}
}
var store = [2][32][18]float32{} var store = [2][32][18]float32{}
//export L3_Hybrid_Synthesis //export L3_Hybrid_Synthesis

View File

@ -47,12 +47,9 @@ static void Error(const char *s,int e);
static void L3_Antialias(unsigned gr,unsigned ch); static void L3_Antialias(unsigned gr,unsigned ch);
static void L3_Requantize(unsigned gr,unsigned ch); static void L3_Requantize(unsigned gr,unsigned ch);
static void L3_Reorder(unsigned gr,unsigned ch); static void L3_Reorder(unsigned gr,unsigned ch);
static void L3_Stereo(unsigned gr);
static void Read_Ancillary(void); static void Read_Ancillary(void);
static void Requantize_Process_Long(unsigned gr,unsigned ch,unsigned is_pos,unsigned sfb); static void Requantize_Process_Long(unsigned gr,unsigned ch,unsigned is_pos,unsigned sfb);
static void Requantize_Process_Short(unsigned gr,unsigned ch,unsigned is_pos,unsigned sfb,unsigned win); static void Requantize_Process_Short(unsigned gr,unsigned ch,unsigned is_pos,unsigned sfb,unsigned win);
static void Stereo_Process_Intensity_Long(unsigned gr,unsigned sfb);
static void Stereo_Process_Intensity_Short(unsigned gr,unsigned sfb);
static const unsigned g_mpeg1_bitrates[3 /* layer 1-3 */][15 /* header bitrate_index */] = { static const unsigned g_mpeg1_bitrates[3 /* layer 1-3 */][15 /* header bitrate_index */] = {
{ /* Layer 1 */ { /* Layer 1 */
@ -70,8 +67,7 @@ g_sampling_frequency[3] = { 44100 * Hz,48000 * Hz,32000 * Hz };
static const float //ci[8]={-0.6,-0.535,-0.33,-0.185,-0.095,-0.041,-0.0142,-0.0037}, static const float //ci[8]={-0.6,-0.535,-0.33,-0.185,-0.095,-0.041,-0.0142,-0.0037},
cs[8]={0.857493,0.881742,0.949629,0.983315,0.995518,0.999161,0.999899,0.999993}, cs[8]={0.857493,0.881742,0.949629,0.983315,0.995518,0.999161,0.999899,0.999993},
ca[8]={-0.514496,-0.471732,-0.313377,-0.181913,-0.094574,-0.040966,-0.014199,-0.003700}, ca[8]={-0.514496,-0.471732,-0.313377,-0.181913,-0.094574,-0.040966,-0.014199,-0.003700};
is_ratios[6] = {0.000000f,0.267949f,0.577350f,1.000000f,1.732051f,3.732051f};
#ifdef POW34_ITERATE #ifdef POW34_ITERATE
static const float powtab34[32] = { static const float powtab34[32] = {
0.000000f,1.000000f,2.519842f,4.326749f,6.349605f,8.549880f,10.902724f, 0.000000f,1.000000f,2.519842f,4.326749f,6.349605f,8.549880f,10.902724f,
@ -583,73 +579,6 @@ static void L3_Requantize(unsigned gr,unsigned ch){
return; /* Done */ return; /* Done */
} }
/**Description: TBD
* Parameters: TBD
* Return value: TBD
* Author: Krister Lagerström(krister@kmlager.com) **/
static void L3_Stereo(unsigned gr){
unsigned max_pos,i,sfreq,sfb /* scalefac band index */;
float left,right;
/* Do nothing if joint stereo is not enabled */
if((g_frame_header.mode != 1)||(g_frame_header.mode_extension == 0)) return;
/* Do Middle/Side("normal") stereo processing */
if(g_frame_header.mode_extension & 0x2) {
/* Determine how many frequency lines to transform */
max_pos = g_side_info.count1[gr][!!(g_side_info.count1[gr][0] > g_side_info.count1[gr][1])];
/* Do the actual processing */
for(i = 0; i < max_pos; i++) {
left =(g_main_data.is[gr][0][i] + g_main_data.is[gr][1][i])
*(C_INV_SQRT_2);
right =(g_main_data.is[gr][0][i] - g_main_data.is[gr][1][i])
*(C_INV_SQRT_2);
g_main_data.is[gr][0][i] = left;
g_main_data.is[gr][1][i] = right;
} /* end for(i... */
} /* end if(ms_stereo... */
/* Do intensity stereo processing */
if(g_frame_header.mode_extension & 0x1) {
/* Setup sampling frequency index */
sfreq = g_frame_header.sampling_frequency;
/* First band that is intensity stereo encoded is first band scale factor
* band on or above count1 frequency line. N.B.: Intensity stereo coding is
* only done for higher subbands, but logic is here for lower subbands. */
/* Determine type of block to process */
if((g_side_info.win_switch_flag[gr][0] == 1) &&
(g_side_info.block_type[gr][0] == 2)) { /* Short blocks */
/* Check if the first two subbands
*(=2*18 samples = 8 long or 3 short sfb's) uses long blocks */
if(g_side_info.mixed_block_flag[gr][0] != 0) { /* 2 longbl. sb first */
for(sfb = 0; sfb < 8; sfb++) {/* First process 8 sfb's at start */
/* Is this scale factor band above count1 for the right channel? */
if(g_sf_band_indices[sfreq].l[sfb] >= g_side_info.count1[gr][1])
Stereo_Process_Intensity_Long(gr,sfb);
} /* end if(sfb... */
/* And next the remaining bands which uses short blocks */
for(sfb = 3; sfb < 12; sfb++) {
/* Is this scale factor band above count1 for the right channel? */
if(g_sf_band_indices[sfreq].s[sfb]*3 >= g_side_info.count1[gr][1])
Stereo_Process_Intensity_Short(gr,sfb); /* intensity stereo processing */
}
}else{ /* Only short blocks */
for(sfb = 0; sfb < 12; sfb++) {
/* Is this scale factor band above count1 for the right channel? */
if(g_sf_band_indices[sfreq].s[sfb]*3 >= g_side_info.count1[gr][1])
Stereo_Process_Intensity_Short(gr,sfb); /* intensity stereo processing */
}
} /* end else(only short blocks) */
}else{ /* Only long blocks */
for(sfb = 0; sfb < 21; sfb++) {
/* Is this scale factor band above count1 for the right channel? */
if(g_sf_band_indices[sfreq].l[sfb] >= g_side_info.count1[gr][1]) {
/* Perform the intensity stereo processing */
Stereo_Process_Intensity_Long(gr,sfb);
}
}
} /* end else(only long blocks) */
} /* end if(intensity_stereo processing) */
}
/**Description: called by Read_Main_L3 to read Huffman coded data from bitstream. /**Description: called by Read_Main_L3 to read Huffman coded data from bitstream.
* Parameters: None * Parameters: None
* Return value: None. The data is stored in g_main_data.is[ch][gr][freqline]. * Return value: None. The data is stored in g_main_data.is[ch][gr][freqline].
@ -757,74 +686,6 @@ static void Requantize_Process_Short(unsigned gr,unsigned ch,unsigned is_pos,uns
return; /* Done */ return; /* Done */
} }
/**Description: intensity stereo processing for entire subband with long blocks.
* Parameters: TBD
* Return value: TBD
* Author: Krister Lagerström(krister@kmlager.com) **/
static void Stereo_Process_Intensity_Long(unsigned gr,unsigned sfb){
unsigned i,sfreq,sfb_start,sfb_stop,is_pos;
float is_ratio_l,is_ratio_r,left,right;
/* Check that((is_pos[sfb]=scalefac) != 7) => no intensity stereo */
if((is_pos = g_main_data.scalefac_l[gr][0][sfb]) != 7) {
sfreq = g_frame_header.sampling_frequency; /* Setup sampling freq index */
sfb_start = g_sf_band_indices[sfreq].l[sfb];
sfb_stop = g_sf_band_indices[sfreq].l[sfb+1];
if(is_pos == 6) { /* tan((6*PI)/12 = PI/2) needs special treatment! */
is_ratio_l = 1.0f;
is_ratio_r = 0.0f;
}else{
is_ratio_l = is_ratios[is_pos] /(1.0f + is_ratios[is_pos]);
is_ratio_r = 1.0f /(1.0f + is_ratios[is_pos]);
}
/* Now decode all samples in this scale factor band */
for(i = sfb_start; i < sfb_stop; i++) {
left = is_ratio_l * g_main_data.is[gr][0][i];
right = is_ratio_r * g_main_data.is[gr][0][i];
g_main_data.is[gr][0][i] = left;
g_main_data.is[gr][1][i] = right;
}
}
return; /* Done */
} /* end Stereo_Process_Intensity_Long() */
/**Description: This function is used to perform intensity stereo processing
* for an entire subband that uses short blocks.
* Parameters: TBD
* Return value: TBD
* Author: Krister Lagerström(krister@kmlager.com) **/
static void Stereo_Process_Intensity_Short(unsigned gr,unsigned sfb){
unsigned sfb_start,sfb_stop,is_pos,is_ratio_l,is_ratio_r,i,sfreq,win,win_len;
float left,right;
sfreq = g_frame_header.sampling_frequency; /* Setup sampling freq index */
/* The window length */
win_len = g_sf_band_indices[sfreq].s[sfb+1] - g_sf_band_indices[sfreq].s[sfb];
/* The three windows within the band has different scalefactors */
for(win = 0; win < 3; win++) {
/* Check that((is_pos[sfb]=scalefac) != 7) => no intensity stereo */
if((is_pos = g_main_data.scalefac_s[gr][0][sfb][win]) != 7) {
sfb_start = g_sf_band_indices[sfreq].s[sfb]*3 + win_len*win;
sfb_stop = sfb_start + win_len;
if(is_pos == 6) { /* tan((6*PI)/12 = PI/2) needs special treatment! */
is_ratio_l = 1.0;
is_ratio_r = 0.0;
}else{
is_ratio_l = is_ratios[is_pos] /(1.0 + is_ratios[is_pos]);
is_ratio_r = 1.0 /(1.0 + is_ratios[is_pos]);
}
/* Now decode all samples in this scale factor band */
for(i = sfb_start; i < sfb_stop; i++) {
left = is_ratio_l = g_main_data.is[gr][0][i];
right = is_ratio_r = g_main_data.is[gr][0][i];
g_main_data.is[gr][0][i] = left;
g_main_data.is[gr][1][i] = right;
}
} /* end if(not illegal is_pos) */
} /* end for(win... */
return; /* Done */
} /* end Stereo_Process_Intensity_Short() */
/**Description: output audio data /**Description: output audio data
* Parameters: Pointers to the samples,the number of samples * Parameters: Pointers to the samples,the number of samples
* Return value: None * Return value: None

View File

@ -99,6 +99,7 @@ int Read_Audio_L3(void);
static int Read_Header(void); static int Read_Header(void);
void Read_Huffman(unsigned part_2_start,unsigned gr,unsigned ch); void Read_Huffman(unsigned part_2_start,unsigned gr,unsigned ch);
void L3_Stereo(unsigned gr);
void L3_Hybrid_Synthesis(unsigned gr,unsigned ch); void L3_Hybrid_Synthesis(unsigned gr,unsigned ch);
void L3_Frequency_Inversion(unsigned gr,unsigned ch); void L3_Frequency_Inversion(unsigned gr,unsigned ch);
void L3_Subband_Synthesis(unsigned gr,unsigned ch, unsigned* outdata); void L3_Subband_Synthesis(unsigned gr,unsigned ch, unsigned* outdata);