mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-05-22 22:24:16 -04:00
jaudio_NES/driver.c 98%
This commit is contained in:
@@ -168,6 +168,36 @@ extern "C" {
|
||||
|
||||
#define aFirLoadTable(pkt, size, addr) aFirFilter(pkt, 2, size, addr)
|
||||
|
||||
#define aEnvMixer2(pkt, dmemi, count, swapLR, x0, x1, x2, x3, m, bits) \
|
||||
{ \
|
||||
Acmd *_a = (Acmd *)pkt; \
|
||||
\
|
||||
_a->words.w0 = (bits | _SHIFTL(dmemi >> 4, 16, 8) | \
|
||||
_SHIFTL(count, 8, 8) | _SHIFTL(swapLR, 4, 1) | \
|
||||
_SHIFTL(x0, 3, 1) | _SHIFTL(x1, 2, 1) | \
|
||||
_SHIFTL(x2, 1, 1) | _SHIFTL(x3, 0, 1)); \
|
||||
_a->words.w1 = (unsigned int)(m); \
|
||||
}
|
||||
|
||||
#define aAddMixer(pkt, count, dmemi, dmemo, a4) \
|
||||
{ \
|
||||
Acmd *_a = (Acmd *)pkt; \
|
||||
\
|
||||
_a->words.w0 = (_SHIFTL(A_CMD_ADDMIXER, 24, 8) | \
|
||||
_SHIFTL(count >> 4, 16, 8) | _SHIFTL(a4, 0, 16)); \
|
||||
_a->words.w1 = _SHIFTL(dmemi, 16, 16) | _SHIFTL(dmemo, 0, 16); \
|
||||
}
|
||||
|
||||
// from MM
|
||||
#define aResampleZoh(pkt, pitch, pitchAccu) \
|
||||
{ \
|
||||
Acmd *_a = (Acmd *)pkt; \
|
||||
\
|
||||
_a->words.w0 = (_SHIFTL(A_CMD_RESAMPLE_ZOH, 24, 8) | \
|
||||
_SHIFTL(pitch, 0, 16)); \
|
||||
_a->words.w1 = _SHIFTL(pitchAccu, 0, 16); \
|
||||
}
|
||||
|
||||
#define NA_MAKE_COMMAND(a0, a1, a2, a3) \
|
||||
(u32)((((a0) & 0xFF) << 24) | (((a1) & 0xFF) << 16) | (((a2) & 0xFF) << 8) | (((a3) & 0xFF) << 0))
|
||||
|
||||
|
||||
@@ -278,7 +278,7 @@ typedef struct driverch_ {
|
||||
/* 0x06 */ u8 comb_filter_needs_init;
|
||||
/* 0x07 */ u8 vel_conv_table_idx;
|
||||
/* 0x08 */ u16 sample_pos_fractional_part;
|
||||
/* 0x0A */ u16 sound_effect_gain;
|
||||
/* 0x0A */ u16 surround_effect_gain;
|
||||
/* 0x0C */ s32 sample_pos_integer_part;
|
||||
/* 0x10 */ synthparams* synth_params;
|
||||
/* 0x14 */ s16 current_volume_left;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
extern Acmd* Nas_smzAudioFrame(Acmd* cmds, s32* processed_cmds, s16* pSamples, s32 nSamples);
|
||||
extern Acmd* Nas_DriveRsp(s16* aiBuf, s32 aiBufLen, Acmd* cmd, s32 updateIndex);
|
||||
extern Acmd* Nas_SynthMain(s32 chan_id, commonch* common, driverch* driver, s16* samples, s32 samples_per_update, Acmd* cmd, s32 update_idx);
|
||||
extern Acmd* Nas_Synth_Resample(Acmd* cmd, const driverch* driver, s32 size, u16 frequencyFixedPoint, u16 sampleDmemBeforeResampling, s32 flags);
|
||||
extern Acmd* Nas_Synth_Resample(Acmd* cmd, const driverch* driver, s32 size, u16 pitch, u16 sampleDmemBeforeResampling, s32 flags);
|
||||
extern Acmd* Nas_DolbySurround(Acmd* cmd, commonch* common, driverch* driver, s32 samples_per_update, s32 dmem, s32 flags);
|
||||
extern Acmd* Nas_Synth_Envelope(Acmd* cmd, commonch* common, driverch* driver, s32 samples_per_update, u16 dmem, s32 haasEffectDelaySide, s32 flags);
|
||||
extern Acmd* Nas_Synth_Delay(Acmd* cmd, commonch* common, driverch* driver, s32 size, s32 flags, s32 haasEffectDelaySide);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "jaudio_NES/driver.h"
|
||||
|
||||
#include "PR/abi.h"
|
||||
#include "jaudio_NES/audiocommon.h"
|
||||
#include "jaudio_NES/audiostruct.h"
|
||||
#include "jaudio_NES/astest.h"
|
||||
@@ -7,6 +8,7 @@
|
||||
#include "jaudio_NES/track.h"
|
||||
#include "jaudio_NES/system.h"
|
||||
#include "os/OSCache.h"
|
||||
#include "types.h"
|
||||
|
||||
#define DMEM_TEMP 0x380
|
||||
#define DMEM_WET_TEMP 0x3A0
|
||||
@@ -14,8 +16,11 @@
|
||||
#define DMEM_LEFT_CH 0x900
|
||||
#define DMEM_RIGHT_CH 0xAA0
|
||||
#define DMEM_WET_LEFT_CH 0xC40
|
||||
#define DMEM_WET_RIGHT_CH 0xDE0
|
||||
#define DMEM_UNCOMPRESSED_NOTE 0x540
|
||||
#define DMEM_COMPRESSED_ADPCM_DATA 0x900
|
||||
#define DMEM_HAAS_TEMP 0x580
|
||||
#define DMEM_SURROUND_TEMP 0x480
|
||||
|
||||
typedef enum {
|
||||
/* 0 */ HAAS_EFFECT_DELAY_NONE,
|
||||
@@ -23,14 +28,14 @@ typedef enum {
|
||||
/* 2 */ HAAS_EFFECT_DELAY_RIGHT // Delay right channel so that left channel is heard first
|
||||
} HaasEffectDelaySide;
|
||||
|
||||
static u16 NOISE_TABLE[] = { 0, 1, 2, 4, 8, 12, 16, 20, 24, 32, 36, 40, 46, 52, 56, 53 };
|
||||
static u16 NOISE_TABLE[] = { 0, 1, 2, 4, 8, 12, 16, 20, 24, 32, 36, 40, 46, 52, 56, 64 };
|
||||
static dspch_ DSPCH[64];
|
||||
static s32 STOP_VELOCONV = 0;
|
||||
|
||||
static u32 Env_DataH = (A_ENVMIXER << 24) | (0x00 << 16) | (0x00 << 8) | (0x00);
|
||||
static u32 Env_DataL1 = 0x58AAC4DE;
|
||||
static u32 Env_DataL2 = 0x9058C4DE;
|
||||
static u32 Env_DataL3 = 0x9058C4DE;
|
||||
static u32 Env_DataH = (A_CMD_ENVMIXER << 24) | (0x00 << 16) | (0x00 << 8) | (0x00);
|
||||
static u32 Env_Data_L1 = 0x58AAC4DE;
|
||||
static u32 Env_Data_L2 = 0x9058C4DE;
|
||||
static u32 Env_Data_L3 = 0x90AAC4DE;
|
||||
|
||||
static Acmd* __LoadAuxBuf(Acmd* cmd, u16 ofs, u16 startPos, s32 size, delay* del_p);
|
||||
static Acmd* __SaveAuxBuf(Acmd* cmd, u16 ofs, u16 startPos, s32 size, delay* del_p);
|
||||
@@ -1240,3 +1245,216 @@ codec_continue_and_skip:
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
Acmd* Nas_DolbySurround(Acmd* cmd, commonch* common, driverch* driver, s32 num_samples_per_update, s32 haas_dmem, s32 flags) {
|
||||
s32 size;
|
||||
s32 wetGain;
|
||||
u16 dryGain;
|
||||
s64 dmem = DMEM_SURROUND_TEMP;
|
||||
f32 decayGain;
|
||||
|
||||
size = num_samples_per_update * SAMPLE_SIZE;
|
||||
Nas_DMEMMove(cmd++, haas_dmem, DMEM_HAAS_TEMP, size);
|
||||
dryGain = driver->surround_effect_gain;
|
||||
|
||||
if (flags == A_INIT) {
|
||||
aClearBuffer(cmd++, dmem, sizeof(driver->synth_params->surround_effect_state));
|
||||
driver->surround_effect_gain = 0;
|
||||
} else {
|
||||
wetGain = (driver->surround_effect_gain * driver->cur_reverb_vol) >> 7;
|
||||
|
||||
aLoadBuffer2(cmd++, driver->synth_params->surround_effect_state, dmem, sizeof(driver->synth_params->surround_effect_state));
|
||||
|
||||
aMix(cmd++, size >> 4, dryGain, dmem, DMEM_LEFT_CH);
|
||||
aMix(cmd++, size >> 4, (dryGain ^ 0xFFFF), dmem, DMEM_RIGHT_CH);
|
||||
|
||||
aMix(cmd++, size >> 4, wetGain, dmem, DMEM_WET_LEFT_CH);
|
||||
aMix(cmd++, size >> 4, (wetGain ^ 0xFFFF), dmem, DMEM_WET_RIGHT_CH);
|
||||
}
|
||||
|
||||
aSaveBuffer2(cmd++, DMEM_SURROUND_TEMP + size, driver->synth_params->surround_effect_state, sizeof(driver->synth_params->surround_effect_state));
|
||||
|
||||
decayGain = (common->target_volume_left + common->target_volume_right) / 8192.0f; // 1.0f / 0x2000
|
||||
|
||||
if (decayGain > 1.0f) {
|
||||
decayGain = 1.0f;
|
||||
}
|
||||
|
||||
decayGain = decayGain * StereoLeft[127 - common->surround_effect_idx];
|
||||
driver->surround_effect_gain = ((decayGain * 0x7FFF) + driver->surround_effect_gain) / 2;
|
||||
|
||||
Nas_DMEMMove(cmd++, DMEM_HAAS_TEMP, haas_dmem, size);
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
extern Acmd* Nas_Synth_Resample(Acmd* cmd, const driverch* driver, s32 size, u16 pitch, u16 sampleDmemBeforeResampling, s32 flags) {
|
||||
if (pitch == 0) {
|
||||
Nas_ClearBuffer(cmd++, DMEM_TEMP, size);
|
||||
} else {
|
||||
aSetBuffer(cmd++, 0, sampleDmemBeforeResampling, DMEM_TEMP, size);
|
||||
aResample(cmd++, flags, pitch, driver->synth_params->final_resample_state);
|
||||
}
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
extern Acmd* Nas_Synth_Envelope(Acmd* cmd, commonch* common, driverch* driver, s32 samples_per_update, u16 dmem, s32 haasEffectDelaySide, s32 flags) {
|
||||
u16 targetVolRight;
|
||||
u16 targetVolLeft;
|
||||
u32 dmemDests;
|
||||
u16 curVolLeft;
|
||||
u16 curVolRight;
|
||||
s32 curReverbVolAndFlags;
|
||||
u16 curReverbVol;
|
||||
s32 targetReverbVol;
|
||||
s16 rampLeft;
|
||||
s16 rampRight;
|
||||
s16 rampReverb;
|
||||
f32 defaultPanVolume;
|
||||
|
||||
|
||||
targetReverbVol = common->target_reverb_volume;
|
||||
curVolLeft = driver->current_volume_left;
|
||||
curVolRight = driver->current_volume_right;
|
||||
|
||||
targetVolLeft = common->target_volume_left << 4;
|
||||
targetVolRight = common->target_volume_right << 4;
|
||||
|
||||
if ((AG.sound_mode == SOUND_OUTPUT_DOLBY_SURROUND)) {
|
||||
u8 idx = common->surround_effect_idx;
|
||||
|
||||
if (idx != 0xFF) {
|
||||
defaultPanVolume = StereoLeft[idx];
|
||||
targetVolLeft *= defaultPanVolume;
|
||||
targetVolRight *= defaultPanVolume;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetVolLeft != curVolLeft) {
|
||||
rampLeft = (targetVolLeft - curVolLeft) / (samples_per_update >> 3);
|
||||
} else {
|
||||
rampLeft = 0;
|
||||
}
|
||||
|
||||
if (targetVolRight != curVolRight) {
|
||||
rampRight = (targetVolRight - curVolRight) / (samples_per_update >> 3);
|
||||
} else {
|
||||
rampRight = 0;
|
||||
}
|
||||
|
||||
curReverbVolAndFlags = (s16)driver->cur_reverb_vol;
|
||||
if (targetReverbVol != curReverbVolAndFlags) {
|
||||
curReverbVol = curReverbVolAndFlags & 0x7F;
|
||||
rampReverb = (((targetReverbVol & 0x7F) - (curReverbVol)) << 9) / (samples_per_update >> 3);
|
||||
driver->cur_reverb_vol = targetReverbVol;
|
||||
} else {
|
||||
rampReverb = 0;
|
||||
}
|
||||
|
||||
driver->current_volume_left = curVolLeft + (rampLeft * (samples_per_update >> 3));
|
||||
driver->current_volume_right = curVolRight + (rampRight * (samples_per_update >> 3));
|
||||
|
||||
if (common->use_haas_effect) {
|
||||
Nas_ClearBuffer(cmd++, DMEM_HAAS_TEMP, DMEM_1CH_SIZE);
|
||||
curReverbVol = curReverbVolAndFlags & 0x7F;
|
||||
Nas_SetEnvParam(cmd++, curReverbVol * 2, rampReverb, rampLeft, rampRight);
|
||||
Nas_SetEnvParam2(cmd++, curVolLeft, curVolRight);
|
||||
|
||||
switch (haasEffectDelaySide) {
|
||||
case HAAS_EFFECT_DELAY_LEFT:
|
||||
// Store the left dry channel in a temp space to be delayed to produce the haas effect
|
||||
dmemDests = Env_Data_L1;
|
||||
break;
|
||||
|
||||
case HAAS_EFFECT_DELAY_RIGHT:
|
||||
// Store the right dry channel in a temp space to be delayed to produce the haas effect
|
||||
dmemDests = Env_Data_L2;
|
||||
break;
|
||||
|
||||
default: // HAAS_EFFECT_DELAY_NONE
|
||||
dmemDests = Env_Data_L3;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
curReverbVol = curReverbVolAndFlags & 0x7F;
|
||||
aSetEnvParam(cmd++, curReverbVol * 2, rampReverb, rampLeft, rampRight);
|
||||
aSetEnvParam2(cmd++, curVolLeft, curVolRight);
|
||||
dmemDests = Env_Data_L3;
|
||||
}
|
||||
|
||||
aEnvMixer2(cmd++, dmem, samples_per_update, (curReverbVolAndFlags & 0x80) >> 7,
|
||||
common->strong_reverb_right, common->strong_reverb_left,
|
||||
common->strong_right, common->strong_left, dmemDests, Env_DataH);
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
extern Acmd* Nas_Synth_Delay(Acmd* cmd, commonch* common, driverch* driver, s32 size, s32 flags, s32 haasEffectDelaySide) {
|
||||
u16 dmemDest;
|
||||
u16 pitch;
|
||||
u16 prevHaasEffectDelaySize;
|
||||
u16 haasEffectDelaySize;
|
||||
|
||||
switch (haasEffectDelaySide) {
|
||||
case HAAS_EFFECT_DELAY_LEFT:
|
||||
// Delay the sample on the left channel
|
||||
// This allows the right channel to be heard first
|
||||
dmemDest = DMEM_LEFT_CH;
|
||||
haasEffectDelaySize = common->haas_effect_left_delay_size;
|
||||
prevHaasEffectDelaySize = driver->prev_haas_effect_left_delay_size;
|
||||
driver->prev_haas_effect_left_delay_size = haasEffectDelaySize;
|
||||
driver->prev_haas_effect_right_delay_size = 0;
|
||||
break;
|
||||
|
||||
case HAAS_EFFECT_DELAY_RIGHT:
|
||||
// Delay the sample on the right channel
|
||||
// This allows the left channel to be heard first
|
||||
dmemDest = DMEM_RIGHT_CH;
|
||||
haasEffectDelaySize = common->haas_effect_right_delay_size;
|
||||
prevHaasEffectDelaySize = driver->prev_haas_effect_right_delay_size;
|
||||
driver->prev_haas_effect_right_delay_size = haasEffectDelaySize;
|
||||
driver->prev_haas_effect_left_delay_size = 0;
|
||||
break;
|
||||
|
||||
default: // HAAS_EFFECT_DELAY_NONE
|
||||
return cmd;
|
||||
}
|
||||
|
||||
if (flags != A_INIT) {
|
||||
// Slightly adjust the sample rate in order to fit a change in sample delay
|
||||
if (haasEffectDelaySize != prevHaasEffectDelaySize) {
|
||||
pitch = (((size << 0xF) / 2) - 1) / ((size + haasEffectDelaySize - prevHaasEffectDelaySize - 2) / 2);
|
||||
aSetBuffer(cmd++, 0, DMEM_HAAS_TEMP, DMEM_TEMP, size + haasEffectDelaySize - prevHaasEffectDelaySize);
|
||||
aResampleZoh(cmd++, pitch, 0);
|
||||
} else {
|
||||
aDMEMMove(cmd++, DMEM_HAAS_TEMP, DMEM_TEMP, size);
|
||||
}
|
||||
|
||||
if (prevHaasEffectDelaySize != 0) {
|
||||
aLoadBuffer2(cmd++, driver->synth_params->haas_effect_delay_state, DMEM_HAAS_TEMP,
|
||||
ALIGN_NEXT(prevHaasEffectDelaySize, 16));
|
||||
aDMEMMove(cmd++, DMEM_TEMP, DMEM_HAAS_TEMP + prevHaasEffectDelaySize,
|
||||
size + haasEffectDelaySize - prevHaasEffectDelaySize);
|
||||
} else {
|
||||
aDMEMMove(cmd++, DMEM_TEMP, DMEM_HAAS_TEMP, size + haasEffectDelaySize);
|
||||
}
|
||||
} else {
|
||||
// Just apply a delay directly
|
||||
aDMEMMove(cmd++, DMEM_HAAS_TEMP, DMEM_TEMP, size);
|
||||
if (haasEffectDelaySize) { // != 0
|
||||
aClearBuffer(cmd++, DMEM_HAAS_TEMP, haasEffectDelaySize);
|
||||
}
|
||||
aDMEMMove(cmd++, DMEM_TEMP, DMEM_HAAS_TEMP + haasEffectDelaySize, size);
|
||||
}
|
||||
|
||||
if (haasEffectDelaySize) { // != 0
|
||||
// Save excessive samples for next iteration
|
||||
aSaveBuffer2(cmd++, DMEM_HAAS_TEMP + size, driver->synth_params->haas_effect_delay_state,
|
||||
ALIGN_NEXT(haasEffectDelaySize, 16));
|
||||
}
|
||||
|
||||
aAddMixer(cmd++, ALIGN_NEXT(size, 64), DMEM_HAAS_TEMP, dmemDest, 0x7FFF);
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user