mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 10:48:53 +01:00
audio/mp3: Move Decode_L3 to Go
This commit is contained in:
parent
1c86a90c8e
commit
e53d5920b0
@ -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 {
|
||||
|
@ -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]
|
||||
}
|
||||
}
|
||||
|
@ -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() */
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user