diff --git a/Core/BaseSoundFilter.cpp b/Core/BaseSoundFilter.cpp
deleted file mode 100644
index 92e92554..00000000
--- a/Core/BaseSoundFilter.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-#include "stdafx.h"
-#include "BaseSoundFilter.h"
-
-void BaseSoundFilter::UpdateBufferSize(size_t sampleCount, bool isStereo)
-{
- if(_maxSampleCount < sampleCount) {
- if(_filterBuffer) {
- delete[] _filterBuffer;
- }
- _maxSampleCount = sampleCount;
- _filterBuffer = new int16_t[_maxSampleCount * (isStereo ? 2 : 1)];
- memset(_filterBuffer, 0, _maxSampleCount * sizeof(int16_t) * (isStereo ? 2 : 1));
- }
-}
-
-BaseSoundFilter::~BaseSoundFilter()
-{
- if(_filterBuffer) {
- delete[] _filterBuffer;
- }
-}
\ No newline at end of file
diff --git a/Core/BaseSoundFilter.h b/Core/BaseSoundFilter.h
deleted file mode 100644
index cf3a7a71..00000000
--- a/Core/BaseSoundFilter.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#pragma once
-#include "stdafx.h"
-
-class BaseSoundFilter
-{
-protected:
- int16_t* _filterBuffer = nullptr;
- size_t _maxSampleCount = 0;
-
- void UpdateBufferSize(size_t sampleCount, bool isStereo);
-
-public:
- virtual ~BaseSoundFilter();
-};
\ No newline at end of file
diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj
index b5f18f82..ceac124b 100644
--- a/Core/Core.vcxproj
+++ b/Core/Core.vcxproj
@@ -413,7 +413,6 @@
-
@@ -747,7 +746,6 @@
-
diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters
index fb21afb0..44989428 100644
--- a/Core/Core.vcxproj.filters
+++ b/Core/Core.vcxproj.filters
@@ -523,9 +523,6 @@
Nes\APU\Filters
-
- Nes\APU\Filters
-
Nes\Mappers\Taito
@@ -1236,9 +1233,6 @@
Nes\APU\Filters
-
- Nes\APU\Filters
-
Nes\APU\Filters
diff --git a/Core/EmulationSettings.cpp b/Core/EmulationSettings.cpp
index 980ec3f5..5a816b17 100644
--- a/Core/EmulationSettings.cpp
+++ b/Core/EmulationSettings.cpp
@@ -13,6 +13,7 @@ uint32_t EmulationSettings::_flags = 0;
uint32_t EmulationSettings::_audioLatency = 20000;
double EmulationSettings::_channelVolume[11] = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 };
+double EmulationSettings::_channelPanning[11] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
double EmulationSettings::_masterVolume = 1.0;
uint32_t EmulationSettings::_sampleRate = 44100;
StereoFilter EmulationSettings::_stereoFilter = StereoFilter::None;
diff --git a/Core/EmulationSettings.h b/Core/EmulationSettings.h
index de6ee1cc..174d9311 100644
--- a/Core/EmulationSettings.h
+++ b/Core/EmulationSettings.h
@@ -301,6 +301,7 @@ private:
static uint32_t _audioLatency;
static double _channelVolume[11];
+ static double _channelPanning[11];
static double _masterVolume;
static uint32_t _sampleRate;
static StereoFilter _stereoFilter;
@@ -429,6 +430,11 @@ public:
_masterVolume = volume;
}
+ static void SetChannelPanning(AudioChannel channel, double panning)
+ {
+ _channelPanning[(int)channel] = panning;
+ }
+
static void SetSampleRate(uint32_t sampleRate)
{
_sampleRate = sampleRate;
@@ -647,6 +653,11 @@ public:
return _masterVolume;
}
+ static double GetChannelPanning(AudioChannel channel)
+ {
+ return _channelPanning[(int)channel];
+ }
+
static uint32_t GetAudioLatency()
{
return _audioLatency;
diff --git a/Core/ReverbFilter.cpp b/Core/ReverbFilter.cpp
index eac69eee..da75fb44 100644
--- a/Core/ReverbFilter.cpp
+++ b/Core/ReverbFilter.cpp
@@ -8,24 +8,22 @@ void ReverbFilter::ResetFilter()
}
}
-int16_t* ReverbFilter::ApplyFilter(int16_t* monoBuffer, size_t sampleCount, uint32_t sampleRate, double reverbStrength, double reverbDelay)
+void ReverbFilter::ApplyFilter(int16_t* stereoBuffer, size_t sampleCount, uint32_t sampleRate, double reverbStrength, double reverbDelay)
{
- _delay[0].SetParameters(550 * reverbDelay, 0.25 * reverbStrength, sampleRate);
- _delay[1].SetParameters(330 * reverbDelay, 0.15 * reverbStrength, sampleRate);
- _delay[2].SetParameters(485 * reverbDelay, 0.12 * reverbStrength, sampleRate);
- _delay[3].SetParameters(150 * reverbDelay, 0.20 * reverbStrength, sampleRate);
- _delay[4].SetParameters(285 * reverbDelay, 0.05 * reverbStrength, sampleRate);
-
- UpdateBufferSize(sampleCount, false);
-
- memcpy(_filterBuffer, monoBuffer, sampleCount * sizeof(int16_t));
-
- for(int i = 0; i < 5; i++) {
- _delay[i].ApplyReverb(_filterBuffer, sampleCount);
- }
- for(int i = 0; i < 5; i++) {
- _delay[i].AddSamples(_filterBuffer, sampleCount);
+ for(int i = 0; i < 2; i++) {
+ _delay[i*5].SetParameters(550 * reverbDelay, 0.25 * reverbStrength, sampleRate);
+ _delay[i*5+1].SetParameters(330 * reverbDelay, 0.15 * reverbStrength, sampleRate);
+ _delay[i*5+2].SetParameters(485 * reverbDelay, 0.12 * reverbStrength, sampleRate);
+ _delay[i*5+3].SetParameters(150 * reverbDelay, 0.20 * reverbStrength, sampleRate);
+ _delay[i*5+4].SetParameters(285 * reverbDelay, 0.05 * reverbStrength, sampleRate);
}
- return _filterBuffer;
+ for(int i = 0; i < 5; i++) {
+ _delay[i].ApplyReverb(stereoBuffer, sampleCount);
+ _delay[i+5].ApplyReverb(stereoBuffer+1, sampleCount);
+ }
+ for(int i = 0; i < 5; i++) {
+ _delay[i].AddSamples(stereoBuffer, sampleCount);
+ _delay[i+5].AddSamples(stereoBuffer+1, sampleCount);
+ }
}
\ No newline at end of file
diff --git a/Core/ReverbFilter.h b/Core/ReverbFilter.h
index e4733b5c..c96f2187 100644
--- a/Core/ReverbFilter.h
+++ b/Core/ReverbFilter.h
@@ -1,6 +1,5 @@
#pragma once
#include "stdafx.h"
-#include "BaseSoundFilter.h"
#include
class ReverbDelay
@@ -29,7 +28,7 @@ public:
void AddSamples(int16_t* buffer, size_t sampleCount)
{
for(size_t i = 0; i < sampleCount; i++) {
- _samples.push_back(buffer[i]);
+ _samples.push_back(buffer[i*2]);
}
}
@@ -39,19 +38,19 @@ public:
size_t samplesToInsert = std::min(_samples.size() - _delay, sampleCount);
for(size_t j = sampleCount - samplesToInsert; j < sampleCount; j++) {
- buffer[j] += (int16_t)((double)_samples.front() * _decay);
+ buffer[j*2] += (int16_t)((double)_samples.front() * _decay);
_samples.pop_front();
}
}
}
};
-class ReverbFilter : public BaseSoundFilter
+class ReverbFilter
{
private:
- ReverbDelay _delay[5];
+ ReverbDelay _delay[10];
public:
void ResetFilter();
- int16_t* ApplyFilter(int16_t* monoBuffer, size_t sampleCount, uint32_t sampleRate, double reverbStrength, double reverbDelay);
+ void ApplyFilter(int16_t* stereoBuffer, size_t sampleCount, uint32_t sampleRate, double reverbStrength, double reverbDelay);
};
\ No newline at end of file
diff --git a/Core/SoundMixer.cpp b/Core/SoundMixer.cpp
index 7f3eb875..8eec4e61 100644
--- a/Core/SoundMixer.cpp
+++ b/Core/SoundMixer.cpp
@@ -2,7 +2,6 @@
#include "SoundMixer.h"
#include "APU.h"
#include "CPU.h"
-#include "CrossFeedFilter.h"
IAudioDevice* SoundMixer::AudioDevice = nullptr;
unique_ptr SoundMixer::_waveRecorder;
@@ -13,7 +12,8 @@ uint32_t SoundMixer::_muteFrameCount;
SoundMixer::SoundMixer()
{
_outputBuffer = new int16_t[SoundMixer::MaxSamplesPerFrame];
- _blipBuf = blip_new(SoundMixer::MaxSamplesPerFrame);
+ _blipBufLeft = blip_new(SoundMixer::MaxSamplesPerFrame);
+ _blipBufRight = blip_new(SoundMixer::MaxSamplesPerFrame);
_sampleRate = EmulationSettings::GetSampleRate();
_model = NesModel::NTSC;
@@ -25,7 +25,8 @@ SoundMixer::~SoundMixer()
delete[] _outputBuffer;
_outputBuffer = nullptr;
- blip_delete(_blipBuf);
+ blip_delete(_blipBufLeft);
+ blip_delete(_blipBufRight);
}
void SoundMixer::StreamState(bool saving)
@@ -38,7 +39,7 @@ void SoundMixer::StreamState(bool saving)
}
ArrayInfo currentOutput = { _currentOutput, MaxChannelCount };
- Stream(_previousOutput, currentOutput);
+ Stream(_previousOutputLeft, currentOutput, _previousOutputRight);
}
void SoundMixer::RegisterAudioDevice(IAudioDevice *audioDevice)
@@ -62,13 +63,16 @@ void SoundMixer::Reset()
_fadeRatio = 1.0;
_muteFrameCount = 0;
- _previousOutput = 0;
- blip_clear(_blipBuf);
+ _previousOutputLeft = 0;
+ _previousOutputRight = 0;
+ blip_clear(_blipBufLeft);
+ blip_clear(_blipBufRight);
_timestamps.clear();
for(int i = 0; i < MaxChannelCount; i++) {
- _volumes[0] = 0;
+ _volumes[i] = 0;
+ _panning[i] = 0;
}
memset(_channelOutput, 0, sizeof(_channelOutput));
memset(_currentOutput, 0, sizeof(_currentOutput));
@@ -77,7 +81,10 @@ void SoundMixer::Reset()
void SoundMixer::PlayAudioBuffer(uint32_t time)
{
EndFrame(time);
- size_t sampleCount = blip_read_samples(_blipBuf, _outputBuffer, SoundMixer::MaxSamplesPerFrame, 0);
+
+ size_t sampleCount = blip_read_samples(_blipBufLeft, _outputBuffer, SoundMixer::MaxSamplesPerFrame, 1);
+ blip_read_samples(_blipBufRight, _outputBuffer + 1, SoundMixer::MaxSamplesPerFrame, 1);
+
if(SoundMixer::AudioDevice && !EmulationSettings::IsPaused()) {
//Apply low pass filter/volume reduction when in background (based on options)
if(!_waveRecorder && !EmulationSettings::CheckFlag(EmulationFlags::NsfPlayerEnabled) && EmulationSettings::CheckFlag(EmulationFlags::InBackground)) {
@@ -88,36 +95,26 @@ void SoundMixer::PlayAudioBuffer(uint32_t time)
}
}
- int16_t* soundBuffer = _outputBuffer;
if(EmulationSettings::GetReverbStrength() > 0) {
- soundBuffer = _reverbFilter.ApplyFilter(soundBuffer, sampleCount, _sampleRate, EmulationSettings::GetReverbStrength(), EmulationSettings::GetReverbDelay());
+ _reverbFilter.ApplyFilter(_outputBuffer, sampleCount, _sampleRate, EmulationSettings::GetReverbStrength(), EmulationSettings::GetReverbDelay());
} else {
_reverbFilter.ResetFilter();
}
- bool isStereo = false;
switch(EmulationSettings::GetStereoFilter()) {
- case StereoFilter::Delay:
- soundBuffer = _stereoDelay.ApplyFilter(soundBuffer, sampleCount, _sampleRate);
- isStereo = true;
- break;
-
- case StereoFilter::Panning:
- soundBuffer = _stereoPanning.ApplyFilter(soundBuffer, sampleCount);
- isStereo = true;
- break;
+ case StereoFilter::Delay: _stereoDelay.ApplyFilter(_outputBuffer, sampleCount, _sampleRate); break;
+ case StereoFilter::Panning: _stereoPanning.ApplyFilter(_outputBuffer, sampleCount); break;
}
- if(isStereo && EmulationSettings::GetCrossFeedRatio() > 0) {
- CrossFeedFilter filter;
- filter.ApplyFilter(soundBuffer, sampleCount, EmulationSettings::GetCrossFeedRatio());
+ if(EmulationSettings::GetCrossFeedRatio() > 0) {
+ _crossFeedFilter.ApplyFilter(_outputBuffer, sampleCount, EmulationSettings::GetCrossFeedRatio());
}
- SoundMixer::AudioDevice->PlayBuffer(soundBuffer, (uint32_t)sampleCount, _sampleRate, isStereo);
+ SoundMixer::AudioDevice->PlayBuffer(_outputBuffer, (uint32_t)sampleCount, _sampleRate, true);
if(_waveRecorder) {
auto lock = _waveRecorderLock.AcquireSafe();
if(_waveRecorder) {
- if(!_waveRecorder->WriteSamples(soundBuffer, (uint32_t)sampleCount, _sampleRate, isStereo)) {
+ if(!_waveRecorder->WriteSamples(_outputBuffer, (uint32_t)sampleCount, _sampleRate, true)) {
_waveRecorder.reset();
}
}
@@ -147,30 +144,35 @@ void SoundMixer::UpdateRates(bool forceUpdate)
if(_clockRate != newRate || forceUpdate) {
_clockRate = newRate;
- blip_set_rates(_blipBuf, _clockRate, _sampleRate);
+ blip_set_rates(_blipBufLeft, _clockRate, _sampleRate);
+ blip_set_rates(_blipBufRight, _clockRate, _sampleRate);
}
}
-double SoundMixer::GetChannelOutput(AudioChannel channel)
+double SoundMixer::GetChannelOutput(AudioChannel channel, bool forRightChannel)
{
- return _currentOutput[(int)channel] * _volumes[(int)channel];
+ if(forRightChannel) {
+ return _currentOutput[(int)channel] * _volumes[(int)channel] * _panning[(int)channel];
+ } else {
+ return _currentOutput[(int)channel] * _volumes[(int)channel] * (1.0 - _panning[(int)channel]);
+ }
}
-int16_t SoundMixer::GetOutputVolume()
+int16_t SoundMixer::GetOutputVolume(bool forRightChannel)
{
- double squareOutput = GetChannelOutput(AudioChannel::Square1) + GetChannelOutput(AudioChannel::Square2);
- double tndOutput = 3 * GetChannelOutput(AudioChannel::Triangle) + 2 * GetChannelOutput(AudioChannel::Noise) + GetChannelOutput(AudioChannel::DMC);
+ double squareOutput = GetChannelOutput(AudioChannel::Square1, forRightChannel) + GetChannelOutput(AudioChannel::Square2, forRightChannel);
+ double tndOutput = 3 * GetChannelOutput(AudioChannel::Triangle, forRightChannel) + 2 * GetChannelOutput(AudioChannel::Noise, forRightChannel) + GetChannelOutput(AudioChannel::DMC, forRightChannel);
uint16_t squareVolume = (uint16_t)(95.52 / (8128.0 / squareOutput + 100.0) * 5000);
uint16_t tndVolume = (uint16_t)(163.67 / (24329.0 / tndOutput + 100.0) * 5000);
return (int16_t)(squareVolume + tndVolume +
- GetChannelOutput(AudioChannel::FDS) * 20 +
- GetChannelOutput(AudioChannel::MMC5) * 40 +
- GetChannelOutput(AudioChannel::Namco163) * 20 +
- GetChannelOutput(AudioChannel::Sunsoft5B) * 15 +
- GetChannelOutput(AudioChannel::VRC6) * 75 +
- GetChannelOutput(AudioChannel::VRC7));
+ GetChannelOutput(AudioChannel::FDS, forRightChannel) * 20 +
+ GetChannelOutput(AudioChannel::MMC5, forRightChannel) * 40 +
+ GetChannelOutput(AudioChannel::Namco163, forRightChannel) * 20 +
+ GetChannelOutput(AudioChannel::Sunsoft5B, forRightChannel) * 15 +
+ GetChannelOutput(AudioChannel::VRC6, forRightChannel) * 75 +
+ GetChannelOutput(AudioChannel::VRC7, forRightChannel));
}
void SoundMixer::AddDelta(AudioChannel channel, uint32_t time, int16_t delta)
@@ -188,7 +190,6 @@ void SoundMixer::EndFrame(uint32_t time)
_timestamps.erase(std::unique(_timestamps.begin(), _timestamps.end()), _timestamps.end());
bool muteFrame = true;
- int16_t originalOutput = _previousOutput;
for(size_t i = 0, len = _timestamps.size(); i < len; i++) {
uint32_t stamp = _timestamps[i];
for(int j = 0; j < MaxChannelCount; j++) {
@@ -200,13 +201,17 @@ void SoundMixer::EndFrame(uint32_t time)
_currentOutput[j] += _channelOutput[j][stamp];
}
- int16_t currentOutput = GetOutputVolume();
- blip_add_delta(_blipBuf, stamp, (int)((currentOutput - _previousOutput) * masterVolume * _fadeRatio));
+ int16_t currentOutput = GetOutputVolume(false);
+ blip_add_delta(_blipBufLeft, stamp, (int)((currentOutput - _previousOutputLeft) * masterVolume * _fadeRatio));
+ _previousOutputLeft = currentOutput;
- _previousOutput = currentOutput;
+ currentOutput = GetOutputVolume(true);
+ blip_add_delta(_blipBufRight, stamp, (int)((currentOutput - _previousOutputRight) * masterVolume * _fadeRatio));
+ _previousOutputRight = currentOutput;
}
- blip_end_frame(_blipBuf, time);
+ blip_end_frame(_blipBufLeft, time);
+ blip_end_frame(_blipBufRight, time);
if(muteFrame) {
_muteFrameCount++;
@@ -217,6 +222,7 @@ void SoundMixer::EndFrame(uint32_t time)
//Reset everything
for(int i = 0; i < MaxChannelCount; i++) {
_volumes[i] = EmulationSettings::GetChannelVolume((AudioChannel)i);
+ _panning[i] = EmulationSettings::GetChannelPanning((AudioChannel)i);
}
_timestamps.clear();
@@ -226,7 +232,7 @@ void SoundMixer::EndFrame(uint32_t time)
void SoundMixer::StartRecording(string filepath)
{
auto lock = _waveRecorderLock.AcquireSafe();
- _waveRecorder.reset(new WaveRecorder(filepath, EmulationSettings::GetSampleRate(), EmulationSettings::GetStereoFilter() != StereoFilter::None));
+ _waveRecorder.reset(new WaveRecorder(filepath, EmulationSettings::GetSampleRate(), true));
}
void SoundMixer::StopRecording()
diff --git a/Core/SoundMixer.h b/Core/SoundMixer.h
index 13885ffd..26d61eb6 100644
--- a/Core/SoundMixer.h
+++ b/Core/SoundMixer.h
@@ -9,6 +9,7 @@
#include "StereoPanningFilter.h"
#include "StereoDelayFilter.h"
#include "ReverbFilter.h"
+#include "CrossFeedFilter.h"
#include "WaveRecorder.h"
class SoundMixer : public Snapshotable
@@ -25,30 +26,34 @@ private:
static IAudioDevice* AudioDevice;
static const uint32_t MaxSampleRate = 48000;
- static const uint32_t MaxSamplesPerFrame = MaxSampleRate / 60 * 4; //x4 to allow CPU overclocking up to 10x
+ static const uint32_t MaxSamplesPerFrame = MaxSampleRate / 60 * 4 * 2; //x4 to allow CPU overclocking up to 10x, x2 for panning stereo
static const uint32_t MaxChannelCount = 11;
+ CrossFeedFilter _crossFeedFilter;
LowPassFilter _lowPassFilter;
StereoPanningFilter _stereoPanning;
StereoDelayFilter _stereoDelay;
ReverbFilter _reverbFilter;
- int16_t _previousOutput = 0;
+ int16_t _previousOutputLeft = 0;
+ int16_t _previousOutputRight = 0;
vector _timestamps;
int16_t _channelOutput[MaxChannelCount][CycleLength];
int16_t _currentOutput[MaxChannelCount];
- blip_t* _blipBuf;
+ blip_t* _blipBufLeft;
+ blip_t* _blipBufRight;
int16_t *_outputBuffer;
double _volumes[MaxChannelCount];
+ double _panning[MaxChannelCount];
NesModel _model;
uint32_t _sampleRate;
uint32_t _clockRate;
- double GetChannelOutput(AudioChannel channel);
- int16_t GetOutputVolume();
+ double GetChannelOutput(AudioChannel channel, bool forRightChannel);
+ int16_t GetOutputVolume(bool forRightChannel);
void EndFrame(uint32_t time);
void UpdateRates(bool forceUpdate);
diff --git a/Core/StereoDelayFilter.cpp b/Core/StereoDelayFilter.cpp
index 9bb0f1ac..21b6d896 100644
--- a/Core/StereoDelayFilter.cpp
+++ b/Core/StereoDelayFilter.cpp
@@ -1,33 +1,28 @@
#include "stdafx.h"
#include "StereoDelayFilter.h"
-int16_t* StereoDelayFilter::ApplyFilter(int16_t* monoBuffer, size_t sampleCount, uint32_t sampleRate)
+void StereoDelayFilter::ApplyFilter(int16_t* stereoBuffer, size_t sampleCount, uint32_t sampleRate)
{
- UpdateBufferSize(sampleCount, true);
-
size_t delaySampleCount = (int32_t)((double)EmulationSettings::GetStereoDelay() / 1000 * sampleRate);
if(delaySampleCount != _lastDelay) {
- _delayedSamples.clear();
+ _delayedSamplesLeft.clear();
+ _delayedSamplesRight.clear();
}
_lastDelay = delaySampleCount;
- for(size_t i = 0; i < sampleCount; i++) {
- _delayedSamples.push_back(monoBuffer[i]);
+ for(size_t i = 0; i < sampleCount * 2; i+=2) {
+ _delayedSamplesLeft.push_back(stereoBuffer[i]);
+ _delayedSamplesRight.push_back(stereoBuffer[i+1]);
}
- for(size_t i = 0; i < sampleCount; i++) {
- _filterBuffer[i * 2] = monoBuffer[i];
- _filterBuffer[i * 2 + 1] = 0;
- }
-
- if(_delayedSamples.size() > delaySampleCount) {
- size_t samplesToInsert = std::max(_delayedSamples.size() - delaySampleCount, sampleCount);
+ if(_delayedSamplesLeft.size() > delaySampleCount) {
+ size_t samplesToInsert = std::max(_delayedSamplesLeft.size() - delaySampleCount, sampleCount);
for(size_t i = sampleCount - samplesToInsert; i < sampleCount; i++) {
- _filterBuffer[i * 2 + 1] = _delayedSamples.front();
- _delayedSamples.pop_front();
+ stereoBuffer[i*2] = (stereoBuffer[i*2] + stereoBuffer[i*2+1]) / 2;
+ stereoBuffer[i*2+1] = (_delayedSamplesRight.front() + _delayedSamplesLeft.front()) / 2;
+ _delayedSamplesLeft.pop_front();
+ _delayedSamplesRight.pop_front();
}
}
-
- return _filterBuffer;
}
diff --git a/Core/StereoDelayFilter.h b/Core/StereoDelayFilter.h
index cf47a51e..51275693 100644
--- a/Core/StereoDelayFilter.h
+++ b/Core/StereoDelayFilter.h
@@ -3,14 +3,14 @@
#include
#include
#include "EmulationSettings.h"
-#include "BaseSoundFilter.h"
-class StereoDelayFilter : public BaseSoundFilter
+class StereoDelayFilter
{
private:
- std::deque _delayedSamples;
+ std::deque _delayedSamplesLeft;
+ std::deque _delayedSamplesRight;
size_t _lastDelay = 0;
public:
- int16_t* ApplyFilter(int16_t* monoBuffer, size_t sampleCount, uint32_t sampleRate);
+ void ApplyFilter(int16_t* stereoBuffer, size_t sampleCount, uint32_t sampleRate);
};
\ No newline at end of file
diff --git a/Core/StereoPanningFilter.cpp b/Core/StereoPanningFilter.cpp
index 4f696a52..fa130715 100644
--- a/Core/StereoPanningFilter.cpp
+++ b/Core/StereoPanningFilter.cpp
@@ -10,15 +10,14 @@ void StereoPanningFilter::UpdateFactors()
_rightChannelFactor = _baseFactor * (std::cos(angle) + std::sin(angle));
}
-int16_t* StereoPanningFilter::ApplyFilter(int16_t* monoBuffer, size_t sampleCount)
+void StereoPanningFilter::ApplyFilter(int16_t* stereoBuffer, size_t sampleCount)
{
UpdateFactors();
- UpdateBufferSize(sampleCount, true);
- for(size_t i = 0; i < sampleCount; i++) {
- _filterBuffer[i * 2] = (int16_t)(_leftChannelFactor * (double)monoBuffer[i]);
- _filterBuffer[i * 2 + 1] = (int16_t)(_rightChannelFactor * (double)monoBuffer[i]);
+ for(size_t i = 0; i < sampleCount * 2; i+=2) {
+ int16_t leftSample = stereoBuffer[i];
+ int16_t rightSample = stereoBuffer[i+1];
+ stereoBuffer[i] = (int16_t)((_leftChannelFactor * leftSample + _leftChannelFactor * rightSample) / 2);
+ stereoBuffer[i+1] = (int16_t)((_rightChannelFactor * rightSample + _rightChannelFactor * leftSample) / 2);
}
-
- return _filterBuffer;
}
\ No newline at end of file
diff --git a/Core/StereoPanningFilter.h b/Core/StereoPanningFilter.h
index fe018726..f6923cd7 100644
--- a/Core/StereoPanningFilter.h
+++ b/Core/StereoPanningFilter.h
@@ -1,8 +1,7 @@
#pragma once
#include "stdafx.h"
-#include "BaseSoundFilter.h"
-class StereoPanningFilter : public BaseSoundFilter
+class StereoPanningFilter
{
private:
const double _baseFactor = 0.70710678118654752440084436210485; // == sqrt(2)/2
@@ -12,5 +11,5 @@ private:
void UpdateFactors();
public:
- int16_t* ApplyFilter(int16_t* monoBuffer, size_t sampleCount);
+ void ApplyFilter(int16_t* stereoBuffer, size_t sampleCount);
};
\ No newline at end of file
diff --git a/GUI.NET/Config/AudioInfo.cs b/GUI.NET/Config/AudioInfo.cs
index 726aead2..afb83639 100644
--- a/GUI.NET/Config/AudioInfo.cs
+++ b/GUI.NET/Config/AudioInfo.cs
@@ -26,6 +26,19 @@ namespace Mesen.GUI.Config
public UInt32 Vrc7Volume = 100;
public UInt32 Namco163Volume = 100;
public UInt32 Sunsoft5bVolume = 100;
+
+ public Int32 Square1Panning = 0;
+ public Int32 Square2Panning = 0;
+ public Int32 TrianglePanning = 0;
+ public Int32 NoisePanning = 0;
+ public Int32 DmcPanning = 0;
+ public Int32 FdsPanning = 0;
+ public Int32 Mmc5Panning = 0;
+ public Int32 Vrc6Panning = 0;
+ public Int32 Vrc7Panning = 0;
+ public Int32 Namco163Panning = 0;
+ public Int32 Sunsoft5bPanning = 0;
+
public UInt32 SampleRate = 44100;
public bool ReduceSoundInBackground = true;
public bool MuteSoundInBackground = false;
@@ -54,6 +67,11 @@ namespace Mesen.GUI.Config
}
}
+ static private double ConvertPanning(Int32 panning)
+ {
+ return (double)((panning + 100) / 200d);
+ }
+
static public void ApplyConfig()
{
AudioInfo audioInfo = ConfigManager.Config.AudioInfo;
@@ -71,6 +89,19 @@ namespace Mesen.GUI.Config
InteropEmu.SetChannelVolume(AudioChannel.VRC7, ConvertVolume(audioInfo.Vrc7Volume));
InteropEmu.SetChannelVolume(AudioChannel.Namco163, ConvertVolume(audioInfo.Namco163Volume));
InteropEmu.SetChannelVolume(AudioChannel.Sunsoft5B, ConvertVolume(audioInfo.Sunsoft5bVolume));
+
+ InteropEmu.SetChannelPanning(AudioChannel.Square1, ConvertPanning(audioInfo.Square1Panning));
+ InteropEmu.SetChannelPanning(AudioChannel.Square2, ConvertPanning(audioInfo.Square2Panning));
+ InteropEmu.SetChannelPanning(AudioChannel.Triangle, ConvertPanning(audioInfo.TrianglePanning));
+ InteropEmu.SetChannelPanning(AudioChannel.Noise, ConvertPanning(audioInfo.NoisePanning));
+ InteropEmu.SetChannelPanning(AudioChannel.DMC, ConvertPanning(audioInfo.DmcPanning));
+ InteropEmu.SetChannelPanning(AudioChannel.FDS, ConvertPanning(audioInfo.FdsPanning));
+ InteropEmu.SetChannelPanning(AudioChannel.MMC5, ConvertPanning(audioInfo.Mmc5Panning));
+ InteropEmu.SetChannelPanning(AudioChannel.VRC6, ConvertPanning(audioInfo.Vrc6Panning));
+ InteropEmu.SetChannelPanning(AudioChannel.VRC7, ConvertPanning(audioInfo.Vrc7Panning));
+ InteropEmu.SetChannelPanning(AudioChannel.Namco163, ConvertPanning(audioInfo.Namco163Panning));
+ InteropEmu.SetChannelPanning(AudioChannel.Sunsoft5B, ConvertPanning(audioInfo.Sunsoft5bPanning));
+
InteropEmu.SetSampleRate(audioInfo.SampleRate);
InteropEmu.SetFlag(EmulationFlags.MuteSoundInBackground, audioInfo.MuteSoundInBackground);
diff --git a/GUI.NET/Controls/ctrlHorizontalTrackbar.cs b/GUI.NET/Controls/ctrlHorizontalTrackbar.cs
index 62389074..723e188c 100644
--- a/GUI.NET/Controls/ctrlHorizontalTrackbar.cs
+++ b/GUI.NET/Controls/ctrlHorizontalTrackbar.cs
@@ -50,7 +50,7 @@ namespace Mesen.GUI.Controls
get { return trackBar.Value; }
set
{
- trackBar.Value = value;
+ trackBar.Value = Math.Max(trackBar.Minimum, Math.Min(value, trackBar.Maximum));
txtValue.Text = trackBar.Value.ToString();
}
}
diff --git a/GUI.NET/Forms/Config/frmAudioConfig.Designer.cs b/GUI.NET/Forms/Config/frmAudioConfig.Designer.cs
index 6a2e2dc7..4e91502e 100644
--- a/GUI.NET/Forms/Config/frmAudioConfig.Designer.cs
+++ b/GUI.NET/Forms/Config/frmAudioConfig.Designer.cs
@@ -59,6 +59,18 @@
this.tabMain = new System.Windows.Forms.TabControl();
this.tpgGeneral = new System.Windows.Forms.TabPage();
this.tpgVolume = new System.Windows.Forms.TabPage();
+ this.tpgPanning = new System.Windows.Forms.TabPage();
+ this.tableLayoutPanel6 = new System.Windows.Forms.TableLayoutPanel();
+ this.trkDmcPan = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
+ this.trkNoisePan = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
+ this.trkVrc6Pan = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
+ this.trkVrc7Pan = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
+ this.trkNamcoPan = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
+ this.trkSunsoftPan = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
+ this.trkSquare1Pan = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
+ this.trkFdsPan = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
+ this.trkSquare2Pan = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
+ this.trkMmc5Pan = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
this.tpgEffects = new System.Windows.Forms.TabPage();
this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel();
this.grpStereo = new System.Windows.Forms.GroupBox();
@@ -72,10 +84,6 @@
this.flowLayoutPanel4 = new System.Windows.Forms.FlowLayoutPanel();
this.nudStereoPanning = new System.Windows.Forms.NumericUpDown();
this.lblStereoPanningAngle = new System.Windows.Forms.Label();
- this.flowLayoutPanel5 = new System.Windows.Forms.FlowLayoutPanel();
- this.chkCrossFeedEnabled = new System.Windows.Forms.CheckBox();
- this.nudCrossFeedRatio = new System.Windows.Forms.NumericUpDown();
- this.lblCrossFeedRatio = new System.Windows.Forms.Label();
this.grpReverb = new System.Windows.Forms.GroupBox();
this.tableLayoutPanel5 = new System.Windows.Forms.TableLayoutPanel();
this.chkReverbEnabled = new System.Windows.Forms.CheckBox();
@@ -83,11 +91,16 @@
this.lblReverbDelay = new System.Windows.Forms.Label();
this.trkReverbDelay = new System.Windows.Forms.TrackBar();
this.trkReverbStrength = new System.Windows.Forms.TrackBar();
+ this.flowLayoutPanel5 = new System.Windows.Forms.FlowLayoutPanel();
+ this.chkCrossFeedEnabled = new System.Windows.Forms.CheckBox();
+ this.nudCrossFeedRatio = new System.Windows.Forms.NumericUpDown();
+ this.lblCrossFeedRatio = new System.Windows.Forms.Label();
this.tpgAdvanced = new System.Windows.Forms.TabPage();
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
this.chkSilenceTriangleHighFreq = new System.Windows.Forms.CheckBox();
this.chkSwapDutyCycles = new System.Windows.Forms.CheckBox();
this.chkReduceDmcPopping = new System.Windows.Forms.CheckBox();
+ this.trkTrianglePan = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
this.baseConfigPanel.SuspendLayout();
this.grpVolume.SuspendLayout();
this.tableLayoutPanel1.SuspendLayout();
@@ -98,6 +111,8 @@
this.tabMain.SuspendLayout();
this.tpgGeneral.SuspendLayout();
this.tpgVolume.SuspendLayout();
+ this.tpgPanning.SuspendLayout();
+ this.tableLayoutPanel6.SuspendLayout();
this.tpgEffects.SuspendLayout();
this.tableLayoutPanel4.SuspendLayout();
this.grpStereo.SuspendLayout();
@@ -106,12 +121,12 @@
((System.ComponentModel.ISupportInitialize)(this.nudStereoDelay)).BeginInit();
this.flowLayoutPanel4.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.nudStereoPanning)).BeginInit();
- this.flowLayoutPanel5.SuspendLayout();
- ((System.ComponentModel.ISupportInitialize)(this.nudCrossFeedRatio)).BeginInit();
this.grpReverb.SuspendLayout();
this.tableLayoutPanel5.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.trkReverbDelay)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.trkReverbStrength)).BeginInit();
+ this.flowLayoutPanel5.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.nudCrossFeedRatio)).BeginInit();
this.tpgAdvanced.SuspendLayout();
this.tableLayoutPanel3.SuspendLayout();
this.SuspendLayout();
@@ -119,8 +134,8 @@
// baseConfigPanel
//
this.baseConfigPanel.Controls.Add(this.btnReset);
- this.baseConfigPanel.Location = new System.Drawing.Point(0, 375);
- this.baseConfigPanel.Size = new System.Drawing.Size(477, 29);
+ this.baseConfigPanel.Location = new System.Drawing.Point(0, 376);
+ this.baseConfigPanel.Size = new System.Drawing.Size(474, 29);
this.baseConfigPanel.Controls.SetChildIndex(this.btnReset, 0);
//
// grpVolume
@@ -358,7 +373,7 @@
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
- this.tableLayoutPanel2.Size = new System.Drawing.Size(463, 343);
+ this.tableLayoutPanel2.Size = new System.Drawing.Size(460, 344);
this.tableLayoutPanel2.TabIndex = 3;
//
// chkMuteSoundInBackground
@@ -532,13 +547,14 @@
//
this.tabMain.Controls.Add(this.tpgGeneral);
this.tabMain.Controls.Add(this.tpgVolume);
+ this.tabMain.Controls.Add(this.tpgPanning);
this.tabMain.Controls.Add(this.tpgEffects);
this.tabMain.Controls.Add(this.tpgAdvanced);
this.tabMain.Dock = System.Windows.Forms.DockStyle.Fill;
this.tabMain.Location = new System.Drawing.Point(0, 0);
this.tabMain.Name = "tabMain";
this.tabMain.SelectedIndex = 0;
- this.tabMain.Size = new System.Drawing.Size(477, 375);
+ this.tabMain.Size = new System.Drawing.Size(474, 376);
this.tabMain.TabIndex = 4;
//
// tpgGeneral
@@ -547,7 +563,7 @@
this.tpgGeneral.Location = new System.Drawing.Point(4, 22);
this.tpgGeneral.Name = "tpgGeneral";
this.tpgGeneral.Padding = new System.Windows.Forms.Padding(3);
- this.tpgGeneral.Size = new System.Drawing.Size(469, 349);
+ this.tpgGeneral.Size = new System.Drawing.Size(466, 350);
this.tpgGeneral.TabIndex = 0;
this.tpgGeneral.Text = "General";
this.tpgGeneral.UseVisualStyleBackColor = true;
@@ -558,18 +574,210 @@
this.tpgVolume.Location = new System.Drawing.Point(4, 22);
this.tpgVolume.Name = "tpgVolume";
this.tpgVolume.Padding = new System.Windows.Forms.Padding(3);
- this.tpgVolume.Size = new System.Drawing.Size(469, 349);
+ this.tpgVolume.Size = new System.Drawing.Size(466, 350);
this.tpgVolume.TabIndex = 1;
this.tpgVolume.Text = "Volume";
this.tpgVolume.UseVisualStyleBackColor = true;
//
+ // tpgPanning
+ //
+ this.tpgPanning.Controls.Add(this.tableLayoutPanel6);
+ this.tpgPanning.Location = new System.Drawing.Point(4, 22);
+ this.tpgPanning.Name = "tpgPanning";
+ this.tpgPanning.Padding = new System.Windows.Forms.Padding(3);
+ this.tpgPanning.Size = new System.Drawing.Size(466, 350);
+ this.tpgPanning.TabIndex = 4;
+ this.tpgPanning.Text = "Panning";
+ this.tpgPanning.UseVisualStyleBackColor = true;
+ //
+ // tableLayoutPanel6
+ //
+ this.tableLayoutPanel6.ColumnCount = 2;
+ this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
+ this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
+ this.tableLayoutPanel6.Controls.Add(this.trkSquare1Pan, 0, 0);
+ this.tableLayoutPanel6.Controls.Add(this.trkFdsPan, 1, 0);
+ this.tableLayoutPanel6.Controls.Add(this.trkSquare2Pan, 0, 1);
+ this.tableLayoutPanel6.Controls.Add(this.trkMmc5Pan, 1, 1);
+ this.tableLayoutPanel6.Controls.Add(this.trkTrianglePan, 0, 2);
+ this.tableLayoutPanel6.Controls.Add(this.trkNoisePan, 0, 3);
+ this.tableLayoutPanel6.Controls.Add(this.trkDmcPan, 0, 4);
+ this.tableLayoutPanel6.Controls.Add(this.trkVrc6Pan, 1, 2);
+ this.tableLayoutPanel6.Controls.Add(this.trkVrc7Pan, 1, 3);
+ this.tableLayoutPanel6.Controls.Add(this.trkNamcoPan, 1, 4);
+ this.tableLayoutPanel6.Controls.Add(this.trkSunsoftPan, 1, 5);
+ this.tableLayoutPanel6.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.tableLayoutPanel6.Location = new System.Drawing.Point(3, 3);
+ this.tableLayoutPanel6.Name = "tableLayoutPanel6";
+ this.tableLayoutPanel6.RowCount = 7;
+ this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+ this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+ this.tableLayoutPanel6.Size = new System.Drawing.Size(460, 344);
+ this.tableLayoutPanel6.TabIndex = 3;
+ //
+ // trkDmcPan
+ //
+ this.trkDmcPan.Anchor = System.Windows.Forms.AnchorStyles.Top;
+ this.trkDmcPan.Location = new System.Drawing.Point(12, 220);
+ this.trkDmcPan.Margin = new System.Windows.Forms.Padding(0);
+ this.trkDmcPan.Maximum = 100;
+ this.trkDmcPan.MaximumSize = new System.Drawing.Size(63, 160);
+ this.trkDmcPan.Minimum = -100;
+ this.trkDmcPan.MinimumSize = new System.Drawing.Size(206, 55);
+ this.trkDmcPan.Name = "trkDmcPan";
+ this.trkDmcPan.Size = new System.Drawing.Size(206, 55);
+ this.trkDmcPan.TabIndex = 16;
+ this.trkDmcPan.Text = "DMC";
+ this.trkDmcPan.Value = 0;
+ //
+ // trkNoisePan
+ //
+ this.trkNoisePan.Anchor = System.Windows.Forms.AnchorStyles.Top;
+ this.trkNoisePan.Location = new System.Drawing.Point(12, 165);
+ this.trkNoisePan.Margin = new System.Windows.Forms.Padding(0);
+ this.trkNoisePan.Maximum = 100;
+ this.trkNoisePan.MaximumSize = new System.Drawing.Size(63, 160);
+ this.trkNoisePan.Minimum = -100;
+ this.trkNoisePan.MinimumSize = new System.Drawing.Size(206, 55);
+ this.trkNoisePan.Name = "trkNoisePan";
+ this.trkNoisePan.Size = new System.Drawing.Size(206, 55);
+ this.trkNoisePan.TabIndex = 15;
+ this.trkNoisePan.Text = "Noise";
+ this.trkNoisePan.Value = 0;
+ //
+ // trkVrc6Pan
+ //
+ this.trkVrc6Pan.Anchor = System.Windows.Forms.AnchorStyles.Top;
+ this.trkVrc6Pan.Location = new System.Drawing.Point(242, 110);
+ this.trkVrc6Pan.Margin = new System.Windows.Forms.Padding(0);
+ this.trkVrc6Pan.Maximum = 100;
+ this.trkVrc6Pan.MaximumSize = new System.Drawing.Size(63, 160);
+ this.trkVrc6Pan.Minimum = -100;
+ this.trkVrc6Pan.MinimumSize = new System.Drawing.Size(206, 55);
+ this.trkVrc6Pan.Name = "trkVrc6Pan";
+ this.trkVrc6Pan.Size = new System.Drawing.Size(206, 55);
+ this.trkVrc6Pan.TabIndex = 19;
+ this.trkVrc6Pan.Text = "VRC6";
+ this.trkVrc6Pan.Value = 0;
+ //
+ // trkVrc7Pan
+ //
+ this.trkVrc7Pan.Anchor = System.Windows.Forms.AnchorStyles.Top;
+ this.trkVrc7Pan.Location = new System.Drawing.Point(242, 165);
+ this.trkVrc7Pan.Margin = new System.Windows.Forms.Padding(0);
+ this.trkVrc7Pan.Maximum = 100;
+ this.trkVrc7Pan.MaximumSize = new System.Drawing.Size(63, 160);
+ this.trkVrc7Pan.Minimum = -100;
+ this.trkVrc7Pan.MinimumSize = new System.Drawing.Size(206, 55);
+ this.trkVrc7Pan.Name = "trkVrc7Pan";
+ this.trkVrc7Pan.Size = new System.Drawing.Size(206, 55);
+ this.trkVrc7Pan.TabIndex = 20;
+ this.trkVrc7Pan.Text = "VRC7";
+ this.trkVrc7Pan.Value = 0;
+ //
+ // trkNamcoPan
+ //
+ this.trkNamcoPan.Anchor = System.Windows.Forms.AnchorStyles.Top;
+ this.trkNamcoPan.Location = new System.Drawing.Point(242, 220);
+ this.trkNamcoPan.Margin = new System.Windows.Forms.Padding(0);
+ this.trkNamcoPan.Maximum = 100;
+ this.trkNamcoPan.MaximumSize = new System.Drawing.Size(63, 160);
+ this.trkNamcoPan.Minimum = -100;
+ this.trkNamcoPan.MinimumSize = new System.Drawing.Size(206, 55);
+ this.trkNamcoPan.Name = "trkNamcoPan";
+ this.trkNamcoPan.Size = new System.Drawing.Size(206, 55);
+ this.trkNamcoPan.TabIndex = 21;
+ this.trkNamcoPan.Text = "Namco";
+ this.trkNamcoPan.Value = 0;
+ //
+ // trkSunsoftPan
+ //
+ this.trkSunsoftPan.Anchor = System.Windows.Forms.AnchorStyles.Top;
+ this.trkSunsoftPan.Location = new System.Drawing.Point(242, 275);
+ this.trkSunsoftPan.Margin = new System.Windows.Forms.Padding(0);
+ this.trkSunsoftPan.Maximum = 100;
+ this.trkSunsoftPan.MaximumSize = new System.Drawing.Size(63, 160);
+ this.trkSunsoftPan.Minimum = -100;
+ this.trkSunsoftPan.MinimumSize = new System.Drawing.Size(206, 55);
+ this.trkSunsoftPan.Name = "trkSunsoftPan";
+ this.trkSunsoftPan.Size = new System.Drawing.Size(206, 55);
+ this.trkSunsoftPan.TabIndex = 22;
+ this.trkSunsoftPan.Text = "Sunsoft";
+ this.trkSunsoftPan.Value = 0;
+ //
+ // trkSquare1Pan
+ //
+ this.trkSquare1Pan.Anchor = System.Windows.Forms.AnchorStyles.Top;
+ this.trkSquare1Pan.Location = new System.Drawing.Point(12, 0);
+ this.trkSquare1Pan.Margin = new System.Windows.Forms.Padding(0);
+ this.trkSquare1Pan.Maximum = 100;
+ this.trkSquare1Pan.MaximumSize = new System.Drawing.Size(63, 160);
+ this.trkSquare1Pan.Minimum = -100;
+ this.trkSquare1Pan.MinimumSize = new System.Drawing.Size(206, 55);
+ this.trkSquare1Pan.Name = "trkSquare1Pan";
+ this.trkSquare1Pan.Size = new System.Drawing.Size(206, 55);
+ this.trkSquare1Pan.TabIndex = 12;
+ this.trkSquare1Pan.Text = "Square 1";
+ this.trkSquare1Pan.Value = 0;
+ //
+ // trkFdsPan
+ //
+ this.trkFdsPan.Anchor = System.Windows.Forms.AnchorStyles.Top;
+ this.trkFdsPan.Location = new System.Drawing.Point(242, 0);
+ this.trkFdsPan.Margin = new System.Windows.Forms.Padding(0);
+ this.trkFdsPan.Maximum = 100;
+ this.trkFdsPan.MaximumSize = new System.Drawing.Size(63, 160);
+ this.trkFdsPan.Minimum = -100;
+ this.trkFdsPan.MinimumSize = new System.Drawing.Size(206, 55);
+ this.trkFdsPan.Name = "trkFdsPan";
+ this.trkFdsPan.Size = new System.Drawing.Size(206, 55);
+ this.trkFdsPan.TabIndex = 17;
+ this.trkFdsPan.Text = "FDS";
+ this.trkFdsPan.Value = 0;
+ //
+ // trkSquare2Pan
+ //
+ this.trkSquare2Pan.Anchor = System.Windows.Forms.AnchorStyles.Top;
+ this.trkSquare2Pan.Location = new System.Drawing.Point(12, 55);
+ this.trkSquare2Pan.Margin = new System.Windows.Forms.Padding(0);
+ this.trkSquare2Pan.Maximum = 100;
+ this.trkSquare2Pan.MaximumSize = new System.Drawing.Size(63, 160);
+ this.trkSquare2Pan.Minimum = -100;
+ this.trkSquare2Pan.MinimumSize = new System.Drawing.Size(206, 55);
+ this.trkSquare2Pan.Name = "trkSquare2Pan";
+ this.trkSquare2Pan.Size = new System.Drawing.Size(206, 55);
+ this.trkSquare2Pan.TabIndex = 13;
+ this.trkSquare2Pan.Text = "Square 2";
+ this.trkSquare2Pan.Value = 0;
+ //
+ // trkMmc5Pan
+ //
+ this.trkMmc5Pan.Anchor = System.Windows.Forms.AnchorStyles.Top;
+ this.trkMmc5Pan.Location = new System.Drawing.Point(242, 55);
+ this.trkMmc5Pan.Margin = new System.Windows.Forms.Padding(0);
+ this.trkMmc5Pan.Maximum = 100;
+ this.trkMmc5Pan.MaximumSize = new System.Drawing.Size(63, 160);
+ this.trkMmc5Pan.Minimum = -100;
+ this.trkMmc5Pan.MinimumSize = new System.Drawing.Size(206, 55);
+ this.trkMmc5Pan.Name = "trkMmc5Pan";
+ this.trkMmc5Pan.Size = new System.Drawing.Size(206, 55);
+ this.trkMmc5Pan.TabIndex = 18;
+ this.trkMmc5Pan.Text = "MMC5";
+ this.trkMmc5Pan.Value = 0;
+ //
// tpgEffects
//
this.tpgEffects.Controls.Add(this.tableLayoutPanel4);
this.tpgEffects.Location = new System.Drawing.Point(4, 22);
this.tpgEffects.Name = "tpgEffects";
this.tpgEffects.Padding = new System.Windows.Forms.Padding(3);
- this.tpgEffects.Size = new System.Drawing.Size(469, 349);
+ this.tpgEffects.Size = new System.Drawing.Size(466, 350);
this.tpgEffects.TabIndex = 3;
this.tpgEffects.Text = "Effects";
this.tpgEffects.UseVisualStyleBackColor = true;
@@ -580,14 +788,16 @@
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel4.Controls.Add(this.grpStereo, 0, 0);
this.tableLayoutPanel4.Controls.Add(this.grpReverb, 0, 1);
+ this.tableLayoutPanel4.Controls.Add(this.flowLayoutPanel5, 0, 2);
this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel4.Location = new System.Drawing.Point(3, 3);
this.tableLayoutPanel4.Name = "tableLayoutPanel4";
- this.tableLayoutPanel4.RowCount = 3;
+ this.tableLayoutPanel4.RowCount = 4;
+ this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
- this.tableLayoutPanel4.Size = new System.Drawing.Size(463, 343);
+ this.tableLayoutPanel4.Size = new System.Drawing.Size(460, 344);
this.tableLayoutPanel4.TabIndex = 0;
//
// grpStereo
@@ -596,7 +806,7 @@
this.grpStereo.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpStereo.Location = new System.Drawing.Point(3, 3);
this.grpStereo.Name = "grpStereo";
- this.grpStereo.Size = new System.Drawing.Size(457, 130);
+ this.grpStereo.Size = new System.Drawing.Size(454, 95);
this.grpStereo.TabIndex = 0;
this.grpStereo.TabStop = false;
this.grpStereo.Text = "Stereo";
@@ -611,18 +821,17 @@
this.tlpStereoFilter.Controls.Add(this.radStereoDelay, 0, 1);
this.tlpStereoFilter.Controls.Add(this.radStereoPanning, 0, 2);
this.tlpStereoFilter.Controls.Add(this.flowLayoutPanel4, 1, 2);
- this.tlpStereoFilter.Controls.Add(this.flowLayoutPanel5, 0, 4);
this.tlpStereoFilter.Dock = System.Windows.Forms.DockStyle.Fill;
this.tlpStereoFilter.Location = new System.Drawing.Point(3, 16);
this.tlpStereoFilter.Name = "tlpStereoFilter";
- this.tlpStereoFilter.RowCount = 6;
+ this.tlpStereoFilter.RowCount = 4;
this.tlpStereoFilter.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpStereoFilter.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpStereoFilter.RowStyles.Add(new System.Windows.Forms.RowStyle());
- this.tlpStereoFilter.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 10F));
- this.tlpStereoFilter.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpStereoFilter.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
- this.tlpStereoFilter.Size = new System.Drawing.Size(451, 111);
+ this.tlpStereoFilter.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+ this.tlpStereoFilter.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+ this.tlpStereoFilter.Size = new System.Drawing.Size(448, 76);
this.tlpStereoFilter.TabIndex = 0;
//
// flowLayoutPanel3
@@ -633,7 +842,7 @@
this.flowLayoutPanel3.Location = new System.Drawing.Point(72, 23);
this.flowLayoutPanel3.Margin = new System.Windows.Forms.Padding(0);
this.flowLayoutPanel3.Name = "flowLayoutPanel3";
- this.flowLayoutPanel3.Size = new System.Drawing.Size(379, 26);
+ this.flowLayoutPanel3.Size = new System.Drawing.Size(376, 26);
this.flowLayoutPanel3.TabIndex = 1;
//
// nudStereoDelay
@@ -665,7 +874,6 @@
this.radStereoDisabled.Tag = "None";
this.radStereoDisabled.Text = "Disabled";
this.radStereoDisabled.UseVisualStyleBackColor = true;
- this.radStereoDisabled.CheckedChanged += new System.EventHandler(this.radStereoDisabled_CheckedChanged);
//
// radStereoDelay
//
@@ -699,7 +907,7 @@
this.flowLayoutPanel4.Location = new System.Drawing.Point(72, 49);
this.flowLayoutPanel4.Margin = new System.Windows.Forms.Padding(0);
this.flowLayoutPanel4.Name = "flowLayoutPanel4";
- this.flowLayoutPanel4.Size = new System.Drawing.Size(379, 26);
+ this.flowLayoutPanel4.Size = new System.Drawing.Size(376, 26);
this.flowLayoutPanel4.TabIndex = 4;
//
// nudStereoPanning
@@ -729,58 +937,13 @@
this.lblStereoPanningAngle.TabIndex = 1;
this.lblStereoPanningAngle.Text = "(Angle in degrees)";
//
- // flowLayoutPanel5
- //
- this.tlpStereoFilter.SetColumnSpan(this.flowLayoutPanel5, 2);
- this.flowLayoutPanel5.Controls.Add(this.chkCrossFeedEnabled);
- this.flowLayoutPanel5.Controls.Add(this.nudCrossFeedRatio);
- this.flowLayoutPanel5.Controls.Add(this.lblCrossFeedRatio);
- this.flowLayoutPanel5.Dock = System.Windows.Forms.DockStyle.Fill;
- this.flowLayoutPanel5.Location = new System.Drawing.Point(20, 85);
- this.flowLayoutPanel5.Margin = new System.Windows.Forms.Padding(20, 0, 0, 0);
- this.flowLayoutPanel5.Name = "flowLayoutPanel5";
- this.flowLayoutPanel5.Size = new System.Drawing.Size(431, 25);
- this.flowLayoutPanel5.TabIndex = 5;
- //
- // chkCrossFeedEnabled
- //
- this.chkCrossFeedEnabled.Anchor = System.Windows.Forms.AnchorStyles.Left;
- this.chkCrossFeedEnabled.AutoSize = true;
- this.chkCrossFeedEnabled.Enabled = false;
- this.chkCrossFeedEnabled.Location = new System.Drawing.Point(3, 5);
- this.chkCrossFeedEnabled.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3);
- this.chkCrossFeedEnabled.Name = "chkCrossFeedEnabled";
- this.chkCrossFeedEnabled.Size = new System.Drawing.Size(112, 17);
- this.chkCrossFeedEnabled.TabIndex = 1;
- this.chkCrossFeedEnabled.Text = "Enable Crossfeed:";
- this.chkCrossFeedEnabled.UseVisualStyleBackColor = true;
- //
- // nudCrossFeedRatio
- //
- this.nudCrossFeedRatio.Anchor = System.Windows.Forms.AnchorStyles.Left;
- this.nudCrossFeedRatio.Enabled = false;
- this.nudCrossFeedRatio.Location = new System.Drawing.Point(121, 3);
- this.nudCrossFeedRatio.Name = "nudCrossFeedRatio";
- this.nudCrossFeedRatio.Size = new System.Drawing.Size(42, 20);
- this.nudCrossFeedRatio.TabIndex = 2;
- //
- // lblCrossFeedRatio
- //
- this.lblCrossFeedRatio.Anchor = System.Windows.Forms.AnchorStyles.Left;
- this.lblCrossFeedRatio.AutoSize = true;
- this.lblCrossFeedRatio.Location = new System.Drawing.Point(169, 6);
- this.lblCrossFeedRatio.Name = "lblCrossFeedRatio";
- this.lblCrossFeedRatio.Size = new System.Drawing.Size(15, 13);
- this.lblCrossFeedRatio.TabIndex = 3;
- this.lblCrossFeedRatio.Text = "%";
- //
// grpReverb
//
this.grpReverb.Controls.Add(this.tableLayoutPanel5);
this.grpReverb.Dock = System.Windows.Forms.DockStyle.Fill;
- this.grpReverb.Location = new System.Drawing.Point(3, 139);
+ this.grpReverb.Location = new System.Drawing.Point(3, 104);
this.grpReverb.Name = "grpReverb";
- this.grpReverb.Size = new System.Drawing.Size(457, 109);
+ this.grpReverb.Size = new System.Drawing.Size(454, 109);
this.grpReverb.TabIndex = 1;
this.grpReverb.TabStop = false;
this.grpReverb.Text = "Reverb";
@@ -803,7 +966,7 @@
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 32F));
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 32F));
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
- this.tableLayoutPanel5.Size = new System.Drawing.Size(451, 90);
+ this.tableLayoutPanel5.Size = new System.Drawing.Size(448, 90);
this.tableLayoutPanel5.TabIndex = 0;
//
// chkReverbEnabled
@@ -859,13 +1022,55 @@
this.trkReverbStrength.TabIndex = 1;
this.trkReverbStrength.Value = 1;
//
+ // flowLayoutPanel5
+ //
+ this.flowLayoutPanel5.Controls.Add(this.chkCrossFeedEnabled);
+ this.flowLayoutPanel5.Controls.Add(this.nudCrossFeedRatio);
+ this.flowLayoutPanel5.Controls.Add(this.lblCrossFeedRatio);
+ this.flowLayoutPanel5.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.flowLayoutPanel5.Location = new System.Drawing.Point(6, 216);
+ this.flowLayoutPanel5.Margin = new System.Windows.Forms.Padding(6, 0, 0, 0);
+ this.flowLayoutPanel5.Name = "flowLayoutPanel5";
+ this.flowLayoutPanel5.Size = new System.Drawing.Size(454, 25);
+ this.flowLayoutPanel5.TabIndex = 6;
+ //
+ // chkCrossFeedEnabled
+ //
+ this.chkCrossFeedEnabled.Anchor = System.Windows.Forms.AnchorStyles.Left;
+ this.chkCrossFeedEnabled.AutoSize = true;
+ this.chkCrossFeedEnabled.Location = new System.Drawing.Point(3, 5);
+ this.chkCrossFeedEnabled.Margin = new System.Windows.Forms.Padding(3, 5, 3, 3);
+ this.chkCrossFeedEnabled.Name = "chkCrossFeedEnabled";
+ this.chkCrossFeedEnabled.Size = new System.Drawing.Size(112, 17);
+ this.chkCrossFeedEnabled.TabIndex = 1;
+ this.chkCrossFeedEnabled.Text = "Enable Crossfeed:";
+ this.chkCrossFeedEnabled.UseVisualStyleBackColor = true;
+ //
+ // nudCrossFeedRatio
+ //
+ this.nudCrossFeedRatio.Anchor = System.Windows.Forms.AnchorStyles.Left;
+ this.nudCrossFeedRatio.Location = new System.Drawing.Point(121, 3);
+ this.nudCrossFeedRatio.Name = "nudCrossFeedRatio";
+ this.nudCrossFeedRatio.Size = new System.Drawing.Size(42, 20);
+ this.nudCrossFeedRatio.TabIndex = 2;
+ //
+ // lblCrossFeedRatio
+ //
+ this.lblCrossFeedRatio.Anchor = System.Windows.Forms.AnchorStyles.Left;
+ this.lblCrossFeedRatio.AutoSize = true;
+ this.lblCrossFeedRatio.Location = new System.Drawing.Point(169, 6);
+ this.lblCrossFeedRatio.Name = "lblCrossFeedRatio";
+ this.lblCrossFeedRatio.Size = new System.Drawing.Size(15, 13);
+ this.lblCrossFeedRatio.TabIndex = 3;
+ this.lblCrossFeedRatio.Text = "%";
+ //
// tpgAdvanced
//
this.tpgAdvanced.Controls.Add(this.tableLayoutPanel3);
this.tpgAdvanced.Location = new System.Drawing.Point(4, 22);
this.tpgAdvanced.Name = "tpgAdvanced";
this.tpgAdvanced.Padding = new System.Windows.Forms.Padding(3);
- this.tpgAdvanced.Size = new System.Drawing.Size(469, 349);
+ this.tpgAdvanced.Size = new System.Drawing.Size(466, 350);
this.tpgAdvanced.TabIndex = 2;
this.tpgAdvanced.Text = "Advanced";
this.tpgAdvanced.UseVisualStyleBackColor = true;
@@ -885,7 +1090,7 @@
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
- this.tableLayoutPanel3.Size = new System.Drawing.Size(463, 343);
+ this.tableLayoutPanel3.Size = new System.Drawing.Size(460, 344);
this.tableLayoutPanel3.TabIndex = 1;
//
// chkSilenceTriangleHighFreq
@@ -922,6 +1127,21 @@
this.chkReduceDmcPopping.TextAlign = System.Drawing.ContentAlignment.TopLeft;
this.chkReduceDmcPopping.UseVisualStyleBackColor = true;
//
+ // trkTrianglePan
+ //
+ this.trkTrianglePan.Anchor = System.Windows.Forms.AnchorStyles.Top;
+ this.trkTrianglePan.Location = new System.Drawing.Point(12, 110);
+ this.trkTrianglePan.Margin = new System.Windows.Forms.Padding(0);
+ this.trkTrianglePan.Maximum = 100;
+ this.trkTrianglePan.MaximumSize = new System.Drawing.Size(63, 160);
+ this.trkTrianglePan.Minimum = -100;
+ this.trkTrianglePan.MinimumSize = new System.Drawing.Size(206, 55);
+ this.trkTrianglePan.Name = "trkTrianglePan";
+ this.trkTrianglePan.Size = new System.Drawing.Size(206, 55);
+ this.trkTrianglePan.TabIndex = 14;
+ this.trkTrianglePan.Text = "Triangle";
+ this.trkTrianglePan.Value = 0;
+ //
// frmAudioConfig
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -949,6 +1169,8 @@
this.tabMain.ResumeLayout(false);
this.tpgGeneral.ResumeLayout(false);
this.tpgVolume.ResumeLayout(false);
+ this.tpgPanning.ResumeLayout(false);
+ this.tableLayoutPanel6.ResumeLayout(false);
this.tpgEffects.ResumeLayout(false);
this.tableLayoutPanel4.ResumeLayout(false);
this.grpStereo.ResumeLayout(false);
@@ -960,14 +1182,14 @@
this.flowLayoutPanel4.ResumeLayout(false);
this.flowLayoutPanel4.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.nudStereoPanning)).EndInit();
- this.flowLayoutPanel5.ResumeLayout(false);
- this.flowLayoutPanel5.PerformLayout();
- ((System.ComponentModel.ISupportInitialize)(this.nudCrossFeedRatio)).EndInit();
this.grpReverb.ResumeLayout(false);
this.tableLayoutPanel5.ResumeLayout(false);
this.tableLayoutPanel5.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.trkReverbDelay)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.trkReverbStrength)).EndInit();
+ this.flowLayoutPanel5.ResumeLayout(false);
+ this.flowLayoutPanel5.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.nudCrossFeedRatio)).EndInit();
this.tpgAdvanced.ResumeLayout(false);
this.tableLayoutPanel3.ResumeLayout(false);
this.tableLayoutPanel3.PerformLayout();
@@ -1034,9 +1256,22 @@
private System.Windows.Forms.CheckBox chkReduceDmcPopping;
private System.Windows.Forms.PictureBox picLatencyWarning;
private System.Windows.Forms.Label lblLatencyWarning;
+ private System.Windows.Forms.TabPage tpgPanning;
+ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel6;
+ private Controls.ctrlHorizontalTrackbar trkDmcPan;
+ private Controls.ctrlHorizontalTrackbar trkNoisePan;
+ private Controls.ctrlHorizontalTrackbar trkSquare2Pan;
+ private Controls.ctrlHorizontalTrackbar trkFdsPan;
+ private Controls.ctrlHorizontalTrackbar trkMmc5Pan;
+ private Controls.ctrlHorizontalTrackbar trkVrc6Pan;
+ private Controls.ctrlHorizontalTrackbar trkVrc7Pan;
+ private Controls.ctrlHorizontalTrackbar trkNamcoPan;
+ private Controls.ctrlHorizontalTrackbar trkSunsoftPan;
+ private Controls.ctrlHorizontalTrackbar trkSquare1Pan;
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel5;
private System.Windows.Forms.CheckBox chkCrossFeedEnabled;
private System.Windows.Forms.NumericUpDown nudCrossFeedRatio;
private System.Windows.Forms.Label lblCrossFeedRatio;
+ private Controls.ctrlHorizontalTrackbar trkTrianglePan;
}
}
\ No newline at end of file
diff --git a/GUI.NET/Forms/Config/frmAudioConfig.cs b/GUI.NET/Forms/Config/frmAudioConfig.cs
index 9f3dd676..bccd74cf 100644
--- a/GUI.NET/Forms/Config/frmAudioConfig.cs
+++ b/GUI.NET/Forms/Config/frmAudioConfig.cs
@@ -36,6 +36,18 @@ namespace Mesen.GUI.Forms.Config
AddBinding("Namco163Volume", trkNamco163Vol);
AddBinding("Sunsoft5bVolume", trkSunsoft5b);
+ AddBinding("Square1Panning", trkSquare1Pan);
+ AddBinding("Square2Panning", trkSquare2Pan);
+ AddBinding("TrianglePanning", trkTrianglePan);
+ AddBinding("NoisePanning", trkNoisePan);
+ AddBinding("DmcPanning", trkDmcPan);
+ AddBinding("FdsPanning", trkFdsPan);
+ AddBinding("Mmc5Panning", trkMmc5Pan);
+ AddBinding("Vrc6Panning", trkVrc6Pan);
+ AddBinding("Vrc7Panning", trkVrc7Pan);
+ AddBinding("Namco163Panning", trkNamcoPan);
+ AddBinding("Sunsoft5bPanning", trkSunsoftPan);
+
AddBinding("AudioLatency", nudLatency);
AddBinding("SampleRate", cboSampleRate);
AddBinding("AudioDevice", cboAudioDevice);
@@ -95,11 +107,5 @@ namespace Mesen.GUI.Forms.Config
picLatencyWarning.Visible = nudLatency.Value <= 30;
lblLatencyWarning.Visible = nudLatency.Value <= 30;
}
-
- private void radStereoDisabled_CheckedChanged(object sender, EventArgs e)
- {
- chkCrossFeedEnabled.Enabled = !radStereoDisabled.Checked;
- nudCrossFeedRatio.Enabled = !radStereoDisabled.Checked;
- }
}
}
diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs
index 3e669170..6457bf33 100644
--- a/GUI.NET/InteropEmu.cs
+++ b/GUI.NET/InteropEmu.cs
@@ -128,6 +128,7 @@ namespace Mesen.GUI
[DllImport(DLLPath)] public static extern void SetRamPowerOnState(RamPowerOnState state);
[DllImport(DLLPath)] public static extern void SetMasterVolume(double volume);
[DllImport(DLLPath)] public static extern void SetChannelVolume(AudioChannel channel, double volume);
+ [DllImport(DLLPath)] public static extern void SetChannelPanning(AudioChannel channel, double panning);
[DllImport(DLLPath)] public static extern void SetSampleRate(UInt32 sampleRate);
[DllImport(DLLPath)] public static extern void SetAudioLatency(UInt32 msLatency);
[DllImport(DLLPath)] public static extern void SetStereoFilter(StereoFilter stereoFilter);
diff --git a/InteropDLL/ConsoleWrapper.cpp b/InteropDLL/ConsoleWrapper.cpp
index 77bd8e79..efd85014 100644
--- a/InteropDLL/ConsoleWrapper.cpp
+++ b/InteropDLL/ConsoleWrapper.cpp
@@ -323,6 +323,7 @@ namespace InteropEmu {
DllExport void __stdcall SetRamPowerOnState(RamPowerOnState state) { EmulationSettings::SetRamPowerOnState(state); }
DllExport void __stdcall SetDisplayLanguage(Language lang) { EmulationSettings::SetDisplayLanguage(lang); }
DllExport void __stdcall SetChannelVolume(uint32_t channel, double volume) { EmulationSettings::SetChannelVolume((AudioChannel)channel, volume); }
+ DllExport void __stdcall SetChannelPanning(uint32_t channel, double panning) { EmulationSettings::SetChannelPanning((AudioChannel)channel, panning); }
DllExport void __stdcall SetMasterVolume(double volume) { EmulationSettings::SetMasterVolume(volume); }
DllExport void __stdcall SetSampleRate(uint32_t sampleRate) { EmulationSettings::SetSampleRate(sampleRate); }
DllExport void __stdcall SetAudioLatency(uint32_t msLatency) { EmulationSettings::SetAudioLatency(msLatency); }
diff --git a/Utilities/LowPassFilter.h b/Utilities/LowPassFilter.h
index 52d1d37c..4550ecb9 100644
--- a/Utilities/LowPassFilter.h
+++ b/Utilities/LowPassFilter.h
@@ -7,21 +7,30 @@ class LowPassFilter
{
private:
uint8_t _prevSampleCounter = 0;
- int16_t _prevSamples[10] = { 0,0,0,0,0,0,0,0,0,0};
+ int16_t _prevSamplesLeft[10] = { 0,0,0,0,0,0,0,0,0,0 };
+ int16_t _prevSamplesRight[10] = { 0,0,0,0,0,0,0,0,0,0 };
+
+ void UpdateSample(int16_t *buffer, size_t index, int strength, double volume, int16_t *_prevSamples)
+ {
+ if(strength > 0) {
+ int32_t sum = std::accumulate(_prevSamples, _prevSamples + strength, 0);
+ buffer[index] = (int16_t)((sum + buffer[index]) / (strength + 1) * volume);
+ _prevSamples[_prevSampleCounter] = buffer[index];
+ } else {
+ buffer[index] = (int16_t)(buffer[index] * volume);
+ }
+ }
public:
void ApplyFilter(int16_t *buffer, size_t sampleCount, int strength, double volume = 1.0f)
{
assert(strength <= 10);
- for(size_t i = 0; i < sampleCount; i++) {
+ for(size_t i = 0; i < sampleCount*2; i+=2) {
+ UpdateSample(buffer, i, strength, volume, _prevSamplesLeft);
+ UpdateSample(buffer, i+1, strength, volume, _prevSamplesRight);
if(strength > 0) {
- int32_t sum = std::accumulate(&_prevSamples[0], &_prevSamples[strength], 0);
- buffer[i] = (int16_t)((sum + buffer[i]) / (strength + 1) * volume);
- _prevSamples[_prevSampleCounter] = buffer[i];
_prevSampleCounter = (_prevSampleCounter + 1) % strength;
- } else {
- buffer[i] = (int16_t)(buffer[i] * volume);
}
}
}