alesis_samplepad_lib/
lib.rs

1use std::str;
2
3const CHECKSUM_BYTE: usize = 0x08;
4
5fn calculate_checksum(kit_file_vec: &Vec<u8>) -> usize {
6    return (kit_file_vec[CHECKSUM_BYTE] as usize + kit_file_vec[CHECKSUM_BYTE + 1] as usize) % 256;
7}
8
9fn verify_checksum(kit_file_vec: &Vec<u8>) -> Result<(), String> {
10    let checksum = kit_file_vec[CHECKSUM_BYTE as usize] as usize;
11    let calculated_checksum = calculate_checksum(kit_file_vec);
12    if checksum == calculated_checksum {
13        Ok(())
14    } else {
15        Err(format!(
16            "Kit file says checksum should be {checksum} but calculated {calculated_checksum}"
17        ))
18    }
19}
20
21#[derive(Debug, PartialEq)]
22pub struct Pad {
23    pub name: String,
24    pub midi_note: u8,
25    pub location: u8,
26    pub level: u8,
27    pub tune: u8,
28    pub pan: u8,
29    pub reverb: u8,
30    pub mode: u8,
31    pub sensitivity: u8,
32    pub mgrp: u8,
33    pub velocity_min: u8,
34    pub velocity_max: u8,
35    pub velocity_min_b: u8,
36    pub velocity_max_b: u8,
37    pub file_layer_a: String,
38    pub file_layer_b: String,
39}
40
41fn pad_file_order() -> [&'static str; 17] {
42    return [
43        "pad_01", "pad_02", "pad_03", "pad_04", "pad_05", "pad_06", "pad_07", "pad_08", "ext_1a",
44        "ext_1b", "ext_2", "kick", "hh_ope", "hh_mid", "hh_clo", "hh_chk", "hh_spl",
45    ];
46}
47
48const HEADER_LENGTH: usize = 128;
49const BLOCK_LENGTH: usize = 256;
50fn get_pads(kit_file_vec: &Vec<u8>) -> Result<Vec<Pad>, String> {
51    let mut pads = vec![];
52    let pad_file_order = pad_file_order();
53    for (i, pad_name) in pad_file_order.iter().enumerate() {
54        let offset1 = HEADER_LENGTH + i * BLOCK_LENGTH;
55        let block1 = &kit_file_vec[offset1..offset1 + BLOCK_LENGTH];
56        let offset2 = HEADER_LENGTH + (pad_file_order.len() * BLOCK_LENGTH) + i * BLOCK_LENGTH;
57        let block2 = &kit_file_vec[offset2..offset2 + BLOCK_LENGTH];
58        pads.push(Pad {
59            name: pad_name.to_string(),
60            midi_note: block1[LOC_MIDI_NOTE],
61            location: block1[LOC_LOCATION],
62            level: block1[LOC_LEVEL],
63            tune: block1[LOC_TUNE],
64            pan: block1[LOC_PAN],
65            reverb: block1[LOC_REVERB],
66            mode: block1[LOC_MODE],
67            sensitivity: block1[LOC_SENSITIVITY],
68            mgrp: block1[LOC_MGRP],
69            velocity_min: block2[LOC_VELOCITY_MIN],
70            velocity_max: block2[LOC_VELOCITY_MAX],
71            velocity_min_b: block2[LOC_VELOCITY_MIN_B],
72            velocity_max_b: block2[LOC_VELOCITY_MAX_B],
73            file_layer_a: if block2[LOC_HAS_FILE_LAYER_A] != 0xaa {
74                "".to_string()
75            } else {
76                str::from_utf8(
77                    &block2[LOC_FILE_NAME as usize
78                        ..(LOC_FILE_NAME + &(block2[LOC_FILE_NAME_LENGTH] as usize)) as usize],
79                )
80                .expect("Invalid UTF-8 sequence")
81                .to_string()
82            },
83            file_layer_b: if block2[LOC_HAS_FILE_LAYER_B] != 0xaa {
84                "".to_string()
85            } else {
86                str::from_utf8(
87                    &block2[LOC_FILE_NAME_B as usize
88                        ..(LOC_FILE_NAME_B + &(block2[LOC_FILE_NAME_LENGTH_B] as usize)) as usize],
89                )
90                .expect("Invalid UTF-8 sequence")
91                .to_string()
92            },
93        });
94    }
95    Ok(pads)
96}
97
98#[derive(Debug, PartialEq)]
99pub struct Kit {
100    pub name: String,
101    pub pads: Vec<Pad>,
102}
103
104fn get_kit_name(kit_vec: &Vec<u8>) -> String {
105    str::from_utf8(&kit_vec[0x48 as usize..(0x48 + &kit_vec[0x47]) as usize])
106        .expect("Invalid UTF-8 sequence")
107        .to_string()
108}
109
110const LOC_MIDI_NOTE: usize = 0x39;
111const LOC_LOCATION: usize = 0x07;
112const LOC_LEVEL: usize = 0x29;
113const LOC_TUNE: usize = 0x2d;
114const LOC_PAN: usize = 0x31;
115const LOC_REVERB: usize = 0x35;
116const LOC_MODE: usize = 0x3d;
117const LOC_SENSITIVITY: usize = 0x41;
118const LOC_MGRP: usize = 0x49;
119const LOC_VELOCITY_MIN: usize = 0x82;
120const LOC_VELOCITY_MAX: usize = 0x83;
121const LOC_VELOCITY_MIN_B: usize = 0xa2;
122const LOC_VELOCITY_MAX_B: usize = 0xa4;
123const LOC_FILE_NAME_LENGTH: usize = 0x87;
124const LOC_DISPLAY_NAME: usize = 0x88;
125const LOC_FILE_NAME: usize = 0x90;
126const LOC_HAS_FILE_LAYER_A: usize = 0x80;
127const LOC_FILE_NAME_LENGTH_B: usize = 0xa7;
128const LOC_DISPLAY_NAME_B: usize = 0xa8;
129const LOC_FILE_NAME_B: usize = 0xb0;
130const LOC_HAS_FILE_LAYER_B: usize = 0xa0;
131const LOC_KIT_NAME_LENGTH: usize = 0x47;
132const LOC_KIT_NAME: usize = 0x48;
133
134/// Given a Kit value, return a serialized byte vector of a KIT file that could be written to disk.
135///
136/// ```
137/// use alesis_samplepad_lib::serialize_kit;
138/// # use alesis_samplepad_lib::deserialize_kit;
139/// # let kit_vec = std::fs::read("./test_data/SMPLPDBS1/KITS/USER_001.KIT").expect("Couldn't read test kit file");
140/// # let kit = deserialize_kit(&kit_vec).expect("Error deserializing kit file");
141/// std::fs::write("USER_001.KIT", serialize_kit(kit));
142///
143pub fn serialize_kit(kit: Kit) -> Vec<u8> {
144    let mut header = vec![
145        0x4b, 0x49, 0x54, 0x48, 0x00, 0x80, 0x00, 0x00, 0xeb, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
146        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154    ];
155    header[LOC_KIT_NAME_LENGTH] = kit.name.len() as u8;
156    let kit_name = kit.name.as_bytes().to_owned();
157    header.splice(LOC_KIT_NAME..LOC_KIT_NAME + kit_name.len(), kit_name);
158
159    let mut blocks_one = vec![];
160    let mut blocks_two = vec![];
161    for pad in kit.pads.iter() {
162        let mut block1 = vec![
163            0x4b, 0x49, 0x54, 0x49, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164            0x00, 0x07, 0x32, 0x32, 0x41, 0x63, 0x42, 0x64, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00,
165            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x09, 0x00, 0x00, 0x00, 0x05,
166            0x00, 0x0a, 0x01, 0x00, 0x04, 0x08, 0x02, 0x00, 0x04, 0x08, 0x03, 0x00, 0x00, 0x0a,
167            0x08, 0x00, 0x00, 0x7f, 0x09, 0x01, 0x00, 0x05, 0x0c, 0x0c, 0x00, 0x08, 0x0d, 0x00,
168            0x00, 0x09, 0x0e, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x7f, 0x09, 0x00, 0x00, 0x00,
169            0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00,
170            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171            0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
172            0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
173            0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00,
174            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175            0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00,
176            0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181            0x00, 0x00, 0x00, 0x00,
182        ];
183
184        block1[LOC_MIDI_NOTE] = pad.midi_note;
185        block1[LOC_LOCATION] = pad.location;
186        block1[LOC_LEVEL] = pad.level;
187        block1[LOC_TUNE] = pad.tune;
188        block1[LOC_PAN] = pad.pan;
189        block1[LOC_REVERB] = pad.reverb;
190        block1[LOC_MODE] = pad.mode;
191        block1[LOC_SENSITIVITY] = pad.sensitivity;
192        block1[LOC_MGRP] = pad.mgrp;
193        blocks_one.append(&mut block1);
194
195        let mut block2 = vec![
196            0x4b, 0x49, 0x54, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x09, 0x00, 0x00, 0x00, 0x05,
199            0x00, 0x0a, 0x01, 0x00, 0x04, 0x08, 0x02, 0x00, 0x04, 0x08, 0x03, 0x00, 0x00, 0x0a,
200            0x08, 0x00, 0x00, 0x7f, 0x09, 0x01, 0x00, 0x05, 0x0c, 0x0c, 0x00, 0x08, 0x0d, 0x00,
201            0x00, 0x09, 0x0e, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
202            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
203            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205            0x00, 0x00, 0xff, 0xaa, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
207            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xaa, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00,
208            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
213            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214            0x00, 0x00, 0x00, 0x00,
215        ];
216        block2[LOC_MIDI_NOTE] = pad.midi_note;
217        block2[LOC_LOCATION] = pad.location;
218        block2[LOC_LEVEL] = pad.level;
219        block2[LOC_TUNE] = pad.tune;
220        block2[LOC_PAN] = pad.pan;
221        block2[LOC_REVERB] = pad.reverb;
222        block2[LOC_MODE] = pad.mode;
223        block2[LOC_SENSITIVITY] = pad.sensitivity;
224        block2[LOC_MGRP] = pad.mgrp;
225        block2[LOC_VELOCITY_MIN] = pad.velocity_min;
226        block2[LOC_VELOCITY_MAX] = pad.velocity_max;
227        block2[LOC_VELOCITY_MIN_B] = pad.velocity_min_b;
228        block2[LOC_VELOCITY_MAX_B] = pad.velocity_max_b;
229
230        // file layer a
231        block2[LOC_FILE_NAME_LENGTH] = pad.file_layer_a.len() as u8;
232        let mut display_name = pad.file_layer_a.to_uppercase().as_bytes().to_owned();
233        if display_name.len() < 9 {
234            display_name.resize(8, 0x20);
235        }
236        block2.splice(
237            LOC_DISPLAY_NAME..LOC_DISPLAY_NAME + display_name.len(),
238            display_name,
239        );
240
241        let mut file_name = pad.file_layer_a.as_bytes().to_owned();
242        if file_name.len() < 9 {
243            file_name.resize(8, 0x00);
244        }
245        block2.splice(LOC_FILE_NAME..LOC_FILE_NAME + file_name.len(), file_name);
246        block2[LOC_HAS_FILE_LAYER_A] = if pad.file_layer_a == "" { 0xff } else { 0xaa };
247
248        // file layer b
249        block2[LOC_FILE_NAME_LENGTH_B] = pad.file_layer_b.len() as u8;
250        let mut display_name = pad.file_layer_b.to_uppercase().as_bytes().to_owned();
251        if display_name.len() < 9 {
252            display_name.resize(8, 0x20);
253        }
254        block2.splice(
255            LOC_DISPLAY_NAME_B..LOC_DISPLAY_NAME_B + display_name.len(),
256            display_name,
257        );
258        let mut file_name = pad.file_layer_b.as_bytes().to_owned();
259        if file_name.len() < 9 {
260            file_name.resize(8, 0x00);
261        }
262        block2.splice(
263            LOC_FILE_NAME_B..LOC_FILE_NAME_B + file_name.len(),
264            file_name,
265        );
266        block2[LOC_HAS_FILE_LAYER_B] = if pad.file_layer_b == "" { 0xff } else { 0xaa };
267
268        blocks_two.append(&mut block2);
269    }
270    [header, blocks_one, blocks_two].concat()
271}
272
273/// Given a reference to a byte vector of a KIT file, return a parsed Kit value
274///
275/// ```
276/// use alesis_samplepad_lib::deserialize_kit;
277/// let kit_vec = std::fs::read("./test_data/SMPLPDBS1/KITS/USER_001.KIT").expect("Couldn't read test kit file");
278/// let kit = deserialize_kit(&kit_vec).expect("Error deserializing kit file");
279/// assert_eq!(kit.name, "Acoustic");
280///
281pub fn deserialize_kit(kit_vec: &Vec<u8>) -> Result<Kit, String> {
282    verify_checksum(kit_vec)?;
283    Ok(Kit {
284        name: get_kit_name(&kit_vec),
285        pads: get_pads(&kit_vec)?,
286    })
287}
288
289#[cfg(test)]
290mod tests {
291    use super::*;
292    use pretty_assertions::assert_eq;
293    use std::fs;
294
295    fn get_test_kit() -> Vec<u8> {
296        return fs::read("./test_data/SMPLPDBS1/KITS/USER_001.KIT")
297            .expect("Couldn't read test kit file");
298    }
299
300    #[test]
301    fn test_checksum() {
302        assert_eq!(verify_checksum(&get_test_kit()), Ok(()));
303    }
304
305    #[test]
306    fn test_kit_name() {
307        // This is just a weird quirk, the file stores a kit name, but user kits are displayed with
308        // the filename as the kit name and this value is ignored.
309        assert_eq!("Acoustic", get_kit_name(&get_test_kit()));
310    }
311
312    #[test]
313    fn test_serde_round_trip() {
314        let kv = get_test_kit();
315        assert_eq!(
316            deserialize_kit(&kv),
317            deserialize_kit(&serialize_kit(
318                deserialize_kit(&kv).expect("Failed to deserialize kit")
319            ))
320        );
321    }
322
323    #[test]
324    fn test_get_pads() {
325        assert_eq!(
326            get_pads(&get_test_kit()),
327            Ok(vec![
328                Pad {
329                    name: "pad_01".to_string(),
330                    midi_note: 49,
331                    location: 1,
332                    level: 8,
333                    tune: 0,
334                    pan: 0,
335                    reverb: 3,
336                    mode: 0,
337                    sensitivity: 16,
338                    mgrp: 0,
339                    velocity_min: 0,
340                    velocity_max: 127,
341                    velocity_min_b: 0,
342                    velocity_max_b: 0,
343                    file_layer_a: "G_Sub_Hit".to_string(),
344                    file_layer_b: "".to_string()
345                },
346                Pad {
347                    name: "pad_02".to_string(),
348                    midi_note: 51,
349                    location: 1,
350                    level: 4,
351                    tune: 0,
352                    pan: 0,
353                    reverb: 0,
354                    mode: 1,
355                    sensitivity: 16,
356                    mgrp: 0,
357                    velocity_min: 0,
358                    velocity_max: 127,
359                    velocity_min_b: 0,
360                    velocity_max_b: 0,
361                    file_layer_a: "Y_Noise_Hit".to_string(),
362                    file_layer_b: "".to_string()
363                },
364                Pad {
365                    name: "pad_03".to_string(),
366                    midi_note: 48,
367                    location: 1,
368                    level: 10,
369                    tune: 0,
370                    pan: 0,
371                    reverb: 3,
372                    mode: 0,
373                    sensitivity: 16,
374                    mgrp: 0,
375                    velocity_min: 0,
376                    velocity_max: 127,
377                    velocity_min_b: 0,
378                    velocity_max_b: 0,
379                    file_layer_a: "O_Kick_2".to_string(),
380                    file_layer_b: "".to_string()
381                },
382                Pad {
383                    name: "pad_04".to_string(),
384                    midi_note: 45,
385                    location: 1,
386                    level: 8,
387                    tune: 0,
388                    pan: 0,
389                    reverb: 0,
390                    mode: 0,
391                    sensitivity: 16,
392                    mgrp: 0,
393                    velocity_min: 0,
394                    velocity_max: 127,
395                    velocity_min_b: 0,
396                    velocity_max_b: 0,
397                    file_layer_a: "R_Tom_Mute_H".to_string(),
398                    file_layer_b: "".to_string()
399                },
400                Pad {
401                    name: "pad_05".to_string(),
402                    midi_note: 46,
403                    location: 1,
404                    level: 8,
405                    tune: 0,
406                    pan: 0,
407                    reverb: 3,
408                    mode: 1,
409                    sensitivity: 16,
410                    mgrp: 1,
411                    velocity_min: 0,
412                    velocity_max: 127,
413                    velocity_min_b: 0,
414                    velocity_max_b: 0,
415                    file_layer_a: "R_Tom_Mute_L".to_string(),
416                    file_layer_b: "".to_string()
417                },
418                Pad {
419                    name: "pad_06".to_string(),
420                    midi_note: 36,
421                    location: 1,
422                    level: 10,
423                    tune: 0,
424                    pan: 0,
425                    reverb: 2,
426                    mode: 0,
427                    sensitivity: 16,
428                    mgrp: 0,
429                    velocity_min: 0,
430                    velocity_max: 127,
431                    velocity_min_b: 0,
432                    velocity_max_b: 0,
433                    file_layer_a: "R_Kick_2".to_string(),
434                    file_layer_b: "".to_string()
435                },
436                Pad {
437                    name: "pad_07".to_string(),
438                    midi_note: 38,
439                    location: 1,
440                    level: 8,
441                    tune: 0,
442                    pan: 0,
443                    reverb: 0,
444                    mode: 1,
445                    sensitivity: 16,
446                    mgrp: 0,
447                    velocity_min: 0,
448                    velocity_max: 127,
449                    velocity_min_b: 0,
450                    velocity_max_b: 0,
451                    file_layer_a: "SNR_OFF_5".to_string(),
452                    file_layer_b: "".to_string()
453                },
454                Pad {
455                    name: "pad_08".to_string(),
456                    midi_note: 42,
457                    location: 1,
458                    level: 8,
459                    tune: 0,
460                    pan: 0,
461                    reverb: 0,
462                    mode: 1,
463                    sensitivity: 16,
464                    mgrp: 0,
465                    velocity_min: 0,
466                    velocity_max: 127,
467                    velocity_min_b: 0,
468                    velocity_max_b: 0,
469                    file_layer_a: "R_Clap_Wet".to_string(),
470                    file_layer_b: "".to_string()
471                },
472                Pad {
473                    name: "ext_1a".to_string(),
474                    midi_note: 38,
475                    location: 0,
476                    level: 8,
477                    tune: 0,
478                    pan: 0,
479                    reverb: 3,
480                    mode: 0,
481                    sensitivity: 16,
482                    mgrp: 0,
483                    velocity_min: 0,
484                    velocity_max: 127,
485                    velocity_min_b: 0,
486                    velocity_max_b: 0,
487                    file_layer_a: "".to_string(),
488                    file_layer_b: "".to_string()
489                },
490                Pad {
491                    name: "ext_1b".to_string(),
492                    midi_note: 40,
493                    location: 0,
494                    level: 8,
495                    tune: 0,
496                    pan: 0,
497                    reverb: 3,
498                    mode: 0,
499                    sensitivity: 16,
500                    mgrp: 0,
501                    velocity_min: 0,
502                    velocity_max: 127,
503                    velocity_min_b: 0,
504                    velocity_max_b: 0,
505                    file_layer_a: "".to_string(),
506                    file_layer_b: "".to_string()
507                },
508                Pad {
509                    name: "ext_2".to_string(),
510                    midi_note: 43,
511                    location: 0,
512                    level: 8,
513                    tune: 0,
514                    pan: 1,
515                    reverb: 3,
516                    mode: 0,
517                    sensitivity: 16,
518                    mgrp: 0,
519                    velocity_min: 0,
520                    velocity_max: 127,
521                    velocity_min_b: 0,
522                    velocity_max_b: 0,
523                    file_layer_a: "".to_string(),
524                    file_layer_b: "".to_string()
525                },
526                Pad {
527                    name: "kick".to_string(),
528                    midi_note: 36,
529                    location: 0,
530                    level: 8,
531                    tune: 2,
532                    pan: 0,
533                    reverb: 2,
534                    mode: 0,
535                    sensitivity: 16,
536                    mgrp: 0,
537                    velocity_min: 0,
538                    velocity_max: 127,
539                    velocity_min_b: 0,
540                    velocity_max_b: 0,
541                    file_layer_a: "".to_string(),
542                    file_layer_b: "".to_string()
543                },
544                Pad {
545                    name: "hh_ope".to_string(),
546                    midi_note: 46,
547                    location: 0,
548                    level: 8,
549                    tune: 0,
550                    pan: 253,
551                    reverb: 3,
552                    mode: 1,
553                    sensitivity: 16,
554                    mgrp: 1,
555                    velocity_min: 0,
556                    velocity_max: 127,
557                    velocity_min_b: 0,
558                    velocity_max_b: 0,
559                    file_layer_a: "".to_string(),
560                    file_layer_b: "".to_string()
561                },
562                Pad {
563                    name: "hh_mid".to_string(),
564                    midi_note: 23,
565                    location: 0,
566                    level: 8,
567                    tune: 0,
568                    pan: 253,
569                    reverb: 3,
570                    mode: 1,
571                    sensitivity: 16,
572                    mgrp: 1,
573                    velocity_min: 0,
574                    velocity_max: 127,
575                    velocity_min_b: 0,
576                    velocity_max_b: 0,
577                    file_layer_a: "".to_string(),
578                    file_layer_b: "".to_string()
579                },
580                Pad {
581                    name: "hh_clo".to_string(),
582                    midi_note: 42,
583                    location: 0,
584                    level: 8,
585                    tune: 0,
586                    pan: 253,
587                    reverb: 3,
588                    mode: 1,
589                    sensitivity: 16,
590                    mgrp: 1,
591                    velocity_min: 0,
592                    velocity_max: 127,
593                    velocity_min_b: 0,
594                    velocity_max_b: 0,
595                    file_layer_a: "".to_string(),
596                    file_layer_b: "".to_string()
597                },
598                Pad {
599                    name: "hh_chk".to_string(),
600                    midi_note: 44,
601                    location: 0,
602                    level: 8,
603                    tune: 0,
604                    pan: 253,
605                    reverb: 3,
606                    mode: 0,
607                    sensitivity: 16,
608                    mgrp: 1,
609                    velocity_min: 0,
610                    velocity_max: 127,
611                    velocity_min_b: 0,
612                    velocity_max_b: 0,
613                    file_layer_a: "".to_string(),
614                    file_layer_b: "".to_string()
615                },
616                Pad {
617                    name: "hh_spl".to_string(),
618                    midi_note: 21,
619                    location: 0,
620                    level: 8,
621                    tune: 0,
622                    pan: 253,
623                    reverb: 3,
624                    mode: 0,
625                    sensitivity: 16,
626                    mgrp: 1,
627                    velocity_min: 0,
628                    velocity_max: 127,
629                    velocity_min_b: 0,
630                    velocity_max_b: 0,
631                    file_layer_a: "".to_string(),
632                    file_layer_b: "".to_string()
633                }
634            ])
635        );
636    }
637}