Manually tweak source formatting and then re-run clang-format
This commit is contained in:
parent
784b96d87f
commit
396a8d91a4
169 changed files with 805 additions and 809 deletions
|
@ -23,7 +23,7 @@ StereoBuffer16 DecodeADPCM(const u8* const data, const size_t sample_count,
|
|||
|
||||
constexpr size_t FRAME_LEN = 8;
|
||||
constexpr size_t SAMPLES_PER_FRAME = 14;
|
||||
constexpr std::array<int, 16> SIGNED_NIBBLES{
|
||||
constexpr std::array<int, 16> SIGNED_NIBBLES = {
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1}};
|
||||
|
||||
const size_t ret_size =
|
||||
|
|
|
@ -49,7 +49,8 @@ static SharedMemory& WriteRegion() {
|
|||
static std::array<Source, num_sources> sources = {
|
||||
Source(0), Source(1), Source(2), Source(3), Source(4), Source(5), Source(6), Source(7),
|
||||
Source(8), Source(9), Source(10), Source(11), Source(12), Source(13), Source(14), Source(15),
|
||||
Source(16), Source(17), Source(18), Source(19), Source(20), Source(21), Source(22), Source(23)};
|
||||
Source(16), Source(17), Source(18), Source(19), Source(20), Source(21), Source(22), Source(23),
|
||||
};
|
||||
static Mixers mixers;
|
||||
|
||||
static StereoFrame16 GenerateCurrentFrame() {
|
||||
|
|
|
@ -23,16 +23,15 @@ class Sink;
|
|||
namespace DSP {
|
||||
namespace HLE {
|
||||
|
||||
// The application-accessible region of DSP memory consists of two parts.
|
||||
// Both are marked as IO and have Read/Write permissions.
|
||||
// The application-accessible region of DSP memory consists of two parts. Both are marked as IO and
|
||||
// have Read/Write permissions.
|
||||
//
|
||||
// First Region: 0x1FF50000 (Size: 0x8000)
|
||||
// Second Region: 0x1FF70000 (Size: 0x8000)
|
||||
//
|
||||
// The DSP reads from each region alternately based on the frame counter for each region much like a
|
||||
// double-buffer. The frame counter is located as the very last u16 of each region and is
|
||||
// incremented
|
||||
// each audio tick.
|
||||
// incremented each audio tick.
|
||||
|
||||
constexpr VAddr region0_base = 0x1FF50000;
|
||||
constexpr VAddr region1_base = 0x1FF70000;
|
||||
|
@ -92,14 +91,12 @@ static_assert(std::is_trivially_copyable<u32_dsp>::value, "u32_dsp isn't trivial
|
|||
// See also: DSP::HLE::PipeRead.
|
||||
//
|
||||
// Note that the above addresses do vary slightly between audio firmwares observed; the addresses
|
||||
// are
|
||||
// not fixed in stone. The addresses above are only an examplar; they're what this implementation
|
||||
// does and provides to applications.
|
||||
// are not fixed in stone. The addresses above are only an examplar; they're what this
|
||||
// implementation does and provides to applications.
|
||||
//
|
||||
// Application requests the DSP service to convert DSP addresses into ARM11 virtual addresses using
|
||||
// the
|
||||
// ConvertProcessAddressFromDspDram service call. Applications seem to derive the addresses for the
|
||||
// second region via:
|
||||
// the ConvertProcessAddressFromDspDram service call. Applications seem to derive the addresses for
|
||||
// the second region via:
|
||||
// second_region_dsp_addr = first_region_dsp_addr | 0x10000
|
||||
//
|
||||
// Applications maintain most of its own audio state, the memory region is used mainly for
|
||||
|
@ -107,7 +104,7 @@ static_assert(std::is_trivially_copyable<u32_dsp>::value, "u32_dsp isn't trivial
|
|||
//
|
||||
// In the documentation below, filter and effect transfer functions are specified in the z domain.
|
||||
// (If you are more familiar with the Laplace transform, z = exp(sT). The z domain is the digital
|
||||
// frequency domain, just like how the s domain is the analog frequency domain.)
|
||||
// frequency domain, just like how the s domain is the analog frequency domain.)
|
||||
|
||||
#define INSERT_PADDING_DSPWORDS(num_words) INSERT_PADDING_BYTES(2 * (num_words))
|
||||
|
||||
|
@ -137,8 +134,8 @@ struct SourceConfiguration {
|
|||
BitField<0, 1, u32_le> format_dirty;
|
||||
BitField<1, 1, u32_le> mono_or_stereo_dirty;
|
||||
BitField<2, 1, u32_le> adpcm_coefficients_dirty;
|
||||
BitField<3, 1, u32_le>
|
||||
partial_embedded_buffer_dirty; ///< Tends to be set when a looped buffer is queued.
|
||||
/// Tends to be set when a looped buffer is queued.
|
||||
BitField<3, 1, u32_le> partial_embedded_buffer_dirty;
|
||||
BitField<4, 1, u32_le> partial_reset_flag;
|
||||
|
||||
BitField<16, 1, u32_le> enable_dirty;
|
||||
|
@ -146,8 +143,8 @@ struct SourceConfiguration {
|
|||
BitField<18, 1, u32_le> rate_multiplier_dirty;
|
||||
BitField<19, 1, u32_le> buffer_queue_dirty;
|
||||
BitField<20, 1, u32_le> loop_related_dirty;
|
||||
BitField<21, 1, u32_le>
|
||||
play_position_dirty; ///< Tends to also be set when embedded buffer is updated.
|
||||
/// Tends to also be set when embedded buffer is updated.
|
||||
BitField<21, 1, u32_le> play_position_dirty;
|
||||
BitField<22, 1, u32_le> filters_enabled_dirty;
|
||||
BitField<23, 1, u32_le> simple_filter_dirty;
|
||||
BitField<24, 1, u32_le> biquad_filter_dirty;
|
||||
|
@ -162,9 +159,9 @@ struct SourceConfiguration {
|
|||
// Gain control
|
||||
|
||||
/**
|
||||
* Gain is between 0.0-1.0. This determines how much will this source appear on
|
||||
* each of the 12 channels that feed into the intermediate mixers.
|
||||
* Each of the three intermediate mixers is fed two left and two right channels.
|
||||
* Gain is between 0.0-1.0. This determines how much will this source appear on each of the
|
||||
* 12 channels that feed into the intermediate mixers. Each of the three intermediate mixers
|
||||
* is fed two left and two right channels.
|
||||
*/
|
||||
float_le gain[3][4];
|
||||
|
||||
|
@ -173,7 +170,11 @@ struct SourceConfiguration {
|
|||
/// Multiplier for sample rate. Resampling occurs with the selected interpolation method.
|
||||
float_le rate_multiplier;
|
||||
|
||||
enum class InterpolationMode : u8 { Polyphase = 0, Linear = 1, None = 2 };
|
||||
enum class InterpolationMode : u8 {
|
||||
Polyphase = 0,
|
||||
Linear = 1,
|
||||
None = 2,
|
||||
};
|
||||
|
||||
InterpolationMode interpolation_mode;
|
||||
INSERT_PADDING_BYTES(1); ///< Interpolation related
|
||||
|
@ -197,8 +198,7 @@ struct SourceConfiguration {
|
|||
* The transfer function of this filter is:
|
||||
* H(z) = (b0 + b1 z^-1 + b2 z^-2) / (1 - a1 z^-1 - a2 z^-2)
|
||||
* Nintendo chose to negate the feedbackward coefficients. This differs from standard
|
||||
* notation
|
||||
* as in: https://ccrma.stanford.edu/~jos/filters/Direct_Form_I.html
|
||||
* notation as in: https://ccrma.stanford.edu/~jos/filters/Direct_Form_I.html
|
||||
* Values are signed fixed point with 14 fractional bits.
|
||||
*/
|
||||
struct BiquadFilter {
|
||||
|
@ -246,8 +246,8 @@ struct SourceConfiguration {
|
|||
u8 is_looping;
|
||||
|
||||
/// This value is shown in SourceStatus::previous_buffer_id when this buffer has
|
||||
/// finished.
|
||||
/// This allows the emulated application to tell what buffer is currently playing
|
||||
/// finished. This allows the emulated application to tell what buffer is currently
|
||||
/// playing.
|
||||
u16_le buffer_id;
|
||||
|
||||
INSERT_PADDING_DSPWORDS(1);
|
||||
|
@ -275,9 +275,16 @@ struct SourceConfiguration {
|
|||
/// Note a sample takes up different number of bytes in different buffer formats.
|
||||
u32_dsp length;
|
||||
|
||||
enum class MonoOrStereo : u16_le { Mono = 1, Stereo = 2 };
|
||||
enum class MonoOrStereo : u16_le {
|
||||
Mono = 1,
|
||||
Stereo = 2,
|
||||
};
|
||||
|
||||
enum class Format : u16_le { PCM8 = 0, PCM16 = 1, ADPCM = 2 };
|
||||
enum class Format : u16_le {
|
||||
PCM8 = 0,
|
||||
PCM16 = 1,
|
||||
ADPCM = 2,
|
||||
};
|
||||
|
||||
union {
|
||||
u16_le flags1_raw;
|
||||
|
@ -349,12 +356,16 @@ struct DspConfiguration {
|
|||
};
|
||||
|
||||
/// The DSP has three intermediate audio mixers. This controls the volume level (0.0-1.0) for
|
||||
/// each at the final mixer
|
||||
/// each at the final mixer.
|
||||
float_le volume[3];
|
||||
|
||||
INSERT_PADDING_DSPWORDS(3);
|
||||
|
||||
enum class OutputFormat : u16_le { Mono = 0, Stereo = 1, Surround = 2 };
|
||||
enum class OutputFormat : u16_le {
|
||||
Mono = 0,
|
||||
Stereo = 1,
|
||||
Surround = 2,
|
||||
};
|
||||
|
||||
OutputFormat output_format;
|
||||
|
||||
|
@ -386,9 +397,10 @@ struct DspConfiguration {
|
|||
u16_le enable;
|
||||
INSERT_PADDING_DSPWORDS(1);
|
||||
u16_le outputs;
|
||||
u32_dsp work_buffer_address; ///< The application allocates a block of memory for the DSP to
|
||||
/// use as a work buffer.
|
||||
u16_le frame_count; ///< Frames to delay by
|
||||
/// The application allocates a block of memory for the DSP to use as a work buffer.
|
||||
u32_dsp work_buffer_address;
|
||||
/// Frames to delay by
|
||||
u16_le frame_count;
|
||||
|
||||
// Coefficients
|
||||
s16_le g; ///< Fixed point with 7 fractional bits
|
||||
|
|
|
@ -61,6 +61,7 @@ void SourceFilters::SimpleFilter::Reset() {
|
|||
|
||||
void SourceFilters::SimpleFilter::Configure(
|
||||
SourceConfiguration::Configuration::SimpleFilter config) {
|
||||
|
||||
a1 = config.a1;
|
||||
b0 = config.b0;
|
||||
}
|
||||
|
@ -91,6 +92,7 @@ void SourceFilters::BiquadFilter::Reset() {
|
|||
|
||||
void SourceFilters::BiquadFilter::Configure(
|
||||
SourceConfiguration::Configuration::BiquadFilter config) {
|
||||
|
||||
a1 = config.a1;
|
||||
a2 = config.a2;
|
||||
b0 = config.b0;
|
||||
|
|
|
@ -77,9 +77,8 @@ void Mixers::ParseConfig(DspConfiguration& config) {
|
|||
|
||||
if (config.headphones_connected_dirty) {
|
||||
config.headphones_connected_dirty.Assign(0);
|
||||
// Do nothing.
|
||||
// (Note: Whether headphones are connected does affect coefficients used for surround
|
||||
// sound.)
|
||||
// Do nothing. (Note: Whether headphones are connected does affect coefficients used for
|
||||
// surround sound.)
|
||||
LOG_TRACE(Audio_DSP, "mixers headphones_connected=%hu", config.headphones_connected);
|
||||
}
|
||||
|
||||
|
|
|
@ -97,7 +97,8 @@ static void AudioPipeWriteStructAddresses() {
|
|||
0x8000 + offsetof(SharedMemory, unknown11) / 2,
|
||||
0x8000 + offsetof(SharedMemory, unknown12) / 2,
|
||||
0x8000 + offsetof(SharedMemory, unknown13) / 2,
|
||||
0x8000 + offsetof(SharedMemory, unknown14) / 2};
|
||||
0x8000 + offsetof(SharedMemory, unknown14) / 2,
|
||||
};
|
||||
|
||||
// Begin with a u16 denoting the number of structs.
|
||||
WriteU16(DspPipe::Audio, static_cast<u16>(struct_addresses.size()));
|
||||
|
@ -118,7 +119,12 @@ void PipeWrite(DspPipe pipe_number, const std::vector<u8>& buffer) {
|
|||
return;
|
||||
}
|
||||
|
||||
enum class StateChange { Initalize = 0, Shutdown = 1, Wakeup = 2, Sleep = 3 };
|
||||
enum class StateChange {
|
||||
Initalize = 0,
|
||||
Shutdown = 1,
|
||||
Wakeup = 2,
|
||||
Sleep = 3,
|
||||
};
|
||||
|
||||
// The difference between Initialize and Wakeup is that Input state is maintained
|
||||
// when sleeping but isn't when turning it off and on again. (TODO: Implement this.)
|
||||
|
|
|
@ -15,7 +15,12 @@ namespace HLE {
|
|||
/// Reset the pipes by setting pipe positions back to the beginning.
|
||||
void ResetPipes();
|
||||
|
||||
enum class DspPipe { Debug = 0, Dma = 1, Audio = 2, Binary = 3 };
|
||||
enum class DspPipe {
|
||||
Debug = 0,
|
||||
Dma = 1,
|
||||
Audio = 2,
|
||||
Binary = 3,
|
||||
};
|
||||
constexpr size_t NUM_DSP_PIPE = 8;
|
||||
|
||||
/**
|
||||
|
@ -46,7 +51,12 @@ size_t GetPipeReadableSize(DspPipe pipe_number);
|
|||
*/
|
||||
void PipeWrite(DspPipe pipe_number, const std::vector<u8>& buffer);
|
||||
|
||||
enum class DspState { Off, On, Sleeping };
|
||||
enum class DspState {
|
||||
Off,
|
||||
On,
|
||||
Sleeping,
|
||||
};
|
||||
|
||||
/// Get the state of the DSP
|
||||
DspState GetDspState();
|
||||
|
||||
|
|
|
@ -163,16 +163,18 @@ void Source::ParseConfig(SourceConfiguration::Configuration& config,
|
|||
|
||||
if (config.embedded_buffer_dirty) {
|
||||
config.embedded_buffer_dirty.Assign(0);
|
||||
state.input_queue.emplace(Buffer{config.physical_address,
|
||||
config.length,
|
||||
static_cast<u8>(config.adpcm_ps),
|
||||
{config.adpcm_yn[0], config.adpcm_yn[1]},
|
||||
config.adpcm_dirty.ToBool(),
|
||||
config.is_looping.ToBool(),
|
||||
config.buffer_id,
|
||||
state.mono_or_stereo,
|
||||
state.format,
|
||||
false});
|
||||
state.input_queue.emplace(Buffer{
|
||||
config.physical_address,
|
||||
config.length,
|
||||
static_cast<u8>(config.adpcm_ps),
|
||||
{config.adpcm_yn[0], config.adpcm_yn[1]},
|
||||
config.adpcm_dirty.ToBool(),
|
||||
config.is_looping.ToBool(),
|
||||
config.buffer_id,
|
||||
state.mono_or_stereo,
|
||||
state.format,
|
||||
false,
|
||||
});
|
||||
LOG_TRACE(Audio_DSP, "enqueuing embedded addr=0x%08x len=%u id=%hu",
|
||||
config.physical_address, config.length, config.buffer_id);
|
||||
}
|
||||
|
@ -182,16 +184,18 @@ void Source::ParseConfig(SourceConfiguration::Configuration& config,
|
|||
for (size_t i = 0; i < 4; i++) {
|
||||
if (config.buffers_dirty & (1 << i)) {
|
||||
const auto& b = config.buffers[i];
|
||||
state.input_queue.emplace(Buffer{b.physical_address,
|
||||
b.length,
|
||||
static_cast<u8>(b.adpcm_ps),
|
||||
{b.adpcm_yn[0], b.adpcm_yn[1]},
|
||||
b.adpcm_dirty != 0,
|
||||
b.is_looping != 0,
|
||||
b.buffer_id,
|
||||
state.mono_or_stereo,
|
||||
state.format,
|
||||
true});
|
||||
state.input_queue.emplace(Buffer{
|
||||
b.physical_address,
|
||||
b.length,
|
||||
static_cast<u8>(b.adpcm_ps),
|
||||
{b.adpcm_yn[0], b.adpcm_yn[1]},
|
||||
b.adpcm_dirty != 0,
|
||||
b.is_looping != 0,
|
||||
b.buffer_id,
|
||||
state.mono_or_stereo,
|
||||
state.format,
|
||||
true,
|
||||
});
|
||||
LOG_TRACE(Audio_DSP, "enqueuing queued %zu addr=0x%08x len=%u id=%hu", i,
|
||||
b.physical_address, b.length, b.buffer_id);
|
||||
}
|
||||
|
|
|
@ -71,15 +71,17 @@ StereoBuffer16 None(State& state, const StereoBuffer16& input, float rate_multip
|
|||
|
||||
StereoBuffer16 Linear(State& state, const StereoBuffer16& input, float rate_multiplier) {
|
||||
// Note on accuracy: Some values that this produces are +/- 1 from the actual firmware.
|
||||
return StepOverSamples(state, input, rate_multiplier, [](u64 fraction, const auto& x0,
|
||||
const auto& x1, const auto& x2) {
|
||||
// This is a saturated subtraction. (Verified by black-box fuzzing.)
|
||||
s64 delta0 = MathUtil::Clamp<s64>(x1[0] - x0[0], -32768, 32767);
|
||||
s64 delta1 = MathUtil::Clamp<s64>(x1[1] - x0[1], -32768, 32767);
|
||||
return StepOverSamples(state, input, rate_multiplier,
|
||||
[](u64 fraction, const auto& x0, const auto& x1, const auto& x2) {
|
||||
// This is a saturated subtraction. (Verified by black-box fuzzing.)
|
||||
s64 delta0 = MathUtil::Clamp<s64>(x1[0] - x0[0], -32768, 32767);
|
||||
s64 delta1 = MathUtil::Clamp<s64>(x1[1] - x0[1], -32768, 32767);
|
||||
|
||||
return std::array<s16, 2>{static_cast<s16>(x0[0] + fraction * delta0 / scale_factor),
|
||||
static_cast<s16>(x0[1] + fraction * delta1 / scale_factor)};
|
||||
});
|
||||
return std::array<s16, 2>{
|
||||
static_cast<s16>(x0[0] + fraction * delta0 / scale_factor),
|
||||
static_cast<s16>(x0[1] + fraction * delta1 / scale_factor),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace AudioInterp
|
||||
|
|
|
@ -25,7 +25,7 @@ struct State {
|
|||
* @param input Input buffer.
|
||||
* @param rate_multiplier Stretch factor. Must be a positive non-zero value.
|
||||
* rate_multiplier > 1.0 performs decimation and rate_multipler < 1.0
|
||||
* performs upsampling.
|
||||
* performs upsampling.
|
||||
* @return The resampled audio buffer.
|
||||
*/
|
||||
StereoBuffer16 None(State& state, const StereoBuffer16& input, float rate_multiplier);
|
||||
|
@ -35,7 +35,7 @@ StereoBuffer16 None(State& state, const StereoBuffer16& input, float rate_multip
|
|||
* @param input Input buffer.
|
||||
* @param rate_multiplier Stretch factor. Must be a positive non-zero value.
|
||||
* rate_multiplier > 1.0 performs decimation and rate_multipler < 1.0
|
||||
* performs upsampling.
|
||||
* performs upsampling.
|
||||
* @return The resampled audio buffer.
|
||||
*/
|
||||
StereoBuffer16 Linear(State& state, const StereoBuffer16& input, float rate_multiplier);
|
||||
|
|
|
@ -19,8 +19,7 @@ public:
|
|||
return native_sample_rate;
|
||||
}
|
||||
|
||||
void EnqueueSamples(const s16*, size_t) override {
|
||||
}
|
||||
void EnqueueSamples(const s16*, size_t) override {}
|
||||
|
||||
size_t SamplesInQueue() const override {
|
||||
return 0;
|
||||
|
|
|
@ -12,8 +12,8 @@ namespace AudioCore {
|
|||
|
||||
/**
|
||||
* This class is an interface for an audio sink. An audio sink accepts samples in stereo signed
|
||||
* PCM16 format to be output.
|
||||
* Sinks *do not* handle resampling and expect the correct sample rate. They are dumb outputs.
|
||||
* PCM16 format to be output. Sinks *do not* handle resampling and expect the correct sample rate.
|
||||
* They are dumb outputs.
|
||||
*/
|
||||
class Sink {
|
||||
public:
|
||||
|
|
|
@ -14,8 +14,7 @@ class Sink;
|
|||
|
||||
struct SinkDetails {
|
||||
SinkDetails(const char* id_, std::function<std::unique_ptr<Sink>()> factory_)
|
||||
: id(id_), factory(factory_) {
|
||||
}
|
||||
: id(id_), factory(factory_) {}
|
||||
|
||||
/// Name for this sink.
|
||||
const char* id;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue