Esp32-esp32snow WebRadio Code Learning _eespressif

Source: Internet
Author: User

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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.