2019-02-16 11:23:01 -05:00
|
|
|
#include "stdafx.h"
|
|
|
|
#include "SoundMixer.h"
|
2019-03-10 17:39:14 -04:00
|
|
|
#include "Console.h"
|
|
|
|
#include "EmuSettings.h"
|
|
|
|
#include "SoundResampler.h"
|
2019-03-12 12:06:42 -04:00
|
|
|
#include "RewindManager.h"
|
2019-03-15 12:48:34 -04:00
|
|
|
#include "VideoRenderer.h"
|
2019-03-15 12:58:30 -04:00
|
|
|
#include "WaveRecorder.h"
|
2019-03-10 17:39:14 -04:00
|
|
|
#include "../Utilities/Equalizer.h"
|
|
|
|
#include "../Utilities/blip_buf.h"
|
2019-02-16 11:23:01 -05:00
|
|
|
|
2019-03-10 17:39:14 -04:00
|
|
|
SoundMixer::SoundMixer(Console *console)
|
2019-02-16 11:23:01 -05:00
|
|
|
{
|
2019-03-10 17:39:14 -04:00
|
|
|
_console = console;
|
2019-02-16 11:23:01 -05:00
|
|
|
_audioDevice = nullptr;
|
2019-03-10 17:39:14 -04:00
|
|
|
_resampler.reset(new SoundResampler(console));
|
|
|
|
_sampleBuffer = new int16_t[0x10000];
|
2019-02-16 11:23:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
SoundMixer::~SoundMixer()
|
|
|
|
{
|
2019-03-10 17:39:14 -04:00
|
|
|
delete[] _sampleBuffer;
|
2019-02-16 11:23:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void SoundMixer::RegisterAudioDevice(IAudioDevice *audioDevice)
|
|
|
|
{
|
|
|
|
_audioDevice = audioDevice;
|
|
|
|
}
|
|
|
|
|
2019-03-10 17:39:14 -04:00
|
|
|
AudioStatistics SoundMixer::GetStatistics()
|
|
|
|
{
|
|
|
|
if(_audioDevice) {
|
|
|
|
return _audioDevice->GetStatistics();
|
|
|
|
} else {
|
|
|
|
return AudioStatistics();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-16 11:23:01 -05:00
|
|
|
void SoundMixer::StopAudio(bool clearBuffer)
|
|
|
|
{
|
|
|
|
if(_audioDevice) {
|
|
|
|
if(clearBuffer) {
|
|
|
|
_audioDevice->Stop();
|
|
|
|
} else {
|
|
|
|
_audioDevice->Pause();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SoundMixer::PlayAudioBuffer(int16_t* samples, uint32_t sampleCount)
|
|
|
|
{
|
2019-03-15 12:48:34 -04:00
|
|
|
AudioConfig cfg = _console->GetSettings()->GetAudioConfig();
|
2019-03-10 17:39:14 -04:00
|
|
|
|
2019-03-15 12:48:34 -04:00
|
|
|
if(cfg.EnableEqualizer) {
|
|
|
|
ProcessEqualizer(samples, sampleCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(cfg.MasterVolume != 25) {
|
|
|
|
//Apply volume if not using the default value
|
|
|
|
for(uint32_t i = 0; i < sampleCount * 2; i++) {
|
|
|
|
samples[i] = (int32_t)samples[i] * (int32_t)cfg.MasterVolume / 25;
|
2019-03-10 17:39:14 -04:00
|
|
|
}
|
2019-03-15 12:48:34 -04:00
|
|
|
}
|
2019-03-10 17:39:14 -04:00
|
|
|
|
2019-03-15 12:48:34 -04:00
|
|
|
shared_ptr<RewindManager> rewindManager = _console->GetRewindManager();
|
|
|
|
if(rewindManager && rewindManager->SendAudio(samples, (uint32_t)sampleCount)) {
|
|
|
|
int16_t *out = nullptr;
|
|
|
|
uint32_t count = 0;
|
|
|
|
if(cfg.SampleRate == SoundResampler::SpcSampleRate && cfg.DisableDynamicSampleRate) {
|
|
|
|
out = samples;
|
|
|
|
count = sampleCount;
|
|
|
|
} else {
|
|
|
|
count = _resampler->Resample(samples, sampleCount, cfg.SampleRate, _sampleBuffer);
|
|
|
|
out = _sampleBuffer;
|
2019-03-10 17:39:14 -04:00
|
|
|
}
|
|
|
|
|
2019-03-15 12:58:30 -04:00
|
|
|
bool isRecording = _waveRecorder || _console->GetVideoRenderer()->IsRecording();
|
2019-03-15 12:48:34 -04:00
|
|
|
if(isRecording) {
|
2019-03-15 12:58:30 -04:00
|
|
|
if(_waveRecorder) {
|
|
|
|
_waveRecorder->WriteSamples(out, count, cfg.SampleRate, true);
|
|
|
|
}
|
2019-03-15 12:48:34 -04:00
|
|
|
_console->GetVideoRenderer()->AddRecordingSound(out, count, cfg.SampleRate);
|
2019-03-10 17:39:14 -04:00
|
|
|
}
|
|
|
|
|
2019-03-15 12:48:34 -04:00
|
|
|
if(_audioDevice) {
|
|
|
|
if(!cfg.EnableAudio) {
|
|
|
|
_audioDevice->Stop();
|
|
|
|
return;
|
2019-03-12 12:06:42 -04:00
|
|
|
}
|
2019-03-15 12:48:34 -04:00
|
|
|
|
|
|
|
_audioDevice->PlayBuffer(out, count, cfg.SampleRate, true);
|
|
|
|
_audioDevice->ProcessEndOfFrame();
|
2019-03-10 17:39:14 -04:00
|
|
|
}
|
2019-02-16 11:23:01 -05:00
|
|
|
}
|
|
|
|
}
|
2019-03-10 17:39:14 -04:00
|
|
|
|
|
|
|
void SoundMixer::ProcessEqualizer(int16_t* samples, uint32_t sampleCount)
|
|
|
|
{
|
|
|
|
AudioConfig cfg = _console->GetSettings()->GetAudioConfig();
|
|
|
|
if(!_equalizer) {
|
|
|
|
_equalizer.reset(new Equalizer());
|
|
|
|
}
|
|
|
|
vector<double> bandGains = {
|
|
|
|
cfg.Band1Gain, cfg.Band2Gain, cfg.Band3Gain, cfg.Band4Gain, cfg.Band5Gain,
|
|
|
|
cfg.Band6Gain, cfg.Band7Gain, cfg.Band8Gain, cfg.Band9Gain, cfg.Band10Gain,
|
|
|
|
cfg.Band11Gain, cfg.Band12Gain, cfg.Band13Gain, cfg.Band14Gain, cfg.Band15Gain,
|
|
|
|
cfg.Band16Gain, cfg.Band17Gain, cfg.Band18Gain, cfg.Band19Gain, cfg.Band20Gain
|
|
|
|
};
|
|
|
|
_equalizer->UpdateEqualizers(bandGains, SoundResampler::SpcSampleRate);
|
|
|
|
_equalizer->ApplyEqualizer(sampleCount, samples);
|
|
|
|
}
|
|
|
|
|
|
|
|
double SoundMixer::GetRateAdjustment()
|
|
|
|
{
|
|
|
|
return _resampler->GetRateAdjustment();
|
2019-03-15 12:58:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void SoundMixer::StartRecording(string filepath)
|
|
|
|
{
|
|
|
|
_waveRecorder.reset(new WaveRecorder(filepath, _console->GetSettings()->GetAudioConfig().SampleRate, true));
|
|
|
|
}
|
|
|
|
|
|
|
|
void SoundMixer::StopRecording()
|
|
|
|
{
|
|
|
|
_waveRecorder.reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMixer::IsRecording()
|
|
|
|
{
|
|
|
|
return _waveRecorder.get() != nullptr;
|
2019-03-10 17:39:14 -04:00
|
|
|
}
|