Added 3DS dsp1 loading and implemented an aac decoding example

It still doesn't want to read from main memory though
This commit is contained in:
Gericom 2019-11-11 12:36:07 +01:00
parent c2ebf9fd11
commit a5bd5afc96
7 changed files with 573 additions and 54 deletions

View File

@ -62,6 +62,9 @@ int main() {
writePowerManagement(PM_CONTROL_REG, ( readPowerManagement(PM_CONTROL_REG) & ~PM_SOUND_MUTE ) | PM_SOUND_AMP );
powerOn(POWER_SOUND);
if(isDSiMode())
REG_SNDEXTCNT |= SNDEXTCNT_FREQ_47KHZ;
readUserSettings();
ledBlink(0);
@ -87,7 +90,7 @@ int main() {
setPowerButtonCB(powerButtonCB);
REG_SNDEXTCNT = 0x8000;
//REG_SNDEXTCNT = 0x8000;
// Keep the ARM7 mostly idle
while (!exitflag) {

View File

@ -0,0 +1,79 @@
#include <nds.h>
#include "dsp.h"
#include "dsp_pipe.h"
#include "CtrDspProcess.h"
void CtrDspProcess::OnPipeResponse(int port, int dir)
{
if(dir != DSP_PIPE_DIR_IN)
return;
dsp_pipe_t pipe;
dsp_loadPipe(&pipe, port, dir);
if(dsp_getPipeReadLength(&pipe) < sizeof(dsp_codec_cmd_t))
return;
dsp_readPipe(&pipe, (void*)&_lastResponse, sizeof(dsp_codec_cmd_t));
if(_lastResponse.codecType == DSP_CODEC_TYPE_AACDEC && _lastResponse.command == DSP_CODEC_CMD_PROCESS)
{
memcpy(&_lastAACDecResponse, &_lastResponse.params.aacDecProcResp, sizeof(dsp_codec_cmd_aacdec_proc_resp_t));
_lastAACDecResponseValid = true;
}
_gotResponse = true;
}
bool CtrDspProcess::AACDecInitialize(
DspCodecAACDecFormat format,
DspCodecAACDecFrequency frequency,
DspCodecAACDecCRCFlag crcFlag,
DspCodecAACDecReverseFlag reverseFlag)
{
dsp_setPipePortCallback(DSP_PIPE_PORT_BINARY, CtrDspProcess::OnPipeResponse, this);
dsp_pipe_t pipe;
dsp_loadPipe(&pipe, DSP_PIPE_PORT_BINARY, DSP_PIPE_DIR_OUT);
dsp_codec_cmd_t cmd;
cmd.codecType = DSP_CODEC_TYPE_AACDEC;
cmd.command = DSP_CODEC_CMD_INITIALIZE;
cmd.result = DSP_CODEC_RESULT_SUCCESS;
cmd.platform = 0;
cmd.params.aacDecInit.format = format;
cmd.params.aacDecInit.frequency = frequency;
cmd.params.aacDecInit.crcFlag = crcFlag;
cmd.params.aacDecInit.reverseFlag = reverseFlag;
cmd.params.aacDecInit.reserved = 0;
_gotResponse = false;
_lastAACDecResponseValid = false;
dsp_writePipe(&pipe, &cmd, sizeof(cmd));
WaitCodecResponse();
return _lastResponse.result == DSP_CODEC_RESULT_SUCCESS;
}
void CtrDspProcess::AACDecDecode(const void* aacFrame, u32 frameLength, s16* leftOut, s16* rightOut)
{
dsp_setPipePortCallback(DSP_PIPE_PORT_BINARY, CtrDspProcess::OnPipeResponse, this);
dsp_pipe_t pipe;
dsp_loadPipe(&pipe, DSP_PIPE_PORT_BINARY, DSP_PIPE_DIR_OUT);
dsp_codec_cmd_t cmd;
cmd.codecType = DSP_CODEC_TYPE_AACDEC;
cmd.command = DSP_CODEC_CMD_PROCESS;
cmd.result = DSP_CODEC_RESULT_SUCCESS;
cmd.platform = 0;
cmd.params.aacDecProc.dataAddress = (u32)aacFrame;
cmd.params.aacDecProc.frameSize = frameLength;
cmd.params.aacDecProc.leftPCMAddress = (u32)leftOut;
cmd.params.aacDecProc.rightPCMAddress = (u32)rightOut;
cmd.params.aacDecProc.paramAddress = 0;
_gotResponse = false;
dsp_writePipe(&pipe, &cmd, sizeof(cmd));
}

View File

@ -0,0 +1,164 @@
#pragma once
#include "DspProcess.h"
enum DspCodecType : u16
{
DSP_CODEC_TYPE_UNKNOWN = 0,
DSP_CODEC_TYPE_AACDEC = 1,
DSP_CODEC_TYPE_AACENC = 2,
DSP_CODEC_TYPE_MP3DEC = 3,
DSP_CODEC_TYPE_MP3ENC = 4
};
enum DspCodecCmd : u16
{
DSP_CODEC_CMD_INITIALIZE = 0,
DSP_CODEC_CMD_PROCESS = 1,
DSP_CODEC_CMD_FINALIZE = 2,
DSP_CODEC_CMD_RESUME = 3,
DSP_CODEC_CMD_SUSPEND = 4
};
enum DspCodecResult : u16
{
DSP_CODEC_RESULT_SUCCESS = 0,
DSP_CODEC_RESULT_FAILURE = 1
};
enum DspCodecAACDecFormat : u32
{
DSP_CODEC_AACDEC_FORMAT_RAW = 0,
DSP_CODEC_AACDEC_FORMAT_ADTS = 1
};
enum DspCodecAACDecFrequency : int
{
DSP_CODEC_AACDEC_FREQUENCY_UNKNOWN = -1,
DSP_CODEC_AACDEC_FREQUENCY_48000 = 0,
DSP_CODEC_AACDEC_FREQUENCY_44100 = 1,
DSP_CODEC_AACDEC_FREQUENCY_32000 = 2,
DSP_CODEC_AACDEC_FREQUENCY_24000 = 3,
DSP_CODEC_AACDEC_FREQUENCY_22050 = 4,
DSP_CODEC_AACDEC_FREQUENCY_16000 = 5,
DSP_CODEC_AACDEC_FREQUENCY_12000 = 6,
DSP_CODEC_AACDEC_FREQUENCY_11025 = 7,
DSP_CODEC_AACDEC_FREQUENCY_8000 = 8
};
enum DspCodecAACDecCRCFlag : u32
{
DSP_CODEC_AACDEC_CRC_FLAG_OFF = 0,
DSP_CODEC_AACDEC_CRC_FLAG_ON = 1
};
enum DspCodecAACDecReverseFlag : u32
{
DSP_CODEC_AACDEC_REVERSE_FLAG_OFF = 0,
DSP_CODEC_AACDEC_REVERSE_FLAG_ON = 1
};
struct dsp_codec_cmd_aacdec_init_t
{
DspCodecAACDecFormat format;
DspCodecAACDecFrequency frequency;
DspCodecAACDecCRCFlag crcFlag;
DspCodecAACDecReverseFlag reverseFlag;
u32 reserved;
};
struct dsp_codec_cmd_aacdec_proc_t
{
u32 dataAddress;
u32 frameSize;
u32 leftPCMAddress;
u32 rightPCMAddress;
u32 paramAddress; //? can be kept 0
};
struct dsp_codec_cmd_aacdec_proc_resp_t
{
DspCodecAACDecFrequency frequency;
u32 nrChannels;
u32 usedBytes;
u32 errorCode;
u32 nrClockCycles;
};
struct dsp_codec_cmd_t
{
DspCodecType codecType;
DspCodecCmd command;
DspCodecResult result;
u16 platform; //?
union
{
dsp_codec_cmd_aacdec_init_t aacDecInit;
dsp_codec_cmd_aacdec_proc_t aacDecProc;
dsp_codec_cmd_aacdec_proc_resp_t aacDecProcResp;
u16 raw[12];
} params;
};
class CtrDspProcess : public DspProcess
{
void OnPipeResponse(int port, int dir);
static void OnPipeResponse(void* arg, int port, int dir)
{
return ((CtrDspProcess*)arg)->OnPipeResponse(port, dir);
}
protected:
volatile bool _gotResponse;
dsp_codec_cmd_t _lastResponse;
dsp_codec_cmd_aacdec_proc_resp_t _lastAACDecResponse;
bool _lastAACDecResponseValid;
public:
CtrDspProcess()
: _gotResponse(false), _lastAACDecResponseValid(false)
{}
bool AACDecInitialize(
DspCodecAACDecFormat format,
DspCodecAACDecFrequency frequency = DSP_CODEC_AACDEC_FREQUENCY_UNKNOWN,
DspCodecAACDecCRCFlag crcFlag = DSP_CODEC_AACDEC_CRC_FLAG_ON,
DspCodecAACDecReverseFlag reverseFlag = DSP_CODEC_AACDEC_REVERSE_FLAG_OFF);
void AACDecDecode(const void* aacFrame, u32 frameLength, s16* leftOut, s16* rightOut);
void WaitCodecResponse()
{
while(!_gotResponse);
}
int AACDecGetSampleRate()
{
static const int aacFrequencies[] =
{ 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000 };
if(!_lastAACDecResponseValid || _lastAACDecResponse.errorCode != 0 || _lastAACDecResponse.frequency == DSP_CODEC_AACDEC_FREQUENCY_UNKNOWN)
return -1;
return aacFrequencies[(int)_lastAACDecResponse.frequency];
}
int AACDecGetChannelCount()
{
if(!_lastAACDecResponseValid || _lastAACDecResponse.errorCode != 0)
return -1;
return _lastAACDecResponse.nrChannels;
}
int AACDecGetErrorCode()
{
if(!_lastAACDecResponseValid)
return -1;
return _lastAACDecResponse.errorCode;
}
int AACDecGetUsedBytes()
{
if(!_lastAACDecResponseValid)
return -1;
return _lastAACDecResponse.usedBytes;
}
};

View File

@ -3,6 +3,7 @@
#include "dsp.h"
#include "dsp_pipe.h"
#include "dsp_coff.h"
#include "dsp_dsp1.h"
#include "DspProcess.h"
static DspProcess* sDspProcess = NULL;
@ -66,20 +67,20 @@ bool DspProcess::SetMemoryMapping(bool isCode, u32 addr, u32 len, bool toDsp)
return true;
}
bool DspProcess::EnumerateSections(dsp_process_sec_callback_t callback)
bool DspProcess::EnumerateSectionsCoff(dsp_process_sec_callback_t callback)
{
if(!callback)
return false;
dsp_coff_header_t coffHeader;
fseek(_coffFile, 0, SEEK_SET);
if(fread(&coffHeader, 1, sizeof(dsp_coff_header_t), _coffFile) != sizeof(dsp_coff_header_t))
fseek(_dspFile, 0, SEEK_SET);
if(fread(&coffHeader, 1, sizeof(dsp_coff_header_t), _dspFile) != sizeof(dsp_coff_header_t))
return false;
int sectabOffset = sizeof(dsp_coff_header_t) + coffHeader.optHdrLength;
dsp_coff_section_t section;
for(int i = 0; i < coffHeader.nrSections; i++)
{
fseek(_coffFile, sectabOffset + i * sizeof(dsp_coff_section_t), SEEK_SET);
if(fread(&section, 1, sizeof(dsp_coff_section_t), _coffFile) != sizeof(dsp_coff_section_t))
fseek(_dspFile, sectabOffset + i * sizeof(dsp_coff_section_t), SEEK_SET);
if(fread(&section, 1, sizeof(dsp_coff_section_t), _dspFile) != sizeof(dsp_coff_section_t))
return false;
if((section.flags & DSP_COFF_SECT_FLAG_BLK_HDR) || section.size == 0)
continue;
@ -89,14 +90,14 @@ bool DspProcess::EnumerateSections(dsp_process_sec_callback_t callback)
return true;
}
bool DspProcess::LoadSection(const dsp_coff_header_t* header, const dsp_coff_section_t* section)
bool DspProcess::LoadSectionCoff(const dsp_coff_header_t* header, const dsp_coff_section_t* section)
{
const char* name = (const char*)section->name.name;
char fullName[128];
if(section->name.zeroIfLong == 0)
{
fseek(_coffFile, header->symTabPtr + 0x12 * header->nrSyms + section->name.longNameOffset, SEEK_SET);
fread(fullName, 1, sizeof(fullName), _coffFile);
fseek(_dspFile, header->symTabPtr + 0x12 * header->nrSyms + section->name.longNameOffset, SEEK_SET);
fread(fullName, 1, sizeof(fullName), _dspFile);
name = fullName;
}
@ -155,7 +156,7 @@ bool DspProcess::LoadSection(const dsp_coff_header_t* header, const dsp_coff_sec
bool isCode = placements[i].isCode;
bool noLoad = placements[i].noLoad;
if(!noLoad)
fseek(_coffFile, section->sectionPtr, SEEK_SET);
fseek(_dspFile, section->sectionPtr, SEEK_SET);
int dst = placements[i].address;
int left = section->size;
while(left > 0)
@ -182,7 +183,7 @@ bool DspProcess::LoadSection(const dsp_coff_header_t* header, const dsp_coff_sec
twr_mapWramCSlot(slot, TWR_WRAM_C_SLOT_MASTER_ARM9, slot, true);
memset(DspToArm9Address(isCode, DSP_MEM_ADDR_TO_DSP(seg << TWR_WRAM_BC_SLOT_SHIFT)), 0, TWR_WRAM_BC_SLOT_SIZE);
}
if(!noLoad && fread(DspToArm9Address(isCode, DSP_MEM_ADDR_TO_DSP(dst)), 1, len, _coffFile) != len)
if(!noLoad && fread(DspToArm9Address(isCode, DSP_MEM_ADDR_TO_DSP(dst)), 1, len, _dspFile) != len)
return false;
left -= len;
dst += len;
@ -191,35 +192,29 @@ bool DspProcess::LoadSection(const dsp_coff_header_t* header, const dsp_coff_sec
return true;
}
bool DspProcess::LoadProcess(const char* path, u16 slotB, u16 slotC)
bool DspProcess::LoadProcessCoff(const char* path, u16 slotB, u16 slotC)
{
_slotB = slotB;
_slotC = slotC;
_coffFile = fopen(path, "rb");
if(!_coffFile)
_dspFile = fopen(path, "rb");
if(!_dspFile)
return false;
bool ok = EnumerateSections(DspProcess::LoadSection);
bool ok = EnumerateSectionsCoff(DspProcess::LoadSectionCoff);
fclose(_coffFile);
_coffFile = NULL;
fclose(_dspFile);
_dspFile = NULL;
if(!ok)
return false;
SetMemoryMapping(true, 0, DSP_MEM_ADDR_TO_DSP(TWR_WRAM_BC_SLOT_SIZE * TWR_WRAM_BC_SLOT_COUNT), true);
SetMemoryMapping(false, 0, DSP_MEM_ADDR_TO_DSP(TWR_WRAM_BC_SLOT_SIZE * TWR_WRAM_BC_SLOT_COUNT), true);
SetMemoryMapping(true, 0, (TWR_WRAM_BC_SLOT_SIZE * TWR_WRAM_BC_SLOT_COUNT) >> 1, true);
SetMemoryMapping(false, 0, (TWR_WRAM_BC_SLOT_SIZE * TWR_WRAM_BC_SLOT_COUNT) >> 1, true);
return true;
}
bool DspProcess::Execute(const char* path, u16 slotB, u16 slotC)
bool DspProcess::Execute()
{
if(sDspProcess)
return false;
if(!LoadProcess(path, slotB, slotC))
return false;
int irq = enterCriticalSection();
{
sDspProcess = this;
@ -238,10 +233,96 @@ bool DspProcess::Execute(const char* path, u16 slotB, u16 slotC)
DspProcess::DspIrqHandler();
}
leaveCriticalSection(irq);
return true;
}
bool DspProcess::ExecuteCoff(const char* path, u16 slotB, u16 slotC)
{
if(sDspProcess)
return false;
if(!LoadProcessCoff(path, slotB, slotC))
return false;
return Execute();
}
bool DspProcess::ExecuteDsp1(const char* path)
{
if(sDspProcess)
return false;
_dspFile = fopen(path, "rb");
if(!_dspFile)
{
printf("Failed opening file\n");
return false;
}
dsp_dsp1_t* dsp1 = new dsp_dsp1_t;
fseek(_dspFile, 0, SEEK_SET);
if(fread(dsp1, 1, sizeof(dsp_dsp1_t), _dspFile) != sizeof(dsp_dsp1_t))
{
printf("Failed reading header\n");
fclose(_dspFile);
_dspFile = NULL;
delete dsp1;
return false;
}
if(dsp1->header.magic != DSP_DSP1_MAGIC)
{
printf("Invalid magic!");
fclose(_dspFile);
_dspFile = NULL;
delete dsp1;
return false;
}
_slotB = 0xFF;//dsp1->header.memoryLayout & 0xFF;
_slotC = 0xFF;//(dsp1->header.memoryLayout >> 8) & 0xFF;
_codeSegs = 0xFF;
_dataSegs = 0xFF;
for(int i = 0; i < TWR_WRAM_BC_SLOT_COUNT; i++)
{
_codeSlots[i] = i;
_dataSlots[i] = i;
twr_mapWramBSlot(i, TWR_WRAM_B_SLOT_MASTER_ARM9, i, true);
memset((void*)(twr_getBlockAddress(TWR_WRAM_BLOCK_B) + i * TWR_WRAM_BC_SLOT_SIZE), 0, TWR_WRAM_BC_SLOT_SIZE);
twr_mapWramCSlot(i, TWR_WRAM_C_SLOT_MASTER_ARM9, i, true);
memset((void*)(twr_getBlockAddress(TWR_WRAM_BLOCK_C) + i * TWR_WRAM_BC_SLOT_SIZE), 0, TWR_WRAM_BC_SLOT_SIZE);
}
if(dsp1->header.flags & DSP_DSP1_FLAG_SYNC_LOAD)
_flags |= DSP_PROCESS_FLAG_SYNC_LOAD;
for(int i = 0; i < dsp1->header.nrSegments; i++)
{
bool isCode = dsp1->segments[i].segmentType != DSP_DSP1_SEG_TYPE_DATA;
fseek(_dspFile, dsp1->segments[i].offset, SEEK_SET);
if(fread(DspToArm9Address(isCode, dsp1->segments[i].address), 1, dsp1->segments[i].size, _dspFile) != dsp1->segments[i].size)
{
printf("Failed reading segment\n");
fclose(_dspFile);
_dspFile = NULL;
delete dsp1;
return false;
}
}
fclose(_dspFile);
_dspFile = NULL;
SetMemoryMapping(true, 0, (TWR_WRAM_BC_SLOT_SIZE * TWR_WRAM_BC_SLOT_COUNT) >> 1, true);
SetMemoryMapping(false, 0, (TWR_WRAM_BC_SLOT_SIZE * TWR_WRAM_BC_SLOT_COUNT) >> 1, true);
delete dsp1;
return Execute();
}
void DspProcess::SetCallback(u32 sources, dsp_process_irq_callback_t func, void* arg)
{
int irq = enterCriticalSection();

View File

@ -17,7 +17,7 @@ typedef void (*dsp_process_irq_callback_t)(void* arg);
class DspProcess
{
FILE* _coffFile;
FILE* _dspFile;
u16 _slotB;
u16 _slotC;
int _codeSegs;
@ -45,15 +45,16 @@ class DspProcess
bool SetMemoryMapping(bool isCode, u32 addr, u32 len, bool toDsp);
bool EnumerateSections(dsp_process_sec_callback_t callback);
bool EnumerateSectionsCoff(dsp_process_sec_callback_t callback);
bool LoadSection(const dsp_coff_header_t* header, const dsp_coff_section_t* section);
static bool LoadSection(DspProcess* process, const dsp_coff_header_t* header, const dsp_coff_section_t* section)
bool LoadSectionCoff(const dsp_coff_header_t* header, const dsp_coff_section_t* section);
static bool LoadSectionCoff(DspProcess* process, const dsp_coff_header_t* header, const dsp_coff_section_t* section)
{
return process->LoadSection(header, section);
return process->LoadSectionCoff(header, section);
}
bool LoadProcess(const char* path, u16 slotB, u16 slotC);
bool LoadProcessCoff(const char* path, u16 slotB, u16 slotC);
bool Execute();
protected:
void SetCallback(u32 sources, dsp_process_irq_callback_t func, void* arg);
@ -63,5 +64,6 @@ protected:
public:
DspProcess(bool forceDspSyncLoad = false);
bool Execute(const char* path, u16 slotB, u16 slotC);
bool ExecuteCoff(const char* path, u16 slotB, u16 slotC);
bool ExecuteDsp1(const char* path);
};

View File

@ -0,0 +1,49 @@
#pragma once
#define DSP_DSP1_MAGIC 0x31505344
enum DspDsp1SegmentType : u8
{
DSP_DSP1_SEG_TYPE_PROG0 = 0,
DSP_DSP1_SEG_TYPE_PROG1 = 1,
DSP_DSP1_SEG_TYPE_DATA = 2
};
#define DSP_DSP1_FLAG_SYNC_LOAD 1
#define DSP_DSP1_FLAG_LOAD_FILTER_SEG 2
struct dsp_dsp1_header_t
{
u8 rsaSignature[0x100];
u32 magic;
u32 fileSize;
u16 memoryLayout;
u16 padding;
u8 unknown;
DspDsp1SegmentType filterSegType;
u8 nrSegments;
u8 flags;
u32 filterSegAddr;
u32 filterSegSize;
u64 zero;
};
static_assert(sizeof(dsp_dsp1_header_t) == 0x120);
struct dsp_dsp1_segment_t
{
u32 offset;
u32 address;
u32 size;
u8 padding[3];
DspDsp1SegmentType segmentType;
u8 sha256[32];
};
static_assert(sizeof(dsp_dsp1_segment_t) == 0x30);
struct dsp_dsp1_t
{
dsp_dsp1_header_t header;
dsp_dsp1_segment_t segments[10];
};

View File

@ -2,10 +2,79 @@
#include <stdio.h>
#include <fat.h>
#include "libdsp/CmnDspProcess.h"
#include "libdsp/CtrDspProcess.h"
#include "libdsp/dsp_fifo.h"
#include "libdsp/dsp_pipe.h"
static CmnDspProcess* sAudioProc;
// static CmnDspProcess* sAudioProc;
// static void testAudio()
// {
// sAudioProc = new CmnDspProcess();
// if(!sAudioProc->ExecuteCoff("/_dsi/dsp/audio.a", 0xFF, 0xFF))
// {
// iprintf("DSP Init Fail!\n");
// while(1);
// }
// iprintf("DSP Init OK!\n");
// //test playing audio
// void* audio = malloc(4 * 1024 * 1024);
// FILE* tmp = fopen("/audio.bin", "rb");
// iprintf("fopen done! %p\n", tmp);
// fread(audio, 1, 4 * 1024 * 1024, tmp);
// fclose(tmp);
// iprintf("Press A to start and B to stop\n");
// while(true)
// {
// swiWaitForVBlank();
// scanKeys();
// if (keysDown()&KEY_START)
// break;
// if (keysDown() & KEY_A)
// sAudioProc->PlaySound(audio, 4 * 1024 * 1024, false);
// else if (keysDown() & KEY_B)
// sAudioProc->StopSound();
// }
// }
static int getAdtsFrameSize(const void* data)
{
//thanks ida :p
u32 v2 = __builtin_bswap32(*(const u32*)data);
u32 v4 = __builtin_bswap32(((const u32*)data)[1]);
if ( v2 >> 20 != 0xFFF )
return 0;
u32 v6 = (v2 >> 10) & 0xF;
if ( (v2 >> 17) & 3 || (u16)v2 >> 14 != 1 || v6 < 3 || v6 >= 0xC || ((v2 >> 6) & 7) > 2 || (v4 >> 8) & 3 )
return 0;
else
return (v4 >> 21) | ((v2 & 3) << 11);
}
static u8 sAudioFrameBuffer[0x600] ALIGN(32);
#define AUDIO_BLOCK_SIZE (1024)
#define NR_WAVE_DATA_BUFFERS (16)
static s16 mWaveDataBufferL[AUDIO_BLOCK_SIZE * NR_WAVE_DATA_BUFFERS] ALIGN(32);
static s16 mWaveDataBufferR[AUDIO_BLOCK_SIZE * NR_WAVE_DATA_BUFFERS] ALIGN(32);
static volatile int nrAudioBlocksAvailable;
static void audioBlockHandler()
{
int savedIrq = enterCriticalSection();
{
nrAudioBlocksAvailable--;
}
leaveCriticalSection(savedIrq);
if(nrAudioBlocksAvailable < 0)
{
iprintf("Audio underflow!\n");
}
}
int main()
{
@ -13,33 +82,105 @@ int main()
consoleDemoInit(); //setup the sub screen for printing
iprintf("DSP Test\n");
sAudioProc = new CmnDspProcess();
if(!sAudioProc->Execute("/_dsi/dsp/audio.a", 0xFF, 0xFF))
CtrDspProcess* testProc = new CtrDspProcess();
if(!testProc->ExecuteDsp1("/_dsi/dsp/dspaudio.cdc"))
{
iprintf("DSP Init Fail!\n");
while(1);
}
iprintf("DSP Init OK!\n");
//test playing audio
void* audio = malloc(4 * 1024 * 1024);
FILE* tmp = fopen("audio.bin", "rb");
iprintf("fopen done! %p\n", tmp);
fread(audio, 1, 4 * 1024 * 1024, tmp);
fclose(tmp);
iprintf("Press A to start and B to stop\n");
while(true)
if(!testProc->AACDecInitialize(DSP_CODEC_AACDEC_FORMAT_ADTS))
{
swiWaitForVBlank();
scanKeys();
if (keysDown()&KEY_START)
break;
if (keysDown() & KEY_A)
sAudioProc->PlaySound(audio, 4 * 1024 * 1024, false);
else if (keysDown() & KEY_B)
sAudioProc->StopSound();
iprintf("AACDecInitialize failed!\n");
while(1);
}
FILE* tmp = fopen("/audio.aac", "rb");
iprintf("Decoding now!\n");
twr_mapWramCSlot(2, TWR_WRAM_C_SLOT_MASTER_ARM9, 2, true);
soundEnable();
bool hasStarted = FALSE;
int audioWriteBlock = 0;
nrAudioBlocksAvailable = 0;
u32 adtsSize;
DC_InvalidateRange(sAudioFrameBuffer, sizeof(sAudioFrameBuffer));
fread(sAudioFrameBuffer, 1, 8, tmp);
adtsSize = getAdtsFrameSize((u8*)sAudioFrameBuffer);
fread((u8*)sAudioFrameBuffer + 8, 1, adtsSize - 8, tmp);
while (*((vu16*)0x04000130) & KEY_START)
{
while (nrAudioBlocksAvailable < NR_WAVE_DATA_BUFFERS - 1)
{
memcpy((void*)(twr_getBlockAddress(TWR_WRAM_BLOCK_C) + 0x16A00), sAudioFrameBuffer, adtsSize);
memset((void*)(twr_getBlockAddress(TWR_WRAM_BLOCK_C) + 0x16A00 + 0x600), 0, 0x1000);
twr_mapWramCSlot(2, TWR_WRAM_C_SLOT_MASTER_DSP_DATA, 2, true);
testProc->AACDecDecode((const void*)0xB500, adtsSize, (s16*)(0xB500 + 0x300), (s16*)(0xB500 + 0x300 + 0x400));
u32 oldAdtsSize = adtsSize;
DC_InvalidateRange(sAudioFrameBuffer, sizeof(sAudioFrameBuffer));
fread(sAudioFrameBuffer, 1, 8, tmp);
adtsSize = getAdtsFrameSize((u8*)sAudioFrameBuffer);
fread((u8*)sAudioFrameBuffer + 8, 1, adtsSize - 8, tmp);
testProc->WaitCodecResponse();
int errorCode = testProc->AACDecGetErrorCode();
if(errorCode != 0)
{
iprintf("Error (%d)!", errorCode);
while(1);
}
int usedBytes = testProc->AACDecGetUsedBytes();
if(usedBytes != oldAdtsSize)
{
iprintf("Number of bytes used (%d) not equal to frame size (%d)!", usedBytes, oldAdtsSize);
while(1);
}
twr_mapWramCSlot(2, TWR_WRAM_C_SLOT_MASTER_ARM9, 2, true);
memcpy(&mWaveDataBufferL[audioWriteBlock * AUDIO_BLOCK_SIZE], (void*)(twr_getBlockAddress(TWR_WRAM_BLOCK_C) + 0x16A00 + 0x600), 0x800);
memcpy(&mWaveDataBufferR[audioWriteBlock * AUDIO_BLOCK_SIZE], (void*)(twr_getBlockAddress(TWR_WRAM_BLOCK_C) + 0x16A00 + 0x600 + 0x800), 0x800);
DC_FlushRange(&mWaveDataBufferL[audioWriteBlock * AUDIO_BLOCK_SIZE], AUDIO_BLOCK_SIZE * 2);
DC_FlushRange(&mWaveDataBufferR[audioWriteBlock * AUDIO_BLOCK_SIZE], AUDIO_BLOCK_SIZE * 2);
int savedIrq = enterCriticalSection();
{
nrAudioBlocksAvailable++;
}
leaveCriticalSection(savedIrq);
audioWriteBlock++;
if (audioWriteBlock == NR_WAVE_DATA_BUFFERS)
audioWriteBlock = 0;
if (!hasStarted && nrAudioBlocksAvailable == (NR_WAVE_DATA_BUFFERS / 4))
{
hasStarted = TRUE;
int freq = testProc->AACDecGetSampleRate();
//libnds is gay here
timerStart(3, ClockDivider_1024, /*TIMER_FREQ(32000)*/-((0x1000000 / freq) << 1), audioBlockHandler);
soundPlaySample(mWaveDataBufferL, SoundFormat_16Bit, sizeof(mWaveDataBufferL), freq, 127, 0, true, 0);
soundPlaySample(mWaveDataBufferR, SoundFormat_16Bit, sizeof(mWaveDataBufferR), freq, 127, 127, true, 0);
}
}
while (nrAudioBlocksAvailable >= NR_WAVE_DATA_BUFFERS - 1);
}
fclose(tmp);
while(1);
//testAudio();
return 0;
}