mirror of https://github.com/n64decomp/sm64.git
Fix high frequency notes by using downsampled versions
This commit is contained in:
parent
00bf4294e8
commit
3573b75b4b
7
Makefile
7
Makefile
|
|
@ -282,7 +282,8 @@ SOUND_BANK_FILES := $(wildcard sound/sound_banks/*.json)
|
|||
SOUND_SAMPLE_DIRS := $(wildcard sound/samples/*)
|
||||
SOUND_SAMPLE_AIFFS := $(foreach dir,$(SOUND_SAMPLE_DIRS),$(wildcard $(dir)/*.aiff))
|
||||
ifdef TARGET_NDS
|
||||
SOUND_SAMPLE_AIFCS := $(foreach file,$(SOUND_SAMPLE_AIFFS),$(BUILD_DIR)/$(file:.aiff=.ima))
|
||||
SOUND_SAMPLE_HALFS := $(wildcard sound/samples/instruments/*.aiff) sound/samples/sfx_9/03.aiff
|
||||
SOUND_SAMPLE_AIFCS := $(foreach file,$(SOUND_SAMPLE_AIFFS),$(BUILD_DIR)/$(file:.aiff=.ima)) $(foreach file,$(SOUND_SAMPLE_HALFS),$(BUILD_DIR)/$(file:.aiff=.half.ima))
|
||||
else
|
||||
SOUND_SAMPLE_TABLES := $(foreach file,$(SOUND_SAMPLE_AIFFS),$(BUILD_DIR)/$(file:.aiff=.table))
|
||||
SOUND_SAMPLE_AIFCS := $(foreach file,$(SOUND_SAMPLE_AIFFS),$(BUILD_DIR)/$(file:.aiff=.aifc))
|
||||
|
|
@ -639,6 +640,10 @@ endif
|
|||
#==============================================================================#
|
||||
|
||||
ifdef TARGET_NDS
|
||||
$(BUILD_DIR)/%.half.wav: %.aiff
|
||||
$(call print,Converting AIFF:,$<,$@)
|
||||
$(V)sox $^ -r $(shell echo $(shell sox --i -r $^) / 2 | bc) $@
|
||||
|
||||
$(BUILD_DIR)/%.wav: %.aiff
|
||||
$(call print,Converting AIFF:,$<,$@)
|
||||
$(V)sox $^ $@
|
||||
|
|
|
|||
|
|
@ -6,10 +6,11 @@
|
|||
#undef SOUND_FREQ
|
||||
#define SOUND_FREQ(n) (-(BUS_CLOCK >> 1) / (n))
|
||||
|
||||
static u16 calculate_freq(const struct Note *note) {
|
||||
static u16 high_freqs;
|
||||
|
||||
static u16 calculate_freq(f32 frequency) {
|
||||
// Calculate the DS frequency for a note
|
||||
// Some frequencies are too high, but clipping at least lets them get as close as possible
|
||||
u32 freq = note->frequency * 32000;
|
||||
u32 freq = frequency * 32000;
|
||||
if (freq > 0xFFFF) freq = 0xFFFF;
|
||||
return SOUND_FREQ((u16)freq);
|
||||
}
|
||||
|
|
@ -39,17 +40,29 @@ void play_notes(struct Note *notes) {
|
|||
// Ensure the channel is properly reset
|
||||
SCHANNEL_CR(i) &= ~SCHANNEL_ENABLE;
|
||||
|
||||
// Start playing a note on the current channel
|
||||
SCHANNEL_SOURCE(i) = (u32)sample->sampleAddr;
|
||||
SCHANNEL_REPEAT_POINT(i) = sample->loop->start / sizeof(u32);
|
||||
SCHANNEL_LENGTH(i) = (sample->loop->end - sample->loop->start) / sizeof(u32);
|
||||
SCHANNEL_TIMER(i) = calculate_freq(note);
|
||||
if (note->frequency >= 2.0f && *(u32*)sample->sampleAddr != 0) {
|
||||
// If the frequency is too high, play the downsampled version at half frequency
|
||||
SCHANNEL_SOURCE(i) = (u32)sample->sampleAddr + *(u32*)sample->sampleAddr + 4;
|
||||
SCHANNEL_REPEAT_POINT(i) = sample->loop->start / 2 / sizeof(u32) + 1;
|
||||
SCHANNEL_LENGTH(i) = (sample->loop->end - sample->loop->start) / 2 / sizeof(u32) + 1;
|
||||
SCHANNEL_TIMER(i) = calculate_freq(note->frequency / 2);
|
||||
high_freqs |= BIT(i);
|
||||
} else {
|
||||
// Play the normal version at full frequency
|
||||
SCHANNEL_SOURCE(i) = (u32)sample->sampleAddr + 4;
|
||||
SCHANNEL_REPEAT_POINT(i) = sample->loop->start / sizeof(u32) + 1;
|
||||
SCHANNEL_LENGTH(i) = (sample->loop->end - sample->loop->start) / sizeof(u32) + 1;
|
||||
SCHANNEL_TIMER(i) = calculate_freq(note->frequency);
|
||||
high_freqs &= ~BIT(i);
|
||||
}
|
||||
|
||||
// Start the channel
|
||||
SCHANNEL_CR(i) = SCHANNEL_ENABLE | SOUND_FORMAT_ADPCM | calculate_vol_pan(note) | loop;
|
||||
|
||||
note->needsInit = false;
|
||||
} else if (SCHANNEL_CR(i) & SCHANNEL_ENABLE) {
|
||||
// Update the parameters of a currently playing note
|
||||
SCHANNEL_TIMER(i) = calculate_freq(note);
|
||||
SCHANNEL_TIMER(i) = calculate_freq(note->frequency / ((high_freqs & BIT(i)) ? 2 : 1));
|
||||
SCHANNEL_CR(i) = (SCHANNEL_CR(i) & ~(SOUND_VOL(127) | SOUND_PAN(127))) | calculate_vol_pan(note);
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -184,8 +184,8 @@ def parse_ima(data, name, fname, bank_name):
|
|||
if tp == b"COMM":
|
||||
sample_rate = parse_f80(aiff_data[8:18])
|
||||
elif tp == b"MARK":
|
||||
start = (struct.unpack('>I', aiff_data[4:8])[0] >> 1) + 4
|
||||
end = (struct.unpack('>I', aiff_data[16:20])[0] >> 1) + 4
|
||||
start = struct.unpack('>I', aiff_data[4:8])[0] >> 1
|
||||
end = struct.unpack('>I', aiff_data[16:20])[0] >> 1
|
||||
loop = Loop(start, end, 1, None)
|
||||
|
||||
return Aifc(name, fname, data, sample_rate, None, loop)
|
||||
|
|
@ -705,7 +705,17 @@ def serialize_tbl(sample_bank, ser, is_shindou):
|
|||
continue
|
||||
ser.align(16)
|
||||
aifc.offset = ser.size - base_addr
|
||||
ser.add(aifc.data)
|
||||
if aifc.fname.endswith(".ima"):
|
||||
if os.path.exists(aifc.fname[:-4] + ".half.ima"):
|
||||
ser.add(len(aifc.data).to_bytes(4, 'little'))
|
||||
ser.add(aifc.data)
|
||||
with open(aifc.fname[:-4] + ".half.ima", "rb") as half:
|
||||
ser.add(half.read())
|
||||
else:
|
||||
ser.add(b"\0\0\0\0")
|
||||
ser.add(aifc.data)
|
||||
else:
|
||||
ser.add(aifc.data)
|
||||
ser.align(2)
|
||||
if is_shindou and sample_bank.index not in [4, 10]:
|
||||
ser.align(16)
|
||||
|
|
@ -1031,7 +1041,7 @@ def main():
|
|||
data = inf.read()
|
||||
if f.endswith(".aifc"):
|
||||
entries.append(parse_aifc(data, f[:-5], fname))
|
||||
elif f.endswith(".ima"):
|
||||
elif not f.endswith(".half.ima") and f.endswith(".ima"):
|
||||
entries.append(parse_ima(data, f[:-4], fname, name))
|
||||
except Exception as e:
|
||||
fail("malformed audio file " + fname + ": " + str(e))
|
||||
|
|
|
|||
Loading…
Reference in New Issue