gzdoom/libraries/timidityplus/timiditypp/instrum.h
Christoph Oelckers 7468c0f36d - consolidated the different file access interfaces in the backends into one shared version.
This was getting a bit unwieldy. The include path setup is not perfect yet, that's work for later.
(It's about time we're getting C++20 with modules so that this include path madness can be put to an end.)
2019-09-28 23:17:16 +02:00

564 lines
17 KiB
C++

/*
TiMidity++ -- MIDI to WAVE converter and player
Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
instrum.h
*/
#ifndef ___INSTRUM_H_
#define ___INSTRUM_H_
#include <string>
#include "common.h"
#include "sysdep.h"
#include "sffile.h"
#include "sflayer.h"
#include "sfitem.h"
#include "../../music_common/fileio.h"
namespace TimidityPlus
{
using timidity_file = MusicIO::FileInterface;
enum
{
READ_CONFIG_SUCCESS = 0,
READ_CONFIG_ERROR = 1,
READ_CONFIG_RECURSION = 2, /* Too much recursion */
READ_CONFIG_FILE_NOT_FOUND = 3, /* Returned only w. allow_missing_file */
};
struct Sample
{
splen_t
loop_start, loop_end, data_length;
int32_t
sample_rate, low_freq, high_freq, root_freq;
int8_t panning, note_to_use;
int32_t
envelope_rate[6], envelope_offset[6],
modenv_rate[6], modenv_offset[6];
double
volume;
sample_t
*data;
int32_t
tremolo_sweep_increment, tremolo_phase_increment,
vibrato_sweep_increment, vibrato_control_ratio;
int16_t
tremolo_depth;
int16_t vibrato_depth;
uint8_t
modes, data_alloced,
low_vel, high_vel;
int32_t cutoff_freq; /* in Hz, [1, 20000] */
int16_t resonance; /* in centibels, [0, 960] */
/* in cents, [-12000, 12000] */
int16_t tremolo_to_pitch, tremolo_to_fc, modenv_to_pitch, modenv_to_fc,
envelope_keyf[6], envelope_velf[6], modenv_keyf[6], modenv_velf[6],
vel_to_fc, key_to_fc;
int16_t vel_to_resonance; /* in centibels, [-960, 960] */
int8_t envelope_velf_bpo, modenv_velf_bpo,
key_to_fc_bpo, vel_to_fc_threshold; /* in notes */
int32_t vibrato_delay, tremolo_delay, envelope_delay, modenv_delay; /* in samples */
int16_t scale_freq; /* in notes */
int16_t scale_factor; /* in 1024divs/key */
int8_t inst_type;
int32_t sf_sample_index, sf_sample_link; /* for stereo SoundFont */
uint16_t sample_type; /* 1 = Mono, 2 = Right, 4 = Left, 8 = Linked, $8000 = ROM */
double root_freq_detected; /* root freq from pitch detection */
int transpose_detected; /* note offset from detected root */
int chord; /* type of chord for detected pitch */
};
/* Bits in modes: */
enum
{
MODES_16BIT = (1 << 0),
MODES_UNSIGNED = (1 << 1),
MODES_LOOPING = (1 << 2),
MODES_PINGPONG = (1 << 3),
MODES_REVERSE = (1 << 4),
MODES_SUSTAIN = (1 << 5),
MODES_ENVELOPE = (1 << 6),
MODES_CLAMPED = (1 << 7), /* ?? (for last envelope??) */
INST_GUS = 0,
INST_SF2 = 1,
INST_MOD = 2,
INST_PCM = 3, /* %sample */
/* sfSampleType */
SF_SAMPLETYPE_MONO = 1,
SF_SAMPLETYPE_RIGHT = 2,
SF_SAMPLETYPE_LEFT = 4,
SF_SAMPLETYPE_LINKED = 8,
SF_SAMPLETYPE_ROM = 0x8000,
};
struct Instrument
{
int type;
int samples;
Sample *sample;
char *instname;
};
struct ToneBankElement
{
char *name;
char *comment;
Instrument *instrument;
int8_t note, pan, strip_loop, strip_envelope, strip_tail, loop_timeout,
font_preset, font_keynote, legato, tva_level, play_note, damper_mode;
uint8_t font_bank;
uint8_t instype; /* 0: Normal
1: %font
2: %sample
3-255: reserved
*/
int16_t amp;
int16_t rnddelay;
int tunenum;
float *tune;
int sclnotenum;
int16_t *sclnote;
int scltunenum;
int16_t *scltune;
int fcnum;
int16_t *fc;
int resonum;
int16_t *reso;
int trempitchnum, tremfcnum, modpitchnum, modfcnum;
int16_t *trempitch, *tremfc, *modpitch, *modfc;
int envratenum, envofsnum;
int **envrate, **envofs;
int modenvratenum, modenvofsnum;
int **modenvrate, **modenvofs;
int envvelfnum, envkeyfnum;
int **envvelf, **envkeyf;
int modenvvelfnum, modenvkeyfnum;
int **modenvvelf, **modenvkeyf;
int tremnum, vibnum;
struct Quantity_ **trem, **vib;
int16_t vel_to_fc, key_to_fc, vel_to_resonance;
int8_t reverb_send, chorus_send, delay_send;
};
/* A hack to delay instrument loading until after reading the
entire MIDI file. */
#define MAGIC_LOAD_INSTRUMENT ((Instrument *)(-1))
#define MAGIC_ERROR_INSTRUMENT ((Instrument *)(-2))
#define IS_MAGIC_INSTRUMENT(ip) ((ip) == MAGIC_LOAD_INSTRUMENT || (ip) == MAGIC_ERROR_INSTRUMENT)
#define DYNAMIC_INSTRUMENT_NAME ""
struct AlternateAssign
{
/* 128 bit vector:
* bits[(note >> 5) & 0x3] & (1 << (note & 0x1F))
*/
uint32_t bits[4];
AlternateAssign* next;
};
struct ToneBank
{
ToneBankElement tone[128];
AlternateAssign *alt;
};
struct SpecialPatch /* To be used MIDI Module play mode */
{
int type;
int samples;
Sample *sample;
char *name;
int32_t sample_offset;
};
enum instrument_mapID
{
INST_NO_MAP = 0,
SC_55_TONE_MAP,
SC_55_DRUM_MAP,
SC_88_TONE_MAP,
SC_88_DRUM_MAP,
SC_88PRO_TONE_MAP,
SC_88PRO_DRUM_MAP,
SC_8850_TONE_MAP,
SC_8850_DRUM_MAP,
XG_NORMAL_MAP,
XG_SFX64_MAP,
XG_SFX126_MAP,
XG_DRUM_MAP,
GM2_TONE_MAP,
GM2_DRUM_MAP,
NUM_INST_MAP
};
enum
{
MAP_BANK_COUNT = 256,
NSPECIAL_PATCH = 256,
SPECIAL_PROGRAM = -1,
MAX_MREL = 5000,
DEFAULT_MREL = 800,
};
struct SFInsts;
struct InstList;
struct SampleList;
struct AIFFCommonChunk;
struct AIFFSoundDataChunk;
struct SampleImporter;
class Instruments
{
std::string configFileName;
MusicIO::SoundFontReaderInterface *sfreader;
ToneBank standard_tonebank, standard_drumset;
enum
{
INSTRUMENT_HASH_SIZE = 128,
};
struct InstrumentCache
{
char *name;
int panning, amp, note_to_use, strip_loop, strip_envelope, strip_tail;
Instrument *ip;
InstrumentCache *next;
};
InstrumentCache *instrument_cache[INSTRUMENT_HASH_SIZE] = { nullptr };
/* bank mapping (mapped bank) */
struct bank_map_elem
{
int16_t used = 0, mapid = 0;
int bankno = 0;
};
bank_map_elem map_bank[MAP_BANK_COUNT], map_drumset[MAP_BANK_COUNT];
int map_bank_counter = 0;
struct inst_map_elem
{
int set, elem, mapped;
};
inst_map_elem *inst_map_table[NUM_INST_MAP][128] = { { nullptr} };
struct UserInstrument
{
int8_t bank;
int8_t prog;
int8_t source_map;
int8_t source_bank;
int8_t source_prog;
int8_t vibrato_rate;
int8_t vibrato_depth;
int8_t cutoff_freq;
int8_t resonance;
int8_t env_attack;
int8_t env_decay;
int8_t env_release;
int8_t vibrato_delay;
UserInstrument *next;
};
UserInstrument *userinst_first = (UserInstrument *)NULL;
UserInstrument *userinst_last = (UserInstrument *)NULL;
struct UserDrumset {
int8_t bank;
int8_t prog;
int8_t play_note;
int8_t level;
int8_t assign_group;
int8_t pan;
int8_t reverb_send_level;
int8_t chorus_send_level;
int8_t rx_note_off;
int8_t rx_note_on;
int8_t delay_send_level;
int8_t source_map;
int8_t source_prog;
int8_t source_note;
UserDrumset *next;
};
struct SFBags
{
int nbags;
uint16_t *bag;
int ngens;
SFGenRec *gen;
};
SFBags prbags, inbags;
UserDrumset *userdrum_first = (UserDrumset *)NULL;
UserDrumset *userdrum_last = (UserDrumset *)NULL;
AlternateAssign alt[2];
/* Some functions get aggravated if not even the standard banks are available. */
ToneBank
*tonebank[128 + MAP_BANK_COUNT] = { &standard_tonebank },
*drumset[128 + MAP_BANK_COUNT] = { &standard_drumset };
Instrument *default_instrument = 0;
SpecialPatch *special_patch[NSPECIAL_PATCH] = { nullptr };
int default_program[MAX_CHANNELS] = { 0 }; /* This is only used for tracks that don't specify a program */
char *default_instrument_name = nullptr;
int progbase = 0;
int32_t modify_release = 0;
bool opt_sf_close_each_file = true;
char def_instr_name[256] = { '\0' };
SFInsts *sfrecs = nullptr;
SFInsts *current_sfrec = nullptr;
int last_sample_type = 0;
int last_sample_instrument = 0;
int last_sample_keyrange = 0;
SampleList *last_sample_list = nullptr;
LayerItem layer_items[SF_EOF];
/* convert from 8bit value to fractional offset (15.15) */
int32_t to_offset_22(int offset)
{
return (int32_t)offset << (7 + 15);
}
int32_t calc_rate_i(int diff, double msec);
int32_t convert_envelope_rate(uint8_t rate);
int32_t convert_envelope_offset(uint8_t offset);
int32_t convert_tremolo_sweep(uint8_t sweep);
int32_t convert_vibrato_sweep(uint8_t sweep, int32_t vib_control_ratio);
int32_t convert_tremolo_rate(uint8_t rate);
int32_t convert_vibrato_rate(uint8_t rate);
void reverse_data(int16_t *sp, int32_t ls, int32_t le);
int name_hash(char *name);
Instrument *search_instrument_cache(char *name, int panning, int amp, int note_to_use, int strip_loop, int strip_envelope, int strip_tail);
void store_instrument_cache(Instrument *ip, char *name, int panning, int amp, int note_to_use, int strip_loop, int strip_envelope, int strip_tail);
int32_t to_rate(int rate);
void apply_bank_parameter(Instrument *ip, ToneBankElement *tone);
Instrument *load_gus_instrument(char *name, ToneBank *bank, int dr, int prog);
int fill_bank(int dr, int b, int *rc);
void free_tone_bank_list(ToneBank *tb[]);
void free_tone_bank(void);
void free_instrument_map(void);
int set_default_instrument(char *name);
void *safe_memdup(void *s, size_t size);
void MarkInstrument(int banknum, int percussion, int instr);
//smplfile.c
Instrument *extract_sample_file(char *);
int32_t convert_envelope_rate_s(uint8_t rate);
void initialize_sample(Instrument *inst, int frames, int sample_bits, int sample_rate);
int get_importers(const char *sample_file, int limit, SampleImporter **importers);
int get_next_importer(char *sample_file, int start, int count, SampleImporter **importers);
int import_wave_discriminant(char *sample_file);
int import_wave_load(char *sample_file, Instrument *inst);
int import_aiff_discriminant(char *sample_file);
int import_aiff_load(char *sample_file, Instrument *inst);
int read_AIFFCommonChunk(timidity_file *tf, AIFFCommonChunk *comm, int csize, int compressed);
int read_AIFFSoundData(timidity_file *tf, Instrument *inst, AIFFCommonChunk *common);
int read_AIFFSoundDataChunk(timidity_file *tf, AIFFSoundDataChunk *sound, int csize, int mode);
// sndfont.cpp
SFInsts *find_soundfont(char *sf_file);
SFInsts *new_soundfont(char *sf_file);
void init_sf(SFInsts *rec);
void end_soundfont(SFInsts *rec);
Instrument *try_load_soundfont(SFInsts *rec, int order, int bank, int preset, int keynote);
Instrument *load_from_file(SFInsts *rec, InstList *ip);
int is_excluded(SFInsts *rec, int bank, int preset, int keynote);
int is_ordered(SFInsts *rec, int bank, int preset, int keynote);
int load_font(SFInfo *sf, int pridx);
int parse_layer(SFInfo *sf, int pridx, LayerTable *tbl, int level);
int is_global(SFGenLayer *layer);
void clear_table(LayerTable *tbl);
void set_to_table(SFInfo *sf, LayerTable *tbl, SFGenLayer *lay, int level);
void add_item_to_table(LayerTable *tbl, int oper, int amount, int level);
void merge_table(SFInfo *sf, LayerTable *dst, LayerTable *src);
void init_and_merge_table(SFInfo *sf, LayerTable *dst, LayerTable *src);
int sanity_range(LayerTable *tbl);
int make_patch(SFInfo *sf, int pridx, LayerTable *tbl);
void make_info(SFInfo *sf, SampleList *vp, LayerTable *tbl);
double calc_volume(LayerTable *tbl);
void set_sample_info(SFInfo *sf, SampleList *vp, LayerTable *tbl);
void set_init_info(SFInfo *sf, SampleList *vp, LayerTable *tbl);
void reset_last_sample_info(void);
int abscent_to_Hz(int abscents);
void set_rootkey(SFInfo *sf, SampleList *vp, LayerTable *tbl);
void set_rootfreq(SampleList *vp);
int32_t to_offset(int32_t offset);
int32_t to_rate(int32_t diff, int timecent);
int32_t calc_rate(int32_t diff, double msec);
double to_msec(int timecent);
int32_t calc_sustain(int sust_cB);
void convert_volume_envelope(SampleList *vp, LayerTable *tbl);
void convert_tremolo(SampleList *vp, LayerTable *tbl);
void convert_vibrato(SampleList *vp, LayerTable *tbl);
void set_envelope_parameters(SampleList *vp);
// configfile
int set_patchconf(const char *name, int line, ToneBank *bank, char *w[], int dr, int mapid, int bankmapfrom, int bankno);
int strip_trailing_comment(char *string, int next_token_index);
char *expand_variables(char *string, MBlockList *varbuf, const char *basedir);
int set_gus_patchconf(const char *name, int line, ToneBankElement *tone, char *pat, char **opts);
void reinit_tone_bank_element(ToneBankElement *tone);
int set_gus_patchconf_opts(const char *name, int line, char *opts, ToneBankElement *tone);
int copymap(int mapto, int mapfrom, int isdrum);
void copybank(ToneBank *to, ToneBank *from, int mapid, int bankmapfrom, int bankno);
// sffile.cpp
int chunkid(char *id);
int process_list(int size, SFInfo *sf, timidity_file *fd);
int process_info(int size, SFInfo *sf, timidity_file *fd);
int process_sdta(int size, SFInfo *sf, timidity_file *fd);
int process_pdta(int size, SFInfo *sf, timidity_file *fd);
void load_sample_names(int size, SFInfo *sf, timidity_file *fd);
void load_preset_header(int size, SFInfo *sf, timidity_file *fd);
void load_inst_header(int size, SFInfo *sf, timidity_file *fd);
void load_bag(int size, SFBags *bagp, timidity_file *fd);
void load_gen(int size, SFBags *bagp, timidity_file *fd);
void load_sample_info(int size, SFInfo *sf, timidity_file *fd);
void convert_layers(SFInfo *sf);
void generate_layers(SFHeader *hdr, SFHeader *next, SFBags *bags);
void free_layer(SFHeader *hdr);
int load_soundfont(SFInfo *sf, timidity_file *fd);
void free_soundfont(SFInfo *sf);
void correct_samples(SFInfo *sf);
public:
Instruments();
bool load(MusicIO::SoundFontReaderInterface *);
~Instruments();
const ToneBank *toneBank(int i) const
{
return tonebank[i];
}
int defaultProgram(int i) const
{
return default_program[i];
}
const ToneBank *drumSet(int i) const
{
return drumset[i];
}
const SpecialPatch *specialPatch(int i) const
{
return special_patch[i];
}
void setSpecialPatchOffset(int i, int32_t ofs)
{
special_patch[i]->sample_offset = ofs;
}
Instrument *defaultInstrument() const
{
return default_instrument;
}
/* instrum.c */
int load_missing_instruments(int *rc);
void free_instruments(int reload_default_inst);
void free_special_patch(int id);
void clear_magic_instruments(void);
Instrument *load_instrument(int dr, int b, int prog);
int find_instrument_map_bank(int dr, int map, int bk);
int alloc_instrument_map_bank(int dr, int map, int bk);
void alloc_instrument_bank(int dr, int bankset);
int instrument_map(int mapID, int *set_in_out, int *elem_in_out) const;
void set_instrument_map(int mapID, int set_from, int elem_from, int set_to, int elem_to);
AlternateAssign *add_altassign_string(AlternateAssign *old, char **params, int n);
AlternateAssign *find_altassign(AlternateAssign *altassign, int note);
void copy_tone_bank_element(ToneBankElement *elm, const ToneBankElement *src);
void free_tone_bank_element(ToneBankElement *elm);
void free_instrument(Instrument *ip);
void squash_sample_16to8(Sample *sp);
Instrument *play_midi_load_instrument(int dr, int bk, int prog, bool *pLoad_success);
void recompute_userinst(int bank, int prog);
Instrument *recompute_userdrum(int bank, int prog);
UserInstrument *get_userinst(int bank, int prog);
UserDrumset *get_userdrum(int bank, int prog);
void recompute_userdrum_altassign(int bank, int group);
/*! initialize GS user drumset. */
void init_userdrum();
void free_userdrum();
void init_userinst() { free_userinst(); }
void free_userinst();
void mark_instrument(int newbank, int newprog)
{
if (!(tonebank[newbank]->tone[newprog].instrument))
tonebank[newbank]->tone[newprog].instrument =
MAGIC_LOAD_INSTRUMENT;
}
void mark_drumset(int newbank, int newprog)
{
if (!(drumset[newbank]->tone[newprog].instrument))
drumset[newbank]->tone[newprog].instrument =
MAGIC_LOAD_INSTRUMENT;
}
/* sndfont.c */
void add_soundfont(char *sf_file, int sf_order, int cutoff_allowed, int resonance_allowed, int amp);
void remove_soundfont(char *sf_file);
void init_load_soundfont(void);
Instrument *load_soundfont_inst(int order, int bank, int preset, int keynote);
Instrument *extract_soundfont(char *sf_file, int bank, int preset, int keynote);
int exclude_soundfont(int bank, int preset, int keynote);
int order_soundfont(int bank, int preset, int keynote, int order);
char *soundfont_preset_name(int bank, int preset, int keynote, char **sndfile);
void free_soundfonts(void);
void PrecacheInstruments(const uint16_t *instruments, int count);
int read_config_file(const char *name, int self, int allow_missing_file);
void set_default_instrument()
{
set_default_instrument(def_instr_name);
}
};
}
#endif /* ___INSTRUM_H_ */