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); diff --git a/src/SB/Core/gc/iSnd.cpp b/src/SB/Core/gc/iSnd.cpp index a5ecbc1f0..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 @@ -63,8 +65,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 +278,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 +329,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 +344,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 +365,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 +375,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 +438,6 @@ static void fcb() } if ((orig_flags & 0x800) || (orig_flags & 0x4000000)) { - U32 length; - U32 source; if (orig_flags & 0x800) { length = 0x4000; @@ -440,10 +453,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 +462,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 +487,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 +502,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) { @@ -675,6 +685,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); @@ -803,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) { } @@ -865,7 +956,7 @@ void sndloadcb(tag_xFile* tag) { SoundFlags = 0; } -/* Matching + void iSndDIEDIEDIE() { if (!soundInited) @@ -903,7 +994,7 @@ void iSndDIEDIEDIE() AXQuit(); } -*/ + void iSndSetExternalCallback(iSndExternalCallback callback) { }