jak-project/game/sound/989snd/midi_handler.h

135 lines
3 KiB
C
Raw Normal View History

// Copyright: 2021 - 2024, Ziemas
2022-05-19 16:54:36 -04:00
// SPDX-License-Identifier: ISC
#pragma once
#include <exception>
#include <list>
#include <memory>
2022-05-19 16:54:36 -04:00
#include <optional>
#include <string>
#include <utility>
#include "ame_handler.h"
#include "musicbank.h"
#include "sound_handler.h"
#include "vagvoice.h"
#include "common/common_types.h"
2022-05-19 16:54:36 -04:00
namespace snd {
class midi_voice : public VagVoice {
2022-05-19 16:54:36 -04:00
public:
midi_voice(Tone& t, MusicBank::Prog& _prog) : VagVoice(t), prog(_prog) {}
2022-05-19 16:54:36 -04:00
u8 note{0};
u8 channel{0};
u8 velocity{0};
MusicBank::Prog& prog;
2022-05-19 16:54:36 -04:00
};
class AmeHandler;
class MidiHandler : public SoundHandler {
2022-05-19 16:54:36 -04:00
public:
MidiHandler(Midi* block,
VoiceManager& vm,
MusicBank::MIDISound& sound,
s32 vol,
s32 pan,
SoundBank& bank);
2022-05-19 16:54:36 -04:00
MidiHandler(Midi* block,
VoiceManager& vm,
MusicBank::MIDISound& sound,
s32 vol,
s32 pan,
SoundBank& bank,
std::optional<AmeHandler*> parent);
2022-05-19 16:54:36 -04:00
~MidiHandler() override {
2022-05-19 16:54:36 -04:00
for (auto& p : m_voices) {
auto v = p.lock();
if (v != nullptr) {
v->Stop();
2022-05-19 16:54:36 -04:00
}
}
}
void InitMidi();
void Start();
bool Tick() override;
void MuteChannel(u8 channel);
void UnmuteChannel(u8 channel);
SoundBank& Bank() override { return m_bank; };
void Pause() override;
void Stop() override;
void Unpause() override;
u8 Group() override { return m_sound.VolGroup; }
void SetVolPan(s32 vol, s32 pan) override;
bool Complete() { return m_track_complete; };
void SetPMod(s32 mod) override;
2022-05-19 16:54:36 -04:00
private:
static constexpr int tickrate = 240;
static constexpr int mics_per_tick = 1000000 / tickrate;
struct MidiError : public std::exception {
MidiError(std::string text) : msg(std::move(text)) {}
MidiError() : msg("Unknown MIDI error") {}
2022-05-19 16:54:36 -04:00
std::string msg;
const char* what() const noexcept override { return msg.c_str(); }
};
std::optional<AmeHandler*> m_parent;
2022-05-19 16:54:36 -04:00
std::list<std::weak_ptr<midi_voice>> m_voices;
MusicBank::MIDISound& m_sound;
2022-05-19 16:54:36 -04:00
s32 m_vol{0x7f};
s32 m_pan{0};
s32 m_cur_pm{0};
2022-05-19 16:54:36 -04:00
s8 m_repeats{0};
SoundBank& m_bank;
2022-05-19 16:54:36 -04:00
bool m_paused{false};
Midi* m_header{nullptr};
2022-05-19 16:54:36 -04:00
std::array<bool, 16> m_mute_state{};
std::array<s8, 16> m_chanvol{};
2023-01-02 09:40:30 -05:00
std::array<s16, 16> m_chanpan{};
std::array<s16, 16> m_pitch_bend{};
2022-05-19 16:54:36 -04:00
u8* m_sample_data{nullptr};
u8* m_seq_data_start{nullptr};
u8* m_seq_ptr{nullptr};
u8 m_status{0};
u32 m_tempo{500000};
u32 m_ppq{480};
u32 m_time{0};
s32 m_tickerror{0};
s32 m_tickdelta{0};
s32 m_ppt{0};
u64 m_tick_countdown{0};
bool m_get_delta{true};
bool m_track_complete{false};
u32 m_muted_channels{0};
std::array<u8, 16> m_programs{};
VoiceManager& m_vm;
2022-05-19 16:54:36 -04:00
void Step();
void NewDelta();
2022-05-19 16:54:36 -04:00
void NoteOn();
void NoteOff();
void ControllerChange();
void ChannelPressure();
void ProgramChange();
void MetaEvent();
void SystemEvent();
void ChannelPitch();
2022-05-19 16:54:36 -04:00
static std::pair<size_t, u32> ReadVLQ(u8* value);
2022-05-19 16:54:36 -04:00
};
} // namespace snd