Wire audio frame counter (tbc)

Signed-off-by: Adrian.Conlon <adrian.conlon@arup.com>
This commit is contained in:
Adrian.Conlon 2017-09-21 21:26:52 +01:00
parent cd63636895
commit 877618f973
5 changed files with 97 additions and 13 deletions

View File

@ -7,6 +7,8 @@
#include <Processor.h>
#include "AudioFrame.h"
namespace EightBit {
namespace GameBoy {
@ -110,7 +112,8 @@ namespace EightBit {
class WaveVoice : public AudioVoice {
public:
WaveVoice() {}
WaveVoice(int cyclesPerSecond)
: m_cyclesPerSecond(cyclesPerSecond) {}
virtual void reset() override {
AudioVoice::reset();
@ -141,9 +144,8 @@ namespace EightBit {
int hertz() const {
// f = 4194304 / (4 x 8 x (2048 - X)) Hz
auto clock = 4 * 1024 * 1024;
auto division = 4 * 8 * (2048 - frequency());
return clock / division;
return m_cyclesPerSecond / division;
}
void setFrequency(int value) {
@ -158,13 +160,15 @@ namespace EightBit {
}
private:
const int m_cyclesPerSecond;
int m_frequencyLowOrder; // 8 bits
int m_frequencyHighOrder; // 3 bits
};
class RectangularVoice : public WaveVoice {
public:
RectangularVoice() {}
RectangularVoice(int cyclesPerSecond)
: WaveVoice(cyclesPerSecond) {}
virtual void reset() override {
WaveVoice::reset();
@ -194,7 +198,8 @@ namespace EightBit {
// NR2X
class EnvelopedRectangularVoice : public RectangularVoice {
public:
EnvelopedRectangularVoice() {}
EnvelopedRectangularVoice(int cyclesPerSecond)
: RectangularVoice(cyclesPerSecond) {}
virtual void reset() override {
RectangularVoice::reset();
@ -219,7 +224,8 @@ namespace EightBit {
// NR1X
class SweptEnvelopedRectangularVoice : public EnvelopedRectangularVoice {
public:
SweptEnvelopedRectangularVoice() {}
SweptEnvelopedRectangularVoice(int cyclesPerSecond)
: EnvelopedRectangularVoice(cyclesPerSecond) {}
virtual void reset() override {
EnvelopedRectangularVoice::reset();
@ -244,7 +250,8 @@ namespace EightBit {
// NR3X
class UserDefinedWaveVoice : public WaveVoice {
public:
UserDefinedWaveVoice() {}
UserDefinedWaveVoice(int cyclesPerSecond)
: WaveVoice(cyclesPerSecond) {}
virtual void reset() override {
WaveVoice::reset();
@ -391,12 +398,19 @@ namespace EightBit {
class Audio final {
public:
Audio()
: m_enabled(false) {
m_voices[0] = std::make_shared<SweptEnvelopedRectangularVoice>();
m_voices[1] = std::make_shared<EnvelopedRectangularVoice>();
m_voices[2] = std::make_shared<UserDefinedWaveVoice>();
Audio(int cyclesPerSecond)
: m_frameSequencer(cyclesPerSecond),
m_enabled(false) {
m_voices[0] = std::make_shared<SweptEnvelopedRectangularVoice>(cyclesPerSecond);
m_voices[1] = std::make_shared<EnvelopedRectangularVoice>(cyclesPerSecond);
m_voices[2] = std::make_shared<UserDefinedWaveVoice>(cyclesPerSecond);
m_voices[3] = std::make_shared<WhiteNoiseWaveVoice>();
m_frameSequencer.FrameStep.connect(std::bind(&Audio::Sequencer_FrameStep, this, std::placeholders::_1));
m_frameSequencer.LengthStep.connect(std::bind(&Audio::Sequencer_LengthStep, this, std::placeholders::_1));
m_frameSequencer.VolumeStep.connect(std::bind(&Audio::Sequencer_VolumeStep, this, std::placeholders::_1));
m_frameSequencer.SweepStep.connect(std::bind(&Audio::Sequencer_SweepStep, this, std::placeholders::_1));
}
std::shared_ptr<AudioVoice> voice(int i) { return m_voices[i]; }
@ -759,7 +773,25 @@ namespace EightBit {
return voice3()->packedWaveDatum(i);
}
void stepFrame(int cycles) {
m_frameSequencer.step(cycles);
}
void Sequencer_FrameStep(const int step) {
}
void Sequencer_LengthStep(const int step) {
}
void Sequencer_VolumeStep(const int step) {
}
void Sequencer_SweepStep(const int step) {
}
private:
AudioFrame m_frameSequencer;
std::array<std::shared_ptr<AudioVoice>, 4> m_voices;
std::array<OutputChannel, 2> m_channels;
bool m_enabled;

47
LR35902/inc/AudioFrame.h Normal file
View File

@ -0,0 +1,47 @@
#pragma once
#include <Signal.h>
namespace EightBit {
namespace GameBoy {
class AudioFrame final {
private:
enum { StepCycle = 7, Frequency = 512 };
int m_cyclesPerTick;
int m_currentStep;
int m_currentCycles;
public:
AudioFrame(int cyclesPerSecond)
: m_cyclesPerTick(cyclesPerSecond / Frequency),
m_currentStep(0),
m_currentCycles(m_cyclesPerTick) {
}
Signal<int> FrameStep;
Signal<int> LengthStep;
Signal<int> VolumeStep;
Signal<int> SweepStep;
void step() {
m_currentStep = (m_currentStep + 1) % StepCycle;
FrameStep.fire(m_currentStep);
if ((m_currentStep % 2) == 0)
LengthStep.fire(m_currentStep);
if (m_currentStep == 7)
VolumeStep.fire(m_currentStep);
if ((m_currentStep == 2) || (m_currentStep == 6))
SweepStep.fire(m_currentStep);
}
void step(int cycles) {
m_currentCycles -= cycles;
if (m_currentCycles < 0) {
step();
m_currentCycles += m_cyclesPerTick;
}
}
};
}
}

View File

@ -30,7 +30,8 @@ EightBit::GameBoy::Bus::Bus()
m_p13(true),
m_p12(true),
m_p11(true),
m_p10(true) {
m_p10(true),
m_audio(CyclesPerSecond) {
ReadingByte.connect(std::bind(&GameBoy::Bus::Bus_ReadingByte, this, std::placeholders::_1));
WrittenByte.connect(std::bind(&GameBoy::Bus::Bus_WrittenByte, this, std::placeholders::_1));
m_divCounter.word = 0xabcc;

View File

@ -141,6 +141,7 @@
<ItemGroup>
<ClInclude Include="..\inc\AbstractColourPalette.h" />
<ClInclude Include="..\inc\Audio.h" />
<ClInclude Include="..\inc\AudioFrame.h" />
<ClInclude Include="..\inc\GameBoyBus.h" />
<ClInclude Include="..\inc\CharacterDefinition.h" />
<ClInclude Include="..\inc\Disassembler.h" />

View File

@ -41,6 +41,9 @@
<ClInclude Include="..\inc\Audio.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\AudioFrame.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">