2015-05-25 18:36:28 -03:00
|
|
|
// Copyright 2008 Dolphin Emulator Project
|
|
|
|
// Licensed under GPLv2+
|
2013-04-17 23:09:55 -04:00
|
|
|
// Refer to the license.txt file included.
|
2014-07-17 19:56:27 -03:00
|
|
|
// Modified For Ishiiruka By Tino
|
2009-01-17 14:28:09 +00:00
|
|
|
|
2014-04-21 17:40:34 -03:00
|
|
|
#include "AudioCommon/AudioCommon.h"
|
2014-06-03 18:14:53 -03:00
|
|
|
#include "AudioCommon/Mixer.h"
|
|
|
|
#include "Common/Atomic.h"
|
2014-04-21 17:40:34 -03:00
|
|
|
#include "Common/CPUDetect.h"
|
2014-07-14 19:21:49 -03:00
|
|
|
#include "Common/MathUtil.h"
|
2021-06-20 14:16:58 -07:00
|
|
|
#include "Common/CommonFuncs.h"
|
2014-04-21 17:40:34 -03:00
|
|
|
#include "Core/ConfigManager.h"
|
2014-06-03 18:14:53 -03:00
|
|
|
#include "Core/Core.h"
|
2014-04-21 17:40:34 -03:00
|
|
|
#include "Core/HW/AudioInterface.h"
|
2014-06-03 18:14:53 -03:00
|
|
|
#include "Core/HW/VideoInterface.h"
|
2011-01-28 18:39:30 +00:00
|
|
|
|
2015-02-22 23:17:51 -03:00
|
|
|
#ifndef M_PI
|
|
|
|
#define M_PI 3.14159265358979323846
|
2011-01-12 09:34:53 +00:00
|
|
|
#endif
|
|
|
|
|
2015-02-22 23:17:51 -03:00
|
|
|
const float CMixer::MAX_FREQ_SHIFT = 200;
|
|
|
|
const float CMixer::CONTROL_FACTOR = 0.2f;
|
|
|
|
const float CMixer::CONTROL_AVG = 32;
|
|
|
|
|
2015-10-01 06:19:50 -03:00
|
|
|
CMixer::CMixer(u32 BackendSampleRate)
|
|
|
|
: m_dma_mixer(this, 32000)
|
|
|
|
, m_streaming_mixer(this, 48000)
|
|
|
|
, m_wiimote_speaker_mixer(this, 3000)
|
|
|
|
, m_sample_rate(BackendSampleRate)
|
|
|
|
, m_log_dtk_audio(0)
|
|
|
|
, m_log_dsp_audio(0)
|
|
|
|
, m_speed(0)
|
|
|
|
{
|
|
|
|
INFO_LOG(AUDIO_INTERFACE, "Mixer is initialized");
|
|
|
|
}
|
|
|
|
|
2015-02-22 23:17:51 -03:00
|
|
|
void CMixer::LinearMixerFifo::Interpolate(u32 left_input_index, float* left_output, float* right_output)
|
2008-12-08 05:25:12 +00:00
|
|
|
{
|
2015-02-22 23:17:51 -03:00
|
|
|
*left_output = (1 - m_fraction) * m_float_buffer[left_input_index & INDEX_MASK]
|
|
|
|
+ m_fraction * m_float_buffer[(left_input_index + 2) & INDEX_MASK];
|
|
|
|
*right_output = (1 - m_fraction) * m_float_buffer[(left_input_index + 1) & INDEX_MASK]
|
|
|
|
+ m_fraction * m_float_buffer[(left_input_index + 3) & INDEX_MASK];
|
|
|
|
}
|
2010-09-28 21:43:38 +00:00
|
|
|
|
2015-02-22 23:17:51 -03:00
|
|
|
void CMixer::CubicMixerFifo::Interpolate(u32 left_input_index, float* left_output, float* right_output)
|
|
|
|
{
|
2015-10-06 21:15:24 -03:00
|
|
|
static const float cubic_coef[] =
|
|
|
|
{
|
|
|
|
-0.5f, 1.0f, -0.5f, 0.0f,
|
|
|
|
1.5f, -2.5f, 0.0f, 1.0f,
|
|
|
|
-1.5f, 2.0f, 0.5f, 0.0f,
|
|
|
|
0.5f, -0.5f, 0.0f, 0.0f
|
|
|
|
};
|
|
|
|
|
2015-02-22 23:17:51 -03:00
|
|
|
const float x2 = m_fraction; // x
|
|
|
|
const float x1 = x2*x2; // x^2
|
|
|
|
const float x0 = x1*x2; // x^3
|
|
|
|
|
2015-10-06 21:15:24 -03:00
|
|
|
float y0 = cubic_coef[0] * x0 + cubic_coef[1] * x1 + cubic_coef[2] * x2 + cubic_coef[3];
|
|
|
|
float y1 = cubic_coef[4] * x0 + cubic_coef[5] * x1 + cubic_coef[6] * x2 + cubic_coef[7];
|
|
|
|
float y2 = cubic_coef[8] * x0 + cubic_coef[9] * x1 + cubic_coef[10] * x2 + cubic_coef[11];
|
|
|
|
float y3 = cubic_coef[12] * x0 + cubic_coef[13] * x1 + cubic_coef[14] * x2 + cubic_coef[15];
|
2015-02-22 23:17:51 -03:00
|
|
|
|
|
|
|
*left_output = y0 * m_float_buffer[left_input_index & INDEX_MASK]
|
|
|
|
+ y1 * m_float_buffer[(left_input_index + 2) & INDEX_MASK]
|
|
|
|
+ y2 * m_float_buffer[(left_input_index + 4) & INDEX_MASK]
|
|
|
|
+ y3 * m_float_buffer[(left_input_index + 6) & INDEX_MASK];
|
|
|
|
*right_output = y0 * m_float_buffer[(left_input_index + 1) & INDEX_MASK]
|
|
|
|
+ y1 * m_float_buffer[(left_input_index + 3) & INDEX_MASK]
|
2015-10-06 21:15:24 -03:00
|
|
|
+ y2 * m_float_buffer[(left_input_index + 5) & INDEX_MASK]
|
2015-02-22 23:17:51 -03:00
|
|
|
+ y3 * m_float_buffer[(left_input_index + 7) & INDEX_MASK];
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMixer::MixerFifo::Mix(float* samples, u32 numSamples, bool consider_framelimit)
|
|
|
|
{
|
|
|
|
u32 current_sample = 0;
|
|
|
|
// Cache access in non-volatile variable so interpolation loop can be optimized
|
2015-05-25 18:36:28 -03:00
|
|
|
u32 read_index = m_read_index.load();
|
|
|
|
const u32 write_index = m_write_index.load();
|
2015-02-22 23:17:51 -03:00
|
|
|
// Sync input rate by fifo size
|
|
|
|
float num_left = (float)(((write_index - read_index) & INDEX_MASK) / 2);
|
|
|
|
m_num_left_i = (num_left + m_num_left_i * (CONTROL_AVG - 1)) / CONTROL_AVG;
|
2015-12-10 23:33:42 -03:00
|
|
|
|
|
|
|
u32 low_waterwark = m_input_sample_rate * SConfig::GetInstance().iTimingVariance / 1000;
|
|
|
|
low_waterwark = std::min(low_waterwark, MAX_SAMPLES / 2);
|
|
|
|
|
|
|
|
float offset = (m_num_left_i - low_waterwark) * CONTROL_FACTOR;
|
2015-09-19 19:56:20 -03:00
|
|
|
offset = MathUtil::Clamp(offset, -MAX_FREQ_SHIFT, MAX_FREQ_SHIFT);
|
2015-02-22 23:17:51 -03:00
|
|
|
// adjust framerate with framelimit
|
2016-01-07 00:08:27 -03:00
|
|
|
float emulationspeed = SConfig::GetInstance().m_EmulationSpeed;
|
2014-07-14 19:21:49 -03:00
|
|
|
float aid_sample_rate = m_input_sample_rate + offset;
|
2016-01-07 00:08:27 -03:00
|
|
|
if (consider_framelimit && emulationspeed > 0.0f)
|
2014-02-25 22:51:42 -03:00
|
|
|
{
|
2016-01-07 00:08:27 -03:00
|
|
|
aid_sample_rate = aid_sample_rate * emulationspeed;
|
2014-02-25 22:51:42 -03:00
|
|
|
}
|
2015-02-22 23:17:51 -03:00
|
|
|
// ratio = 1 / upscale_factor = stepsize for each sample
|
|
|
|
// e.g. going from 32khz to 48khz is 1 / (3 / 2) = 2 / 3
|
|
|
|
// note because of syncing and framelimit, ratio will rarely be exactly 2 / 3
|
|
|
|
float ratio = aid_sample_rate / (float)m_mixer->m_sample_rate;
|
2015-05-25 18:36:28 -03:00
|
|
|
float l_volume = (float)m_lvolume.load() / 256.f;
|
|
|
|
float r_volume = (float)m_rvolume.load() / 256.f;
|
2015-02-22 23:17:51 -03:00
|
|
|
// for each output sample pair (left and right),
|
|
|
|
// linear interpolate between current and next sample
|
|
|
|
// increment output sample position
|
|
|
|
// increment input sample position by ratio, store fraction
|
|
|
|
// QUESTION: do we need to check for NUM_CROSSINGS samples before we interpolate?
|
|
|
|
// seems to work fine as is
|
2015-10-06 21:15:24 -03:00
|
|
|
for (; current_sample < numSamples * 2 && ((write_index - read_index) & INDEX_MASK) > GetWindowSize(); current_sample += 2)
|
2014-10-04 12:11:42 -03:00
|
|
|
{
|
2015-02-22 23:17:51 -03:00
|
|
|
float l_output, r_output;
|
|
|
|
Interpolate(read_index, &l_output, &r_output);
|
|
|
|
samples[current_sample + 1] += l_volume * l_output;
|
|
|
|
samples[current_sample] += r_volume * r_output;
|
|
|
|
m_fraction += ratio;
|
|
|
|
read_index += 2 * (s32)m_fraction;
|
|
|
|
m_fraction = m_fraction - (s32)m_fraction;
|
2009-12-23 15:34:14 +00:00
|
|
|
}
|
2015-02-22 23:17:51 -03:00
|
|
|
// pad output if not enough input samples
|
|
|
|
float s[2];
|
|
|
|
s[0] = m_float_buffer[(read_index - 1) & INDEX_MASK] * r_volume;
|
|
|
|
s[1] = m_float_buffer[(read_index - 2) & INDEX_MASK] * l_volume;
|
|
|
|
for (; current_sample < numSamples * 2; current_sample += 2)
|
2011-03-12 22:02:46 +00:00
|
|
|
{
|
2015-02-22 23:17:51 -03:00
|
|
|
samples[current_sample] += s[0];
|
|
|
|
samples[current_sample + 1] += s[1];
|
2011-03-12 22:02:46 +00:00
|
|
|
}
|
2015-02-22 23:17:51 -03:00
|
|
|
// update read index
|
2015-05-25 18:36:28 -03:00
|
|
|
m_read_index.store(read_index);
|
2014-07-14 19:21:49 -03:00
|
|
|
}
|
|
|
|
|
2014-07-17 19:56:27 -03:00
|
|
|
u32 CMixer::MixerFifo::AvailableSamples()
|
|
|
|
{
|
2015-05-25 18:36:28 -03:00
|
|
|
return ((m_write_index.load() - m_read_index.load()) & INDEX_MASK) * 48000 / (2 * m_input_sample_rate);
|
2014-07-17 19:56:27 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
u32 CMixer::AvailableSamples()
|
|
|
|
{
|
2015-02-11 18:10:33 -03:00
|
|
|
u32 samples = m_dma_mixer.AvailableSamples();
|
|
|
|
if (samples == 0)
|
|
|
|
{
|
|
|
|
samples = m_streaming_mixer.AvailableSamples();
|
|
|
|
}
|
|
|
|
if (samples == 0)
|
|
|
|
{
|
|
|
|
samples = m_wiimote_speaker_mixer.AvailableSamples();
|
|
|
|
}
|
|
|
|
return samples;
|
2014-07-17 19:56:27 -03:00
|
|
|
}
|
|
|
|
|
2015-02-22 23:17:51 -03:00
|
|
|
u32 CMixer::Mix(s16* samples, u32 num_samples, bool consider_framelimit)
|
2014-07-14 19:21:49 -03:00
|
|
|
{
|
|
|
|
if (!samples)
|
|
|
|
return 0;
|
2015-02-22 23:17:51 -03:00
|
|
|
std::lock_guard<std::mutex> lk(m_cs_mixing);
|
|
|
|
// reset float output buffer
|
|
|
|
m_output_buffer.resize(num_samples * 2);
|
|
|
|
std::fill_n(m_output_buffer.begin(), num_samples * 2, 0.f);
|
|
|
|
m_dma_mixer.Mix(m_output_buffer.data(), num_samples, consider_framelimit);
|
|
|
|
m_streaming_mixer.Mix(m_output_buffer.data(), num_samples, consider_framelimit);
|
|
|
|
m_wiimote_speaker_mixer.Mix(m_output_buffer.data(), num_samples, consider_framelimit);
|
|
|
|
// dither and clamp
|
|
|
|
for (u32 i = 0; i < num_samples * 2; i += 2)
|
|
|
|
{
|
2015-09-26 20:04:16 -03:00
|
|
|
float r_output = m_output_buffer[i] * 32768.0f;
|
|
|
|
float l_output = m_output_buffer[i + 1] * 32768.0f;
|
2015-09-19 19:56:20 -03:00
|
|
|
l_output = MathUtil::Clamp(l_output, -32768.f, 32767.f);
|
|
|
|
r_output = MathUtil::Clamp(r_output, -32768.f, 32767.f);
|
2015-02-22 23:17:51 -03:00
|
|
|
samples[i] = s16(r_output);
|
|
|
|
samples[i + 1] = s16(l_output);
|
|
|
|
}
|
|
|
|
return num_samples;
|
|
|
|
}
|
2014-07-14 19:21:49 -03:00
|
|
|
|
2015-02-22 23:17:51 -03:00
|
|
|
u32 CMixer::Mix(float* samples, u32 num_samples, bool consider_framelimit)
|
|
|
|
{
|
|
|
|
if (!samples)
|
|
|
|
return 0;
|
|
|
|
std::lock_guard<std::mutex> lk(m_cs_mixing);
|
|
|
|
memset(samples, 0, num_samples * 2 * sizeof(float));
|
2014-07-14 19:21:49 -03:00
|
|
|
m_dma_mixer.Mix(samples, num_samples, consider_framelimit);
|
|
|
|
m_streaming_mixer.Mix(samples, num_samples, consider_framelimit);
|
2014-10-04 12:11:42 -03:00
|
|
|
m_wiimote_speaker_mixer.Mix(samples, num_samples, consider_framelimit);
|
2014-07-14 19:21:49 -03:00
|
|
|
return num_samples;
|
|
|
|
}
|
2009-12-23 15:34:14 +00:00
|
|
|
|
2015-02-22 23:17:51 -03:00
|
|
|
|
|
|
|
void CMixer::MixerFifo::PushSamples(const s16* samples, u32 num_samples)
|
2009-12-23 15:34:14 +00:00
|
|
|
{
|
2013-07-11 21:22:38 +02:00
|
|
|
// Cache access in non-volatile variable
|
|
|
|
// indexR isn't allowed to cache in the audio throttling loop as it
|
|
|
|
// needs to get updates to not deadlock.
|
2015-05-25 18:36:28 -03:00
|
|
|
u32 current_write_index = m_write_index.load();
|
2009-12-23 15:34:14 +00:00
|
|
|
// Check if we have enough free space
|
2013-07-11 21:22:38 +02:00
|
|
|
// indexW == m_indexR results in empty buffer, so indexR must always be smaller than indexW
|
2015-05-25 18:36:28 -03:00
|
|
|
if (num_samples * 2 + ((current_write_index - m_read_index.load()) & INDEX_MASK) >= MAX_SAMPLES * 2)
|
feat: add menu + stage music support (#386)
* Add support for Rust in CMake via Corrosion
* Tweak .gitignore to handle Rust target dir
* It's 3AM and I have no desire to deal with this
* Initial scaffolding for loading Rust library in Dolphin
* Expose the Dolphin logging mechanisms to Rust via some callback trickery
* Attempt patching Core.vcxproj to support building Rust dylib
* Attempt patching Core.vcxproj to support building Rust dylib, take 2 OR
* Instruct the build to actually use the steps
* Attempt the older style vcxproj definition format
* Push build targets to end
* Just don't use va_args when calling through from Rust
* Enable Windows project linking, move to generic project structure, start moving out of HW
* Add note to README about Rust requirement
* Update slippi-rust-extensions to have proper EXI Device skeleton
* Attach shadow EXI device to cpp EXI device, add feature flag for playback-specific code, rewrite README for rust extensions slightly
* Remove unused log file
* Ongoing logging work
* Tweak Dolphin LogContainer to auto forward enabled/level status over to Rust, expose more methods on Rust side for control, rebuild logger layer subscriber
* Remove debug flag for release mode but add note about it
* Reorganize module definitions, pass in sampler handler fn for SoundStream
* Fix log target
* Rename to SlippiRustExtensions, separate out into cargo workspace, rename General Rust log
* Tweak logging layer so that we don't double-allocate strings on all log messages, properly surface log locations
* cargo fmt
* initial port of slippi-jukebox code
* minor cleanup and leverage channels rather than atomic bool for stopping
threads
* Add config option for enabling/disabling Jukebox
* Invert shutdown order for Memory and ExpansionInterface so we avoid a null ptr race in the Jukebox, as we need Memory to still be valid at Jukebox shutdown
* update dolphin additional include dirs to facilitate new slippi config pane changes
* Ensure Core is running before trying to find an EXI device, as ExpansionInterface isn't initialized unless Core is running - fixes a crash on bad access
* Expose streaming sampler to jukebox, disable DVDInterface streaming sampler pushes to avoid null data being pushed in
* Expose setters for streaming sample rate and streaming volume to Rust
* jukebox: renaming variables for clarity
* try to use new jukebox sample functions
* jukebox: add support for all star rest area
* jukebox: add support for adventure mode field stages
* jukebox: continuously send chunks of pcm data to dolphin's audio mixer
* Audio somewhat coming through now, albeit with pops and pitch issues...
* Force-log samples to wav
* jukebox: switch from dolphin mixer back to rodio for music playback
* Mark doc example as notest
* Attempt an initial CI pass
* Tinkering with CI
* Specify CI working directory for cargo fmt
* Specify CI working directory for cargo fmt
* Specify CI working directory for cargo fmt
* Specify CI working directory for cargo fmt
* Specify CI working directory for cargo fmt
* Specify CI working directory for cargo fmt
* [CI] More permissive for compiling code
* jukebox: replace rand with fastrand
* jukebox: dont use static memory for menu & tournament tracks
* Attempt to resolve Windows playback lib loading oddity
* Add a method for grabbing the current volume level
* Have Dolphin pass over the iso path and a getter for the volume level
* Cargo fmt pass
* Include rustfmt.toml
* Remove the Jukebox config option from playback builds entirely, do not start the jukebox if we're in WASAPI Exclusive mode
* Ix-nay the bad check I copied by accident, lol
* SlippiRustExtensions: add build instructions for windows
* jukebox: make proper use of dolphin's volume + remove unused dependencies
* SlippiRustExtensions(readme): simplify suggested out-of-band build command
* jukebox: remove 'anyhow' dependency
* jukebox: simplify read_dolphin_state fn
* jukebox: reduce hps fingerprint size for track matching
* jukebox: remove 'bus' dependency and improve comments
* jukebox: add readme
* jukebox: add description field to Cargo.toml
* README cleanup, extra writeup for logcontainer creation
* Cleanup unused imports
* Rename DolphinState to DolphinGameState
* Pin to Rust 1.70.0
* Re-enable SFX, stop force-dumping WAV DTK audiograph logs
* Revert attempted change of disabling DTK reads
* Revise documentation surrounding logging infrastructure changes
* Ensure the Volume getter is outside of a C++ namespace, just to try and be careful with ABI oddities
* Add an extra LogContainer.
- A generic Rust dependencies log container that we can use if we need
to ever inspect dependency tracing logs.
- Moves the AudioCommon::GetVolume call out of the namespace for now
since I want someone (or me, when I get more time) to verify that
being inside a C++ namespace is safe.
- Remove once_cell as a dependency now that this is pinned to `1.70.0`.
* Fix the typo, because C++
* Additional README contexts
* ifndef PLAYBACK for GUI toggles
* Always publish an artifact for macOS even if we're not signing and notarizing
* Try changing into the directory - why is there so little documentation about what is supported in these files...?
* Pin toolchain in CI to 1.70.0, update Visual Studio to change into working directory for pre-build Rust step so that toolchain file is actually detected
* Opt for a root symlink to the toolchain config per Nikki's idea, comment out forced 1.70.0 in CI build flow
* Revert symlink toolchain to see if there's a CI bug for Linux
* jukebox: reduce music volume by 20%
* jukebox: link to hps_decode crate in the docs
* ci: sed out rust version from rust-toolchain.toml
* ci: add id field for rust_ver
* jukebox: stop blocking the main thread when scanning iso for tracks
* jukebox: respect melee's volume setting when restarting jukebox during emulation
* jukebox: improve code readability
* jukebox: leverage disc filesystem table to locate .hps files
* jukebox: minor fst parsing code improvements
* remove '.unwrap()' from Jukebox destructor
---------
Co-authored-by: Ryan McGrath <ryan@rymc.io>
Co-authored-by: Nikhil Narayana <nikhil.narayana@live.com>
2023-07-27 23:22:41 -04:00
|
|
|
{
|
|
|
|
// @TODO: We would ideally like to be able to push Jukebox audio samples through Dolphin's mixer,
|
|
|
|
// however attempts at doing so seem to conflict with some expected logic regarding sample submission.
|
|
|
|
//
|
|
|
|
// For whoever chooses to try and debug this, you may want to uncomment the following line to examine
|
|
|
|
// why some samples get dropped and not pushed into the buffer.
|
|
|
|
// NOTICE_LOG(AUDIO, "PushSamples exiting early");
|
2009-12-23 15:34:14 +00:00
|
|
|
return;
|
feat: add menu + stage music support (#386)
* Add support for Rust in CMake via Corrosion
* Tweak .gitignore to handle Rust target dir
* It's 3AM and I have no desire to deal with this
* Initial scaffolding for loading Rust library in Dolphin
* Expose the Dolphin logging mechanisms to Rust via some callback trickery
* Attempt patching Core.vcxproj to support building Rust dylib
* Attempt patching Core.vcxproj to support building Rust dylib, take 2 OR
* Instruct the build to actually use the steps
* Attempt the older style vcxproj definition format
* Push build targets to end
* Just don't use va_args when calling through from Rust
* Enable Windows project linking, move to generic project structure, start moving out of HW
* Add note to README about Rust requirement
* Update slippi-rust-extensions to have proper EXI Device skeleton
* Attach shadow EXI device to cpp EXI device, add feature flag for playback-specific code, rewrite README for rust extensions slightly
* Remove unused log file
* Ongoing logging work
* Tweak Dolphin LogContainer to auto forward enabled/level status over to Rust, expose more methods on Rust side for control, rebuild logger layer subscriber
* Remove debug flag for release mode but add note about it
* Reorganize module definitions, pass in sampler handler fn for SoundStream
* Fix log target
* Rename to SlippiRustExtensions, separate out into cargo workspace, rename General Rust log
* Tweak logging layer so that we don't double-allocate strings on all log messages, properly surface log locations
* cargo fmt
* initial port of slippi-jukebox code
* minor cleanup and leverage channels rather than atomic bool for stopping
threads
* Add config option for enabling/disabling Jukebox
* Invert shutdown order for Memory and ExpansionInterface so we avoid a null ptr race in the Jukebox, as we need Memory to still be valid at Jukebox shutdown
* update dolphin additional include dirs to facilitate new slippi config pane changes
* Ensure Core is running before trying to find an EXI device, as ExpansionInterface isn't initialized unless Core is running - fixes a crash on bad access
* Expose streaming sampler to jukebox, disable DVDInterface streaming sampler pushes to avoid null data being pushed in
* Expose setters for streaming sample rate and streaming volume to Rust
* jukebox: renaming variables for clarity
* try to use new jukebox sample functions
* jukebox: add support for all star rest area
* jukebox: add support for adventure mode field stages
* jukebox: continuously send chunks of pcm data to dolphin's audio mixer
* Audio somewhat coming through now, albeit with pops and pitch issues...
* Force-log samples to wav
* jukebox: switch from dolphin mixer back to rodio for music playback
* Mark doc example as notest
* Attempt an initial CI pass
* Tinkering with CI
* Specify CI working directory for cargo fmt
* Specify CI working directory for cargo fmt
* Specify CI working directory for cargo fmt
* Specify CI working directory for cargo fmt
* Specify CI working directory for cargo fmt
* Specify CI working directory for cargo fmt
* [CI] More permissive for compiling code
* jukebox: replace rand with fastrand
* jukebox: dont use static memory for menu & tournament tracks
* Attempt to resolve Windows playback lib loading oddity
* Add a method for grabbing the current volume level
* Have Dolphin pass over the iso path and a getter for the volume level
* Cargo fmt pass
* Include rustfmt.toml
* Remove the Jukebox config option from playback builds entirely, do not start the jukebox if we're in WASAPI Exclusive mode
* Ix-nay the bad check I copied by accident, lol
* SlippiRustExtensions: add build instructions for windows
* jukebox: make proper use of dolphin's volume + remove unused dependencies
* SlippiRustExtensions(readme): simplify suggested out-of-band build command
* jukebox: remove 'anyhow' dependency
* jukebox: simplify read_dolphin_state fn
* jukebox: reduce hps fingerprint size for track matching
* jukebox: remove 'bus' dependency and improve comments
* jukebox: add readme
* jukebox: add description field to Cargo.toml
* README cleanup, extra writeup for logcontainer creation
* Cleanup unused imports
* Rename DolphinState to DolphinGameState
* Pin to Rust 1.70.0
* Re-enable SFX, stop force-dumping WAV DTK audiograph logs
* Revert attempted change of disabling DTK reads
* Revise documentation surrounding logging infrastructure changes
* Ensure the Volume getter is outside of a C++ namespace, just to try and be careful with ABI oddities
* Add an extra LogContainer.
- A generic Rust dependencies log container that we can use if we need
to ever inspect dependency tracing logs.
- Moves the AudioCommon::GetVolume call out of the namespace for now
since I want someone (or me, when I get more time) to verify that
being inside a C++ namespace is safe.
- Remove once_cell as a dependency now that this is pinned to `1.70.0`.
* Fix the typo, because C++
* Additional README contexts
* ifndef PLAYBACK for GUI toggles
* Always publish an artifact for macOS even if we're not signing and notarizing
* Try changing into the directory - why is there so little documentation about what is supported in these files...?
* Pin toolchain in CI to 1.70.0, update Visual Studio to change into working directory for pre-build Rust step so that toolchain file is actually detected
* Opt for a root symlink to the toolchain config per Nikki's idea, comment out forced 1.70.0 in CI build flow
* Revert symlink toolchain to see if there's a CI bug for Linux
* jukebox: reduce music volume by 20%
* jukebox: link to hps_decode crate in the docs
* ci: sed out rust version from rust-toolchain.toml
* ci: add id field for rust_ver
* jukebox: stop blocking the main thread when scanning iso for tracks
* jukebox: respect melee's volume setting when restarting jukebox during emulation
* jukebox: improve code readability
* jukebox: leverage disc filesystem table to locate .hps files
* jukebox: minor fst parsing code improvements
* remove '.unwrap()' from Jukebox destructor
---------
Co-authored-by: Ryan McGrath <ryan@rymc.io>
Co-authored-by: Nikhil Narayana <nikhil.narayana@live.com>
2023-07-27 23:22:41 -04:00
|
|
|
}
|
|
|
|
|
2009-12-23 15:34:14 +00:00
|
|
|
// AyuanX: Actual re-sampling work has been moved to sound thread
|
2009-12-25 11:59:04 +00:00
|
|
|
// to alleviate the workload on main thread
|
2015-02-22 23:17:51 -03:00
|
|
|
// convert to float while copying to buffer
|
|
|
|
for (u32 i = 0; i < num_samples * 2; ++i)
|
2009-12-23 15:34:14 +00:00
|
|
|
{
|
2015-02-22 23:17:51 -03:00
|
|
|
m_float_buffer[(current_write_index + i) & INDEX_MASK] = Signed16ToFloat(Common::swap16(samples[i]));
|
2009-12-23 15:34:14 +00:00
|
|
|
}
|
2015-05-25 18:36:28 -03:00
|
|
|
m_write_index.fetch_add(num_samples * 2);
|
2009-12-23 15:34:14 +00:00
|
|
|
return;
|
2008-12-08 05:25:12 +00:00
|
|
|
}
|
2014-06-03 18:14:53 -03:00
|
|
|
|
2015-02-22 23:17:51 -03:00
|
|
|
void CMixer::PushSamples(const s16 *samples, u32 num_samples)
|
2014-07-14 19:21:49 -03:00
|
|
|
{
|
|
|
|
m_dma_mixer.PushSamples(samples, num_samples);
|
2016-07-08 16:14:35 -03:00
|
|
|
int sample_rate = m_dma_mixer.GetInputSampleRate();
|
2014-10-13 09:41:00 -03:00
|
|
|
if (m_log_dsp_audio)
|
2016-07-08 16:14:35 -03:00
|
|
|
g_wave_writer_dsp.AddStereoSamplesBE(samples, num_samples, sample_rate);
|
2014-07-14 19:21:49 -03:00
|
|
|
}
|
|
|
|
|
2015-02-22 23:17:51 -03:00
|
|
|
void CMixer::PushStreamingSamples(const s16 *samples, u32 num_samples)
|
2014-07-14 19:21:49 -03:00
|
|
|
{
|
|
|
|
m_streaming_mixer.PushSamples(samples, num_samples);
|
2016-07-08 16:14:35 -03:00
|
|
|
int sample_rate = m_streaming_mixer.GetInputSampleRate();
|
2014-10-13 09:41:00 -03:00
|
|
|
if (m_log_dtk_audio)
|
2016-07-08 16:14:35 -03:00
|
|
|
g_wave_writer_dtk.AddStereoSamplesBE(samples, num_samples, sample_rate);
|
2014-07-17 19:56:27 -03:00
|
|
|
}
|
|
|
|
|
2015-02-22 23:17:51 -03:00
|
|
|
void CMixer::PushWiimoteSpeakerSamples(const s16 *samples, u32 num_samples, u32 sample_rate)
|
2014-10-04 12:11:42 -03:00
|
|
|
{
|
2015-02-22 23:17:51 -03:00
|
|
|
s16 samples_stereo[MAX_SAMPLES * 2];
|
2014-10-04 12:11:42 -03:00
|
|
|
|
|
|
|
if (num_samples < MAX_SAMPLES)
|
|
|
|
{
|
|
|
|
m_wiimote_speaker_mixer.SetInputSampleRate(sample_rate);
|
|
|
|
|
2015-02-22 23:17:51 -03:00
|
|
|
for (u32 i = 0; i < num_samples; ++i)
|
2014-10-04 12:11:42 -03:00
|
|
|
{
|
|
|
|
samples_stereo[i * 2] = Common::swap16(samples[i]);
|
|
|
|
samples_stereo[i * 2 + 1] = Common::swap16(samples[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_wiimote_speaker_mixer.PushSamples(samples_stereo, num_samples);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-22 23:17:51 -03:00
|
|
|
void CMixer::SetDMAInputSampleRate(u32 rate)
|
2014-08-02 12:00:55 -03:00
|
|
|
{
|
|
|
|
m_dma_mixer.SetInputSampleRate(rate);
|
|
|
|
}
|
|
|
|
|
2015-02-22 23:17:51 -03:00
|
|
|
void CMixer::SetStreamInputSampleRate(u32 rate)
|
2014-08-02 12:00:55 -03:00
|
|
|
{
|
|
|
|
m_streaming_mixer.SetInputSampleRate(rate);
|
|
|
|
}
|
|
|
|
|
2015-02-22 23:17:51 -03:00
|
|
|
void CMixer::SetStreamingVolume(u32 lvolume, u32 rvolume)
|
2014-07-17 19:56:27 -03:00
|
|
|
{
|
|
|
|
m_streaming_mixer.SetVolume(lvolume, rvolume);
|
|
|
|
}
|
|
|
|
|
2015-02-22 23:17:51 -03:00
|
|
|
void CMixer::SetWiimoteSpeakerVolume(u32 lvolume, u32 rvolume)
|
2014-10-04 12:11:42 -03:00
|
|
|
{
|
|
|
|
m_wiimote_speaker_mixer.SetVolume(lvolume, rvolume);
|
|
|
|
}
|
|
|
|
|
2015-02-22 23:17:51 -03:00
|
|
|
void CMixer::MixerFifo::SetInputSampleRate(u32 rate)
|
2014-08-02 12:00:55 -03:00
|
|
|
{
|
|
|
|
m_input_sample_rate = rate;
|
|
|
|
}
|
|
|
|
|
2015-02-22 23:17:51 -03:00
|
|
|
void CMixer::MixerFifo::SetVolume(u32 lvolume, u32 rvolume)
|
2014-07-17 19:56:27 -03:00
|
|
|
{
|
2015-05-25 18:36:28 -03:00
|
|
|
m_lvolume.store(lvolume + (lvolume >> 7));
|
|
|
|
m_rvolume.store(rvolume + (rvolume >> 7));
|
2014-10-04 12:11:42 -03:00
|
|
|
}
|
2015-02-22 23:17:51 -03:00
|
|
|
|
|
|
|
void CMixer::MixerFifo::GetVolume(u32* lvolume, u32* rvolume) const
|
|
|
|
{
|
2015-05-25 18:36:28 -03:00
|
|
|
*lvolume = m_lvolume.load();
|
|
|
|
*rvolume = m_rvolume.load();
|
2015-08-15 17:16:34 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMixer::StartLogDTKAudio(const std::string& filename)
|
|
|
|
{
|
|
|
|
if (!m_log_dtk_audio)
|
|
|
|
{
|
2017-01-15 19:22:44 -03:00
|
|
|
bool success = g_wave_writer_dtk.Start(filename, m_streaming_mixer.GetInputSampleRate());
|
|
|
|
if (success)
|
|
|
|
{
|
|
|
|
m_log_dtk_audio = true;
|
|
|
|
g_wave_writer_dtk.SetSkipSilence(false);
|
|
|
|
NOTICE_LOG(AUDIO, "Starting DTK Audio logging");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_wave_writer_dtk.Stop();
|
|
|
|
NOTICE_LOG(AUDIO, "Unable to start DTK Audio logging");
|
|
|
|
}
|
2015-08-15 17:16:34 -03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WARN_LOG(AUDIO, "DTK Audio logging has already been started");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMixer::StopLogDTKAudio()
|
|
|
|
{
|
|
|
|
if (m_log_dtk_audio)
|
|
|
|
{
|
|
|
|
m_log_dtk_audio = false;
|
|
|
|
g_wave_writer_dtk.Stop();
|
|
|
|
NOTICE_LOG(AUDIO, "Stopping DTK Audio logging");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WARN_LOG(AUDIO, "DTK Audio logging has already been stopped");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMixer::StartLogDSPAudio(const std::string& filename)
|
|
|
|
{
|
|
|
|
if (!m_log_dsp_audio)
|
|
|
|
{
|
2017-01-15 19:22:44 -03:00
|
|
|
bool success = g_wave_writer_dsp.Start(filename, m_dma_mixer.GetInputSampleRate());
|
|
|
|
if (success)
|
|
|
|
{
|
|
|
|
m_log_dsp_audio = true;
|
|
|
|
g_wave_writer_dsp.SetSkipSilence(false);
|
|
|
|
NOTICE_LOG(AUDIO, "Starting DSP Audio logging");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_wave_writer_dsp.Stop();
|
|
|
|
NOTICE_LOG(AUDIO, "Unable to start DSP Audio logging");
|
|
|
|
}
|
2015-08-15 17:16:34 -03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WARN_LOG(AUDIO, "DSP Audio logging has already been started");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMixer::StopLogDSPAudio()
|
|
|
|
{
|
|
|
|
if (m_log_dsp_audio)
|
|
|
|
{
|
|
|
|
m_log_dsp_audio = false;
|
|
|
|
g_wave_writer_dsp.Stop();
|
|
|
|
NOTICE_LOG(AUDIO, "Stopping DSP Audio logging");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WARN_LOG(AUDIO, "DSP Audio logging has already been stopped");
|
|
|
|
}
|
2016-07-08 16:14:35 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int CMixer::MixerFifo::GetInputSampleRate() const
|
|
|
|
{
|
|
|
|
return m_input_sample_rate;
|
feat: add menu + stage music support (#386)
* Add support for Rust in CMake via Corrosion
* Tweak .gitignore to handle Rust target dir
* It's 3AM and I have no desire to deal with this
* Initial scaffolding for loading Rust library in Dolphin
* Expose the Dolphin logging mechanisms to Rust via some callback trickery
* Attempt patching Core.vcxproj to support building Rust dylib
* Attempt patching Core.vcxproj to support building Rust dylib, take 2 OR
* Instruct the build to actually use the steps
* Attempt the older style vcxproj definition format
* Push build targets to end
* Just don't use va_args when calling through from Rust
* Enable Windows project linking, move to generic project structure, start moving out of HW
* Add note to README about Rust requirement
* Update slippi-rust-extensions to have proper EXI Device skeleton
* Attach shadow EXI device to cpp EXI device, add feature flag for playback-specific code, rewrite README for rust extensions slightly
* Remove unused log file
* Ongoing logging work
* Tweak Dolphin LogContainer to auto forward enabled/level status over to Rust, expose more methods on Rust side for control, rebuild logger layer subscriber
* Remove debug flag for release mode but add note about it
* Reorganize module definitions, pass in sampler handler fn for SoundStream
* Fix log target
* Rename to SlippiRustExtensions, separate out into cargo workspace, rename General Rust log
* Tweak logging layer so that we don't double-allocate strings on all log messages, properly surface log locations
* cargo fmt
* initial port of slippi-jukebox code
* minor cleanup and leverage channels rather than atomic bool for stopping
threads
* Add config option for enabling/disabling Jukebox
* Invert shutdown order for Memory and ExpansionInterface so we avoid a null ptr race in the Jukebox, as we need Memory to still be valid at Jukebox shutdown
* update dolphin additional include dirs to facilitate new slippi config pane changes
* Ensure Core is running before trying to find an EXI device, as ExpansionInterface isn't initialized unless Core is running - fixes a crash on bad access
* Expose streaming sampler to jukebox, disable DVDInterface streaming sampler pushes to avoid null data being pushed in
* Expose setters for streaming sample rate and streaming volume to Rust
* jukebox: renaming variables for clarity
* try to use new jukebox sample functions
* jukebox: add support for all star rest area
* jukebox: add support for adventure mode field stages
* jukebox: continuously send chunks of pcm data to dolphin's audio mixer
* Audio somewhat coming through now, albeit with pops and pitch issues...
* Force-log samples to wav
* jukebox: switch from dolphin mixer back to rodio for music playback
* Mark doc example as notest
* Attempt an initial CI pass
* Tinkering with CI
* Specify CI working directory for cargo fmt
* Specify CI working directory for cargo fmt
* Specify CI working directory for cargo fmt
* Specify CI working directory for cargo fmt
* Specify CI working directory for cargo fmt
* Specify CI working directory for cargo fmt
* [CI] More permissive for compiling code
* jukebox: replace rand with fastrand
* jukebox: dont use static memory for menu & tournament tracks
* Attempt to resolve Windows playback lib loading oddity
* Add a method for grabbing the current volume level
* Have Dolphin pass over the iso path and a getter for the volume level
* Cargo fmt pass
* Include rustfmt.toml
* Remove the Jukebox config option from playback builds entirely, do not start the jukebox if we're in WASAPI Exclusive mode
* Ix-nay the bad check I copied by accident, lol
* SlippiRustExtensions: add build instructions for windows
* jukebox: make proper use of dolphin's volume + remove unused dependencies
* SlippiRustExtensions(readme): simplify suggested out-of-band build command
* jukebox: remove 'anyhow' dependency
* jukebox: simplify read_dolphin_state fn
* jukebox: reduce hps fingerprint size for track matching
* jukebox: remove 'bus' dependency and improve comments
* jukebox: add readme
* jukebox: add description field to Cargo.toml
* README cleanup, extra writeup for logcontainer creation
* Cleanup unused imports
* Rename DolphinState to DolphinGameState
* Pin to Rust 1.70.0
* Re-enable SFX, stop force-dumping WAV DTK audiograph logs
* Revert attempted change of disabling DTK reads
* Revise documentation surrounding logging infrastructure changes
* Ensure the Volume getter is outside of a C++ namespace, just to try and be careful with ABI oddities
* Add an extra LogContainer.
- A generic Rust dependencies log container that we can use if we need
to ever inspect dependency tracing logs.
- Moves the AudioCommon::GetVolume call out of the namespace for now
since I want someone (or me, when I get more time) to verify that
being inside a C++ namespace is safe.
- Remove once_cell as a dependency now that this is pinned to `1.70.0`.
* Fix the typo, because C++
* Additional README contexts
* ifndef PLAYBACK for GUI toggles
* Always publish an artifact for macOS even if we're not signing and notarizing
* Try changing into the directory - why is there so little documentation about what is supported in these files...?
* Pin toolchain in CI to 1.70.0, update Visual Studio to change into working directory for pre-build Rust step so that toolchain file is actually detected
* Opt for a root symlink to the toolchain config per Nikki's idea, comment out forced 1.70.0 in CI build flow
* Revert symlink toolchain to see if there's a CI bug for Linux
* jukebox: reduce music volume by 20%
* jukebox: link to hps_decode crate in the docs
* ci: sed out rust version from rust-toolchain.toml
* ci: add id field for rust_ver
* jukebox: stop blocking the main thread when scanning iso for tracks
* jukebox: respect melee's volume setting when restarting jukebox during emulation
* jukebox: improve code readability
* jukebox: leverage disc filesystem table to locate .hps files
* jukebox: minor fst parsing code improvements
* remove '.unwrap()' from Jukebox destructor
---------
Co-authored-by: Ryan McGrath <ryan@rymc.io>
Co-authored-by: Nikhil Narayana <nikhil.narayana@live.com>
2023-07-27 23:22:41 -04:00
|
|
|
}
|