Mesen2/Core/NES/NesSoundMixer.h
2022-09-08 21:29:52 -04:00

71 lines
No EOL
1.9 KiB
C++

#pragma once
#include "pch.h"
#include "Utilities/ISerializable.h"
#include "Utilities/Audio/blip_buf.h"
#include "Utilities/Audio/StereoDelayFilter.h"
#include "Utilities/Audio/StereoPanningFilter.h"
#include "Utilities/Audio/StereoCombFilter.h"
#include "NesTypes.h"
class NesConsole;
class SoundMixer;
class EmuSettings;
enum class ConsoleRegion;
class NesSoundMixer : public ISerializable
{
public:
static constexpr uint32_t CycleLength = 10000;
static constexpr uint32_t BitsPerSample = 16;
private:
static constexpr uint32_t MaxSampleRate = 96000;
static constexpr uint32_t MaxSamplesPerFrame = MaxSampleRate / 60 * 4 * 2; //x4 to allow CPU overclocking up to 10x, x2 for panning stereo
static constexpr uint32_t MaxChannelCount = 11;
NesConsole* _console = nullptr;
SoundMixer* _mixer = nullptr;
StereoPanningFilter _stereoPanning;
StereoDelayFilter _stereoDelay;
StereoCombFilter _stereoCombFilter;
int16_t _previousOutputLeft = 0;
int16_t _previousOutputRight = 0;
vector<uint32_t> _timestamps;
int16_t _channelOutput[MaxChannelCount][CycleLength] = {};
int16_t _currentOutput[MaxChannelCount] = {};
blip_t* _blipBufLeft = nullptr;
blip_t* _blipBufRight = nullptr;
int16_t* _outputBuffer = nullptr;
size_t _sampleCount = 0;
double _volumes[MaxChannelCount] = {};
double _panning[MaxChannelCount] = {};
uint32_t _sampleRate = 0;
uint32_t _clockRate = 0;
bool _hasPanning = false;
__forceinline double GetChannelOutput(AudioChannel channel, bool forRightChannel);
__forceinline int16_t GetOutputVolume(bool forRightChannel);
void EndFrame(uint32_t time);
void ProcessVsDualSystemAudio();
void UpdateRates(bool forceUpdate);
public:
NesSoundMixer(NesConsole* console);
virtual ~NesSoundMixer();
void SetRegion(ConsoleRegion region);
void Reset();
void PlayAudioBuffer(uint32_t cycle);
void AddDelta(AudioChannel channel, uint32_t time, int16_t delta);
void Serialize(Serializer& s) override;
};