audio/mp3: Move Decode_L3 to Go

This commit is contained in:
Hajime Hoshi 2017-06-17 06:28:25 +09:00
parent 1c86a90c8e
commit e53d5920b0
4 changed files with 63 additions and 127 deletions

View File

@ -17,11 +17,14 @@
package mp3
// #include "pdmp3.h"
//
// //extern t_mpeg1_main_data g_main_data;
// extern t_mpeg1_header g_frame_header;
// //extern t_mpeg1_side_info g_side_info;
import "C"
import (
"io"
"unsafe"
)
const (
@ -36,6 +39,57 @@ var (
writer io.Writer
)
func decodeL3() error {
out := make([]int, 576)
/* Number of channels(1 for mono and 2 for stereo) */
nch := 2
if C.g_frame_header.mode == C.mpeg1_mode_single_channel {
nch = 1
}
for gr := 0; gr < 2; gr++ {
for ch := 0; ch < nch; ch++ {
L3_Requantize(C.uint(gr), C.uint(ch)) /* Requantize samples */
L3_Reorder(C.uint(gr), C.uint(ch)) /* Reorder short blocks */
}
L3_Stereo(C.uint(gr)) /* Stereo processing */
for ch := 0; ch < nch; ch++ {
L3_Antialias(C.uint(gr), C.uint(ch))
// (IMDCT,windowing,overlapp add)
L3_Hybrid_Synthesis(C.uint(gr), C.uint(ch))
L3_Frequency_Inversion(C.uint(gr), C.uint(ch))
// Polyphase subband synthesis
l3SubbandSynthesis(gr, ch, out)
}
if err := audioWriteRaw(out); err != nil {
return err
}
}
return nil
}
func audioWriteRaw(samples []int) error {
nch := 2
if C.g_frame_header.mode == C.mpeg1_mode_single_channel {
nch = 1
}
s := make([]uint8, len(samples)*2*nch)
for i, v := range samples {
if nch == 1 {
s[2*i] = uint8(v)
s[2*i+1] = uint8(v >> 8)
} else {
s[4*i] = uint8(v)
s[4*i+1] = uint8(v >> 8)
s[4*i+2] = uint8(v >> 16)
s[4*i+3] = uint8(v >> 24)
}
}
if _, err := writer.Write(s); err != nil {
return err
}
return nil
}
func getByte() (uint8, error) {
for len(readerCache) == 0 && !readerEOF {
buf := make([]uint8, 4096)
@ -77,23 +131,16 @@ func Get_Filepos() C.unsigned {
return C.unsigned(readerPos)
}
//export writeToWriter
func writeToWriter(data unsafe.Pointer, size C.int) C.size_t {
buf := C.GoBytes(data, size)
n, err := writer.Write(buf)
if err != nil {
panic(err)
}
return C.size_t(n)
}
func decode(r io.Reader, w io.Writer) error {
// TODO: Decoder should know number of channels
reader = r
writer = w
for Get_Filepos() != eof {
err := readFrame()
if err == nil {
C.Decode_L3()
if err := decodeL3(); err != nil {
return err
}
continue
}
if Get_Filepos() == eof {

View File

@ -25,7 +25,6 @@ import "C"
import (
"math"
"unsafe"
)
var (
@ -565,13 +564,7 @@ var g_synth_dtbl = [512]float32{
0.000015259, 0.000015259, 0.000015259, 0.000015259,
}
//export L3_Subband_Synthesis
func L3_Subband_Synthesis(gr C.unsigned, ch C.unsigned, outdata *C.unsigned) {
out := make([]C.unsigned, 576)
for i := range out {
out[i] = *(*C.unsigned)(unsafe.Pointer(uintptr(unsafe.Pointer(outdata)) + uintptr(i)*unsafe.Sizeof(*outdata)))
}
func l3SubbandSynthesis(gr int, ch int, out []int) {
u_vec := make([]float32, 512)
s_vec := make([]float32, 32)
@ -620,16 +613,13 @@ func L3_Subband_Synthesis(gr C.unsigned, ch C.unsigned, outdata *C.unsigned) {
if ch == 0 { /* This function must be called for channel 0 first */
/* We always run in stereo mode,& duplicate channels here for mono */
if nch == 1 {
out[32*ss+i] = C.unsigned((samp << 16) | (samp))
out[32*ss+i] = (samp << 16) | (samp)
} else {
out[32*ss+i] = C.unsigned(samp << 16)
out[32*ss+i] = samp << 16
}
} else {
out[32*ss+i] |= C.unsigned(samp)
out[32*ss+i] |= samp
}
}
}
for i := range out {
*(*C.unsigned)(unsafe.Pointer(uintptr(unsafe.Pointer(outdata)) + uintptr(i)*unsafe.Sizeof(*outdata))) = out[i]
}
}

View File

@ -41,9 +41,7 @@ static void dmp_samples(t_mpeg1_main_data *md,int gr,int ch,int type);
static void audio_write(unsigned *samples,unsigned nsamples,int sample_rate);
static void audio_write_raw(unsigned *samples,unsigned nsamples);
static void Decode_L3_Init_Song(void);
static void Error(const char *s,int e);
static void Read_Ancillary(void);
static const unsigned g_mpeg1_bitrates[3 /* layer 1-3 */][15 /* header bitrate_index */] = {
{ /* Layer 1 */
@ -159,51 +157,6 @@ static void dmp_samples(t_mpeg1_main_data *md,int gr,int ch,int type){
}
#endif
/**Description: decodes a layer 3 bitstream into audio samples.
* Parameters: Outdata vector.
* Return value: OK or ERROR if the frame contains errors.
* Author: Krister Lagerström(krister@kmlager.com) **/
int Decode_L3(void){
unsigned gr,ch,nch,out[576];
/* Number of channels(1 for mono and 2 for stereo) */
nch =(g_frame_header.mode == mpeg1_mode_single_channel ? 1 : 2);
for(gr = 0; gr < 2; gr++) {
for(ch = 0; ch < nch; ch++) {
dmp_scf(&g_side_info,&g_main_data,gr,ch); //noop unless debug
dmp_huff(&g_main_data,gr,ch); //noop unless debug
L3_Requantize(gr,ch); /* Requantize samples */
dmp_samples(&g_main_data,gr,ch,0); //noop unless debug
L3_Reorder(gr,ch); /* Reorder short blocks */
} /* end for(ch... */
L3_Stereo(gr); /* Stereo processing */
dmp_samples(&g_main_data,gr,0,1); //noop unless debug
dmp_samples(&g_main_data,gr,1,1); //noop unless debug
for(ch = 0; ch < nch; ch++) {
L3_Antialias(gr,ch); /* Antialias */
dmp_samples(&g_main_data,gr,ch,2); //noop unless debug
L3_Hybrid_Synthesis(gr,ch); /*(IMDCT,windowing,overlapp add) */
L3_Frequency_Inversion(gr,ch); /* Frequency inversion */
dmp_samples(&g_main_data,gr,ch,3); //noop unless debug
L3_Subband_Synthesis(gr,ch,out); /* Polyphase subband synthesis */
} /* end for(ch... */
#ifdef DEBUG
{
int i,ctr = 0;
printf("PCM:\n");
for(i = 0; i < 576; i++) {
printf("%d: %d\n",ctr++,(out[i] >> 16) & 0xffff);
if(nch == 2) printf("%d: %d\n",ctr++,out[i] & 0xffff);
}
}
#endif /* DEBUG */
/*FIXME - replace with simple interface stream*/
audio_write((unsigned *) out,576,
g_sampling_frequency[g_frame_header.sampling_frequency]);
} /* end for(gr... */
return(OK); /* Done */
}
/**Description: TBD
* Parameters: TBD
* Return value: TBD
@ -212,52 +165,3 @@ static void Error(const char *s,int e){
(void) fwrite(s,1,strlen(s),stderr);
exit(e);
}
/**Description: output audio data
* Parameters: Pointers to the samples,the number of samples
* Return value: None
* Author: Krister Lagerström(krister@kmlager.com) **/
static void audio_write(unsigned *samples,unsigned nsamples,int sample_rate){
static int init = 0,audio,curr_sample_rate = 0;
int tmp,dsp_speed = 44100,dsp_stereo = 2;
#ifdef OUTPUT_RAW
audio_write_raw(samples,nsamples);
#endif /* OUTPUT_RAW */
return;
} /* audio_write() */
/******************************************************************************
*
* Name: audio_write_raw
* Author: Krister Lagerström(krister@unidata.se)
* Description: This function is used to output raw data
* Parameters: Pointers to the samples,the number of samples
* Return value: None
* Revision History:
* Author Date Change
* krister 010101 Initial revision
*
******************************************************************************/
static void audio_write_raw(unsigned *samples,unsigned nsamples){
char fname[1024];
unsigned lo,hi;
int i,nch;
unsigned short s[576*2];
nch =(g_frame_header.mode == mpeg1_mode_single_channel ? 1 : 2);
for(i = 0; i < nsamples; i++) {
if(nch == 1) {
lo = samples[i] & 0xffff;
s[i] = lo;
}else{
lo = samples[i] & 0xffff;
hi =(samples[i] & 0xffff0000) >> 16;
s[2*i] = hi;
s[2*i+1] = lo;
}
}
if(writeToWriter((char *) s,nsamples * 2 * nch) != nsamples * 2 * nch)
Error("Unable to write raw data\n",-1);
return;
} /* audio_write_raw() */

View File

@ -85,21 +85,16 @@ typedef struct { /* Scale factor band indices,for long and short windows */
t_sf_band_indices;
unsigned Get_Filepos(void);
int Decode_L3(void);
size_t writeToWriter(void* data, int size);
unsigned Get_Main_Pos(void);
int Set_Main_Pos(unsigned bit_pos);
int Read_Audio_L3(void);
void L3_Requantize(unsigned gr,unsigned ch);
void L3_Reorder(unsigned gr,unsigned ch);
void L3_Stereo(unsigned gr);
void L3_Antialias(unsigned gr,unsigned ch);
void L3_Hybrid_Synthesis(unsigned gr,unsigned ch);
void L3_Frequency_Inversion(unsigned gr,unsigned ch);
void L3_Subband_Synthesis(unsigned gr,unsigned ch, unsigned* outdata);
int Read_CRC(void);