mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 21:27:52 -04:00
5e987cc0e2
Fixes #2545 Fixes #2546 Fixes #2547 Fixes #2548 Fixes #2549 Fixes #2550 Fixes #2551 Fixes #2552 Fixes #2553 Fixes #2554 Fixes #2555 Fixes #2556 Fixes #2557 Fixes #2558 Fixes #2559 Fixes #2560 Fixes #2561 Fixes #2562 Fixes #2563 Fixes #2564 Fixes #2565 Fixes #2567 Fixes #2566 Fixes #2568 Fixes #2569 Fixes #2570 Fixes #2522 Fixes #2571 --------- Co-authored-by: water <awaterford111445@gmail.com> Co-authored-by: Hat Kid <6624576+Hat-Kid@users.noreply.github.com> Co-authored-by: ManDude <7569514+ManDude@users.noreply.github.com>
118 lines
2.4 KiB
C++
118 lines
2.4 KiB
C++
// Copyright: 2021 - 2022, Ziemas
|
|
// SPDX-License-Identifier: ISC
|
|
#pragma once
|
|
#include "bitfield.h"
|
|
#include "envelope.h"
|
|
#include "fifo.h"
|
|
#include "sound_types.h"
|
|
|
|
#include "common/common_types.h"
|
|
|
|
#include "third-party/fmt/core.h"
|
|
|
|
namespace snd {
|
|
|
|
class voice {
|
|
public:
|
|
enum class AllocationType {
|
|
managed,
|
|
permanent,
|
|
};
|
|
|
|
voice(AllocationType alloc = AllocationType::managed) : m_Alloc(alloc) {}
|
|
s16_output run();
|
|
|
|
void key_on();
|
|
|
|
void key_off();
|
|
|
|
bool dead() {
|
|
if (m_Alloc == AllocationType::permanent) {
|
|
return false;
|
|
}
|
|
|
|
return m_ADSR.GetPhase() == ADSR::Phase::Stopped;
|
|
}
|
|
|
|
void set_pitch(u16 reg) {
|
|
// fmt::print("VOICE[{}] PITCH WRITE {:x}\n", m_channel, reg);
|
|
m_Pitch = reg;
|
|
}
|
|
void set_asdr1(u16 reg) {
|
|
// fmt::print("VOICE[{}] ADSR1 WRITE {:x}\n", m_channel, reg);
|
|
m_ADSR.m_Reg.lo.set(reg);
|
|
}
|
|
void set_asdr2(u16 reg) {
|
|
// fmt::print("VOICE[{}] ADSR2 WRITE {:x}\n", m_channel, reg);
|
|
m_ADSR.m_Reg.hi.set(reg);
|
|
}
|
|
void set_volume(u16 left, u16 right) {
|
|
// fmt::print("VOICE[{}] VOLL WRITE {:x}\n", m_channel, left);
|
|
// fmt::print("VOICE[{}] VOLR WRITE {:x}\n", m_channel, right);
|
|
m_Volume.left.Set(left);
|
|
m_Volume.right.Set(right);
|
|
}
|
|
|
|
void set_volume_l(u16 vol) { m_Volume.left.Set(vol); }
|
|
|
|
void set_volume_r(u16 vol) { m_Volume.right.Set(vol); }
|
|
|
|
s16 get_envx() { return m_ADSR.Level(); }
|
|
|
|
void set_sample(u16* sample) {
|
|
m_sample = sample;
|
|
m_SSA = 0;
|
|
}
|
|
|
|
u32 get_nax() { return m_NAX; }
|
|
|
|
void set_ssa(u32 addr) { m_SSA = addr; }
|
|
|
|
void set_lsa(u32 addr) {
|
|
m_LSA = addr;
|
|
m_CustomLoop = true;
|
|
}
|
|
|
|
void stop() { m_ADSR.Stop(); }
|
|
|
|
private:
|
|
union ADPCMHeader {
|
|
u16 bits;
|
|
bitfield<u16, bool, 10, 1> LoopStart;
|
|
bitfield<u16, bool, 9, 1> LoopRepeat;
|
|
bitfield<u16, bool, 8, 1> LoopEnd;
|
|
bitfield<u16, u8, 4, 3> Filter;
|
|
bitfield<u16, u8, 0, 4> Shift;
|
|
};
|
|
|
|
AllocationType m_Alloc;
|
|
bool m_Noise{false};
|
|
bool m_PitchMod{false};
|
|
bool m_KeyOn{false};
|
|
bool m_KeyOff{false};
|
|
bool m_ENDX{false};
|
|
|
|
void DecodeSamples();
|
|
void UpdateBlockHeader();
|
|
|
|
fifo<s16, 0x20> m_DecodeBuf{};
|
|
s16 m_DecodeHist1{0};
|
|
s16 m_DecodeHist2{0};
|
|
u32 m_Counter{0};
|
|
|
|
u16 m_Pitch{0};
|
|
s16 m_Out{0};
|
|
|
|
u16* m_sample{nullptr};
|
|
u32 m_SSA{0};
|
|
u32 m_NAX{0};
|
|
u32 m_LSA{0};
|
|
bool m_CustomLoop{false};
|
|
|
|
ADPCMHeader m_CurHeader{};
|
|
|
|
ADSR m_ADSR{};
|
|
VolumePair m_Volume{};
|
|
};
|
|
} // namespace snd
|