1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
#pragma once
#include <cstdint>
#include <map>
#include <memory>
#include <vector>
#include "factories/BaseFactory.h"
#ifdef BUILD_UI
#include "ui/audio/SequenceDriver.h"
#endif
// Preview-only PM64 audio assets. When preview mode is on, the PM64:AUDIO
// factory walks the SBN container and registers one PM64:BGM asset per song
// and one PM64:BK_SAMPLE asset per bank instrument (see pmret src/audio).
namespace PM64Audio {
// One BK instrument: VADPCM wave data plus its codebook, loop, tuning and
// envelope presets (press/release command list pairs).
struct Instrument {
std::vector<uint8_t> wav;
std::vector<int16_t> book; // codebook s16s (order 2)
int32_t loopStart = 0;
int32_t loopEnd = 0;
int32_t loopCount = 0;
uint16_t keyBase = 4800; // cents
int32_t sampleRate = 32000;
uint8_t type = 0;
std::vector<std::pair<std::vector<uint8_t>, std::vector<uint8_t>>> envelopes;
};
struct Bank {
char name[5] = {};
std::shared_ptr<Instrument> instruments[16];
};
// Banks parsed from ROM, keyed by BK file ROM offset; filled during parsing so
// the BGM driver can resolve (bank set, patch) at preview time.
std::map<uint32_t, std::shared_ptr<Bank>>& BankRegistry();
std::shared_ptr<Bank> ParseBank(const std::vector<uint8_t>& rom, uint32_t off);
// Global PER drum table and PRG program table (parsed from the SBN's INIT
// extra files by the PM64:AUDIO factory).
struct DrumInfo {
uint16_t bankPatch = 0;
uint16_t keyBase = 4800;
uint8_t volume = 127;
int8_t pan = 64;
uint8_t reverb = 0;
uint8_t randTune = 0, randVolume = 0, randPan = 0, randReverb = 0;
};
struct ProgramInfo {
uint16_t bankPatch = 0;
uint8_t volume = 127;
int8_t pan = 64;
uint8_t reverb = 0;
int8_t coarseTune = 0, fineTune = 0;
};
struct GlobalData {
std::vector<DrumInfo> perDrums;
std::vector<ProgramInfo> prgPrograms;
};
GlobalData& Globals();
// Preview asset registration is opt-in so extraction runs stay clean.
void SetPreviewAssets(bool enabled);
bool PreviewAssets();
// Walks the SBN container (big-endian ROM data) and registers the per-song
// and per-instrument preview assets. Called by the PM64:AUDIO factory.
void RegisterPreviewAssets(const std::vector<uint8_t>& rom, uint32_t sbnBase);
} // namespace PM64Audio
class PM64BkSampleData : public IParsedData {
public:
std::shared_ptr<PM64Audio::Bank> bank;
int slot = 0;
};
// Preview assets still need an exporter registered or ParseNode discards the
// parse result; Binary writes the raw payload.
class PM64BkSampleBinaryExporter : public BaseExporter {
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName,
YAML::Node& node, std::string* replacement) override;
};
class PM64BkSampleFactory : public BaseFactory {
public:
std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override;
inline std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override {
return {
REGISTER(Binary, PM64BkSampleBinaryExporter)
};
}
};
class PM64BgmData : public IParsedData {
public:
std::vector<uint8_t> file;
};
class PM64BgmBinaryExporter : public BaseExporter {
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName,
YAML::Node& node, std::string* replacement) override;
};
class PM64BgmFactory : public BaseFactory {
public:
std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override;
inline std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override {
return {
REGISTER(Binary, PM64BgmBinaryExporter)
};
}
};
#ifdef BUILD_UI
class PM64BkSampleFactoryUI : public BaseFactoryUI {
public:
float GetItemHeight(const ParseResultData& data) override;
void DrawUI(const ParseResultData& data) override;
};
// Offline BGM interpreter (port of pmret au_bgm_player_update_playing).
class SequencePlayerPM64 : public UI::SequenceDriver {
public:
bool Render(const ParseResultData& item, int option, UI::RenderedAudio& out) override;
std::vector<std::string> Options(const ParseResultData& item) override;
};
#endif
|