diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp index 70bfb5f509..37a3ae9ede 100644 --- a/Core/HLE/sceMpeg.cpp +++ b/Core/HLE/sceMpeg.cpp @@ -1882,11 +1882,11 @@ static u32 sceMpegAvcCopyYCbCr(u32 mpeg, u32 sourceAddr, u32 YCbCrAddr) MpegContext *ctx = getMpegCtx(mpeg); if (!ctx) { - WARN_LOG(ME, "UNIMPL sceMpegAvcCopyYCbCr(%08x, %08x, %08x): bad mpeg handle", mpeg, sourceAddr, YCbCrAddr); + ERROR_LOG(ME, "UNIMPL sceMpegAvcCopyYCbCr(%08x, %08x, %08x): bad mpeg handle", mpeg, sourceAddr, YCbCrAddr); return -1; } - ERROR_LOG(ME, "UNIMPL sceMpegAvcCopyYCbCr(%08x, %08x, %08x)", mpeg, sourceAddr, YCbCrAddr); + WARN_LOG(ME, "UNIMPL sceMpegAvcCopyYCbCr(%08x, %08x, %08x)", mpeg, sourceAddr, YCbCrAddr); return 0; } diff --git a/UI/BackgroundAudio.cpp b/UI/BackgroundAudio.cpp index 89e173c510..794992adc9 100644 --- a/UI/BackgroundAudio.cpp +++ b/UI/BackgroundAudio.cpp @@ -5,6 +5,7 @@ #include "base/timeutil.h" #include "file/chunk_file.h" #include "file/vfs.h" +#include "ui/root.h" #include "Common/CommonTypes.h" #include "Core/HW/SimpleAudioDec.h" @@ -260,10 +261,12 @@ BackgroundAudio::Sample *BackgroundAudio::LoadSample(const std::string &path) { return nullptr; } - WavData wave; - wave.Read(RIFFReader(data, (int)bytes)); + RIFFReader reader(data, (int)bytes); - if (wave.num_channels != 2) { + WavData wave; + wave.Read(reader); + + if (wave.num_channels != 2 || wave.sample_rate != 44100 || wave.raw_bytes_per_frame_ != 4) { ELOG("Wave format not supported for mixer playback. Must be 16-bit raw stereo. '%s'", path.c_str()); return nullptr; } @@ -279,10 +282,23 @@ void BackgroundAudio::LoadSamples() { samples_[(size_t)MenuSFX::BACK] = std::unique_ptr(LoadSample("sfx_back.wav")); samples_[(size_t)MenuSFX::SELECT] = std::unique_ptr(LoadSample("sfx_select.wav")); samples_[(size_t)MenuSFX::CONFIRM] = std::unique_ptr(LoadSample("sfx_confirm.wav")); + + UI::SetSoundCallback([](UI::UISound sound) { + MenuSFX sfx; + switch (sound) { + case UI::UISound::BACK: sfx = MenuSFX::BACK; break; + case UI::UISound::CONFIRM: sfx = MenuSFX::CONFIRM; break; + case UI::UISound::SELECT: sfx = MenuSFX::SELECT; break; + default: return; + } + + g_BackgroundAudio.PlaySFX(sfx); + }); } void BackgroundAudio::PlaySFX(MenuSFX sfx) { - plays_.push_back(PlayInstance{ sfx, 0 }); + std::lock_guard lock(g_bgMutex); + plays_.push_back(PlayInstance{ sfx, 0, 64, false }); } void BackgroundAudio::Clear(bool hard) { @@ -332,34 +348,59 @@ int BackgroundAudio::Play() { } double now = time_now_d(); + int sz = lastPlaybackTime <= 0.0 ? 44100 / 60 : (int)((now - lastPlaybackTime) * 44100); + sz = std::min(BUFSIZE / 2, sz); if (at3Reader) { - int sz = lastPlaybackTime <= 0.0 ? 44100 / 60 : (int)((now - lastPlaybackTime) * 44100); - sz = std::min(BUFSIZE / 2, sz); if (sz >= 16) { if (at3Reader->Read(buffer, sz)) { - if (!fadingOut) { - __PushExternalAudio(buffer, sz); - } else { + if (fadingOut) { for (int i = 0; i < sz*2; i += 2) { buffer[i] *= volume; buffer[i + 1] *= volume; volume += delta; } - __PushExternalAudio(buffer, sz); - if (volume <= 0.0f) { - Clear(true); - fadingOut = false; - gameLastChanged = 0; - } } } - lastPlaybackTime = now; } } else { - __PushExternalAudio(0, 0); - lastPlaybackTime = now; + for (int i = 0; i < sz * 2; i += 2) { + buffer[i] = 0; + buffer[i + 1] = 0; + } } + // Mix in menu sound effects + if (!plays_.empty()) { + for (int i = 0; i < sz * 2; i += 2) { + std::vector::iterator iter = plays_.begin(); + while (iter != plays_.end()) { + PlayInstance inst = *iter; + auto sample = samples_[(int)inst.sound].get(); + if (iter->offset >= sample->length_) { + iter->done = true; + iter = plays_.erase(iter); + } else { + if (!iter->done) { + buffer[i] += sample->data_[inst.offset * 2] * inst.volume >> 8; + buffer[i + 1] += sample->data_[inst.offset * 2 + 1] * inst.volume >> 8; + } + iter->offset++; + iter++; + } + } + } + } + + __PushExternalAudio(buffer, sz); + + if (at3Reader && fadingOut && volume <= 0.0f) { + Clear(true); + fadingOut = false; + gameLastChanged = 0; + } + + lastPlaybackTime = now; + return 0; } diff --git a/UI/BackgroundAudio.h b/UI/BackgroundAudio.h index 00afb4bab6..fff043e465 100644 --- a/UI/BackgroundAudio.h +++ b/UI/BackgroundAudio.h @@ -45,6 +45,8 @@ private: struct PlayInstance { MenuSFX sound; int offset; + int volume; // 0..255 + bool done; }; struct Sample { diff --git a/ext/native/ui/root.cpp b/ext/native/ui/root.cpp index ef44036747..d65bfc0d33 100644 --- a/ext/native/ui/root.cpp +++ b/ext/native/ui/root.cpp @@ -17,6 +17,9 @@ static bool focusMovementEnabled; bool focusForced; static std::mutex eventMutex_; +static std::function soundCallback; + + struct DispatchQueueItem { Event *e; EventParams params; @@ -133,6 +136,18 @@ void MoveFocus(ViewGroup *root, FocusDirection direction) { if (neigh.view) { neigh.view->SetFocus(); root->SubviewFocused(neigh.view); + + PlayUISound(UISound::SELECT); + } +} + +void SetSoundCallback(std::function func) { + soundCallback = func; +} + +void PlayUISound(UISound sound) { + if (soundCallback) { + soundCallback(UISound::SELECT); } } diff --git a/ext/native/ui/root.h b/ext/native/ui/root.h index 8cfca36f29..5d13c51e2d 100644 --- a/ext/native/ui/root.h +++ b/ext/native/ui/root.h @@ -1,5 +1,6 @@ #pragma once +#include #include "ui/ui_context.h" #include "input/input_state.h" @@ -26,4 +27,14 @@ bool KeyEvent(const KeyInput &key, ViewGroup *root); bool TouchEvent(const TouchInput &touch, ViewGroup *root); bool AxisEvent(const AxisInput &axis, ViewGroup *root); +enum class UISound { + SELECT, + BACK, + CONFIRM, +}; + +void SetSoundCallback(std::function func); + +void PlayUISound(UISound sound); + } // namespace UI