예제 #1
0
파일: mp3.c 프로젝트: Tomwi/FeOSMusic
void freeDecoder(void)
{
	MP3FreeDecoder(mdecoder);
	fclose(fp);
	fp = NULL;
	firstFrame = 0;
	fileSize = 0;
}
예제 #2
0
파일: mp3.c 프로젝트: Manish-cimcon/micro
void mp3_decoder_detach(struct mp3_decoder* decoder)
{
    RT_ASSERT(decoder != RT_NULL);

	/* close audio device */
	if (decoder->snd_device != RT_NULL)
		rt_device_close(decoder->snd_device);

	/* release mp3 decoder */
    MP3FreeDecoder(decoder->decoder);
}
예제 #3
0
파일: main.c 프로젝트: 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;
}
예제 #4
0
파일: labor6.c 프로젝트: BesnikMulici/CEP-1
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);

}
예제 #5
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();
		out_of_data = fill_mp3_buffer(&file,0,true);
		for (cc = 1 ; cc < NUMBER_BUFFERS ; cc++ ) {
			if ( out_of_data ) {
							break;
			}
			out_of_data = fill_mp3_buffer(&file,cc,false);
		}

		// 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,false);

				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);
					MP3FreeDecoder(hMP3Decoder);
					return;
				}


			}
			else {
				// We don't have any work to do, shut down until interrupt (DMA transfer complete)
				__asm__ volatile ("wfi");
			}
		}
	}
예제 #6
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;
}
예제 #7
0
파일: mp3.c 프로젝트: DC-SWAT/DreamShell
void shutdown_mp3() {
	MP3FreeDecoder(hMP3Decoder);
}
예제 #8
0
파일: main.c 프로젝트: elhobbs/hexen2
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;
}
예제 #9
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();
	
}