Exemple #1
0
void decode(uint16_t *outbuf)
{
    offset = MP3FindSyncWord(readPtr, READBUF_SIZE);
    
    if(offset < 0)
    {
        stop();
        
    }
    else
    {
        readPtr += offset;                         //data start point
        bytesLeft -= offset;                 //in buffer
        MP3Decode(hMP3Decoder, &readPtr, &bytesLeft, outbuf, 0);

        if (bytesLeft < READBUF_SIZE)
        {
            memmove(readBuf,readPtr,bytesLeft);
            fr = f_read(&fil, readBuf + bytesLeft, READBUF_SIZE - bytesLeft, &cnt);
            if (cnt < READBUF_SIZE - bytesLeft);
                memset(readBuf + bytesLeft + cnt, 0, READBUF_SIZE - bytesLeft - cnt);
            bytesLeft=READBUF_SIZE;
            readPtr=readBuf;               
            if(fr || cnt == 0){
                stop();
                next_song();
            }
        }

        //MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo);
        //if(mp3FrameInfo.outputSamps != 2304)   decode(outbuf);
    }
}
Exemple #2
0
int decSamples(int length, short * destBuf, void * context)
{
	int samps =0;
	/* Otherwhise we can possibly overwrite the data behind the buffer */
	if(length >= MAX_NGRAN*inf.nChans*MAX_NSAMP) {
		int ret = 0;
		decode:
		/* Possible buffer-underrun */
		if(dataLeft < READ_BUF_SIZE) {
			deFragReadbuf(readBuf, &readOff, dataLeft);
			ret = fread(readBuf+dataLeft, 1, READ_BUF_SIZE-dataLeft, fp);
			dataLeft += ret;
			if(feof(fp) && !dataLeft)
				return DEC_EOF;
		}
		/* check for errors */
		if((ret = MP3Decode(mdecoder, &readOff, &dataLeft, destBuf,0))) {
			switch(ret) {

			case ERR_MP3_FREE_BITRATE_SYNC:
			case ERR_MP3_OUT_OF_MEMORY :
			case ERR_MP3_NULL_POINTER :
			case ERR_UNKNOWN :
				printf("HELIX MP3 ERROR: %d\n", ret);
				return DEC_ERR;

			default:
				findValidSync(&readOff, &dataLeft);
				printf("Seeking error!\n");
				goto decode;
			}
		}
		/* GCC can't know channels being only 1 or 2 */
		samps = inf.outputSamps >> (inf.nChans-1);
	}
Exemple #3
0
/*
 * Called by the audio driver when it is time to provide data to
 * one of the audio buffers (while the other buffer is sent to the
 * CODEC using DMA). One mp3 frame is decoded at a time and
 * provided to the audio driver.
 */
static void AudioCallback(void *context, int buffer) {
	static int16_t audio_buffer0[4096];
	static int16_t audio_buffer1[4096];
	int i=0;
	int offset, err;
	int outOfData = 0;

	int16_t *samples;
	if (buffer) {
		samples = audio_buffer0;
		GPIO_SetBits(GPIOD, GPIO_Pin_13);
		GPIO_ResetBits(GPIOD, GPIO_Pin_14);
	} else {
		samples = audio_buffer1;
		GPIO_SetBits(GPIOD, GPIO_Pin_14);
		GPIO_ResetBits(GPIOD, GPIO_Pin_13);
	}

	offset = MP3FindSyncWord((unsigned char*)read_ptr, bytes_left);
	bytes_left -= offset;
	read_ptr += offset;

	err = MP3Decode(hMP3Decoder, (unsigned char**)&read_ptr, (int*)&bytes_left, samples, 0);

	if (err) {
		/* error occurred */
		switch (err) {
		case ERR_MP3_INDATA_UNDERFLOW:
			outOfData = 1;
			break;
		case ERR_MP3_MAINDATA_UNDERFLOW:
			/* do nothing - next call to decode will provide more mainData */
			break;
		case ERR_MP3_FREE_BITRATE_SYNC:
		default:
			outOfData = 1;
			break;
		}
	} else {
		// no error
		MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo);

		// Duplicate data in case of mono to maintain playback speed
		if (mp3FrameInfo.nChans == 1) {
			for(i = mp3FrameInfo.outputSamps;i >= 0;i--) 	{
				samples[2 * i]=samples[i];
				samples[2 * i + 1]=samples[i];
			}
			mp3FrameInfo.outputSamps *= 2;
		}
	}

	if (!outOfData) {
		ProvideAudioBuffer(samples, mp3FrameInfo.outputSamps);
	}
}
/*
 * Called by the audio driver when it is time to provide data to
 * one of the audio buffers (while the other buffer is sent to the
 * CODEC using DMA). One mp3 frame is decoded at a time and
 * provided to the audio driver.
 */
static void AudioCallback(void *context, int buffer) {
	static int16_t audio_buffer0[4096];
	static int16_t audio_buffer1[4096];

	int offset, err;
	int outOfData = 0;
	static const char *read_ptr = mp3_data;
	static int bytes_left = MP3_SIZE;

	int16_t *samples;

	if (buffer) {
		samples = audio_buffer0;
	} else {
		samples = audio_buffer1;
	}

	offset = MP3FindSyncWord((unsigned char*)read_ptr, bytes_left);
	bytes_left -= offset;

	if (bytes_left <= 10000) {
		read_ptr = mp3_data;
		bytes_left = MP3_SIZE;
		offset = MP3FindSyncWord((unsigned char*)read_ptr, bytes_left);
	}

	read_ptr += offset;
	err = MP3Decode(hMP3Decoder, (unsigned char**)&read_ptr, &bytes_left, samples, 0);

	if (err) {
		/* error occurred */
		switch (err) {
		case ERR_MP3_INDATA_UNDERFLOW:
			outOfData = 1;
			break;
		case ERR_MP3_MAINDATA_UNDERFLOW:
			/* do nothing - next call to decode will provide more mainData */
			break;
		case ERR_MP3_FREE_BITRATE_SYNC:
		default:
			outOfData = 1;
			break;
		}
	} else {
		/* no error */
		MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo);
	}

	if (!outOfData) {
		ProvideAudioBuffer(samples, mp3FrameInfo.outputSamps);
	}
}
Exemple #5
0
int decode_mp3(aica_decoder_t *dat) {
	
	int offset = 0, i = 0;
	int bytes = dat->length;
	unsigned char *buf = (unsigned char*)dat->base;
	short *out = (short*)dat->out;
	
	offset = MP3FindSyncWord(buf, bytes);
	
	if(offset < 0) {
		return -1;
	}
	
	buf += offset;
	bytes -= offset;
	
	if(MP3Decode(hMP3Decoder, &buf, &bytes, out, 0)) {
		return -1;
	}
	
	MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo);
	
	for(i = 0; i < mp3FrameInfo.nChans; i++) {
		mp3_chan[i].cmd = AICA_CH_CMD_START | AICA_CH_START_DELAY;
		mp3_chan[i].base = dat->chan[i];
		mp3_chan[i].type = AICA_SM_16BIT;
		mp3_chan[i].length = (mp3FrameInfo.outputSamps / mp3FrameInfo.nChans);
		mp3_chan[i].loop = 1;
		mp3_chan[i].loopstart = 0;
		mp3_chan[i].loopend = (mp3FrameInfo.outputSamps / mp3FrameInfo.nChans);
		mp3_chan[i].freq = mp3FrameInfo.samprate;
		mp3_chan[i].vol = 255;
		mp3_chan[i].pan = 0;
		
		memcpy((void*)(chans + dat->chan[i]), &mp3_chan[i], sizeof(aica_channel_t));
		chans[dat->chan[i]].pos = 0;
		aica_play(dat->chan[i], 0);
	}
	
	return mp3FrameInfo.nChans;
}
Exemple #6
0
int mp3_decoder_run(struct mp3_decoder* decoder)
{
	int err;
	rt_uint16_t* buffer;
	rt_uint32_t  delta;

    RT_ASSERT(decoder != RT_NULL);

	if ((decoder->read_ptr == RT_NULL) || decoder->bytes_left < 2*MAINBUF_SIZE)
	{
		if(mp3_decoder_fill_buffer(decoder) != 0)
			return -1;
	}

	// rt_kprintf("read offset: 0x%08x\n", decoder->read_ptr - decoder->read_buffer);
	decoder->read_offset = MP3FindSyncWord(decoder->read_ptr, decoder->bytes_left);
	if (decoder->read_offset < 0)
	{
		/* discard this data */
		rt_kprintf("outof sync, byte left: %d\n", decoder->bytes_left);

		decoder->bytes_left = 0;
		return 0;
	}

	decoder->read_ptr += decoder->read_offset;
	delta = decoder->read_offset;
	decoder->bytes_left -= decoder->read_offset;
	if (decoder->bytes_left < 1024)
	{
		/* fill more data */
		if(mp3_decoder_fill_buffer(decoder) != 0)
			return -1;
	}

    /* get a decoder buffer */
    buffer = (rt_uint16_t*)sbuf_alloc();
	decoder->bytes_left_before_decoding = decoder->bytes_left;

	err = MP3Decode(decoder->decoder, &decoder->read_ptr,
        (int*)&decoder->bytes_left, (short*)buffer, 0);
	delta += (decoder->bytes_left_before_decoding - decoder->bytes_left);

	current_offset += delta;

	decoder->frames++;

	if (err != ERR_MP3_NONE)
	{
		switch (err)
		{
		case ERR_MP3_INDATA_UNDERFLOW:
			rt_kprintf("ERR_MP3_INDATA_UNDERFLOW\n");
			decoder->bytes_left = 0;
			if(mp3_decoder_fill_buffer(decoder) != 0)
			{
				/* release this memory block */
				sbuf_release(buffer);
				return -1;
			}
			break;

		case ERR_MP3_MAINDATA_UNDERFLOW:
			/* do nothing - next call to decode will provide more mainData */
			rt_kprintf("ERR_MP3_MAINDATA_UNDERFLOW\n");
			break;

		default:
			rt_kprintf("unknown error: %d, left: %d\n", err, decoder->bytes_left);

			// skip this frame
			if (decoder->bytes_left > 0)
			{
				decoder->bytes_left --;
				decoder->read_ptr ++;
			}
			else
			{
				// TODO
				RT_ASSERT(0);
			}
			break;
		}

		/* release this memory block */
		sbuf_release(buffer);
	}
	else
	{
		int outputSamps;
		/* no error */
		MP3GetLastFrameInfo(decoder->decoder, &decoder->frame_info);

        /* set sample rate */
		if (decoder->frame_info.samprate != current_sample_rate)
		{
			current_sample_rate = decoder->frame_info.samprate;
			rt_device_control(decoder->snd_device, CODEC_CMD_SAMPLERATE, &current_sample_rate);
		}

		/* write to sound device */
		outputSamps = decoder->frame_info.outputSamps;
		if (outputSamps > 0)
		{
			if (decoder->frame_info.nChans == 1)
			{
				int i;
				for (i = outputSamps - 1; i >= 0; i--)
				{
					buffer[i * 2] = buffer[i];
					buffer[i * 2 + 1] = buffer[i];
				}
				outputSamps *= 2;
			}

			rt_device_write(decoder->snd_device, 0, buffer, outputSamps * sizeof(rt_uint16_t));
		}
		else
		{
			/* no output */
			sbuf_release(buffer);
		}
	}

	return 0;
}
Exemple #7
0
int Mp3Decode(const char* pszFile)
{
  int nResult = 0;
  BYTE* pInData = g_Mp3InBuffer;
  UINT unInDataLeft = 0;
  FIL fIn;
  UINT bEof = FALSE;
  UINT bOutOfData = FALSE;
  MP3FrameInfo mp3FrameInfo;
  uint32_t unDmaBufMode = 0;
  g_pMp3DmaBufferPtr = g_pMp3DmaBuffer;
  g_pMp3DecoderThread = chThdSelf();

  FRESULT errFS = f_open(&fIn, pszFile, FA_READ);
  if(errFS != FR_OK)
  {
    chprintf((BaseChannel*)&SD2, "Mp3Decode: Failed to open file \"%s\" for reading, err=%d\r\n", pszFile, errFS);
    return -1;
  }

  HMP3Decoder hMP3Decoder = MP3InitDecoder();
  if(hMP3Decoder == NULL)
  {
    chprintf((BaseChannel*)&SD2, "Mp3Decode: Failed to initialize mp3 decoder engine\r\n");
    return -2;
  }

  chprintf((BaseChannel*)&SD2, "Mp3Decode: Start decoding \"%s\"\r\n", pszFile);

  char szArtist[80];
  char szTitle[80];
  palSetPad(GPIOD, 12); // green LED
  Mp3ReadId3V2Tag(&fIn, szArtist, sizeof(szArtist), szTitle, sizeof(szTitle));
  palClearPad(GPIOD, 12); // green LED
  if(szArtist[0] != 0 || szTitle[0] != 0)
  {
    chprintf((BaseChannel*)&SD2, "Mp3Decode: Now playing (ID3v2): %s - %s\r\n", szArtist, szTitle);
  }
  int nDecodeRes = ERR_MP3_NONE;
  UINT unFramesDecoded = 0;
  do
  {
    if(unInDataLeft < (2 * MAINBUF_SIZE) && (!bEof))
    {
      UINT unRead = Mp3FillReadBuffer(pInData, unInDataLeft, &fIn);
      unInDataLeft += unRead;
      pInData = g_Mp3InBuffer;
      if(unRead == 0)
      {
        bEof = 1;
      }
    }

    // find start of next MP3 frame - assume EOF if no sync found
    int nOffset = MP3FindSyncWord(pInData, unInDataLeft);
    if(nOffset < 0)
    {
      bOutOfData = TRUE;
      break;
    }
    pInData += nOffset;
    unInDataLeft -= nOffset;

    // decode one MP3 frame - if offset < 0 then bytesLeft was less than a full frame
    nDecodeRes = MP3Decode(hMP3Decoder, &pInData, (int*)&unInDataLeft, (short*)g_pMp3OutBuffer, 0);
    switch(nDecodeRes)
    {
      case ERR_MP3_NONE:
      {
        MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo);
        if(unFramesDecoded == 0)
        {
          chprintf((BaseChannel*)&SD2, "Mp3Decode: %d Hz %d Bit %d Channels\r\n",
                   mp3FrameInfo.samprate, mp3FrameInfo.bitsPerSample, mp3FrameInfo.nChans);
          if((mp3FrameInfo.samprate > 48000) || (mp3FrameInfo.bitsPerSample != 16) || (mp3FrameInfo.nChans != 2))
          {
            chprintf((BaseChannel*)&SD2, "Mp3Decode: incompatible MP3 file.\r\n");
            nResult = -5;
            break;
          }
        }
        if((unFramesDecoded) % 100 == 0)
        {
          chprintf((BaseChannel*)&SD2, "Mp3Decode: frame %u, bitrate=%d\r\n", unFramesDecoded, mp3FrameInfo.bitrate);
        }
        unFramesDecoded++;
        g_pMp3OutBufferPtr = g_pMp3OutBuffer;

        uint32_t unOutBufferAvail= mp3FrameInfo.outputSamps;
        while(unOutBufferAvail > 0)
        {
          // fill up the whole dma buffer
          uint32_t unDmaBufferSpace = 0;
          if(unDmaBufMode == 0)
          {
            // fill the whole buffer
            // dma buf ptr was reset to beginning of the buffer
            unDmaBufferSpace = g_pMp3DmaBuffer + MP3_DMA_BUFFER_SIZE - g_pMp3DmaBufferPtr;
          }
          else if(unDmaBufMode == 1)
          {
            // fill the first half of the buffer
            // dma buf ptr was reset to beginning of the buffer
            unDmaBufferSpace = g_pMp3DmaBuffer + (MP3_DMA_BUFFER_SIZE / 2) - g_pMp3DmaBufferPtr;
          }
          else
          {
            // fill the last half of the buffer
            // dma buf ptr was reset to middle of the buffer
            unDmaBufferSpace = g_pMp3DmaBuffer + MP3_DMA_BUFFER_SIZE - g_pMp3DmaBufferPtr;
          }
          uint32_t unCopy = unDmaBufferSpace > unOutBufferAvail ? unOutBufferAvail : unDmaBufferSpace;
          if(unCopy > 0)
          {
            memcpy(g_pMp3DmaBufferPtr, g_pMp3OutBufferPtr, unCopy * sizeof(uint16_t));
            unOutBufferAvail -= unCopy;
            g_pMp3OutBufferPtr += unCopy;
            unDmaBufferSpace -= unCopy;
            g_pMp3DmaBufferPtr += unCopy;
          }
          if(unDmaBufferSpace == 0)
          {
            // dma buffer full
            // see if this was the first run
            if(unDmaBufMode == 0)
            {
              // on the first buffer fill up,
              // start the dma transfer
              if(EVAL_AUDIO_Init(OUTPUT_DEVICE_HEADPHONE, 80, (uint32_t)mp3FrameInfo.samprate))
              {
                chprintf((BaseChannel *) &SD2, "Mp3Decode: audio init failed\r\n");
                nResult = -4;
                break;
              }
              EVAL_AUDIO_Play(g_pMp3DmaBuffer, MP3_DMA_BUFFER_SIZE * sizeof(uint16_t));
            }
            // we must wait for the dma stream tx interrupt here
            eventmask_t em = chEvtWaitAny((eventmask_t)2 | 4 | 8);
            if(em & 8)
            {
              // stop requested
              chprintf((BaseChannel*)&SD2, "Mp3Decode: Stop requested\r\n");
              nResult = 1;
              break;
            }
            if((em & 2) && (em & 4))
            {
              chprintf((BaseChannel*)&SD2, "Mp3Decode: DMA out of sync (HT and TC both set)\r\n");
              nResult = -3;
              break;
            }
            if(unDmaBufMode == 0 || unDmaBufMode == 2)
            {
              // the dma event we expect is "half transfer" (=2)
              if(em & 2)
              {
                // set up first half mode
                unDmaBufMode = 1;
                g_pMp3DmaBufferPtr = g_pMp3DmaBuffer;
              }
              else
              {
                chprintf((BaseChannel*)&SD2, "Mp3Decode: DMA out of sync (expected HT, got TC)\r\n");
                nResult = -3;
                break;
              }
            }
            else
            {
              // the dma event we expect is "transfer complete" (=4)
              if(em & 4)
              {
                // set up last half mode
                unDmaBufMode = 2;
                g_pMp3DmaBufferPtr = g_pMp3DmaBuffer + (MP3_DMA_BUFFER_SIZE / 2);
              }
              else
              {
                chprintf((BaseChannel*)&SD2, "Mp3Decode: DMA out of sync (expected TC, got HT)\r\n");
                nResult = -3;
              }
            }
          }
        }
        break;
      }
      case ERR_MP3_MAINDATA_UNDERFLOW:
      {
        // do nothing - next call to decode will provide more mainData
        break;
      }
      case ERR_MP3_FREE_BITRATE_SYNC:
      {
        break;
      }
      case ERR_MP3_INDATA_UNDERFLOW:
      {
        chprintf((BaseChannel*)&SD2, "Mp3Decode: Decoding error ERR_MP3_INDATA_UNDERFLOW\r\n");
        bOutOfData = TRUE;
        break;
      }
      default:
      {
        chprintf((BaseChannel*)&SD2, "Mp3Decode: Decoding error %d\r\n", nDecodeRes);
        bOutOfData = TRUE;
        break;
      }
    }
  }
  while((!bOutOfData) && (nResult == 0));

  chprintf((BaseChannel*)&SD2, "Mp3Decode: Finished decoding\r\n");

  MP3FreeDecoder(hMP3Decoder);
  if(EVAL_AUDIO_Stop(CODEC_PDWN_HW))
  {
    chprintf((BaseChannel*)&SD2, "Mp3Decode: Failed to stop audio\r\n");
  }
  EVAL_AUDIO_DeInit();
  f_close(&fIn);
  // this is the only legit way I know
  // to remvove still pending event flags
  // from the thread
  chEvtWaitOneTimeout(2, 50);
  chEvtWaitOneTimeout(4, 50);

  return nResult;
}
Exemple #8
0
static void AudioCallback(void *context, int buffer) 
{
        static int16_t audio_buffer0[4096];
	static int16_t audio_buffer1[4096];
        
        int offset;
	int outOfData = 0;
	static int bytes_left = MP3_SIZE;
        
	int16_t *samples;

	if (buffer) 
        {
		samples = audio_buffer0;
		GPIO_SetBits(GPIOD, GPIO_Pin_13);
		GPIO_ResetBits(GPIOD, GPIO_Pin_14);
	} 
        else 
        {
		samples = audio_buffer1;
		GPIO_SetBits(GPIOD, GPIO_Pin_14);
		GPIO_ResetBits(GPIOD, GPIO_Pin_13);
	}

	offset = MP3FindSyncWord((unsigned char*)read_ptr, bytes_left);
        
        if (offset != -1)
        {
          bytes_left -= offset;
        }
        /*
        else
        {
            bytes_left = 0;       //end of buffer, toggle buffers
        }*/
        
        //Played the entire buffer, loop back to play from the front of the buffer
        if (bytes_left <= 1000) {
                  flipBuffers();
                  bytes_left = MP3_SIZE;
                  offset = MP3FindSyncWord((unsigned char*)read_ptr, bytes_left);
	}

        if(offset < MP3_SIZE && offset >= 0)
        {
             read_ptr += offset;
        }
        
        //if (*read_ptr == 0xFF)
        //{
          err = MP3Decode(hMP3Decoder, (unsigned char**)&read_ptr, &bytes_left, samples, 0);
        //}
        
	if (err && (err != -9)) 
        {
		// error occurred
		switch (err) 
                {
		case ERR_MP3_INDATA_UNDERFLOW:
			outOfData = 1;
			break;
		case ERR_MP3_MAINDATA_UNDERFLOW:
                        MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo);
			//do nothing - next call to decode will provide more mainData 
			break;
                        
                case (-6):
                        bytes_left -= 5;
                        read_ptr += 5;
                        //MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo);
                        break;
                
                case (-8):
                        break;
                
		case ERR_MP3_FREE_BITRATE_SYNC:
                        break;
                 
		default:
			outOfData = 1;
                        bytes_left -= 5;
                        read_ptr += 5;
			break;
                }
          /*
          StopAudio();
          
          rxIndex = 0;                   
          dataRxComplete = 0;
          bytes_left = MP3_SIZE;
          
          flipBuffers();
        
          PlayAudioWithCallback(AudioCallback, 0);*/
	} 
        else 
        {
		// no error 
		MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo);
	}
        //MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo);

	if (mp3FrameInfo.outputSamps > 0) 
        {
        ProvideAudioBuffer(samples, mp3FrameInfo.outputSamps);
	}
        else
        {
          ProvideAudioBuffer(samples, 4096);
        }
}
Exemple #9
0
static bool fill_mp3_buffer(FIL *fp, int buffer_number) {

	unsigned int   br;
	unsigned int   btr;

	static char    file_read_buffer[FILE_READ_BUFFER_SIZE];
	static char *  file_read_ptr = file_read_buffer;
	static uint    file_bytes = 0;

	// Copy of above pointers/indicators for roll back if MP3 frame decode failure.
	char *         copy_file_read_ptr;
	uint           copy_file_bytes;

	bool   		   need_data= true;

	FRESULT res;
	int offset,err;
	bool out_of_data = false;

	int copy_samples;

	int i;

	// Turn on blue LED to indicate decoding start.
	GPIO_SetBits(GPIOD, GPIO_Pin_15);

	do {
		if ( need_data ) {
			// Reset the file read buffer
			memmove(file_read_buffer,file_read_ptr,file_bytes);
			file_read_ptr = file_read_buffer;

			// Fill the file read buffer
			btr =      FILE_READ_BUFFER_SIZE - file_bytes;
			res =      f_read(fp, file_read_buffer + file_bytes , btr, &br);
			file_bytes += br;

			if ( res != FR_OK ) {
				// File access failure, dump out.
				out_of_data  = true;
				break;
			}

			// Flag when file is completely read complete.
			out_of_data = f_eof(fp);

			// Clear flag for needing more data.
			need_data = false;
		}

		// Find the next frame in the MP3 file
		offset = MP3FindSyncWord((unsigned char*)file_read_ptr, file_bytes);

		if ( offset < 0 ) {
			// This should never happen unless we have a badly formatted frame.
			// Just exit out and hope the next call gets a good frame.
			need_data = true;
			continue;
		}

		copy_file_bytes    = file_bytes - offset;
		copy_file_read_ptr = file_read_ptr + offset;

		// Decode this frame.
		err = MP3Decode(hMP3Decoder, (unsigned char**)&copy_file_read_ptr, (uint*)&copy_file_bytes, audio_read_buffer + buffer_number * AUDIO_LOCAL_BUFFER_SIZE, 0);

		if (err) {
			/* error occurred */
			switch (err) {
			case ERR_MP3_INDATA_UNDERFLOW:
				// Next loop will refill buffer.
				need_data = true;
				continue;
			case ERR_MP3_MAINDATA_UNDERFLOW:
				// Next loop will refill buffer.
				need_data = true;
				continue;
			case ERR_MP3_FREE_BITRATE_SYNC:
			default:
				out_of_data = true;
				break;
			}
		} else {

			file_bytes    = copy_file_bytes;
			file_read_ptr = copy_file_read_ptr;

			// no error
			MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo);

			// Duplicate data in case of mono to maintain playback speed
			if (mp3FrameInfo.nChans == 1) {
				for(i = mp3FrameInfo.outputSamps;i >= 0;i--) 	{
					audio_read_buffer[ buffer_read * AUDIO_LOCAL_BUFFER_SIZE + 2 * i]     = audio_read_buffer[ buffer_read * AUDIO_LOCAL_BUFFER_SIZE + i];
					audio_read_buffer[ buffer_read * AUDIO_LOCAL_BUFFER_SIZE + 2 * i + 1] = audio_read_buffer[ buffer_read * AUDIO_LOCAL_BUFFER_SIZE + i];
				}
				mp3FrameInfo.outputSamps *= 2;
			}

			audio_buffer_length[ buffer_number ] = mp3FrameInfo.outputSamps;
		}

	} while( offset < 0 && res == FR_OK && !out_of_data );

	// Turn off blue LED to indicate decoding finish.
	GPIO_ResetBits(GPIOD, GPIO_Pin_15);
	return(out_of_data);
}
Exemple #10
0
void labor6(void) {
    run = 1;
    syncword_address =0;
    spi_address = 0;
    pwmVal = 0;
    HMP3Decoder mp3dec;
    bytesLeft = 0;
    bytesTilSyncWord = 0;
    decodeRetVal = 0;
    errorCounter = 0;
    idx_ISR = 0;
    mainBuf_empty = 1;
    interrupt_Counter = 0;
    mseczaehlvar = 0;

    RCC_ClocksTypeDef RCC_Clocks;
    msec = 0;
    int i = 0;

    //Amplitude 1.0V (b_big)
    amplitude = b_big;

    spi_setup();
    setup_TIM8_DAC_PWM();
    mp3dec = MP3InitDecoder();

    //SysTick end of count event each 10ms
    RCC_GetClocksFreq(&RCC_Clocks);
    SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000);

    TFT_cursor_off();

    buf1.isEmpty = 1;
    buf2.isEmpty = 1;

    mp3OutBuffer = &buf1;		//start with buf1
    irsInBuffer = &buf1;

    TFT_cls();
    TFT_gotoxy(1,1);
    TFT_puts("Frequenz:   5000");

    while(B1 != 0 && B2 != 0) {}

    do {
        //Check Buttons
        read_buttons();
        //ausgabe
        print_display();

        //wenn der mainBuf leer ist, muss der durch readSPI mit mp3-daten gefuellt werden
        if (mainBuf_empty) {

            do {

                //Shift bytes to the beginning
                /**
                * Bsp:  mainBufSize = 10
                * 			readBytes = 7 --> bytesLeft = 3
                * 			for(){
                * 				mainBuffer[0] = mainBuffer[(10-3)+0]	idx[0] = idx[7]
                * 				mainBuffer[1] = mainBuffer[(10-3)+1]	idx[1] = ide[8] ...
                */
                for(i = 0; i < bytesLeft; i++) {															//die ungelesene bytes am anfang stellen
                    mainBuf[i] = mainBuf[(MAINBUF_SIZE - bytesLeft) + i];
                }

                //Reads size-bytes from current_SPI_Address and writes them into the given array ((mainBuffer + nBytesLeft))
                //also nach diesem aufruf, ist der mainBuf voll und spiadresse muss verschoben werden
                spiFlashMemRead(SPI_MEM_WORK, spi_address, (mainBuf + bytesLeft),  MAINBUF_SIZE - bytesLeft);

                //nach sync word in dem mainBuf suchen
                bytesTilSyncWord = MP3FindSyncWord(mainBuf, MAINBUF_SIZE);


                if (bytesTilSyncWord == 0) {	//falls guelltige date gleich am anfang liegen
                    spi_address =  spi_address + (MAINBUF_SIZE - bytesLeft);
                } else if (bytesTilSyncWord < 0) {//fehler, kein sync word gefunden
                    run = 0;
                } else if (bytesTilSyncWord > 0) {//falls skip word an der n-te adresse gefunden wurde, verschiebe ich die spiadresse um n, damit ich beim naechsten durchlauf vom flash nur die guelltige daten lese (also muell ueberspringen)
                    spi_address = (spi_address - bytesLeft )+ bytesTilSyncWord;
                }

                bytesLeft = 0;		//MUSS DAS HIER NICHT AUSSERHALB DER WHILE ?? DAMIT DIE NBYTES NICHT VERLOREN GEHEN
            } while(bytesTilSyncWord != 0 && run);

            mainBuf_empty = 0; //mainBuf ist voll
        }


        if (run) {	//wenn kein fehler

            //wenn der mp3OutBuf voll ist ODER der MainBuf leer ist, dann warten (WAITING-LED) anschalten
            if (!mp3OutBuffer->isEmpty || mainBuf_empty) {
                setLED(WAITING_LED);
            } else {
                resetLED(WAITING_LED);

                bytesLeft = MAINBUF_SIZE;																					//in nBytesLeft steht wieviele daten aus dem MainBuf noch in dem mp3OutBuf uebertragen werden muessen
                ptrMainBuf = mainBuf;																			//mainBufPointer soll auf MainBuff zeigen, obwohl es bei der initialisierung schon gemacht wurde !!

                /**
                	* para1: decoder instance
                	*	para2: buffer aus dem die daten decodet werden sollen
                	* para3: (input) --> anzahl gueltige bytes, die gelesen werden sollen,
                	* 			 (output)--> input - gelesene bytes, also die bytes die noch gelesen werden muessen
                	* para4: der buffer in dem geschrieben werden soll, der pointer wird geupdatet (bis wo der voll geschrieben wurde)
                	*/

                //nach diesem aufruf ist der mp3OutBuf auf jeden fall voll
                decodeRetVal = MP3Decode(mp3dec, &ptrMainBuf, &bytesLeft, mp3OutBuffer->data, 0);		//decodeResult -->(0 means no error, < 0 means error)


                mainBuf_empty = 1;																									//der mainBuf ist nicht komplett voll

                if (decodeRetVal < 0) {
                    errorCounter++;
                } else {
                    errorCounter = 0;
                }

                if (errorCounter > 2) {																							//fehler beim decode aufgetreten
                    run = 0;
                } else {
                    mp3OutBuffer->isEmpty = 0;																			//der mp3OutBuffer wurde voll geschrieben, bereit fuer die ISR
                    if(mp3OutBuffer == &buf1) {																			//buffer ist voll, also wechseln
                        mp3OutBuffer = &buf2;
                    } else if (mp3OutBuffer == &buf2) {
                        mp3OutBuffer = &buf1;
                    }
                }
            }
        }

    } while (run);

    MP3FreeDecoder(mp3dec);

}
Exemple #11
0
int decoderMain(chanend pcmChan, chanend rxChan, chanend mp3Reset)
{
	int bytesLeft, nRead, err, offset, outOfData, eofReached, nFrames;
	int reset;
	unsigned char readBuf[READBUF_SIZE], *readPtr;
	// unsigned char mp3_data
	// short outBuf[MAX_NCHAN * MAX_NGRAN * MAX_NSAMP];
	// short outBuf[256];

	MP3FrameInfo mp3FrameInfo;
	HMP3Decoder hMP3Decoder;
	
	if ( (hMP3Decoder = MP3InitDecoder()) == 0 )
	{
		return -2;
		// puts("Init died");
	}
	
	bytesLeft = 0;
	outOfData = 0;
	eofReached = 0;
	readPtr = readBuf;
	nRead = 0;

	nFrames = 0;
		
	do
	{
		
		bytesLeft = RxNewFrame(readBuf, READBUF_SIZE, rxChan, mp3Reset);
		if (bytesLeft == 0)
		{
			break;
		}
		readPtr = readBuf;
		
		/* decode one MP3 frame - if offset < 0 then bytesLeft was less than a full frame */
		
		err = MP3Decode(hMP3Decoder, &readPtr, &bytesLeft, NULL, 1, pcmChan);
		
		// err = MP3Decode(hMP3Decoder, &readPtr, &bytesLeft, NULL, 0, pcmChan);
		nFrames++;
		// printintln(nFrames);
		
		// Need to flush the PCM buffer for next frame decode
		// By outputting all ones to the channel
		// OutputToPCMBuf(0xffff, 0xffff, pcmChan);
		
		if (err)
		{
			/* error occurred */
			switch (err)
			{
			case ERR_MP3_INDATA_UNDERFLOW:
				printstrln("HERE");
				outOfData = 1;
				break;
			case ERR_MP3_MAINDATA_UNDERFLOW:
				/* do nothing - next call to decode will provide more mainData */
				break;
			case ERR_MP3_FREE_BITRATE_SYNC:
			default:
				outOfData = 1;
				// printintln(err);
				// printstrln("\nHERE2");
				// while (1);
				break;
			}
		}
		else 
		{
			/* no error */
			MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo);
		}

	} while (!outOfData);
	
	// printstr("FINISHED: ");
	// printintln(err);
	
	MP3FreeDecoder(hMP3Decoder);
	// printDebug(1, debugChan);
	
	return 0;
}
Exemple #12
0
int main(int argc, char **argv)
{
    int bytesLeft, nRead, err, offset, outOfData, eofReached;
    unsigned char readBuf[READBUF_SIZE], *readPtr;
    short outBuf[MAX_NCHAN * MAX_NGRAN * MAX_NSAMP];
    FILE *infile, *outfile;
    MP3FrameInfo mp3FrameInfo;
    HMP3Decoder hMP3Decoder;
    int startTime, endTime, diffTime, totalDecTime, nFrames;
#ifdef ARM_ADS
    float audioSecs;
#endif

    if (argc != 3) {
        printf("usage: mp3dec infile.mp3 outfile.pcm\n");
        return -1;
    }
    infile = fopen(argv[1], "rb");
    if (!infile) {
        printf("file open error\n");
        return -1;
    }

    if (strcmp(argv[2], "nul")) {
        outfile = fopen(argv[2], "wb");
        if (!outfile) {
            printf("file open error\n");
            return -1;
        }
    } else {
        outfile = 0;	/* nul output */
    }

    DebugMemCheckInit();
    InitTimer();

    DebugMemCheckStartPoint();

    if ( (hMP3Decoder = MP3InitDecoder()) == 0 )
        return -2;

    DebugMemCheckEndPoint();

    bytesLeft = 0;
    outOfData = 0;
    eofReached = 0;
    readPtr = readBuf;
    nRead = 0;
    totalDecTime = 0;
    nFrames = 0;
    do {
        /* somewhat arbitrary trigger to refill buffer - should always be enough for a full frame */
        if (bytesLeft < 2*MAINBUF_SIZE && !eofReached) {
            nRead = FillReadBuffer(readBuf, readPtr, READBUF_SIZE, bytesLeft, infile);
            bytesLeft += nRead;
            readPtr = readBuf;
            if (nRead == 0)
                eofReached = 1;
        }

        /* find start of next MP3 frame - assume EOF if no sync found */
        offset = MP3FindSyncWord(readPtr, bytesLeft);
        if (offset < 0) {
            outOfData = 1;
            break;
        }
        readPtr += offset;
        bytesLeft -= offset;


        /* decode one MP3 frame - if offset < 0 then bytesLeft was less than a full frame */
        startTime = ReadTimer();
        err = MP3Decode(hMP3Decoder, &readPtr, &bytesLeft, outBuf, 0);
        nFrames++;

        endTime = ReadTimer();
        diffTime = CalcTimeDifference(startTime, endTime);
        totalDecTime += diffTime;

#if defined ARM_ADS && defined MAX_ARM_FRAMES
        printf("frame %5d  start = %10d, end = %10d elapsed = %10d ticks\r",
               nFrames, startTime, endTime, diffTime);
        fflush(stdout);
#endif

        if (err) {
            /* error occurred */
            switch (err) {
            case ERR_MP3_INDATA_UNDERFLOW:
                outOfData = 1;
                break;
            case ERR_MP3_MAINDATA_UNDERFLOW:
                /* do nothing - next call to decode will provide more mainData */
                break;
            case ERR_MP3_FREE_BITRATE_SYNC:
            default:
                outOfData = 1;
                break;
            }
        } else {
            /* no error */
            MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo);
            if (outfile)
                fwrite(outBuf, mp3FrameInfo.bitsPerSample / 8, mp3FrameInfo.outputSamps, outfile);
        }

#if defined ARM_ADS && defined MAX_ARM_FRAMES
        if (nFrames >= MAX_ARM_FRAMES)
            break;
#endif
    } while (!outOfData);


#ifdef ARM_ADS
    MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo);
    audioSecs = ((float)nFrames * mp3FrameInfo.outputSamps) / ( (float)mp3FrameInfo.samprate * mp3FrameInfo.nChans);
    printf("\nTotal clock ticks = %d, MHz usage = %.2f\n", totalDecTime, ARMULATE_MUL_FACT * (1.0f / audioSecs) * totalDecTime * GetClockDivFactor() / 1e6f);
    printf("nFrames = %d, output samps = %d, sampRate = %d, nChans = %d\n", nFrames, mp3FrameInfo.outputSamps, mp3FrameInfo.samprate, mp3FrameInfo.nChans);
#endif

    MP3FreeDecoder(hMP3Decoder);

    fclose(infile);
    if (outfile)
        fclose(outfile);

    FreeTimer();
    DebugMemCheckFree();

    return 0;
}
/**
  * @brief  mp3_player 进行mp3文件解码、播放
  * @param  filename:要播放的文件路径
  * @retval none
  */
static void mp3_player(const char *filename)
{
	int err, i, outputSamps, current_sample_rate = 0;	

	int						read_offset = 0;				/* 读偏移指针				*/
	int						bytes_left = 0;					/* 剩余字节数				*/	
	unsigned long	Frames = 0;							/* mP3帧计数				*/
	unsigned char	*read_ptr = buffer;			/* 缓冲区指针				*/
	HMP3Decoder		Mp3Decoder;						  /* mp3解码器指针		*/
	

	
	//打开音频文件
	fres = f_open (&file, filename, FA_READ );
	
	//打开失败
	if (fres!=FR_OK)
	{
		printf("read file %s error  ! open another file\r\n",filename);
		fres = f_close (&file);
		
		if (++play_index>=file_num)	//索引值加1
		{
				play_index=0;						//归0,所以如果所有文件都打开失败会一直循环
		}				
		return ;										//文件无法打开,终止解码。进入下一次循环,读取下一个文件
	}
		
	//打开成功
	//初始化MP3解码器
	Mp3Decoder = MP3InitDecoder();	
	
	//获取输入数据流,调用helix库解码,输出PCM数据,约20ms完成一次循环
	//开始进入播放状态,期间中断会修改touch_even状态
	while(player_state != S_SWITCH)	//循环1, 如果touch_even不是切歌状态则继续呆在循环体里 
	{
		//有时出现解码错误,错误后继续在本循环体内,继续播放
		
		//显示播放图标
		Lcd_GramScan(1);
		LCD_Clear(12,88,8,145,BACKGROUND);
		Lcd_show_bmp(320-(103+((play_index-((current_page-1)*8))*18)),240-20,"/mp3player/ui_playing.bmp");
		
		//读取mp3文件
		fres = f_read(&file, buffer, sizeof(buffer), &rw_num);
		if(fres != FR_OK)
		{
			printf("读取%s失败! %d\r\n",filename,fres);
			break;
			//return;
		}
		read_ptr = buffer;									//指向mp3输入流
		bytes_left = rw_num;								//实际读到的输入流大小大小

		//按帧处理	
		while(player_state != S_SWITCH)			//循环2,循环本过程播放音频,直到按了下一首、上一首	
		{
			if (player_state == S_STOP)
			{								
				even_process();									//检查是否有事件需要处理
				continue;												//暂停的时候结束本次循环
			}
				
			player_state = S_PLAY;						//状态更新为正在播放
			
			read_offset = MP3FindSyncWord(read_ptr, bytes_left);	//寻找帧同步,返回第一个同步字的位置
			if(read_offset < 0)																		//没有找到同步字
			{
				break;																							//跳出循环2,回到循环1	
			}
			
			read_ptr += read_offset;					//偏移至同步字的位置
			bytes_left -= read_offset;				//同步字之后的数据大小	
			if(bytes_left < 1024)							//补充数据
			{
				/* 注意这个地方因为采用的是DMA读取,所以一定要4字节对齐  */
				i=(uint32_t)(bytes_left)&3;									//判断多余的字节
				if(i) i=4-i;														//需要补充的字节
				memcpy(buffer+i, read_ptr, bytes_left);	//从对齐位置开始复制
				read_ptr = buffer+i;										//指向数据对齐位置
				fres = f_read(&file, buffer+bytes_left+i, sizeof(buffer)-bytes_left-i, &rw_num);//补充数据
				bytes_left += rw_num;										//有效数据流大小
			}
			err = MP3Decode(Mp3Decoder, &read_ptr, &bytes_left, outBuf[bufflag], 0);					//开始解码 参数:mp3解码结构体、输入流指针、输入流大小、输出流指针、数据格式
			Frames++;			
			
			if (err != ERR_MP3_NONE)									//错误处理
			{
				switch (err)
				{
					case ERR_MP3_INDATA_UNDERFLOW:
						printf("ERR_MP3_INDATA_UNDERFLOW\r\n");
						read_ptr = buffer;
						fres = f_read(&file, read_ptr, sizeof(buffer), &rw_num);
						bytes_left = rw_num;
						break;
			
					case ERR_MP3_MAINDATA_UNDERFLOW:
						/* do nothing - next call to decode will provide more mainData */
						printf("ERR_MP3_MAINDATA_UNDERFLOW\r\n");
						break;
			
					default:
						printf("UNKNOWN ERROR:%d\r\n", err);
			
						// 跳过此帧
						if (bytes_left > 0)
						{
							bytes_left --;
							read_ptr ++;
						}	
						break;
				}
			}
			else		//解码无错误,准备把数据输出到PCM
			{
				MP3GetLastFrameInfo(Mp3Decoder, &Mp3FrameInfo);		//获取解码信息				

		    /* 根据解码信息设置采样率 */
				if (Mp3FrameInfo.samprate != current_sample_rate)	//采样率 
				{
					current_sample_rate = Mp3FrameInfo.samprate;

					printf(" \r\n Bitrate       %dKbps", Mp3FrameInfo.bitrate/1000);
				  printf(" \r\n Samprate      %dHz", current_sample_rate);
					printf(" \r\n BitsPerSample %db", Mp3FrameInfo.bitsPerSample);
					printf(" \r\n nChans        %d", Mp3FrameInfo.nChans);
					printf(" \r\n Layer         %d", Mp3FrameInfo.layer);
					printf(" \r\n Version       %d", Mp3FrameInfo.version);
					printf(" \r\n OutputSamps   %d", Mp3FrameInfo.outputSamps);

					if(current_sample_rate >= I2S_AudioFreq_Default)	//I2S_AudioFreq_Default = 2,正常的帧,每次都要改速率
					{
						I2S_Freq_Config(current_sample_rate);						//根据采样率修改iis速率
					}
				}
				
				/* 输出到DAC */
				outputSamps = Mp3FrameInfo.outputSamps;							//PCM数据个数
				
				if (outputSamps > 0)
				{
					if (Mp3FrameInfo.nChans == 1)	//单声道
					{
						//单声道数据需要复制一份到另一个声道
						for (i = outputSamps - 1; i >= 0; i--)
						{
							outBuf[bufflag][i * 2] = outBuf[bufflag][i];
							outBuf[bufflag][i * 2 + 1] = outBuf[bufflag][i];
						}
						outputSamps *= 2;
					}
				
					//非单声道数据可直接由DMA传输到IIS交给DAC
					/* 等待DMA播放完,这段时间我们可以干其他的事,扫描事件进行处理 */
					while((DMA1_Channel5->CCR&DMA_CCR1_EN) && !(DMA1->ISR&DMA1_IT_TC5))
					{
							even_process();							
						}
						
					/*DMA传输完毕*/
			    DMA_ClearFlag(DMA1_FLAG_TC5 | DMA1_FLAG_TE5);
			    DMA_I2S_Configuration((uint32_t)outBuf[bufflag], outputSamps);
					bufflag = 1 -bufflag;																			//切换buffer

				}//if (outputSamps > 0)
			}//else 解码正常
			
		
		if(file.fptr==file.fsize) 		//如果指针指向了文件尾,表示数据全部读完
		{
			printf("END\r\n");
			if(play_index<file_num-1)		//自动开始下一首歌曲
			{
				play_index++;
				player_state = S_SWITCH;	//进入切歌状态,跳出
			}
			else
			{
				play_index = 0;
				player_state = S_SWITCH;
			}
					
			break; 										//跳出这首歌的播放状态	while break; 
		}
  	
	}//循环2		内 while(player_state != S_SWITCH)	
	
 }//循环1  	外 while(player_state != S_SWITCH)

	f_close(&file);							//结束播放本歌曲,关闭文件
	MP3FreeDecoder(Mp3Decoder);
	I2S_Stop();
	
}