After the hardware, network initialization is complete (here is a bit), the task of establishing web radio
Xtaskcreate (Web_radio_task, "Web_radio_task", 4096, NULL, 5, NULL);
Vtasksuspend (NULL);
After the web radio initializes the external SPI Ram FIFO, the MP3 decode task is established.
void Web_radio_task (void* pvparameters) {
spiramfifoinit ();
Xtaskcreate (Mp3_decode_task, "Mp3_decode_task", 8192, NULL, 5, NULL);
Start a HTTP Requet
http_client_get ("Http://icecast.omroep.nl/3fm-sb-mp3", &settings,null);
Esp_loge (TAG, "Get completed!");
Vtaskdelete (NULL);
}
In the MP3 decode mission,
First initialize the stream,fram,synth required by mad
void Mp3_decode_task (void *pvparameters) {int ret;
struct Mad_stream *stream;
struct Mad_frame *frame;
struct Mad_synth *synth;
Allocate structs needed for MP3 decoding stream = malloc (sizeof (struct mad_stream));
frame = malloc (sizeof (struct mad_frame));
Synth = malloc (sizeof (struct mad_synth));
buffer_t *buf = buf_create (max_frame_size);
if (stream==null) {printf ("Mad:malloc (stream) failed\n");
if (synth==null) {printf ("mad:malloc (synth) failed\n");
if (frame==null) {printf ("Mad:malloc (frame) failed\n");
uint32_t buf_underrun_cnt = 0;
printf ("Mad:decoder start.\n");
Initialize MP3 Parts Mad_stream_init (stream);
Mad_frame_init (frame);
Mad_synth_init (synth); while (1) {//calls Mad_stream_buffer internally if (input (stream) = = Mad_flow_stop) {break
;
}//decode frames until MAD complains while (1) { Returns 0 OR-1 ret = mad_frame_decode (frame, stream); if (ret = = 1) {if (!)
Mad_recoverable (Stream->error)) {//we ' re most likely out of the buffer and need to call input () again
Break
Error (NULL, stream, frame);
Continue
} mad_synth_frame (synth, frame);
//Esp_logi (TAG, "RAM left%d", esp_get_free_heap_size ());
///Abort:////Avoid noise//i2s_zero_dma_buffer (0);
Free (synth);
Free (frame);
Free (stream);
Clear semaphore for reader task//Spiramfiforeset ();
printf ("Mad:decoder stopped.\n");
Esp_logi (TAG, "MAD decoder stack:%d\n", Uxtaskgetstackhighwatermark (NULL));
Vtaskdelete (NULL); }
Where the mad_stream_buffer is called in input
"This function associates the original, decoded MPEG data with the Mad_stream data structure in order to decode the MPEG frame data using Mad_frame_decode ()" (http://blog.csdn.net/gepanqiang3020/ article/details/73695483).
static enum Mad_flow input (struct mad_stream *stream) {int n, I;
int REM, Fifolen;
Shift remaining contents of BUF to the front rem=stream->bufend-stream->next_frame;
Memmove (Readbuf, Stream->next_frame, REM); while (Rem<sizeof (readbuf)) {n= (sizeof (READBUF)-rem);
Calculate amount of bytes we need to fill buffer.
I=spiramfifofill (); if (i<n) n=i;
If the FIFO can give us less, only take that amount if (n==0) {//can ' t take anything? Wait until there are enough data in the buffer.
This only happens when the data feed//rate are too low, and shouldn ' t normally to be needed!
printf ("Buf uflow, Need%d bytes.\n", sizeof (READBUF)-rem);
bufunderrunct++;
We both silence the "output as" a while by pushing silent the samples into the I2S system.
This is waits for about 200mS i2s_zero_dma_buffer (0);
else {//read Some bytes from the FIFO to re-fill the buffer.
Spiramfiforead (&readbuf[rem], n);
Rem+=n; }
//okay, let MAD decode the buffer.
Mad_stream_buffer (Stream, (unsigned char*) readbuf, sizeof (READBUF));
return mad_flow_continue; }
Among them, Mad_frame_decode
Among them, Mad_synth_frame
void Mad_synth_frame (struct mad_synth *synth, struct mad_frame const *frame)
{
unsigned int nch, NS;
void (*synth_frame) (struct mad_synth *, struct mad_frame const *,
unsigned int, unsigned int);
nch = Mad_nchannels (&frame->header);
NS = mad_nsbsamples (&frame->header);
Synth->pcm.samplerate = frame->header.samplerate;
Set_dac_sample_rate (synth->pcm.samplerate);
Synth->pcm.channels = nch; synth->pcm.length = ns;
Synth->pcm.length = 128 * NS;
Synth_frame = Synth_full;
if (Frame->options & mad_option_halfsamplerate) {
synth->pcm.samplerate/= 2;
Synth->pcm.length /= 2;
Set_dac_sample_rate (synth->pcm.samplerate);
Synth_frame = synth_half;
}
Synth_frame (synth, frame, nch, NS);
Synth->phase = (synth->phase + ns)%
}
Among them, Synth_full
# if defined (aso_synth)
void synth_full (struct mad_synth *, struct mad_frame const *,
unsigned int, unsigned int);
# Else
/* NAME: synth->full ()
* DESCRIPTION: perform full frequency PCM synthesis
* /
static
void synth_full (struct mad_synth *synth, struct mad_frame const *frame,
unsigned int nch, unsigned int ns)
{
unsigned int phase, CH, s, SB, PE, PO;
short int *pcm1, *pcm2;
mad_fixed_t (*filter) [2][2][16][8];
mad_fixed_t (*sbsample) [36][32];
Register mad_fixed_t (*FE) [8], (*FX) [8], (*FO) [8];
Register mad_fixed_t Const (*DPTR) [a], *ptr;
Register mad_fixed64hi_t Hi;
Register mad_fixed64lo_t Lo;
mad_fixed_t raw_sample;
short int short_sample_buff[32];
Phase = synth->phase;
.....
/* Render di un blocco * *
render_sample_block (Short_sample_buff,);
Phase = (phase + 1)%
} /* block for/
}
#endif
Where Render_sample_block writes the data through I2S to codec
/* Render callback for the Libmad synth
/void Render_sample_block (short *short_sample_buff, int no_samples)
{
//esp_logi (TAG, "render_sample_length:%d", Len);
While (nsamples--) {
// signed int sample; /* Output sample (s) in 16-bit signed Little-endian PCM */
/ sample = scale (*left_ch++); Putchar ((sample >> 0) & 0xff); Putchar ((sample >> 8) & 0xff); if (nchannels = = 2) {
// sample = scale (*right_ch++); Putchar ((sample >> 0) & 0xff); Putchar ((sample >> 8) & 0xff); }
//}
uint32_t len=no_samples*4;
for (int i=0;i<no_samples;i++) {short
right=short_sample_buff[i];
Short left=short_sample_buff[i];
Char buf[4];
memcpy (buf,&right,2);
memcpy (buf+2,&left,2);
I2s_write_bytes (0,buf, 4, 1000/porttick_rate_ms);
Render_samples ((char*) sample_buff_ch0, Len, &mad_buffer_fmt);
return;
}
Same
Call Render_sample_block function in Synth_half
Render_sample_block (Short_sample_buff, 16);
Reference:
http://blog.csdn.net/gepanqiang3020/article/details/73695483
http://blog.csdn.net/gepanqiang3020/article/details/73696533
Http://blog.chinaunix.net/uid-30008524-id-5211762.html
Http://www.linuxfromscratch.org/blfs/view/svn/index.html