Skylander Portal: Play Trap Team Audio
Asserts and length handling
This commit is contained in:
parent
019bde6afc
commit
f27e8216a5
|
@ -52,6 +52,7 @@ void Mixer::DoState(PointerWrap& p)
|
||||||
m_dma_mixer.DoState(p);
|
m_dma_mixer.DoState(p);
|
||||||
m_streaming_mixer.DoState(p);
|
m_streaming_mixer.DoState(p);
|
||||||
m_wiimote_speaker_mixer.DoState(p);
|
m_wiimote_speaker_mixer.DoState(p);
|
||||||
|
m_skylander_portal_mixer.DoState(p);
|
||||||
for (auto& mixer : m_gba_mixers)
|
for (auto& mixer : m_gba_mixers)
|
||||||
mixer.DoState(p);
|
mixer.DoState(p);
|
||||||
}
|
}
|
||||||
|
@ -183,6 +184,8 @@ unsigned int Mixer::Mix(short* samples, unsigned int num_samples)
|
||||||
timing_variance);
|
timing_variance);
|
||||||
m_wiimote_speaker_mixer.Mix(m_scratch_buffer.data(), available_samples, false, emulation_speed,
|
m_wiimote_speaker_mixer.Mix(m_scratch_buffer.data(), available_samples, false, emulation_speed,
|
||||||
timing_variance);
|
timing_variance);
|
||||||
|
m_skylander_portal_mixer.Mix(m_scratch_buffer.data(), available_samples, false, emulation_speed,
|
||||||
|
timing_variance);
|
||||||
for (auto& mixer : m_gba_mixers)
|
for (auto& mixer : m_gba_mixers)
|
||||||
{
|
{
|
||||||
mixer.Mix(m_scratch_buffer.data(), available_samples, false, emulation_speed,
|
mixer.Mix(m_scratch_buffer.data(), available_samples, false, emulation_speed,
|
||||||
|
@ -202,6 +205,7 @@ unsigned int Mixer::Mix(short* samples, unsigned int num_samples)
|
||||||
m_dma_mixer.Mix(samples, num_samples, true, emulation_speed, timing_variance);
|
m_dma_mixer.Mix(samples, num_samples, true, emulation_speed, timing_variance);
|
||||||
m_streaming_mixer.Mix(samples, num_samples, true, emulation_speed, timing_variance);
|
m_streaming_mixer.Mix(samples, num_samples, true, emulation_speed, timing_variance);
|
||||||
m_wiimote_speaker_mixer.Mix(samples, num_samples, true, emulation_speed, timing_variance);
|
m_wiimote_speaker_mixer.Mix(samples, num_samples, true, emulation_speed, timing_variance);
|
||||||
|
m_skylander_portal_mixer.Mix(samples, num_samples, true, emulation_speed, timing_variance);
|
||||||
for (auto& mixer : m_gba_mixers)
|
for (auto& mixer : m_gba_mixers)
|
||||||
mixer.Mix(samples, num_samples, true, emulation_speed, timing_variance);
|
mixer.Mix(samples, num_samples, true, emulation_speed, timing_variance);
|
||||||
m_is_stretching = false;
|
m_is_stretching = false;
|
||||||
|
@ -316,6 +320,30 @@ void Mixer::PushWiimoteSpeakerSamples(const short* samples, unsigned int num_sam
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Mixer::PushSkylanderPortalSamples(const u8* samples, unsigned int num_samples)
|
||||||
|
{
|
||||||
|
// Skylander samples are always supplied as 64 bytes, 32 x 16 bit samples
|
||||||
|
// The portal speaker is 1 channel, so duplicate and play as stereo audio
|
||||||
|
static constexpr u32 MAX_PORTAL_SPEAKER_SAMPLES = 32;
|
||||||
|
std::array<short, MAX_PORTAL_SPEAKER_SAMPLES * 2> samples_stereo;
|
||||||
|
|
||||||
|
ASSERT_MSG(AUDIO, num_samples <= MAX_PORTAL_SPEAKER_SAMPLES,
|
||||||
|
"num_samples is not less or equal to 32: {} > {}", num_samples,
|
||||||
|
MAX_PORTAL_SPEAKER_SAMPLES);
|
||||||
|
|
||||||
|
if (num_samples <= MAX_PORTAL_SPEAKER_SAMPLES)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < num_samples; ++i)
|
||||||
|
{
|
||||||
|
s16 sample = static_cast<u16>(samples[i * 2 + 1]) << 8 | static_cast<u16>(samples[i * 2]);
|
||||||
|
samples_stereo[i * 2] = sample;
|
||||||
|
samples_stereo[i * 2 + 1] = sample;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_skylander_portal_mixer.PushSamples(samples_stereo.data(), num_samples);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Mixer::PushGBASamples(int device_number, const short* samples, unsigned int num_samples)
|
void Mixer::PushGBASamples(int device_number, const short* samples, unsigned int num_samples)
|
||||||
{
|
{
|
||||||
m_gba_mixers[device_number].PushSamples(samples, num_samples);
|
m_gba_mixers[device_number].PushSamples(samples, num_samples);
|
||||||
|
|
|
@ -30,6 +30,7 @@ public:
|
||||||
void PushStreamingSamples(const short* samples, unsigned int num_samples);
|
void PushStreamingSamples(const short* samples, unsigned int num_samples);
|
||||||
void PushWiimoteSpeakerSamples(const short* samples, unsigned int num_samples,
|
void PushWiimoteSpeakerSamples(const short* samples, unsigned int num_samples,
|
||||||
unsigned int sample_rate_divisor);
|
unsigned int sample_rate_divisor);
|
||||||
|
void PushSkylanderPortalSamples(const u8* samples, unsigned int num_samples);
|
||||||
void PushGBASamples(int device_number, const short* samples, unsigned int num_samples);
|
void PushGBASamples(int device_number, const short* samples, unsigned int num_samples);
|
||||||
|
|
||||||
unsigned int GetSampleRate() const { return m_sampleRate; }
|
unsigned int GetSampleRate() const { return m_sampleRate; }
|
||||||
|
@ -97,6 +98,7 @@ private:
|
||||||
MixerFifo m_dma_mixer{this, FIXED_SAMPLE_RATE_DIVIDEND / 32000, false};
|
MixerFifo m_dma_mixer{this, FIXED_SAMPLE_RATE_DIVIDEND / 32000, false};
|
||||||
MixerFifo m_streaming_mixer{this, FIXED_SAMPLE_RATE_DIVIDEND / 48000, false};
|
MixerFifo m_streaming_mixer{this, FIXED_SAMPLE_RATE_DIVIDEND / 48000, false};
|
||||||
MixerFifo m_wiimote_speaker_mixer{this, FIXED_SAMPLE_RATE_DIVIDEND / 3000, true};
|
MixerFifo m_wiimote_speaker_mixer{this, FIXED_SAMPLE_RATE_DIVIDEND / 3000, true};
|
||||||
|
MixerFifo m_skylander_portal_mixer{this, FIXED_SAMPLE_RATE_DIVIDEND / 8000, true};
|
||||||
std::array<MixerFifo, 4> m_gba_mixers{MixerFifo{this, FIXED_SAMPLE_RATE_DIVIDEND / 48000, true},
|
std::array<MixerFifo, 4> m_gba_mixers{MixerFifo{this, FIXED_SAMPLE_RATE_DIVIDEND / 48000, true},
|
||||||
MixerFifo{this, FIXED_SAMPLE_RATE_DIVIDEND / 48000, true},
|
MixerFifo{this, FIXED_SAMPLE_RATE_DIVIDEND / 48000, true},
|
||||||
MixerFifo{this, FIXED_SAMPLE_RATE_DIVIDEND / 48000, true},
|
MixerFifo{this, FIXED_SAMPLE_RATE_DIVIDEND / 48000, true},
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "AudioCommon/AudioCommon.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/Random.h"
|
#include "Common/Random.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
|
@ -903,15 +904,21 @@ int SkylanderUSB::SubmitTransfer(std::unique_ptr<IntrMessage> cmd)
|
||||||
s32 expected_count;
|
s32 expected_count;
|
||||||
u64 expected_time_us;
|
u64 expected_time_us;
|
||||||
// Audio requests are 64 bytes long, are the only Interrupt requests longer than 32 bytes,
|
// Audio requests are 64 bytes long, are the only Interrupt requests longer than 32 bytes,
|
||||||
// echo the request as the response and respond after 1ms
|
// echo the request as the response and respond immediately
|
||||||
if (cmd->length > 32 && cmd->length <= 64)
|
if (cmd->length > 32 && cmd->length <= 64)
|
||||||
{
|
{
|
||||||
|
// Play audio through Portal Mixer
|
||||||
|
// Audio is unsigned 16 bit, supplied as 64 bytes which is 32 samples
|
||||||
|
SoundStream* sound_stream = system.GetSoundStream();
|
||||||
|
sound_stream->GetMixer()->PushSkylanderPortalSamples(buf, cmd->length / 2);
|
||||||
|
|
||||||
std::array<u8, 64> audio_interrupt_response = {};
|
std::array<u8, 64> audio_interrupt_response = {};
|
||||||
u8* audio_buf = audio_interrupt_response.data();
|
u8* audio_buf = audio_interrupt_response.data();
|
||||||
memcpy(audio_buf, buf, cmd->length);
|
memcpy(audio_buf, buf, cmd->length);
|
||||||
expected_time_us = 1000;
|
expected_time_us = 0;
|
||||||
expected_count = cmd->length;
|
expected_count = cmd->length;
|
||||||
ScheduleTransfer(std::move(cmd), audio_interrupt_response, expected_count, expected_time_us);
|
ScheduleTransfer(std::move(cmd), audio_interrupt_response, expected_count, expected_time_us);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// If some data was requested from the Control Message, then the Interrupt message needs to
|
// If some data was requested from the Control Message, then the Interrupt message needs to
|
||||||
|
|
|
@ -96,7 +96,7 @@ static size_t s_state_writes_in_queue;
|
||||||
static std::condition_variable s_state_write_queue_is_empty;
|
static std::condition_variable s_state_write_queue_is_empty;
|
||||||
|
|
||||||
// Don't forget to increase this after doing changes on the savestate system
|
// Don't forget to increase this after doing changes on the savestate system
|
||||||
constexpr u32 STATE_VERSION = 159; // Last changed in PR 11640
|
constexpr u32 STATE_VERSION = 160; // Last changed in PR 11644
|
||||||
|
|
||||||
// Maps savestate versions to Dolphin versions.
|
// Maps savestate versions to Dolphin versions.
|
||||||
// Versions after 42 don't need to be added to this list,
|
// Versions after 42 don't need to be added to this list,
|
||||||
|
|
Loading…
Reference in New Issue