diff --git a/sources/APU/APU.hpp b/sources/APU/APU.hpp index 780ef58..aaf273e 100644 --- a/sources/APU/APU.hpp +++ b/sources/APU/APU.hpp @@ -144,7 +144,7 @@ namespace ComSquare::APU std::shared_ptr _map; //! @brief Total size of the buffer containing samples - static constexpr int32_t bufferSize = 0x20000; + static constexpr int32_t bufferSize = 0x10000; //! @brief Buffer containing samples to be played int16_t _soundBuffer[bufferSize]; diff --git a/sources/APU/DSP/DSP.cpp b/sources/APU/DSP/DSP.cpp index 2321ae7..a3036a0 100644 --- a/sources/APU/DSP/DSP.cpp +++ b/sources/APU/DSP/DSP.cpp @@ -8,11 +8,10 @@ namespace ComSquare::APU::DSP { - DSP::DSP(int16_t *buffer, int32_t size, std::weak_ptr map) : _map(map) + DSP::DSP(int16_t *buffer, uint32_t size, std::weak_ptr map) : _map(map) { this->_state.buffer = buffer; - this->_state.bufferStart = buffer; - this->_state.bufferEnd = buffer + size; + this->_state.bufferSize = size; } uint8_t DSP::read(uint24_t addr) const @@ -796,6 +795,6 @@ namespace ComSquare::APU::DSP int32_t DSP::getSamplesCount() const { - return this->_state.buffer - this->_state.bufferStart; + return this->_state.bufferOffset; } } \ No newline at end of file diff --git a/sources/APU/DSP/DSP.hpp b/sources/APU/DSP/DSP.hpp index 4ea52f4..3ae3fd0 100644 --- a/sources/APU/DSP/DSP.hpp +++ b/sources/APU/DSP/DSP.hpp @@ -46,12 +46,20 @@ namespace ComSquare::APU::DSP std::array FIR; //! @brief Echo data start register (ESA) uint8_t data; + //! @brief Offset position after data start + uint16_t offset; //! @brief Echo delay size register (EDL) uint8_t delay; //! @brief Echo enabled (5th bit FLG) bool enabled = true; //! @brief Last sound produced for each voice in each channel std::array, 2> history; + //! @brief Current position inside history + uint8_t historyOffset; + //! @brief Address of the current echo + uint16_t address; + //! @brief Current of value of the echo + uint8_t value; //! @brief Current sound to echo std::array input; //! @brief Current sound echoed produced @@ -123,6 +131,8 @@ namespace ComSquare::APU::DSP uint8_t gain; //! @brief envelope associated with this voice uint8_t envx; + //! @brief Wave height associated with this voice + uint8_t outx; //! @brief Sample end register (ENDX) bool endx : 1; @@ -176,10 +186,10 @@ namespace ComSquare::APU::DSP uint8_t voice = 0; //! @brief Current buffer of samples int16_t *buffer; - //! @brief Limit of the buffer - int16_t *bufferEnd; - //! @brief Beginning of the buffer - int16_t *bufferStart; + //! @brief Size of buffer + uint32_t bufferSize; + //! @brief Current position in the buffer of samples + uint32_t bufferOffset; }; struct Timer { @@ -404,6 +414,10 @@ namespace ComSquare::APU::DSP int32_t interpolate(const Voice &voice); void runEnvelope(Voice &voice); + int32_t loadFIR(bool channel, int fir); + void loadEcho(bool channel); + int16_t outputEcho(bool channel); + void timerTick(); bool timerPoll(uint32_t rate); @@ -414,7 +428,7 @@ namespace ComSquare::APU::DSP uint8_t _readRAM(uint24_t addr); void _writeRAM(uint24_t addr, uint8_t data); public: - DSP(int16_t *buffer, int32_t size, std::weak_ptr map); + DSP(int16_t *buffer, uint32_t size, std::weak_ptr map); DSP(const DSP &) = default; DSP &operator=(const DSP &) = default; ~DSP() = default; diff --git a/sources/APU/DSP/Echo.cpp b/sources/APU/DSP/Echo.cpp index 5b4d999..51823c4 100644 --- a/sources/APU/DSP/Echo.cpp +++ b/sources/APU/DSP/Echo.cpp @@ -6,34 +6,89 @@ namespace ComSquare::APU::DSP { + int32_t DSP::loadFIR(bool channel, int fir) + { + int32_t sample = this->_echo.history[channel][this->_echo.historyOffset + fir + 1]; + + return (sample * this->_echo.FIR[fir]) >> 6; + } + + void DSP::loadEcho(bool channel) + { + uint16_t address = this->_echo.address + channel * 2; + uint8_t low = this->_readRAM(address++); + uint8_t high = this->_readRAM(address); + int16_t echo = (high << 8) + low; + + this->_echo.history[channel][this->_echo.historyOffset] = echo >> 1; + } + + int16_t DSP::outputEcho(bool channel) + { + int16_t master = this->_master.output[channel] * this->_master.volume[channel] >> 7; + int16_t echo = this->_echo.input[channel] * this->_echo.input[channel] >> 7; + + return master + echo; + } + void DSP::echo22() { + this->_echo.historyOffset += 1; + this->_echo.address = (this->_echo.value << 8) + this->_echo.offset; + this->loadEcho(0); + + this->_echo.input[0] = this->loadFIR(0, 0); + this->_echo.input[1] = this->loadFIR(1, 0); } void DSP::echo23() { + this->loadEcho(1); + this->_echo.input[0] += this->loadFIR(0, 1) + this->loadFIR(0, 2); + this->_echo.input[1] += this->loadFIR(1, 1) + this->loadFIR(1, 2); } void DSP::echo24() { - + this->_echo.input[0] += this->loadFIR(0, 3) + this->loadFIR(0, 4) + this->loadFIR(0, 5); + this->_echo.input[1] += this->loadFIR(1, 3) + this->loadFIR(1, 4) + this->loadFIR(1, 5); } void DSP::echo25() { - + this->_echo.input[0] += this->loadFIR(0, 6) + this->loadFIR(0, 7); + this->_echo.input[1] += this->loadFIR(1, 6) + this->loadFIR(1, 7); } void DSP::echo26() { + this->_master.output[0] = this->outputEcho(0); + this->_echo.output[0] += this->_echo.input[0] * this->_echo.feedback >> 7; + this->_echo.output[1] += this->_echo.input[1] * this->_echo.feedback >> 7; } void DSP::echo27() { + int16_t outputLeft = this->_master.output[0]; + int16_t outputRight = this->outputEcho(1); + this->_master.output[0] = 0; + this->_master.output[1] = 0; + + if (this->_master.mute) { + outputLeft = 0; + outputRight = 0; + } + + srand(time(NULL)); + this->_state.buffer[this->_state.bufferOffset] = outputLeft + (INT16_MIN + rand() % (INT16_MAX + 1 - INT16_MIN)); + this->_state.buffer[this->_state.bufferOffset + 1] = outputRight + (INT16_MIN + rand() % (INT16_MAX + 1 - INT16_MIN)); + this->_state.bufferOffset += 2; + if (this->_state.bufferOffset >= this->_state.bufferSize) + this->_state.bufferOffset = 0; } void DSP::echo28() diff --git a/sources/APU/DSP/Voice.cpp b/sources/APU/DSP/Voice.cpp index eccc7a2..197885b 100644 --- a/sources/APU/DSP/Voice.cpp +++ b/sources/APU/DSP/Voice.cpp @@ -141,16 +141,16 @@ namespace ComSquare::APU::DSP void DSP::voice7(Voice &voice) { - + this->_latch.envx = voice.envx; } void DSP::voice8(Voice &voice) { - + voice.outx = this->_latch.outx; } void DSP::voice9(Voice &voice) { - + voice.envx = this->_latch.envx; } } \ No newline at end of file