nt9856x/rtos/code/application/source/cardv/SrcCode/UIApp/WavPlay/WavPlay.c
2023-03-28 15:07:53 +08:00

416 lines
9.2 KiB
C
Executable File

#include <stdio.h>
#include <string.h>
#include <kwrap/error_no.h>
#include "FileSysTsk.h"
//#include "PStore.h"
//#include "SysCommon.h"
#include "GxSound.h"
#include "kdrv_audioio/audlib_aac.h"
#include "WavPlay.h"
#include "sys_mempool.h"
#include "UIWnd/UIFlow.h"
///////////////////////////////////////////////////////////////////////////////
#define __MODULE__ WavPlay
#define __DBGLVL__ 5////2 // 0=FATAL, 1=ERR, 2=WRN, 3=UNIT, 4=FUNC, 5=IND, 6=MSG, 7=VALUE, 8=USER
#define __DBGFLT__ "*" //*=All, [mark]=CustomClass
#include <kwrap/debug.h>
///////////////////////////////////////////////////////////////////////////////
#if (WAV_PLAY_FUNC == ENABLE)
#define PS_WAV_MERGE_DATA "WAVMERGE" // cannot over 12 characters
#define WAV_DATA_MAX 150 // max 150 wav files
#define AAC_BUF_SIZE (80*1024) // 80KB for AAC data
#define WAV_IN_USER_PARTITION ENABLE//DISABLE
#if (USER_PACK_UPDATE == DISABLE)
#undef WAV_IN_USER_PARTITION
#define WAV_IN_USER_PARTITION DISABLE
#endif
#if (WAV_IN_USER_PARTITION == DISABLE)
#include "WavData.c"
#endif
static UINT32 g_WavHeaderAddr = 0;
static BOOL g_WavPlayInit = FALSE;
static SOUND_DATA g_SoundData; // it needs to use global variable for GxSound
ER WavPlay_DecodeAAC(UINT32 inAddr, UINT32 outAddr, UINT32 inLen, UINT32 *pOutLen, AUDLIB_AAC_CFG *pAACDConfig)
{
UINT32 uiBsLen; // AAC bs length
UINT32 uiRemainBsLen; // remaining AAC bs length
UINT32 uiBsAddr; // current AAC bs address
UINT32 uiRawAddr; // current raw output address
UINT32 uiAACFrameLen; // AAC frame length
UINT32 uiAACFrameNum; // AAC frame number
INT32 ErrorCode = E_OK; // error code
AUDLIB_AAC_BUFINFO AACDBuf; // AAC decoder buffer info
AUDLIB_AACD_RTNINFO AACDRtn; // AAC decoder return info
if ((ErrorCode = audlib_aac_decode_init(pAACDConfig)) != E_OK)
{
DBG_ERR("AAC decoder init error %d!\r\n", ErrorCode);
return E_SYS;
}
// init buffer address
uiBsLen = inLen;
uiBsAddr = inAddr;
uiRawAddr = outAddr;
uiRemainBsLen = uiBsLen;
uiAACFrameNum = 0;
while (uiBsAddr < (inAddr + uiBsLen))
{
AACDBuf.bitstram_buffer_in = uiBsAddr;
AACDBuf.bitstram_buffer_out = uiRawAddr;
AACDBuf.bitstram_buffer_length = uiRemainBsLen;
if ((ErrorCode = audlib_aac_decode_one_frame(&AACDBuf, &AACDRtn)) != E_OK)
{
DBG_ERR("AAC decode error %d!\r\n", ErrorCode);
return E_SYS;
}
uiAACFrameLen = AACDRtn.one_frame_consume_bytes;
uiBsAddr += uiAACFrameLen;
uiRawAddr += AACDRtn.output_size * AACDRtn.channel_number * 2; // 2 bytes per sample
uiRemainBsLen -= uiAACFrameLen;
uiAACFrameNum++;
}
*pOutLen = uiRawAddr - outAddr;
return E_OK;
}
ER WavPlay_WriteWavData(void)
{
#define WAV_READ_BUF_SIZE 0x400000 // 4MB
FST_FILE pFile;
char *pFileName = "A:\\WavMerge.bin";
UINT32 uiFileSize;
UINT32 pBuf;
pBuf = SxCmd_GetTempMem(WAV_READ_BUF_SIZE);
if (pBuf == 0)
{
DBG_ERR("No enough buffer for sound data reading!\r\n");
return E_SYS;
}
// open wav merge file (WavMerge.bin)
pFile = FileSys_OpenFile(pFileName, FST_OPEN_READ);
uiFileSize = WAV_READ_BUF_SIZE; // max reading size
if (pFile)
{
FileSys_ReadFile(pFile, (UINT8 *)pBuf, &uiFileSize, 0, NULL);
FileSys_CloseFile(pFile);
DBG_MSG("File %s, size %d\r\n", pFileName, uiFileSize);
if (uiFileSize == WAV_READ_BUF_SIZE)
{
DBG_ERR("Read buffer is not enough!\r\n");
SxCmd_RelTempMem(pBuf);
return E_SYS;
}
}
else
{
DBG_ERR("Open %s for reading failed!\r\n", pFileName);
SxCmd_RelTempMem(pBuf);
return E_SYS;
}
// write merged wav data to user partition
if (UserPartition_Write((INT8 *)pBuf, 0, uiFileSize, USR_PARTI_WAV_DATA) != E_OK)
{
DBG_ERR("write wav data to USR_PARTI_WAV_DATA failed!\r\n");
SxCmd_RelTempMem(pBuf);
return E_SYS;
}
SxCmd_RelTempMem(pBuf);
return E_OK;
}
ER WavPlay_Init(void)
{
UINT32 uiSize;
UINT32 uiPoolSize;
if (g_WavPlayInit == FALSE)
{
g_WavHeaderAddr = mempool_wavplay_header;
uiPoolSize = POOL_SIZE_WAV_PLAY_HEADER;
uiSize = sizeof(WAV_MERGE_DATA) * WAV_DATA_MAX;
DBG_IND("wav header size = %d\r\n", uiSize);
if (uiSize > uiPoolSize)
{
DBG_ERR("read wav header error, buffer not enough!\r\n");
return E_SYS;
}
if (UserPartition_Read((INT8 *)g_WavHeaderAddr, 0, uiSize, USR_PARTI_WAV_DATA) != E_OK)
{
DBG_ERR("read wav header from USR_PARTI_WAV_DATA failed!\r\n");
return E_SYS;
}
g_WavPlayInit = TRUE;
}
return E_OK;
}
ER WavPlay_PlayData(char *pName, UINT32 isWav)
{
UINT32 i;
UINT32 pBuf;
WAV_MERGE_DATA *pWavData;
if (GxSound_IsPlaying())
{
DBG_ERR("sound is playing, cannot play now!\r\n");
return E_SYS;
}
#if WAV_IN_USER_PARTITION
if (WavPlay_Init() != E_OK)
{
return E_SYS;
}
#else
if (isWav == FALSE) // AAC data
{
g_WavHeaderAddr = (UINT32)uiAACData;
}
else
{
g_WavHeaderAddr = (UINT32)uiWavData;
}
#endif
// compare wav file name
i = 0;
while (i < WAV_DATA_MAX)
{
pWavData = (WAV_MERGE_DATA *)(g_WavHeaderAddr + sizeof(WAV_MERGE_DATA) * i);
if (strcmp(pWavData->FileName, pName) == 0)
{
DBG_IND("Find name %s, addr 0x%x, size 0x%x\r\n", pWavData->FileName, pWavData->uiAddr, pWavData->uiSize);
break;
}
i++;
}
if (i == WAV_DATA_MAX)
{
DBG_ERR("No %s found!\r\n", pName);
return E_SYS;
}
#if WAV_IN_USER_PARTITION
UINT32 uiPoolSize;
pBuf = mempool_wavplay_data;
uiPoolSize = POOL_SIZE_WAV_PLAY_DATA;
if (pWavData->uiSize > uiPoolSize)
{
DBG_ERR("read wav data error, buffer not enough!\r\n");
return E_SYS;
}
if (isWav == FALSE) // AAC data
{
pBuf = pBuf + uiPoolSize - AAC_BUF_SIZE;
}
if (UserPartition_Read((INT8 *)pBuf, pWavData->uiAddr, pWavData->uiSize, USR_PARTI_WAV_DATA) != E_OK)
{
DBG_ERR("read wav data from USR_PARTI_WAV_DATA failed!\r\n");
return E_SYS;
}
#else
pBuf = g_WavHeaderAddr + pWavData->uiAddr;
#endif
if (isWav == FALSE) // AAC data
{
ER err;
UINT32 PCMBuf;
UINT32 PCMLen;
AUDLIB_AAC_CFG AACDConfig; // AAC decoder config
AACDConfig.sample_rate = 16000;
AACDConfig.channel_number = 1;
AACDConfig.header_enable = TRUE;
PCMBuf = mempool_wavplay_data;
err = WavPlay_DecodeAAC(pBuf, PCMBuf, pWavData->uiSize, &PCMLen, &AACDConfig);
if (err == E_OK)
{
// play wav data
g_SoundData.puiData = (const UINT8 *)PCMBuf;
g_SoundData.uiSize = PCMLen;
g_SoundData.sampleRate = 16000;
g_SoundData.isMono = TRUE;
g_SoundData.soundId = 0xFFFFFFFF;
GxSound_SetPlayCount(1);
err = GxSound_ActOnSndNotInTbl(SOUND_PLAY_START, &g_SoundData, TRUE);
}
return err;
}
else
{
// play wav data
g_SoundData.puiData = (const UINT8 *)pBuf;
g_SoundData.isMono = TRUE;
GxSound_SetPlayCount(1);
GxSound_ActOnSndNotInTbl(SOUND_PLAY_START, &g_SoundData, FALSE);
}
return E_OK;
}
ER WavPlay_PlayWavData(char *pName)
{
return WavPlay_PlayData(pName, TRUE);
}
ER WavPlay_PlayAACData(char *pName)
{
return WavPlay_PlayData(pName, FALSE);
}
ER WavPlay_PlayWavDataFromFile(char *pFileName)
{
FST_FILE pFile;
UINT32 uiFileSize;
UINT32 pBuf;
UINT32 uiPoolSize;
pBuf = mempool_wavplay_data;
uiPoolSize = POOL_SIZE_WAV_PLAY_DATA;
// open wav file
pFile = FileSys_OpenFile(pFileName, FST_OPEN_READ);
uiFileSize = uiPoolSize; // max reading size
if (pFile)
{
FileSys_ReadFile(pFile, (UINT8 *)pBuf, &uiFileSize, 0, NULL);
FileSys_CloseFile(pFile);
DBG_DUMP("File %s, size %d\r\n", pFileName, uiFileSize);
if (uiFileSize == uiPoolSize)
{
DBG_ERR("Read buffer is not enough!\r\n");
return E_SYS;
}
}
else
{
DBG_ERR("Open %s for reading failed!\r\n", pFileName);
return E_SYS;
}
if (GxSound_IsPlaying())
{
DBG_ERR("sound is playing, cannot play now!\r\n");
return E_SYS;
}
// play wav data
g_SoundData.puiData = (const UINT8 *)pBuf;
g_SoundData.isMono = TRUE;
GxSound_SetPlayCount(1);
GxSound_ActOnSndNotInTbl(SOUND_PLAY_START, &g_SoundData, FALSE);
return E_OK;
}
ER WavPlay_PlayAACDataFromFile(char *pFileName)
{
ER err;
FST_FILE pFile;
UINT32 uiFileSize;
UINT32 uiPoolSize;
UINT32 PCMBuf, AACBuf;
UINT32 PCMLen;
AUDLIB_AAC_CFG AACDConfig; // AAC decoder config
PCMBuf = mempool_wavplay_data;
AACBuf = PCMBuf + POOL_SIZE_WAV_PLAY_DATA - AAC_BUF_SIZE;
uiPoolSize = AAC_BUF_SIZE;
// open wav file
pFile = FileSys_OpenFile(pFileName, FST_OPEN_READ);
uiFileSize = uiPoolSize; // max reading size
if (pFile)
{
FileSys_ReadFile(pFile, (UINT8 *)AACBuf, &uiFileSize, 0, NULL);
FileSys_CloseFile(pFile);
DBG_DUMP("File %s, size %d\r\n", pFileName, uiFileSize);
if (uiFileSize == uiPoolSize)
{
DBG_ERR("Read buffer is not enough!\r\n");
return E_SYS;
}
}
else
{
DBG_ERR("Open %s for reading failed!\r\n", pFileName);
return E_SYS;
}
// decode AAC
AACDConfig.sample_rate = 16000;
AACDConfig.channel_number = 1;
AACDConfig.header_enable = TRUE;
err = WavPlay_DecodeAAC(AACBuf, PCMBuf, uiFileSize, &PCMLen, &AACDConfig);
if (err == E_OK)
{
if (GxSound_IsPlaying())
{
DBG_ERR("sound is playing, cannot play now!\r\n");
return E_SYS;
}
// play wav data
g_SoundData.puiData = (const UINT8 *)PCMBuf;
g_SoundData.uiSize = PCMLen;
g_SoundData.sampleRate = 16000;
g_SoundData.isMono = TRUE;
g_SoundData.soundId = 0xFFFFFFFF;
GxSound_SetPlayCount(1);
err = GxSound_ActOnSndNotInTbl(SOUND_PLAY_START, &g_SoundData, TRUE);
}
return err;
}
#endif // WAV_PLAY_FUNC