CSND: IMA-ADPCM playback support, really fix looping
This commit is contained in:
parent
671ea5f555
commit
cbc1c645a6
@ -14,15 +14,23 @@ typedef enum
|
|||||||
CSND_ENCODING_PSG, // Similar to DS?
|
CSND_ENCODING_PSG, // Similar to DS?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CSND_LOOPMODE_MANUAL = 0,
|
||||||
|
CSND_LOOPMODE_NORMAL,
|
||||||
|
CSND_LOOPMODE_ONESHOT,
|
||||||
|
CSND_LOOPMODE_NORELOAD,
|
||||||
|
};
|
||||||
|
|
||||||
#define SOUND_CHANNEL(n) ((u32)(n) & 0x1F)
|
#define SOUND_CHANNEL(n) ((u32)(n) & 0x1F)
|
||||||
#define SOUND_FORMAT(n) ((u32)(n) << 12)
|
#define SOUND_FORMAT(n) ((u32)(n) << 12)
|
||||||
|
#define SOUND_LOOPMODE(n) ((u32)(n) << 10)
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
SOUND_LINEAR_INTERP = BIT(6),
|
SOUND_LINEAR_INTERP = BIT(6),
|
||||||
SOUND_REPEAT = BIT(10),
|
SOUND_REPEAT = SOUND_LOOPMODE(CSND_LOOPMODE_NORMAL),
|
||||||
SOUND_CONST_BLOCK_SIZE = BIT(11),
|
SOUND_ONE_SHOT = SOUND_LOOPMODE(CSND_LOOPMODE_ONESHOT),
|
||||||
SOUND_ONE_SHOT = 0,
|
|
||||||
SOUND_FORMAT_8BIT = SOUND_FORMAT(CSND_ENCODING_PCM8),
|
SOUND_FORMAT_8BIT = SOUND_FORMAT(CSND_ENCODING_PCM8),
|
||||||
SOUND_FORMAT_16BIT = SOUND_FORMAT(CSND_ENCODING_PCM16),
|
SOUND_FORMAT_16BIT = SOUND_FORMAT(CSND_ENCODING_PCM16),
|
||||||
SOUND_FORMAT_ADPCM = SOUND_FORMAT(CSND_ENCODING_ADPCM),
|
SOUND_FORMAT_ADPCM = SOUND_FORMAT(CSND_ENCODING_ADPCM),
|
||||||
@ -76,6 +84,8 @@ void CSND_ChnSetBlock(u32 channel, int block, u32 physaddr, u32 size);
|
|||||||
void CSND_ChnSetVol(u32 channel, u16 left, u16 right);
|
void CSND_ChnSetVol(u32 channel, u16 left, u16 right);
|
||||||
void CSND_ChnSetTimer(u32 channel, u32 timer);
|
void CSND_ChnSetTimer(u32 channel, u32 timer);
|
||||||
void CSND_ChnSetDuty(u32 channel, u32 duty);
|
void CSND_ChnSetDuty(u32 channel, u32 duty);
|
||||||
|
void CSND_ChnSetAdpcmState(u32 channel, int block, int sample, int index);
|
||||||
|
void CSND_ChnSetAdpcmReload(u32 channel, bool reload);
|
||||||
void CSND_ChnConfig(u32 flags, u32 physaddr0, u32 physaddr1, u32 totalbytesize);
|
void CSND_ChnConfig(u32 flags, u32 physaddr0, u32 physaddr1, u32 totalbytesize);
|
||||||
|
|
||||||
Result CSND_UpdateChnInfo(bool waitDone);
|
Result CSND_UpdateChnInfo(bool waitDone);
|
||||||
|
@ -272,6 +272,31 @@ void CSND_ChnSetDuty(u32 channel, u32 duty)
|
|||||||
csndWriteChnCmd(0x7, (u8*)&cmdparams);
|
csndWriteChnCmd(0x7, (u8*)&cmdparams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSND_ChnSetAdpcmState(u32 channel, int block, int sample, int index)
|
||||||
|
{
|
||||||
|
u32 cmdparams[0x18>>2];
|
||||||
|
|
||||||
|
memset(cmdparams, 0, 0x18);
|
||||||
|
|
||||||
|
cmdparams[0] = channel & 0x1f;
|
||||||
|
cmdparams[1] = sample & 0xFFFF;
|
||||||
|
cmdparams[2] = index & 0x7F;
|
||||||
|
|
||||||
|
csndWriteChnCmd(block ? 0xC : 0xB, (u8*)&cmdparams);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSND_ChnSetAdpcmReload(u32 channel, bool reload)
|
||||||
|
{
|
||||||
|
u32 cmdparams[0x18>>2];
|
||||||
|
|
||||||
|
memset(cmdparams, 0, 0x18);
|
||||||
|
|
||||||
|
cmdparams[0] = channel & 0x1f;
|
||||||
|
cmdparams[1] = reload ? 1 : 0;
|
||||||
|
|
||||||
|
csndWriteChnCmd(0xD, (u8*)&cmdparams);
|
||||||
|
}
|
||||||
|
|
||||||
void CSND_ChnConfig(u32 flags, u32 physaddr0, u32 physaddr1, u32 totalbytesize)
|
void CSND_ChnConfig(u32 flags, u32 physaddr0, u32 physaddr1, u32 totalbytesize)
|
||||||
{
|
{
|
||||||
u32 cmdparams[0x18>>2];
|
u32 cmdparams[0x18>>2];
|
||||||
@ -305,10 +330,20 @@ Result csndChnPlaySound(int chn, u32 flags, u32 sampleRate, void* data0, void* d
|
|||||||
|
|
||||||
u32 paddr0 = 0, paddr1 = 0;
|
u32 paddr0 = 0, paddr1 = 0;
|
||||||
|
|
||||||
if (((flags >> 12) & 3) != CSND_ENCODING_PSG)
|
int encoding = (flags >> 12) & 3;
|
||||||
|
int loopMode = (flags >> 10) & 3;
|
||||||
|
|
||||||
|
if (encoding != CSND_ENCODING_PSG)
|
||||||
{
|
{
|
||||||
if (data0) paddr0 = osConvertVirtToPhys((u32)data0);
|
if (data0) paddr0 = osConvertVirtToPhys((u32)data0);
|
||||||
if (data1) paddr1 = osConvertVirtToPhys((u32)data1);
|
if (data1) paddr1 = osConvertVirtToPhys((u32)data1);
|
||||||
|
|
||||||
|
if (encoding == CSND_ENCODING_ADPCM)
|
||||||
|
{
|
||||||
|
int adpcmSample = ((s16*)data0)[-2];
|
||||||
|
int adpcmIndex = ((u8*)data0)[-2];
|
||||||
|
CSND_ChnSetAdpcmState(chn, 0, adpcmSample, adpcmIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 timer = CSND_TIMER(sampleRate);
|
u32 timer = CSND_TIMER(sampleRate);
|
||||||
@ -319,7 +354,7 @@ Result csndChnPlaySound(int chn, u32 flags, u32 sampleRate, void* data0, void* d
|
|||||||
|
|
||||||
CSND_ChnConfig(flags, paddr0, paddr1, size);
|
CSND_ChnConfig(flags, paddr0, paddr1, size);
|
||||||
|
|
||||||
if ((flags & SOUND_REPEAT) && !(flags & SOUND_CONST_BLOCK_SIZE) && paddr1 > paddr0)
|
if (loopMode == CSND_LOOPMODE_NORMAL && paddr1 > paddr0)
|
||||||
{
|
{
|
||||||
// Now that the first block is playing, configure the size of the subsequent blocks
|
// Now that the first block is playing, configure the size of the subsequent blocks
|
||||||
size -= paddr1 - paddr0;
|
size -= paddr1 - paddr0;
|
||||||
|
Loading…
Reference in New Issue
Block a user