From 4e02a16905c5ba43dc7982b1432636a8e2d19cb4 Mon Sep 17 00:00:00 2001 From: escape209 Date: Sun, 9 Aug 2026 14:06:08 +0100 Subject: [PATCH 1/4] iSnd work: Part 2 --- src/SB/Core/gc/iSnd.cpp | 54 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/src/SB/Core/gc/iSnd.cpp b/src/SB/Core/gc/iSnd.cpp index a5ecbc1f0..7d5e952e6 100644 --- a/src/SB/Core/gc/iSnd.cpp +++ b/src/SB/Core/gc/iSnd.cpp @@ -675,6 +675,56 @@ bool iSndIsPlayingByHandle(U32 handle) return false; } +void iSndStop(U32 snd) +{ + if (snd == 0) + { + return; + } + + U32 enabled = OSDisableInterrupts(); + S32 i; + + for (i = 0; i < 64; i++) + { + if (gSnd.voice[i].sndID == snd) + { + gSnd.voice[i].sndID = 0; + gSnd.voice[i].flags = 0; + break; + } + } + + if (i < 6) + { + if (streams[i].vinf.voice != NULL) + { + DVDCancel(&streams[i].fileInfo.cb); + ARQRemoveRequest(&streams[i].request); + AXSetVoiceState(streams[i].vinf.voice, 0); + MIXReleaseChannel(streams[i].vinf.voice); + iSndMyAXFree(&streams[i].vinf.voice); + streams[i].vinf.flags = 0x40000; + streams[i].vinf.aid = 0; + streams[i].vinf.flags = 0x40000; + } + } + else if (i < 64) + { + i -= 6; + if (voices[i].voice != NULL) + { + AXSetVoiceState(voices[i].voice, 0); + MIXReleaseChannel(voices[i].voice); + iSndMyAXFree(&voices[i].voice); + voices[i].flags = 0; + voices[i].aid = 0; + } + } + + OSRestoreInterrupts(enabled); +} + U32 iVolFromX(F32 param1) { float f = MAX(param1, 1e-20f); @@ -865,7 +915,7 @@ void sndloadcb(tag_xFile* tag) { SoundFlags = 0; } -/* Matching + void iSndDIEDIEDIE() { if (!soundInited) @@ -903,7 +953,7 @@ void iSndDIEDIEDIE() AXQuit(); } -*/ + void iSndSetExternalCallback(iSndExternalCallback callback) { } From 22bbd288ba88a4a58281059a8abe2d31067c9e4f Mon Sep 17 00:00:00 2001 From: escape209 Date: Mon, 10 Aug 2026 08:32:59 +0100 Subject: [PATCH 2/4] Match fcb --- src/SB/Core/gc/iSnd.cpp | 64 +++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/src/SB/Core/gc/iSnd.cpp b/src/SB/Core/gc/iSnd.cpp index 7d5e952e6..3ada097a6 100644 --- a/src/SB/Core/gc/iSnd.cpp +++ b/src/SB/Core/gc/iSnd.cpp @@ -63,8 +63,8 @@ vinfo voices[58]; U32* ua_stream_buffer = NULL; //unaligned stream buffer U32* stream_buffer = 0; u32 silence_buffer = 0; -volatile u32 zero_point = 0; -volatile u32 zero_end = 0; +volatile U32 zero_point = 0; +volatile U32 zero_end = 0; volatile U32 SoundFlags = 0; volatile S32 fc = 0; static char soundInited = 0; @@ -276,34 +276,46 @@ static void iSndMyAXFree(AXVPB**); static void fcb() { + S32 i; + S32 need_update; + U32 orig_flags; + U32 length; + U32 source; + U32 flags_bit_12; + U32 flags_bit_10; + U32 flags_bit_13; + U32 flags_bit_9; + U32 dest; + u32 addr; + xSndVoiceInfo* gsnd_voice; + if (!soundInited && iTRCDisk::IsDiskIDed()) { return; } fc++; - S32 i; - S32 need_update = TRUE; + need_update = FALSE; for (i = 0; i < 6; i++) { - xSndVoiceInfo* gsnd_voice = &gSnd.voice[i]; - U32 orig_flags = streams[i].vinf.flags; + orig_flags = streams[i].vinf.flags; + gsnd_voice = &gSnd.voice[i]; if (streams[i].vinf.voice == NULL) { continue; } - u16 addrHi = streams[i].vinf.voice->pb.addr.currentAddressHi; + U32 addrHi = streams[i].vinf.voice->pb.addr.currentAddressHi; if (orig_flags & 0xe0006) { continue; } - u32 addr = addrHi << 16; + addr = (addrHi << 16); addr += streams[i].vinf.voice->pb.addr.currentAddressLo; - U32 dest = streams[i].dest_b; + dest = streams[i].dest_b; dump_flags(orig_flags); - if (dest * 2 < addr && (orig_flags & 0x4000) == 0 && (orig_flags & 0x8) == 0) + if ((addr < dest * 2) && (orig_flags & 0x4000) == 0 && (orig_flags & 0x8) == 0) { streams[i].vinf.flags |= 0x4000; streams[i].vinf.flags &= ~0x8000; @@ -315,7 +327,7 @@ static void fcb() streams[i].x94 = streams[i].x90; orig_flags = streams[i].vinf.flags; } - else if (dest * 2 >= addr && (orig_flags & 0x8000) == 0) + else if ((addr >= dest * 2) && (orig_flags & 0x8000) == 0) { streams[i].vinf.flags |= 0x8000; streams[i].vinf.flags &= ~0x4000; @@ -330,8 +342,9 @@ static void fcb() if ((orig_flags & 0x20) && (orig_flags & 0x4000)) { streams[i].vinf.flags &= ~0x20; - dest = streams[i].dest_a * 2; - dest += streams[i].x24 & 0xFFFF; + U32 dest = streams[i].dest_a; + dest <<= 1; + dest += (streams[i].x24 & 0xFFFF); AXSetVoiceLoopAddr(streams[i].vinf.voice, zero_point); AXSetVoiceEndAddr(streams[i].vinf.voice, dest - 1); AXSetVoiceLoop(streams[i].vinf.voice, 0); @@ -350,7 +363,7 @@ static void fcb() continue; } - if (dest >= zero_point && dest < zero_end && (orig_flags & 0x40)) + if (addr >= zero_point && addr < zero_end && (orig_flags & 0x40)) { streams[i].vinf.flags &= ~0x40; DVDCancelAsync(&streams[i].fileInfo.cb, NULL); @@ -360,14 +373,14 @@ static void fcb() if (streams[i].vinf.flags & 0x10000) { - u32 priority = gsnd_voice->priority; + U32 priority = gsnd_voice->priority; if (priority > 0xff) { priority = 0xff; } iSndMyAXFree(&streams[i].vinf.voice); - streams[i].vinf.voice = AXAcquireVoice(priority, dv_callback, i); + streams[i].vinf.voice = AXAcquireVoice(priority >> 3, dv_callback, i); if (streams[i].vinf.voice == NULL) { streams[i].vinf.voice = NULL; @@ -423,8 +436,6 @@ static void fcb() } if ((orig_flags & 0x800) || (orig_flags & 0x4000000)) { - U32 length; - U32 source; if (orig_flags & 0x800) { length = 0x4000; @@ -440,10 +451,6 @@ static void fcb() source = streams[i].source_b; } - U32 flags_bit_12; - U32 flags_bit_10; - U32 flags_bit_13; - U32 flags_bit_9; flags_bit_9 = orig_flags & 0x200; flags_bit_12 = orig_flags & 0x1000; flags_bit_10 = orig_flags & 0x400; @@ -453,13 +460,13 @@ static void fcb() if (flags_bit_12 && (orig_flags & 0x4000) && !flags_bit_10 && !flags_bit_13) { streams[i].vinf.flags |= 0x400; - ARQPostRequest(&streams[i].request, (u32)streams[i].vinf.voice, 0, 1, source, + ARQPostRequest(&streams[i].request, (u32)&streams[i], 0, 1, source, streams[i].dest_b, length, arqcb); } else if (flags_bit_13 && (orig_flags & 0x8000) && !flags_bit_9 && !flags_bit_12) { streams[i].vinf.flags |= 0x200; - ARQPostRequest(&streams[i].request, (u32)streams[i].vinf.voice, 0, 1, source, + ARQPostRequest(&streams[i].request, (u32)&streams[i], 0, 1, source, streams[i].dest_a, length, arqcb); } } @@ -478,7 +485,7 @@ static void fcb() need_update = TRUE; } - for (i = 0; i < 58; i++) + for (S32 i = 0; i < 58; i++) { if (voices[i].voice == NULL || (voices[i].flags & 0x1)) { @@ -493,8 +500,9 @@ static void fcb() } else { - U32 addr = (voices[i].voice->pb.addr.currentAddressHi << 16) + - voices[i].voice->pb.addr.currentAddressLo; + addr = voices[i].voice->pb.addr.currentAddressHi; + addr <<= 16; + addr += voices[i].voice->pb.addr.currentAddressLo; if (voices[i].flags & 0x4 && !voices[i].voice->pb.addr.loopFlag && addr >= zero_point && addr < zero_end) { @@ -721,7 +729,7 @@ void iSndStop(U32 snd) voices[i].aid = 0; } } - + OSRestoreInterrupts(enabled); } From d1f8de1cbb54e6fc55643f156fad76b04954b9ec Mon Sep 17 00:00:00 2001 From: escape209 Date: Mon, 10 Aug 2026 15:16:49 +0100 Subject: [PATCH 3/4] Add powf definition to cmath --- .../include/PowerPC_EABI_Support/MSL_C/MSL_Common/cmath | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/PowerPC_EABI_Support/include/PowerPC_EABI_Support/MSL_C/MSL_Common/cmath b/src/PowerPC_EABI_Support/include/PowerPC_EABI_Support/MSL_C/MSL_Common/cmath index 70e0fd02a..acb3e6f50 100644 --- a/src/PowerPC_EABI_Support/include/PowerPC_EABI_Support/MSL_C/MSL_Common/cmath +++ b/src/PowerPC_EABI_Support/include/PowerPC_EABI_Support/MSL_C/MSL_Common/cmath @@ -9,6 +9,7 @@ namespace std #ifndef INLINE float atan2f(float y, float x); + float powf(float x, float y); float atan(float x); float sinf(float x); float cosf(float x); @@ -26,6 +27,11 @@ namespace std return (float)atan2((double)y, (double)x); } + inline float powf(float y, float x) + { + return (float)powf((double)y, (double)x); + } + inline float atan(float x) { return (float)atan((double)x); From 9e5128ee0679ac4b971e3db0feea08944b32a488 Mon Sep 17 00:00:00 2001 From: escape209 Date: Mon, 10 Aug 2026 15:17:10 +0100 Subject: [PATCH 4/4] Match iSndSetPitch --- src/SB/Core/gc/iSnd.cpp | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/SB/Core/gc/iSnd.cpp b/src/SB/Core/gc/iSnd.cpp index 3ada097a6..c6efafb91 100644 --- a/src/SB/Core/gc/iSnd.cpp +++ b/src/SB/Core/gc/iSnd.cpp @@ -18,6 +18,8 @@ #include #include +#include + u32 aram_array[40]; // Size: 0x20 @@ -861,6 +863,37 @@ void iSndSetVol(U32 snd, F32 vol) } } +void iSndSetPitch(U32 snd, F32 pitch) +{ + xSndVoiceInfo* vp = &gSnd.voice[0]; + + S32 i = 0; + for (; i < 64; i++, vp++) + { + if (vp->sndID == snd) + break; + } + + if (i != 64) + { + vinfo* info; + if (i < 6) + { + info = &streams[i].vinf; + } + else + { + info = &voices[i - 6]; + } + if (info->voice != 0) + { + // todo: define std::powf + AXSetVoiceSrcRatio(info->voice, ((1.0f / 32000) * vp->sample_rate) * + std::powf(2.0f, (pitch / 12.0f))); + } + } +} + void iSndStartStereo(U32 id1, U32 id2, F32 pitch) { }