Exemplo n.º 1
0
static void play_mp3(char* filename) {
	unsigned int br, btr;
	FRESULT res;

	bytes_left = FILE_READ_BUFFER_SIZE;
	read_ptr = file_read_buffer;

	if (FR_OK == f_open(&file, filename, FA_OPEN_EXISTING | FA_READ)) {

		// Read ID3v2 Tag
		char szArtist[120];
		char szTitle[120];
		Mp3ReadId3V2Tag(&file, szArtist, sizeof(szArtist), szTitle, sizeof(szTitle));

		// Fill buffer
		f_read(&file, file_read_buffer, FILE_READ_BUFFER_SIZE, &br);

		// Play mp3
		hMP3Decoder = MP3InitDecoder();
		InitializeAudio(Audio44100HzSettings);
		SetAudioVolume(0xAF);
		PlayAudioWithCallback(AudioCallback, 0);

		for(;;) {
			/*
			 * If past half of buffer, refill...
			 *
			 * When bytes_left changes, the audio callback has just been executed. This
			 * means that there should be enough time to copy the end of the buffer
			 * to the beginning and update the pointer before the next audio callback.
			 * Getting audio callbacks while the next part of the file is read from the
			 * file system should not cause problems.
			 */
			if (bytes_left < (FILE_READ_BUFFER_SIZE / 2)) {
				// Copy rest of data to beginning of read buffer
				memcpy(file_read_buffer, read_ptr, bytes_left);

				// Update read pointer for audio sampling
				read_ptr = file_read_buffer;

				// Read next part of file
				btr = FILE_READ_BUFFER_SIZE - bytes_left;
				res = f_read(&file, file_read_buffer + bytes_left, btr, &br);

				// Update the bytes left variable
				bytes_left = FILE_READ_BUFFER_SIZE;

				// Out of data or error or user button... Stop playback!
				if (br < btr || res != FR_OK || BUTTON)
				  {
					StopAudio();

					// Re-initialize and set volume to avoid noise
					InitializeAudio(Audio44100HzSettings);
					SetAudioVolume(0);

					// Close currently open file
					f_close(&file);

					// Wait for user button release
					while(BUTTON){};

					// Return to previous function
					return;
				}
			}
		}
	}
}
Exemplo n.º 2
0
Arquivo: main.c Projeto: ADTL/ARMWork
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;
}
Exemplo n.º 3
0
static void play_mp3(char* filename) {

	bool out_of_data;
	int cc;


	// Open file
	if (FR_OK == f_open(&file, filename, FA_OPEN_EXISTING | FA_READ)) {

		// Read ID3v2 Tag
		char szArtist[120];
		char szTitle[120];
		Mp3ReadId3V2Tag(&file, szArtist, sizeof(szArtist), szTitle, sizeof(szTitle));


		///////////////////////////////////////////////////////////buffer starts getting filled for first time
		// Start Initial fill of buffer
		hMP3Decoder = MP3InitDecoder();
		for (cc = 0 ; cc < NUMBER_BUFFERS ; cc++ ) {
			out_of_data = fill_mp3_buffer(&file,cc);

			if ( out_of_data ) {
				break;
			}
		}

		// Initialize buffer counters
		buffer_read = 0;
		buffer_write = 0;

/////////////////////////////////////////////////////////////////////////////////////////
		// Play mp3
		running_player = true;
		InitializeAudio(Audio44100HzSettings);
		// InitializeAudio(Audio32000HzSettings);
		SetAudioVolume(0xAF);
		PlayAudioWithCallback(AudioCallback, 0);
//////////////////////////////////////////////////////////////////////////////////////////
		for(;;) {
			/*
			 *  If we have an unused buffer, call fill_mp3_buffer to fill it.
			 */
			if ( buffer_read != buffer_write ) {


				// Refill the MP3 buffer
				out_of_data = fill_mp3_buffer(&file,buffer_write);

				if ( !out_of_data ) {
					buffer_write = ( buffer_write + 1 ) % NUMBER_BUFFERS;
				}

				// Out of data or error or user button... Stop playback!
				if (out_of_data || (exitMp3 == 1))
				{
					StopAudio();
					running_player = false;

					// Re-initialize and set volume to avoid noise
					InitializeAudio(Audio44100HzSettings);
					SetAudioVolume(0);

					// Close currently open file
					f_close(&file);
					return;
				}


			}
			else {
				// We don't have any work to do, shut down until interrupt (DMA transfer complete)
				__asm__ volatile ("wfi");
			}
		}
	}