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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
use super::*;
use std::convert::TryFrom;
use std::fmt::{self, Debug};
use std::ops::Index;
#[derive(Clone, Debug)]
pub struct Instrument {
pub header: InstrumentHeader,
pub samples: Vec<Sample>,
}
#[derive(Clone, Debug)]
pub struct InstrumentHeader {
pub name: Name,
pub filename: DOSFilename,
pub flags: InstrumentFlags,
pub new_note_action: u8,
pub duplicate_check_type: u8,
pub duplicate_check_action: u8,
pub instrument_fadeout: u8,
pub pitch_pan_separation: i8,
pub pitch_pan_centre: u8,
pub global_volume: u8,
pub default_panning: RangedU8<0, 128>,
pub random_volume_variation: RangedU8<0, 100>,
pub random_panning_variation: RangedU8<0, 64>,
pub trkver: u16,
pub number_of_samples: u8,
pub initial_filter_cutoff: RangedU8<0, 128>,
pub initial_filter_resonance: RangedU8<0, 128>,
pub mch: u8,
pub mpr: u8,
pub mbank: [u8; 2],
pub sample_map: SampleMap,
pub volume_envelope: Envelope,
pub panning_envelope: Envelope,
pub pitch_filter_envelope: Envelope,
}
bitflags! {
#[derive(Default)]
pub struct InstrumentFlags: u8 {
const ENABLE_PANNING = 1 << 0;
const ENABLE_FILTER_CUTOFF = 1 << 1;
const ENABLE_FILTER_RESONANCE = 1 << 1;
}
}
#[derive(Clone)]
pub struct SampleMap {
pub(crate) map: [Option<SampleId>; 120],
}
#[allow(non_upper_case_globals)]
impl InstrumentHeader {
pub(crate) const dfp_ignorePanning: u8 = 0x80;
pub(crate) const ifc_enableCutoff: u8 = 0x80;
pub(crate) const ifr_enableResonance: u8 = 0x80;
}
impl Default for SampleMap {
fn default() -> SampleMap {
SampleMap {
map: [None; 120],
}
}
}
impl Debug for SampleMap {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_map()
.entries(
(0..120)
.zip(self.map.iter())
.filter_map(|(k, v)| v.map(|v| (Note::try_from(k).unwrap(), v)))
)
.finish()
}
}
impl Index<Note> for SampleMap {
type Output = Option<SampleId>;
fn index(&self, index: Note) -> &Self::Output {
&self.map[u8::from(index) as usize]
}
}
impl Index<&Note> for SampleMap {
type Output = Option<SampleId>;
fn index(&self, index: &Note) -> &Self::Output {
self.index(*index)
}
}