diff --git a/src/Config.cpp b/src/Config.cpp
index a84971a8..23ed2659 100644
--- a/src/Config.cpp
+++ b/src/Config.cpp
@@ -42,6 +42,7 @@ int DSiSDEnable;
char DSiSDPath[1024];
int RandomizeMAC;
+int AudioBitrate;
#ifdef JIT_ENABLED
int JIT_Enable = false;
@@ -67,6 +68,7 @@ ConfigEntry ConfigFile[] =
{"DSiSDPath", 1, DSiSDPath, 0, "", 1023},
{"RandomizeMAC", 0, &RandomizeMAC, 0, NULL, 0},
+ {"AudioBitrate", 0, &AudioBitrate, 0, NULL, 0},
#ifdef JIT_ENABLED
{"JIT_Enable", 0, &JIT_Enable, 0, NULL, 0},
diff --git a/src/Config.h b/src/Config.h
index 54ef63bc..a0c7ea80 100644
--- a/src/Config.h
+++ b/src/Config.h
@@ -55,6 +55,7 @@ extern int DSiSDEnable;
extern char DSiSDPath[1024];
extern int RandomizeMAC;
+extern int AudioBitrate;
#ifdef JIT_ENABLED
extern int JIT_Enable;
diff --git a/src/NDS.cpp b/src/NDS.cpp
index 55b4fdff..f1726770 100644
--- a/src/NDS.cpp
+++ b/src/NDS.cpp
@@ -596,12 +596,25 @@ void Reset()
RTC::Reset();
Wifi::Reset();
+ // The SOUNDBIAS register does nothing on DSi
+ SPU::SetApplyBias(ConsoleType == 0);
+
+ bool degradeAudio = true;
+
if (ConsoleType == 1)
{
DSi::Reset();
KeyInput &= ~(1 << (16+6));
+ degradeAudio = false;
}
+ if (Config::AudioBitrate == 1) // Always 10-bit
+ degradeAudio = true;
+ else if (Config::AudioBitrate == 2) // Always 16-bit
+ degradeAudio = false;
+
+ SPU::SetDegrade10Bit(degradeAudio);
+
AREngine::Reset();
}
diff --git a/src/SPU.cpp b/src/SPU.cpp
index e42bff8a..d1c2d847 100644
--- a/src/SPU.cpp
+++ b/src/SPU.cpp
@@ -81,6 +81,8 @@ Platform::Mutex* AudioLock;
u16 Cnt;
u8 MasterVolume;
u16 Bias;
+bool ApplyBias;
+bool Degrade10Bit;
Channel* Channels[16];
CaptureUnit* Capture[2];
@@ -190,6 +192,14 @@ void SetBias(u16 bias)
Bias = bias;
}
+void SetApplyBias(bool enable) {
+ ApplyBias = enable;
+}
+
+void SetDegrade10Bit(bool enable) {
+ Degrade10Bit = enable;
+}
+
Channel::Channel(u32 num)
{
@@ -795,6 +805,21 @@ void Mix(u32 dummy)
if (rightoutput < -0x8000) rightoutput = -0x8000;
else if (rightoutput > 0x7FFF) rightoutput = 0x7FFF;
+ // The original DS and DS lite degrade the output from 16 to 10 bit before output
+ if (Degrade10Bit)
+ {
+ leftoutput &= 0xFFFFFFC0;
+ rightoutput &= 0xFFFFFFC0;
+ }
+
+ // Add SOUNDBIAS value
+ // The value used by all commercial games is 0x200, so we subtract that so it won't offset the final sound output.
+ if (ApplyBias == true)
+ {
+ leftoutput += (Bias << 6) - 0x8000;
+ rightoutput += (Bias << 6) - 0x8000;
+ }
+
// OutputBufferFrame can never get full because it's
// transfered to OutputBuffer at the end of the frame
OutputBackbuffer[OutputBackbufferWritePosition ] = leftoutput >> 1;
diff --git a/src/SPU.h b/src/SPU.h
index 055a7660..22c87a76 100644
--- a/src/SPU.h
+++ b/src/SPU.h
@@ -35,6 +35,8 @@ void DoSavestate(Savestate* file);
void SetInterpolation(int type);
void SetBias(u16 bias);
+void SetDegrade10Bit(bool enable);
+void SetApplyBias(bool enable);
void Mix(u32 dummy);
diff --git a/src/frontend/qt_sdl/AudioSettingsDialog.cpp b/src/frontend/qt_sdl/AudioSettingsDialog.cpp
index 5ac178ab..970b54b0 100644
--- a/src/frontend/qt_sdl/AudioSettingsDialog.cpp
+++ b/src/frontend/qt_sdl/AudioSettingsDialog.cpp
@@ -39,6 +39,7 @@ AudioSettingsDialog::AudioSettingsDialog(QWidget* parent) : QDialog(parent), ui(
setAttribute(Qt::WA_DeleteOnClose);
oldInterp = Config::AudioInterp;
+ oldBitrate = Config::AudioBitrate;
oldVolume = Config::AudioVolume;
ui->cbInterpolation->addItem("None");
@@ -47,6 +48,11 @@ AudioSettingsDialog::AudioSettingsDialog(QWidget* parent) : QDialog(parent), ui(
ui->cbInterpolation->addItem("Cubic");
ui->cbInterpolation->setCurrentIndex(Config::AudioInterp);
+ ui->cbBitrate->addItem("Automatic");
+ ui->cbBitrate->addItem("10-bit");
+ ui->cbBitrate->addItem("16-bit");
+ ui->cbBitrate->setCurrentIndex(Config::AudioBitrate);
+
ui->slVolume->setValue(Config::AudioVolume);
grpMicMode = new QButtonGroup(this);
@@ -81,11 +87,22 @@ void AudioSettingsDialog::on_AudioSettingsDialog_accepted()
void AudioSettingsDialog::on_AudioSettingsDialog_rejected()
{
Config::AudioInterp = oldInterp;
+ Config::AudioBitrate = oldBitrate;
Config::AudioVolume = oldVolume;
closeDlg();
}
+void AudioSettingsDialog::on_cbBitrate_currentIndexChanged(int idx)
+{
+ // prevent a spurious change
+ if (ui->cbBitrate->count() < 3) return;
+
+ Config::AudioBitrate = ui->cbBitrate->currentIndex();
+
+ emit updateAudioSettings();
+}
+
void AudioSettingsDialog::on_cbInterpolation_currentIndexChanged(int idx)
{
// prevent a spurious change
diff --git a/src/frontend/qt_sdl/AudioSettingsDialog.h b/src/frontend/qt_sdl/AudioSettingsDialog.h
index 51399758..0bb32c68 100644
--- a/src/frontend/qt_sdl/AudioSettingsDialog.h
+++ b/src/frontend/qt_sdl/AudioSettingsDialog.h
@@ -59,6 +59,7 @@ private slots:
void on_AudioSettingsDialog_rejected();
void on_cbInterpolation_currentIndexChanged(int idx);
+ void on_cbBitrate_currentIndexChanged(int idx);
void on_slVolume_valueChanged(int val);
void onChangeMicMode(int mode);
void on_btnMicWavBrowse_clicked();
@@ -67,6 +68,7 @@ private:
Ui::AudioSettingsDialog* ui;
int oldInterp;
+ int oldBitrate;
int oldVolume;
QButtonGroup* grpMicMode;
};
diff --git a/src/frontend/qt_sdl/AudioSettingsDialog.ui b/src/frontend/qt_sdl/AudioSettingsDialog.ui
index e3295238..d7cfadd6 100644
--- a/src/frontend/qt_sdl/AudioSettingsDialog.ui
+++ b/src/frontend/qt_sdl/AudioSettingsDialog.ui
@@ -29,14 +29,14 @@
Audio output
- -
+
-
Volume:
- -
+
-
<html><head/><body><p>Controls the volume of the audio output.</p></body></html>
@@ -66,6 +66,20 @@
+ -
+
+
+ Bitrate:
+
+
+
+ -
+
+
+ <html><head/><body><p>The bitrate of audio playback. If set to "Automatic" this will be 10-bit for DS mode and 16-bit for DSi mode.</p></body></html>
+
+
+
diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp
index d8eca583..272df3cc 100644
--- a/src/frontend/qt_sdl/main.cpp
+++ b/src/frontend/qt_sdl/main.cpp
@@ -2436,6 +2436,11 @@ void MainWindow::onOpenAudioSettings()
void MainWindow::onUpdateAudioSettings()
{
SPU::SetInterpolation(Config::AudioInterp);
+
+ if (Config::AudioBitrate == 0)
+ SPU::SetDegrade10Bit(NDS::ConsoleType == 0);
+ else
+ SPU::SetDegrade10Bit(Config::AudioBitrate == 1);
}
void MainWindow::onAudioSettingsFinished(int res)