📄 play_mp3.c.bak
字号:
/*
Copyright (C) 2006 Andreas Schwarz <andreas@andreas-s.net>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include <stdio.h>
#include <string.h>
#define assert(ignore) ((void)0)
#include "play_mp3.h"
#include "mp3dec.h"
#include "ff.h"
#include "system.h"
//#include "dac.h"
//#include "profile.h"
#define debug_printf
static HMP3Decoder hMP3Decoder;
static MP3FrameInfo mp3FrameInfo;
static u08 *read_ptr;
static i32 bytes_left=0, bytes_leftBeforeDecoding=0, err, offset;
static i32 nFrames = 0;
static u08 *mp3buf;
static u32 mp3buf_size;
static u08 allocated = 0;
//-------------------------------------------------------------------
void wMP3Init(u08 *buffer, u32 buffer_size)
{
mp3buf = buffer;
mp3buf_size = buffer_size;
wMP3Reset();
}
//-------------------------------------------------------------------
void wMP3Reset()
{
read_ptr = NULL;
bytes_leftBeforeDecoding = bytes_left = 0;
nFrames = 0;
}
//-------------------------------------------------------------------
void wMP3Alloc()
{
if (!allocated) hMP3Decoder = MP3InitDecoder();
allocated = 1;
}
//-------------------------------------------------------------------
void wMP3Free()
{
if (allocated) MP3FreeDecoder(hMP3Decoder);
allocated = 0;
}
//-------------------------------------------------------------------
i32 wMP3RefillInbuffer(FIL *mp3file)
{
WORD bytes_read;
i32 bytes_to_read;
//debug_printf("left: %d. refilling inbuffer...\n", bytes_left);
if (bytes_left > 0) {
// after fseeking backwards the FAT has to be read from the beginning -> S L O W
//assert(f_lseek(mp3file, mp3file->fptr - bytes_leftBeforeDecoding) == FR_OK);
// better: move unused rest of buffer to the start
// no overlap as long as (1024 <= mp3buf_size/2), so no need to use memove
memcpy(mp3buf, read_ptr, bytes_left);
}
bytes_to_read = mp3buf_size - bytes_left;
wFileRead(mp3file, (BYTE *)mp3buf + bytes_left, bytes_to_read, &bytes_read);
if (bytes_read == bytes_to_read) {
read_ptr = mp3buf;
offset = 0;
bytes_left = mp3buf_size;
return 0;
} else {
return -1;
}
}
//----------------------------------------------------------------------
i32 wMP3Process(FIL *mp3file)
{
static xTFrame *pxFrameBuffer;
static u32 ulCurrentFrame;
pxFrameBuffer = 0x0C100000;//wMalloc(dulFrameSize * dulFrameNumber);
u32 ulDecodedCount = 0;
ulCurrentFrame = 0;
wMP3DecodeFrame(mp3file, (i16*)(pxFrameBuffer+ulCurrentFrame), &ulDecodedCount);
//ulCurrentFrame++;
//ulDecodedCount = 2000;
wIISDMATransferInit((u32*)pxFrameBuffer, sizeof(xTFrame) * dulFrameNumber2 , 0x00000001);
u32 ulDMACount = 0;
u32 ulDMACurrCount;
while (1)
{
//wDelayMs(7);
ulDMACurrCount = /*(*bdicnt0&0x000FFFFF)-(*bdccnt0&0x000FFFFF);*/wIISBufferStatusInspect();
if ( ulDMACurrCount< ulDMACount)
{ // DMA jumped onto start of buffer. We have to fill any left buffers in buffer end
ulDMACount = ulDMACurrCount;
for (;ulCurrentFrame<dulFrameNumber;ulCurrentFrame++)
wMP3DecodeFrame(mp3file, (i16*)(pxFrameBuffer+ulCurrentFrame), &ulDecodedCount);
ulCurrentFrame = 0;
/* While we were decoding, DMA could fetch a lot of data. So the DMA pointer must be refreshed.
The best idea is to restart the cycle*/
continue;
}
// In this point we are just behind the DMA pointer
ulDMACount = ulDMACurrCount;
if (ulCurrentFrame == dulFrameNumber) ulCurrentFrame = 0;
if ( (ulCurrentFrame+1) * sizeof(xTFrame)< ulDMACurrCount )// && (ulCurrentFrame<dulFrameNumber))
{
//do
{
wMP3DecodeFrame(mp3file, (i16*)(pxFrameBuffer+ulCurrentFrame), &ulDecodedCount);
}
//while (ulDecodedCount < 1000);
ulCurrentFrame++;
continue;
}
//no action needed so we can perform a task switch or a simple delay
//wDelayMs(10);
}
wFree(pxFrameBuffer);
}
//----------------------------------------------------------------------
i32 wMP3DecodeFrame(FIL *mp3file, i16 *iBuffer, u32 *ulBufferSize)
{
i32 writeable_buffer;
if (read_ptr == NULL)
{
if(wMP3RefillInbuffer(mp3file) != 0)
return -1;
}
offset = MP3FindSyncWord(read_ptr, bytes_left);
if (offset < 0)
{
if(wMP3RefillInbuffer(mp3file) != 0)
return -1;
}
read_ptr += offset;
bytes_left -= offset;
bytes_leftBeforeDecoding = bytes_left;
// check if this is really a valid frame
// (the decoder does not seem to calculate CRC, so make some plausibility checks)
if (MP3GetNextFrameInfo(hMP3Decoder, &mp3FrameInfo, read_ptr) == 0 &&
mp3FrameInfo.nChans == 2 &&
mp3FrameInfo.version == 0)
{
//debug_printf("Found a frame at offset %x\n", offset + read_ptr - mp3buf + mp3file->fptr);
}
else
{
//puts("this is no valid frame");
// advance data pointer
// TODO: handle bytes_left == 0
//assert(bytes_left > 0);
bytes_left -= 1;
read_ptr += 1;
return 0;
}
if (bytes_left < 1024)
{
if(wMP3RefillInbuffer(mp3file) != 0)
return -1;
}
//debug_printf("bytes_leftBeforeDecoding: %i\n", bytes_leftBeforeDecoding);
//PROFILE_START("MP3Decode");
err = MP3Decode(hMP3Decoder, &read_ptr, &bytes_left, iBuffer, 0);
//PROFILE_END();
nFrames++;
if (err)
{
switch (err)
{
case ERR_MP3_INDATA_UNDERFLOW:
{
//puts("ERR_MP3_INDATA_UNDERFLOW");
bytes_left = 0;
if(wMP3RefillInbuffer(mp3file) != 0)
return -1;
break;
}
case ERR_MP3_MAINDATA_UNDERFLOW:
{
/* do nothing - next call to decode will provide more mainData */
//puts("ERR_MP3_MAINDATA_UNDERFLOW");
break;
}
default:
{
//iprintf("unknown error: %i\n", err);
// skip this frame
if (bytes_left > 0) {
bytes_left --;
read_ptr ++;
} else {
// TODO
assert(0);
}
break;
}
}
*ulBufferSize = 0;
}
else
{
/* no error */
MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo);
//debug_printf("Bitrate: %i\r\n", mp3FrameInfo.bitrate);
//debug_printf("%i samples\n", mp3FrameInfo.outputSamps);
//debug_printf("Words remaining in first DMA buffer: %i\n", *AT91C_SSC_TCR);
//debug_printf("Words remaining in next DMA buffer: %i\n", *AT91C_SSC_TNCR);
*ulBufferSize = mp3FrameInfo.outputSamps;
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -