Files
ComSquare/sources/APU/DSP/Voice.cpp
Melefo b0fb1e3351 new MemoryMap architecture
starting to working of voices and so on BRR, Envelopes, Gauss and Timers as they use each others
2021-02-04 00:06:39 +01:00

156 lines
3.9 KiB
C++

//
// Created by melefo on 2/1/21.
//
#include "DSP.hpp"
#include "../APU.hpp"
#include <algorithm>
namespace ComSquare::APU::DSP
{
void DSP::voiceOutput(Voice &voice, bool channel)
{
int out = this->_latch.output * voice.volume[channel] >> 7;
this->_master.output[channel] += out;
if (!voice.echo)
return;
this->_echo.volume[channel] += out;
}
void DSP::voice1(Voice &voice)
{
this->_brr.address = (this->_brr.offsetAddr << 8) + (this->_brr.source << 2);
this->_brr.source = voice.srcn;
}
void DSP::voice2(Voice &voice)
{
uint16_t addr = this->_brr.address;
if (!voice.konDelay)
addr += 2;
this->_brr.nextAddress = this->_readRAM(addr++);
this->_brr.nextAddress += this->_readRAM(addr++) << 8;
this->_latch.adsr1 = voice.adsr1;
this->_latch.pitch = voice.pitch & 0xFF;
}
void DSP::voice3(Voice &voice)
{
this->voice3a(voice);
this->voice3b(voice);
this->voice3c(voice);
}
void DSP::voice3a(Voice &voice)
{
this->_latch.pitch |= (voice.pitchH & 0x3F) << 8;
}
void DSP::voice3b(Voice &voice)
{
this->_brr.header = this->_readRAM(this->_brr.address);
this->_brr.value = this->_readRAM(this->_brr.address + voice.brrOffset);
}
void DSP::voice3c(Voice &voice)
{
if (voice.prevPmon)
this->_latch.pitch += (this->_latch.output >> 5) * this->_latch.pitch >> 10;
if (voice.konDelay) {
if (voice.konDelay == 5) {
voice.brrAddress = this->_brr.nextAddress;
voice.brrOffset = 1;
voice.sampleOffset = 0;
this->_brr.header = 0;
}
voice.envelope = 0;
voice.hiddenEnvelope = 0;
voice.gaussOffset = 0;
voice.konDelay -= 1;
if (voice.konDelay & 3)
voice.gaussOffset = 0x4000;
this->_latch.pitch = 0;
}
int32_t interpolated = this->interpolate(voice);
if (voice.tempNon)
interpolated = this->_noise.lfsr << 1;
this->_latch.output = interpolated * voice.envelope >> 11 & ~1;
voice.envx = voice.envelope >> 4;
if (this->_master.reset || (this->_brr.header & 3) == 1) {
voice.envelope = 0;
voice.envelopeMode = Envelope::Release;
}
if (this->_timer.sample)
{
if (voice.tempKof)
voice.envelopeMode = Envelope::Release;
if (voice.tempKon) {
voice.konDelay = 5;
voice.envelopeMode = Envelope::Attack;
}
}
if (!voice.konDelay)
this->runEnvelope(voice);
}
void DSP::voice4(Voice &voice)
{
voice.loop = false;
if (voice.gaussOffset >= 0x4000) {
this->decodeBRR(voice);
voice.brrOffset += 2;
if (voice.brrOffset >= 9) {
voice.brrOffset = voice.brrAddress + 9;
if (this->_brr.header & 0b1) {
voice.brrAddress = this->_brr.nextAddress;
voice.loop = true;
}
voice.brrOffset = 1;
}
}
voice.gaussOffset = (voice.gaussOffset & 0x3FFF) + this->_latch.pitch;
if (voice.gaussOffset > 0x7FFF)
voice.gaussOffset = 0x7FFF;
this->voiceOutput(voice, 0);
}
void DSP::voice5(Voice &voice)
{
this->voiceOutput(voice, 1);
voice.endx |= voice.loop;
if (voice.konDelay == 5)
voice.endx &= ~voice.endx;
}
void DSP::voice6(Voice &)
{
this->_latch.outx = this->_latch.output >> 8;
}
void DSP::voice7(Voice &voice)
{
}
void DSP::voice8(Voice &voice)
{
}
void DSP::voice9(Voice &voice)
{
}
}