Allow audio samples to be played back from anywhere in memory rather than ARAM.

This is accomplished through a new mAramBaseAddress field on the DSP channels, which effectively relocates ARAM for that channel.
This commit is contained in:
PJB3005
2026-07-25 15:49:13 +02:00
parent 30c36df76b
commit ad80933ccf
8 changed files with 57 additions and 3 deletions
@@ -13,6 +13,12 @@ struct JASBasicWaveBank : public JASWaveBank {
TWaveHandle() { mHeap = NULL; }
virtual intptr_t getWavePtr() const;
virtual const JASWaveInfo* getWaveInfo() const { return &mWaveInfo; }
#if TARGET_PC
/**
* @see JASChannel::mAramBaseAddress
*/
[[nodiscard]] void const* getAramBaseAddress() const override { return nullptr; }
#endif
bool compareHeap(JASHeap* heap) const { return mHeap == heap;}
/* 0x04 */ JASWaveInfo mWaveInfo;
@@ -166,6 +166,18 @@ public:
u32 field_0x104;
};
#if TARGET_PC
/**
* Memory address at which this sound effect should consider ARAM to start.
*
* By changing this, sound effects can effectively be played back from anywhere in memory,
* rather than just the emulated ARAM space.
*
* If nullptr, the regular emulated ARAM is used.
*/
void const* mAramBaseAddress;
#endif
static DUSK_GAME_DATA OSMessageQueue sBankDisposeMsgQ;
static DUSK_GAME_DATA OSMessage sBankDisposeMsg[16];
static DUSK_GAME_DATA OSMessage sBankDisposeList[16];
@@ -179,6 +179,20 @@ namespace JASDsp {
/* 0x130 */ u8 _unused9[0x148 - 0x130];
/* 0x148 */ s16 iir_filter_params[8];
/* 0x158 */ u8 _unused10[0x180 - 0x158];
#endif
#if TARGET_PC
/**
* Memory address at which this sound effect should consider ARAM to start.
* This means fields like mWaveAramAddress will be relative to this pointer instead.
*
* By changing this, sound effects can effectively be played back from anywhere in memory,
* rather than just the emulated ARAM space.
*
* If nullptr, the regular emulated ARAM is used.
*/
void const* mAramBaseAddress;
#endif
};
void boot(void (*)(void*));
@@ -10,6 +10,12 @@ struct JASSimpleWaveBank : JASWaveBank, JASWaveArc {
intptr_t getWavePtr() const;
TWaveHandle();
const JASWaveInfo* getWaveInfo() const;
#if TARGET_PC
/**
* @see JASChannel::mAramBaseAddress
*/
[[nodiscard]] void const* getAramBaseAddress() const override { return nullptr; }
#endif
/* 0x04 */ JASWaveInfo mWaveInfo;
/* 0x28 */ JASHeap* mHeap;
@@ -45,6 +45,12 @@ public:
virtual ~JASWaveHandle() {}
virtual const JASWaveInfo* getWaveInfo() const = 0;
virtual intptr_t getWavePtr() const = 0;
#if TARGET_PC
/**
* @see JASChannel::mAramBaseAddress
*/
[[nodiscard]] virtual void const* getAramBaseAddress() const = 0;
#endif
};
/**
+4 -1
View File
@@ -33,7 +33,7 @@ JASChannel* JASBank::noteOn(JASBank const* param_0, int param_1, u8 param_2, u8
return NULL;
}
intptr_t wavePtr = waveHandle->getWavePtr();
if (!wavePtr) {
if (!wavePtr IF_DUSK(&& !waveHandle->getAramBaseAddress())) {
return NULL;
}
@@ -44,6 +44,9 @@ JASChannel* JASBank::noteOn(JASBank const* param_0, int param_1, u8 param_2, u8
channel->setPriority(param_4);
channel->field_0xdc.mWaveInfo = *waveInfo;
channel->mWaveAramAddress = wavePtr;
#if TARGET_PC
channel->mAramBaseAddress = waveHandle->getAramBaseAddress();
#endif
channel->field_0xdc.mChannelType = stack_60.field_0x1c;
channel->setBankDisposeID(param_0);
channel->setInitPitch(stack_60.mPitch * (waveInfo->mSampleRate / JASDriver::getDacRate()));
+6
View File
@@ -26,6 +26,9 @@ JASChannel::JASChannel(Callback i_callback, void* i_callbackData) :
mCallback(i_callback),
mCallbackData(i_callbackData),
mUpdateTimer(0),
#if TARGET_PC
mAramBaseAddress(nullptr),
#endif
mBankDisposeID(NULL),
mKey(0),
mVelocity(0x7f),
@@ -256,6 +259,9 @@ s32 JASChannel::initialUpdateDSPChannel(JASDsp::TChannel* i_channel) {
switch (field_0xdc.mChannelType) {
case 0:
i_channel->setWaveInfo(field_0xdc.mWaveInfo, mWaveAramAddress, mSkipSamples);
#if TARGET_PC
i_channel->mAramBaseAddress = mAramBaseAddress;
#endif
break;
case 2:
i_channel->setOscInfo(mOscillatorSomething);
+3 -2
View File
@@ -317,7 +317,7 @@ void dusk::audio::DspRender(OutputSubframe& subframe) {
}
OutputSubframe channelSubframe = {};
if (channel.mWaveAramAddress == 0) {
if (channel.mWaveAramAddress == 0 && !channel.mAramBaseAddress) {
RenderOscChannel(channel, channelAux, channelSubframe);
} else {
ValidateChannel(channel);
@@ -455,7 +455,8 @@ static int ReadChannelSamplesChunk(
assert(desiredSamples >= 0);
auto aramBase = static_cast<u8*>(ARGetStorageAddress()) + channel.mWaveAramAddress;
auto aramBase = static_cast<u8 const*>(channel.mAramBaseAddress ? channel.mAramBaseAddress : ARGetStorageAddress());
aramBase += channel.mWaveAramAddress;
auto curSamplePosition = channel.mSamplePosition;
u32 skipSamples = curSamplePosition % channel.mSamplesPerBlock;