mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
audio/mp3: Move Read_Huffman to Go
This commit is contained in:
parent
4b9242cbd0
commit
f6e7e3601f
@ -348,27 +348,22 @@ var huffmanMain = [...]huffTables{
|
|||||||
{huffmanTable[2261:], 31, 0}, /* Table 33 */
|
{huffmanTable[2261:], 31, 0}, /* Table 33 */
|
||||||
}
|
}
|
||||||
|
|
||||||
//export Huffman_Decode
|
func huffmanDecode(table_num int) (x, y, v, w int, err error) {
|
||||||
func Huffman_Decode(table_num C.unsigned, x, y, v, w *C.int32_t) C.int {
|
|
||||||
point := 0
|
point := 0
|
||||||
error := 1
|
error := 1
|
||||||
bitsleft := 32
|
bitsleft := 32
|
||||||
treelen := huffmanMain[table_num].treelen
|
treelen := huffmanMain[table_num].treelen
|
||||||
linbits := huffmanMain[table_num].linbits
|
linbits := huffmanMain[table_num].linbits
|
||||||
if treelen == 0 { /* Check for empty tables */
|
if treelen == 0 { /* Check for empty tables */
|
||||||
*x = 0
|
return 0, 0, 0, 0, nil
|
||||||
*y = 0
|
|
||||||
*v = 0
|
|
||||||
*w = 0
|
|
||||||
return C.OK
|
|
||||||
}
|
}
|
||||||
htptr := huffmanMain[table_num].hufftable
|
htptr := huffmanMain[table_num].hufftable
|
||||||
for { /* Start reading the Huffman code word,bit by bit */
|
for { /* Start reading the Huffman code word,bit by bit */
|
||||||
/* Check if we've matched a code word */
|
/* Check if we've matched a code word */
|
||||||
if (htptr[point] & 0xff00) == 0 {
|
if (htptr[point] & 0xff00) == 0 {
|
||||||
error = 0
|
error = 0
|
||||||
*x = C.int32_t((htptr[point] >> 4) & 0xf)
|
x = int((htptr[point] >> 4) & 0xf)
|
||||||
*y = C.int32_t(htptr[point] & 0xf)
|
y = int(htptr[point] & 0xf)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if getMainBit() != 0 { /* Go right in tree */
|
if getMainBit() != 0 { /* Go right in tree */
|
||||||
@ -390,43 +385,38 @@ func Huffman_Decode(table_num C.unsigned, x, y, v, w *C.int32_t) C.int {
|
|||||||
if error != 0 { /* Check for error. */
|
if error != 0 { /* Check for error. */
|
||||||
err := fmt.Errorf("mp3: illegal Huff code in data. bleft = %d, point = %d. tab = %d.",
|
err := fmt.Errorf("mp3: illegal Huff code in data. bleft = %d, point = %d. tab = %d.",
|
||||||
bitsleft, point, table_num)
|
bitsleft, point, table_num)
|
||||||
*x = 0
|
return 0, 0, 0, 0, err
|
||||||
*y = 0
|
|
||||||
g_error = err
|
|
||||||
}
|
}
|
||||||
if table_num > 31 { /* Process sign encodings for quadruples tables. */
|
if table_num > 31 { /* Process sign encodings for quadruples tables. */
|
||||||
*v = (*y >> 3) & 1
|
v = (y >> 3) & 1
|
||||||
*w = (*y >> 2) & 1
|
w = (y >> 2) & 1
|
||||||
*x = (*y >> 1) & 1
|
x = (y >> 1) & 1
|
||||||
*y = *y & 1
|
y = y & 1
|
||||||
if (*v > 0) && (getMainBit() == 1) {
|
if (v > 0) && (getMainBit() == 1) {
|
||||||
*v = -*v
|
v = -v
|
||||||
}
|
}
|
||||||
if (*w > 0) && (getMainBit() == 1) {
|
if (w > 0) && (getMainBit() == 1) {
|
||||||
*w = -*w
|
w = -w
|
||||||
}
|
}
|
||||||
if (*x > 0) && (getMainBit() == 1) {
|
if (x > 0) && (getMainBit() == 1) {
|
||||||
*x = -*x
|
x = -x
|
||||||
}
|
}
|
||||||
if (*y > 0) && (getMainBit() == 1) {
|
if (y > 0) && (getMainBit() == 1) {
|
||||||
*y = -*y
|
y = -y
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (linbits > 0) && (*x == 15) {
|
if (linbits > 0) && (x == 15) {
|
||||||
*x += C.int32_t(getMainBits(linbits)) /* Get linbits */
|
x += getMainBits(linbits) /* Get linbits */
|
||||||
}
|
}
|
||||||
if (*x > 0) && (getMainBit() == 1) {
|
if (x > 0) && (getMainBit() == 1) {
|
||||||
*x = -*x /* Get sign bit */
|
x = -x /* Get sign bit */
|
||||||
}
|
}
|
||||||
if (linbits > 0) && (*y == 15) {
|
if (linbits > 0) && (y == 15) {
|
||||||
*y += C.int32_t(getMainBits(linbits)) /* Get linbits */
|
y += getMainBits(linbits) /* Get linbits */
|
||||||
}
|
}
|
||||||
if (*y > 0) && (getMainBit() == 1) {
|
if (y > 0) && (getMainBit() == 1) {
|
||||||
*y = -*y /* Get sign bit */
|
y = -y /* Get sign bit */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if error != 0 {
|
return x, y, v, w, nil
|
||||||
return C.ERROR
|
|
||||||
}
|
|
||||||
return C.OK
|
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ func Read_Main_L3() C.int {
|
|||||||
}
|
}
|
||||||
for gr := 0; gr < 2; gr++ {
|
for gr := 0; gr < 2; gr++ {
|
||||||
for ch := 0; ch < nch; ch++ {
|
for ch := 0; ch < nch; ch++ {
|
||||||
part_2_start := Get_Main_Pos()
|
part_2_start := int(Get_Main_Pos())
|
||||||
/* Number of bits in the bitstream for the bands */
|
/* Number of bits in the bitstream for the bands */
|
||||||
slen1 := mpeg1_scalefac_sizes[C.g_side_info.scalefac_compress[gr][ch]][0]
|
slen1 := mpeg1_scalefac_sizes[C.g_side_info.scalefac_compress[gr][ch]][0]
|
||||||
slen2 := mpeg1_scalefac_sizes[C.g_side_info.scalefac_compress[gr][ch]][1]
|
slen2 := mpeg1_scalefac_sizes[C.g_side_info.scalefac_compress[gr][ch]][1]
|
||||||
@ -149,7 +149,10 @@ func Read_Main_L3() C.int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Read Huffman coded data. Skip stuffing bits. */
|
/* Read Huffman coded data. Skip stuffing bits. */
|
||||||
C.Read_Huffman(part_2_start, C.uint(gr), C.uint(ch))
|
if err := readHuffman(part_2_start, gr, ch); err != nil {
|
||||||
|
g_error = err
|
||||||
|
return C.ERROR
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* The ancillary data is stored here,but we ignore it. */
|
/* The ancillary data is stored here,but we ignore it. */
|
||||||
|
@ -350,76 +350,6 @@ static void Decode_L3_Init_Song(void){
|
|||||||
synth_init = 1;
|
synth_init = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Description: called by Read_Main_L3 to read Huffman coded data from bitstream.
|
|
||||||
* Parameters: None
|
|
||||||
* Return value: None. The data is stored in g_main_data.is[ch][gr][freqline].
|
|
||||||
* Author: Krister Lagerström(krister@kmlager.com) **/
|
|
||||||
void Read_Huffman(unsigned part_2_start,unsigned gr,unsigned ch){
|
|
||||||
int32_t x,y,v,w;
|
|
||||||
unsigned table_num,is_pos,bit_pos_end,sfreq;
|
|
||||||
unsigned region_1_start,region_2_start; /* region_0_start = 0 */
|
|
||||||
|
|
||||||
/* Check that there is any data to decode. If not,zero the array. */
|
|
||||||
if(g_side_info.part2_3_length[gr][ch] == 0) {
|
|
||||||
for(is_pos = 0; is_pos < 576; is_pos++)
|
|
||||||
g_main_data.is[gr][ch][is_pos] = 0.0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* Calculate bit_pos_end which is the index of the last bit for this part. */
|
|
||||||
bit_pos_end = part_2_start + g_side_info.part2_3_length[gr][ch] - 1;
|
|
||||||
/* Determine region boundaries */
|
|
||||||
if((g_side_info.win_switch_flag[gr][ch] == 1)&&
|
|
||||||
(g_side_info.block_type[gr][ch] == 2)) {
|
|
||||||
region_1_start = 36; /* sfb[9/3]*3=36 */
|
|
||||||
region_2_start = 576; /* No Region2 for short block case. */
|
|
||||||
}else{
|
|
||||||
sfreq = g_frame_header.sampling_frequency;
|
|
||||||
region_1_start =
|
|
||||||
g_sf_band_indices[sfreq].l[g_side_info.region0_count[gr][ch] + 1];
|
|
||||||
region_2_start =
|
|
||||||
g_sf_band_indices[sfreq].l[g_side_info.region0_count[gr][ch] +
|
|
||||||
g_side_info.region1_count[gr][ch] + 2];
|
|
||||||
}
|
|
||||||
/* Read big_values using tables according to region_x_start */
|
|
||||||
for(is_pos = 0; is_pos < g_side_info.big_values[gr][ch] * 2; is_pos++) {
|
|
||||||
if(is_pos < region_1_start) {
|
|
||||||
table_num = g_side_info.table_select[gr][ch][0];
|
|
||||||
} else if(is_pos < region_2_start) {
|
|
||||||
table_num = g_side_info.table_select[gr][ch][1];
|
|
||||||
}else table_num = g_side_info.table_select[gr][ch][2];
|
|
||||||
/* Get next Huffman coded words */
|
|
||||||
(void) Huffman_Decode(table_num,&x,&y,&v,&w);
|
|
||||||
/* In the big_values area there are two freq lines per Huffman word */
|
|
||||||
g_main_data.is[gr][ch][is_pos++] = x;
|
|
||||||
g_main_data.is[gr][ch][is_pos] = y;
|
|
||||||
}
|
|
||||||
/* Read small values until is_pos = 576 or we run out of huffman data */
|
|
||||||
table_num = g_side_info.count1table_select[gr][ch] + 32;
|
|
||||||
for(is_pos = g_side_info.big_values[gr][ch] * 2;
|
|
||||||
(is_pos <= 572) &&(Get_Main_Pos() <= bit_pos_end); is_pos++) {
|
|
||||||
/* Get next Huffman coded words */
|
|
||||||
(void) Huffman_Decode(table_num,&x,&y,&v,&w);
|
|
||||||
g_main_data.is[gr][ch][is_pos++] = v;
|
|
||||||
if(is_pos >= 576) break;
|
|
||||||
g_main_data.is[gr][ch][is_pos++] = w;
|
|
||||||
if(is_pos >= 576) break;
|
|
||||||
g_main_data.is[gr][ch][is_pos++] = x;
|
|
||||||
if(is_pos >= 576) break;
|
|
||||||
g_main_data.is[gr][ch][is_pos] = y;
|
|
||||||
}
|
|
||||||
/* Check that we didn't read past the end of this section */
|
|
||||||
if(Get_Main_Pos() >(bit_pos_end+1)) /* Remove last words read */
|
|
||||||
is_pos -= 4;
|
|
||||||
/* Setup count1 which is the index of the first sample in the rzero reg. */
|
|
||||||
g_side_info.count1[gr][ch] = is_pos;
|
|
||||||
/* Zero out the last part if necessary */
|
|
||||||
for(/* is_pos comes from last for-loop */; is_pos < 576; is_pos++)
|
|
||||||
g_main_data.is[gr][ch][is_pos] = 0.0;
|
|
||||||
/* Set the bitpos to point to the next part to read */
|
|
||||||
(void) Set_Main_Pos(bit_pos_end+1);
|
|
||||||
return; /* Done */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**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
|
||||||
|
@ -97,7 +97,6 @@ int Set_Main_Pos(unsigned bit_pos);
|
|||||||
int Read_Main_L3(void);
|
int Read_Main_L3(void);
|
||||||
int Read_Audio_L3(void);
|
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 L3_Requantize(unsigned gr,unsigned ch);
|
void L3_Requantize(unsigned gr,unsigned ch);
|
||||||
void L3_Reorder(unsigned gr,unsigned ch);
|
void L3_Reorder(unsigned gr,unsigned ch);
|
||||||
@ -109,6 +108,4 @@ void L3_Subband_Synthesis(unsigned gr,unsigned ch, unsigned* outdata);
|
|||||||
|
|
||||||
int Read_CRC(void);
|
int Read_CRC(void);
|
||||||
|
|
||||||
int Huffman_Decode(unsigned table_num, int32_t* x, int32_t*y, int32_t* v, int32_t* w);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
110
audio/mp3/read.go
Normal file
110
audio/mp3/read.go
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
// Copyright 2017 The Ebiten Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// +build !js
|
||||||
|
|
||||||
|
package mp3
|
||||||
|
|
||||||
|
// #include "pdmp3.h"
|
||||||
|
//
|
||||||
|
// extern t_mpeg1_main_data g_main_data;
|
||||||
|
// extern t_mpeg1_side_info g_side_info;
|
||||||
|
// extern t_mpeg1_header g_frame_header;
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func readHuffman(part_2_start, gr, ch int) error {
|
||||||
|
/* Check that there is any data to decode. If not,zero the array. */
|
||||||
|
if C.g_side_info.part2_3_length[gr][ch] == 0 {
|
||||||
|
for is_pos := 0; is_pos < 576; is_pos++ {
|
||||||
|
C.g_main_data.is[gr][ch][is_pos] = 0.0
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
/* Calculate bit_pos_end which is the index of the last bit for this part. */
|
||||||
|
bit_pos_end := part_2_start + int(C.g_side_info.part2_3_length[gr][ch]) - 1
|
||||||
|
/* Determine region boundaries */
|
||||||
|
region_1_start := 0
|
||||||
|
region_2_start := 0
|
||||||
|
if (C.g_side_info.win_switch_flag[gr][ch] == 1) && (C.g_side_info.block_type[gr][ch] == 2) {
|
||||||
|
region_1_start = 36 /* sfb[9/3]*3=36 */
|
||||||
|
region_2_start = 576 /* No Region2 for short block case. */
|
||||||
|
} else {
|
||||||
|
sfreq := C.g_frame_header.sampling_frequency
|
||||||
|
region_1_start =
|
||||||
|
sfBandIndicesSet[sfreq].l[C.g_side_info.region0_count[gr][ch]+1]
|
||||||
|
region_2_start =
|
||||||
|
sfBandIndicesSet[sfreq].l[C.g_side_info.region0_count[gr][ch]+
|
||||||
|
C.g_side_info.region1_count[gr][ch]+2]
|
||||||
|
}
|
||||||
|
/* Read big_values using tables according to region_x_start */
|
||||||
|
for is_pos := 0; is_pos < int(C.g_side_info.big_values[gr][ch])*2; is_pos++ {
|
||||||
|
table_num := 0
|
||||||
|
if is_pos < region_1_start {
|
||||||
|
table_num = int(C.g_side_info.table_select[gr][ch][0])
|
||||||
|
} else if is_pos < region_2_start {
|
||||||
|
table_num = int(C.g_side_info.table_select[gr][ch][1])
|
||||||
|
} else {
|
||||||
|
table_num = int(C.g_side_info.table_select[gr][ch][2])
|
||||||
|
}
|
||||||
|
/* Get next Huffman coded words */
|
||||||
|
x, y, _, _, err := huffmanDecode(table_num)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
/* In the big_values area there are two freq lines per Huffman word */
|
||||||
|
C.g_main_data.is[gr][ch][is_pos] = C.float(x)
|
||||||
|
is_pos++
|
||||||
|
C.g_main_data.is[gr][ch][is_pos] = C.float(y)
|
||||||
|
}
|
||||||
|
/* Read small values until is_pos = 576 or we run out of huffman data */
|
||||||
|
table_num := int(C.g_side_info.count1table_select[gr][ch]) + 32
|
||||||
|
is_pos := int(C.g_side_info.big_values[gr][ch]) * 2
|
||||||
|
for ; (is_pos <= 572) && (int(Get_Main_Pos()) <= bit_pos_end); is_pos++ {
|
||||||
|
/* Get next Huffman coded words */
|
||||||
|
x, y, v, w, err := huffmanDecode(table_num)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
C.g_main_data.is[gr][ch][is_pos] = C.float(v)
|
||||||
|
is_pos++
|
||||||
|
if is_pos >= 576 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
C.g_main_data.is[gr][ch][is_pos] = C.float(w)
|
||||||
|
is_pos++
|
||||||
|
if is_pos >= 576 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
C.g_main_data.is[gr][ch][is_pos] = C.float(x)
|
||||||
|
is_pos++
|
||||||
|
if is_pos >= 576 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
C.g_main_data.is[gr][ch][is_pos] = C.float(y)
|
||||||
|
}
|
||||||
|
/* Check that we didn't read past the end of this section */
|
||||||
|
if int(C.Get_Main_Pos()) > (bit_pos_end + 1) {
|
||||||
|
/* Remove last words read */
|
||||||
|
is_pos -= 4
|
||||||
|
}
|
||||||
|
/* Setup count1 which is the index of the first sample in the rzero reg. */
|
||||||
|
C.g_side_info.count1[gr][ch] = C.unsigned(is_pos)
|
||||||
|
/* Zero out the last part if necessary */
|
||||||
|
for ; /* is_pos comes from last for-loop */ is_pos < 576; is_pos++ {
|
||||||
|
C.g_main_data.is[gr][ch][is_pos] = 0.0
|
||||||
|
}
|
||||||
|
/* Set the bitpos to point to the next part to read */
|
||||||
|
C.Set_Main_Pos(C.unsigned(bit_pos_end) + 1)
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user