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
134pub 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 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 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
273pub 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 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}