moe-bius/vgm2opl_next/vgm2opl_next/opmctx.h
2025-08-12 23:48:52 +07:00

239 lines
6 KiB
C++

#pragma once
#include <stdint.h>
#include "opmfile.h"
#include "vgm.h"
#include <vector>
#include <string>
#include <map>
struct opm_control_track_t {
uint32_t frame;
int type, data;
};
/*
oof
â îáùåì, äëÿ êàæäîãî ôðåéìà ïîíàäîáèòñÿ õðàíèòü öåïî÷êó ñîáûòèé, ðàçäåëÿåìûõ
çàïèñüþ â key on (åñëè òàêîâàÿ åñòü), ïîñêîëüêó äëÿ ðåòðèãà íîòû íàäî ñíà÷àëà
ñáîðñèòü key on â 0, çàòåì ïîñòàâèòü â 1
*/
enum : uint64_t {
// control stream
OPM_REC_REG24 = (1 << 0),
OPM_REC_REG25 = (1 << 1),
OPM_REC_REG27 = (1 << 2),
OPM_REC_REG22 = (1 << 3),
OPM_REC_EXTCH3_OP1_LOW = (1 << 4),
OPM_REC_EXTCH3_OP1_HIGH = (1 << 5),
OPM_REC_EXTCH3_OP2_LOW = (1 << 6),
OPM_REC_EXTCH3_OP2_HIGH = (1 << 7),
OPM_REC_EXTCH3_OP3_LOW = (1 << 8),
OPM_REC_EXTCH3_OP3_HIGH = (1 << 9),
// FM stream
OPM_REC_REG30 = (1 << 0),
OPM_REC_REG40 = (1 << 1),
OPM_REC_REG50 = (1 << 2),
OPM_REC_REG60 = (1 << 3),
OPM_REC_REG70 = (1 << 4),
OPM_REC_REG80 = (1 << 5),
OPM_REC_REG90 = (1 << 6),
OPM_REC_REG30_IDX = 0,
OPM_REC_REG40_IDX = 1,
OPM_REC_REG50_IDX = 2,
OPM_REC_REG60_IDX = 3,
OPM_REC_REG70_IDX = 4,
OPM_REC_REG80_IDX = 5,
OPM_REC_REG90_IDX = 6,
OPM_REC_OP_SHIFTMUL = 7,
OPM_REC_CHREG_SHIFT = OPM_REC_OP_SHIFTMUL*4,
OPM_REC_REGA0 = (1ULL << (OPM_REC_CHREG_SHIFT + 0)),
OPM_REC_REGA4 = (1ULL << (OPM_REC_CHREG_SHIFT + 1)),
OPM_REC_REGB0 = (1ULL << (OPM_REC_CHREG_SHIFT + 2)),
OPM_REC_REGB4 = (1ULL << (OPM_REC_CHREG_SHIFT + 3)),
OPM_REC_KEY = (1ULL << (OPM_REC_CHREG_SHIFT + 4)),
// SSG tone stream
OPM_REC_AYTONE_VOLUME = (1 << 0),
OPM_REC_AYTONE_PERIOD_LOW = (1 << 1),
OPM_REC_AYTONE_PERIOD_HIGH = (1 << 2),
OPM_REC_AYTONE_MASK = (1 << 3),
// SSG env/noise stream
OPM_REC_AYENV_NOISE = (1 << 0),
OPM_REC_AYENV_PERIOD_LOW = (1 << 1),
OPM_REC_AYENV_PERIOD_HIGH = (1 << 2),
OPM_REC_AYENV_ENVTYPE = (1 << 3),
// rhythm stream
OPM_RHYTHM_REG10_KEYON = (1 << 16),
};
struct opm_frame_record {
uint64_t flags; // yeah!
union {
struct {
// control channel
int reg24, reg25, reg27, reg22;
struct {
int freq[2][4];
} extch3;
};
struct {
// fm channel
int opdata[4][9-3+1]; // regs 30..90
int fnum, block, fb, pan, key;
};
struct {
// SSG tone channel
int volume, mask, period_low, period_hi;
} aytone;
struct {
// SSG envelope/noise channel
int noise, envtype, period_low, period_hi;
} ayenv;
struct {
// rhythm channels
int regs[16];
int key_on;
} rhythm;
};
};
enum {
OPM_CHAN_NEWPATTERN = (1 << 0),
OPM_CHAN_LOOP_POINT = (1 << 1),
OPM_FRAME0 = (1 << 2),
OPM_CHAN_BACKREF = (1 << 8),
};
struct opm_channel_record_t {
// current frame index
uint32_t frame;
// distance between next and this frame
uint32_t frame_dist;
// flags
int flags;
// raw data
std::vector<uint8_t> rawdata;
// records
std::vector<opm_frame_record> records;
// compression data
int distance_frames, distance_bytes, frames_to_play, frames_to_play_total;
// byte stamp
uint32_t byte_stamp;
};
struct opm_framerate_estimate_t {
float max_delay_freq; // maximum possible frequency, delays faster are concatenated together
float max_delay_base; // maximum base delay allowed
float min_delay_threshold; // percentile of delays used to find the minimum delay
float trim_threshold; // delays with occurence lower than threshld will be trimmed
float rescale_min_ratio; // used to rescale delays to one base
};
struct vgm_context_t {
std::vector<uint8_t> vgmfile;
VGMHeader* header;
uint32_t loop_pos;
uint32_t start, end; // offsets
};
struct opm_channel_rawdata_t {
// current frame index
uint32_t frame;
// loop flag
bool loop;
// raw OPL data
std::vector<uint8_t> data;
};
struct opm_channel_t {
// non-empty (i.e key on present)
bool used;
// OPL register stream (parsed from VGM)
std::vector<opm_channel_rawdata_t> opl;
// records
std::vector<opm_channel_record_t> records;
// packed records
std::vector<opm_channel_record_t> packed;
// raw stream bytes
std::vector<uint8_t> rawstream;
// stream descriptor
opm_header_stream_desc_t streamdesc;
};
struct opm_convert_context_t {
// VGM context
vgm_context_t vgm;
// chip type
uint32_t chip_type; // OPM_FLAG_CHIP_*
uint32_t max_channels;
uint32_t ctrl_chidx;
uint32_t fm_chidx;
uint32_t ssg_chidx;
uint32_t rhy_chidx;
uint32_t dual_chidx;
bool percussion_mode;
// conversion flags
struct {
int compress_level;
int max_stack_depth;
int verbosity;
bool optimize_vgm;
} flags;
// frame rate stuff
double delay;
opm_framerate_estimate_t estimate;
// total frames
uint32_t total_frames;
// -----------------------------------
// channel struct
std::vector<opm_channel_t> ch;
// raw per-channel OPL data
std::vector<std::vector<opm_channel_rawdata_t>> oplchan;
std::vector<std::vector<uint8_t>> oplchan_out;
// -----------------------------------
// channel records
std::vector<std::vector<opm_channel_record_t>> opmrecords;
// compressed streams
std::vector<std::vector<opm_channel_record_t>> opmpacked;
// final OPM stream
std::vector<std::vector<uint8_t>> opmstream;
// -----------------------------------
struct {
std::string name_prefix;
std::string filename;
std::string foldername;
opm_header_t header;
std::vector<opm_header_stream_desc_t> streamdesc;
} opmfile;
std::string logname;
};