aboutsummaryrefslogtreecommitdiff
path: root/src/adldata.hh
blob: 6602e1a0619beb4aaf10dfec5ada2e8566a2667a (plain)
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
135
136
137
/*
 * libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
 *
 * Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
 * ADLMIDI Library API:   Copyright (c) 2015-2019 Vitaly Novichkov <admin@wohlnet.ru>
 *
 * Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
 * http://iki.fi/bisqwit/source/adlmidi.html
 *
 * 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 3 of the License, or
 * 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, see <http://www.gnu.org/licenses/>.
 */

#ifndef ADLDATA_H
#define ADLDATA_H

#include <string.h>
#include <stdint.h>
#include <cstring>

#pragma pack(push, 1)
#define ADLDATA_BYTE_COMPARABLE(T)                      \
    inline bool operator==(const T &a, const T &b)      \
    { return !memcmp(&a, &b, sizeof(T)); }              \
    inline bool operator!=(const T &a, const T &b)      \
    { return !operator==(a, b); }

struct adldata
{
    uint32_t    modulator_E862, carrier_E862;  // See below
    uint8_t     modulator_40, carrier_40; // KSL/attenuation settings
    uint8_t     feedconn; // Feedback/connection bits for the channel

    int8_t      finetune;
};
ADLDATA_BYTE_COMPARABLE(struct adldata)

struct adlinsdata
{
    enum { Flag_Pseudo4op = 0x01, Flag_NoSound = 0x02, Flag_Real4op = 0x04 };

    enum { Flag_RM_BassDrum  = 0x08, Flag_RM_Snare = 0x10, Flag_RM_TomTom = 0x18,
           Flag_RM_Cymbal = 0x20, Flag_RM_HiHat = 0x28, Mask_RhythmMode = 0x38 };

    uint16_t    adlno1, adlno2;
    uint8_t     tone;
    uint8_t     flags;
    uint16_t    ms_sound_kon;  // Number of milliseconds it produces sound;
    uint16_t    ms_sound_koff;
    int8_t      midi_velocity_offset;
    double      voice2_fine_tune;
};
ADLDATA_BYTE_COMPARABLE(struct adlinsdata)

enum { adlNoteOnMaxTime = 40000 };

/**
 * @brief Instrument data with operators included
 */
struct adlinsdata2
{
    adldata     adl[2];
    uint8_t     tone;
    uint8_t     flags;
    uint16_t    ms_sound_kon;  // Number of milliseconds it produces sound;
    uint16_t    ms_sound_koff;
    int8_t      midi_velocity_offset;
    double      voice2_fine_tune;
    static adlinsdata2 from_adldata(const adlinsdata &d);
};
ADLDATA_BYTE_COMPARABLE(struct adlinsdata2)

#undef ADLDATA_BYTE_COMPARABLE
#pragma pack(pop)

/**
 * @brief Bank global setup
 */
struct AdlBankSetup
{
    int     volumeModel;
    bool    deepTremolo;
    bool    deepVibrato;
    bool    scaleModulators;
};

#ifndef DISABLE_EMBEDDED_BANKS
int maxAdlBanks();
extern const adldata adl[];
extern const adlinsdata adlins[];
extern const unsigned short banks[][256];
extern const char* const banknames[];
extern const AdlBankSetup adlbanksetup[];
#endif

/**
 * @brief Conversion of storage formats
 */
inline adlinsdata2 adlinsdata2::from_adldata(const adlinsdata &d)
{
    adlinsdata2 ins;
    ins.tone = d.tone;
    ins.flags = d.flags;
    ins.ms_sound_kon = d.ms_sound_kon;
    ins.ms_sound_koff = d.ms_sound_koff;
    ins.midi_velocity_offset = d.midi_velocity_offset;
    ins.voice2_fine_tune = d.voice2_fine_tune;
#ifdef DISABLE_EMBEDDED_BANKS
    std::memset(ins.adl, 0, sizeof(adldata) * 2);
#else
    ins.adl[0] = ::adl[d.adlno1];
    ins.adl[1] = ::adl[d.adlno2];
#endif
    return ins;
}

/**
 * @brief Convert external instrument to internal instrument
 */
void cvt_ADLI_to_FMIns(adlinsdata2 &dst, const struct ADL_Instrument &src);

/**
 * @brief Convert internal instrument to external instrument
 */
void cvt_FMIns_to_ADLI(struct ADL_Instrument &dst, const adlinsdata2 &src);

#endif //ADLDATA_H