use crate::OtToolsIoError;
use crate::{Defaults, HasHeaderField};
use ot_tools_io_derive::{
ArrayDefaults, AsMutDerive, AsRefDerive, BoxedBigArrayDefaults, ContainerArrayMethods,
IsDefaultCheck,
};
use serde::{Deserialize, Serialize};
use serde_big_array::{Array, BigArray};
use std::array::from_fn;
use std::slice::{Iter, IterMut};
const PART_HEADER: [u8; 4] = [0x50, 0x41, 0x52, 0x54];
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub enum OnOrOff {
On = 1,
Off = 0,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
ArrayDefaults,
BoxedBigArrayDefaults,
)]
pub struct AudioTrackVolume {
pub main: u8,
pub cue: u8,
}
impl Default for AudioTrackVolume {
fn default() -> Self {
Self {
main: 0x6c, cue: 0x6c, }
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct ActiveScenes {
pub scene_a: u8,
pub scene_b: u8,
}
impl Default for ActiveScenes {
fn default() -> Self {
Self {
scene_a: 0,
scene_b: 8,
}
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct AudioTrackMachineParamsSetupStd {
pub xloop: u8,
pub slic: u8,
pub len: u8,
pub rate: u8,
pub tstr: u8,
pub tsns: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct AudioTrackMachineParamsSetupThru {
pub unused_1: u8,
pub unused_2: u8,
pub unused_3: u8,
pub unused_4: u8,
pub unused_5: u8,
pub unused_6: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct AudioTrackMachineParamsSetupNeighbor {
pub unused_1: u8,
pub unused_2: u8,
pub unused_3: u8,
pub unused_4: u8,
pub unused_5: u8,
pub unused_6: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct AudioTrackMachineParamsSetupPickup {
pub unused_1: u8,
pub unused_2: u8,
pub unused_3: u8,
pub unused_4: u8,
pub tstr: u8,
pub tsns: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
ArrayDefaults,
BoxedBigArrayDefaults,
)]
pub struct AudioTrackMachinesParamsSetup {
pub static_machine: AudioTrackMachineParamsSetupStd,
pub flex_machine: AudioTrackMachineParamsSetupStd,
pub thru_machine: AudioTrackMachineParamsSetupThru,
pub neighbor_machine: AudioTrackMachineParamsSetupNeighbor,
pub pickup_machine: AudioTrackMachineParamsSetupPickup,
}
impl Default for AudioTrackMachinesParamsSetup {
fn default() -> Self {
Self {
static_machine: AudioTrackMachineParamsSetupStd {
xloop: 1,
slic: 0,
len: 0,
rate: 0,
tstr: 1,
tsns: 64,
},
flex_machine: AudioTrackMachineParamsSetupStd {
xloop: 1,
slic: 0,
len: 0,
rate: 0,
tstr: 1,
tsns: 64,
},
thru_machine: AudioTrackMachineParamsSetupThru {
unused_1: 0,
unused_2: 0,
unused_3: 0,
unused_4: 0,
unused_5: 0,
unused_6: 0,
},
neighbor_machine: AudioTrackMachineParamsSetupNeighbor {
unused_1: 0,
unused_2: 0,
unused_3: 0,
unused_4: 0,
unused_5: 0,
unused_6: 0,
},
pickup_machine: AudioTrackMachineParamsSetupPickup {
unused_1: 0,
unused_2: 0,
unused_3: 0,
unused_4: 0,
tstr: 1,
tsns: 64,
},
}
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
BoxedBigArrayDefaults,
)]
pub struct AudioTrackMachineSlot {
pub static_slot_id: u8,
pub flex_slot_id: u8,
pub unused_1: u8,
pub unused_2: u8,
pub recorder_slot_id: u8,
}
impl Default for AudioTrackMachineSlot {
fn default() -> Self {
Self {
static_slot_id: 0,
flex_slot_id: 0,
unused_1: 0,
unused_2: 0,
recorder_slot_id: 128,
}
}
}
impl<const N: usize> Defaults<[Self; N]> for AudioTrackMachineSlot {
fn defaults() -> [Self; N]
where
Self: Default,
{
from_fn(|i| Self {
static_slot_id: i as u8,
flex_slot_id: i as u8,
recorder_slot_id: 128 + i as u8,
..Default::default()
})
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct AudioTrackMachineParamsValuesStd {
pub ptch: u8,
pub strt: u8,
pub len: u8,
pub rate: u8,
pub rtrg: u8,
pub rtim: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct AudioTrackMachineParamsValuesThru {
pub in_ab: u8,
pub vol_ab: u8,
pub unused_1: u8,
pub in_cd: u8,
pub vol_cd: u8,
pub unused_2: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct AudioTrackMachineParamsValuesNeighbor {
pub unused_1: u8,
pub unused_2: u8,
pub unused_3: u8,
pub unused_4: u8,
pub unused_5: u8,
pub unused_6: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct AudioTrackMachineParamsValuesPickup {
pub ptch: u8,
pub dir: u8,
pub len: u8,
pub unused_1: u8,
pub gain: u8,
pub op: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
ArrayDefaults,
BoxedBigArrayDefaults,
)]
pub struct AudioTrackMachinesParamsValues {
pub static_machine: AudioTrackMachineParamsValuesStd,
pub flex_machine: AudioTrackMachineParamsValuesStd,
pub thru_machine: AudioTrackMachineParamsValuesThru,
pub neighbor_machine: AudioTrackMachineParamsValuesNeighbor,
pub pickup_machine: AudioTrackMachineParamsValuesPickup,
}
impl Default for AudioTrackMachinesParamsValues {
fn default() -> Self {
Self {
static_machine: AudioTrackMachineParamsValuesStd {
ptch: 64,
strt: 0,
len: 0,
rate: 127,
rtrg: 0,
rtim: 79,
},
flex_machine: AudioTrackMachineParamsValuesStd {
ptch: 64,
strt: 0,
len: 0,
rate: 127,
rtrg: 0,
rtim: 79,
},
thru_machine: AudioTrackMachineParamsValuesThru {
in_ab: 0,
vol_ab: 64,
unused_1: 0,
in_cd: 0,
vol_cd: 64,
unused_2: 0,
},
neighbor_machine: AudioTrackMachineParamsValuesNeighbor {
unused_1: 0,
unused_2: 0,
unused_3: 0,
unused_4: 0,
unused_5: 0,
unused_6: 0,
},
pickup_machine: AudioTrackMachineParamsValuesPickup {
ptch: 64,
dir: 2,
len: 1,
unused_1: 127,
gain: 64,
op: 1,
},
}
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct LfoParamsValues {
pub spd1: u8,
pub spd2: u8,
pub spd3: u8,
pub dep1: u8,
pub dep2: u8,
pub dep3: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct AudioTrackAmpParamsValues {
pub atk: u8,
pub hold: u8,
pub rel: u8,
pub vol: u8,
pub bal: u8,
pub f: u8,
}
#[allow(clippy::derivable_impls)]
impl Default for AudioTrackAmpParamsValues {
fn default() -> Self {
Self {
atk: 0,
hold: 127,
rel: 127,
vol: 64,
bal: 64,
f: 127,
}
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct AudioTrackFxParamsValues {
pub param_1: u8,
pub param_2: u8,
pub param_3: u8,
pub param_4: u8,
pub param_5: u8,
pub param_6: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
ArrayDefaults,
BoxedBigArrayDefaults,
)]
pub struct AudioTrackParamsValues {
pub lfo: LfoParamsValues,
pub amp: AudioTrackAmpParamsValues,
pub fx1: AudioTrackFxParamsValues,
pub fx2: AudioTrackFxParamsValues,
}
impl Default for AudioTrackParamsValues {
fn default() -> Self {
Self {
lfo: LfoParamsValues {
spd1: 32,
spd2: 32,
spd3: 32,
dep1: 0,
dep2: 0,
dep3: 0,
},
amp: AudioTrackAmpParamsValues::default(),
fx1: AudioTrackFxParamsValues {
param_1: 0,
param_2: 127,
param_3: 0,
param_4: 64,
param_5: 0,
param_6: 64,
},
fx2: AudioTrackFxParamsValues {
param_1: 47,
param_2: 0,
param_3: 127,
param_4: 0,
param_5: 127,
param_6: 0,
},
}
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct LfoParamsSetup1 {
pub lfo1_pmtr: u8,
pub lfo2_pmtr: u8,
pub lfo3_pmtr: u8,
pub lfo1_wave: u8,
pub lfo2_wave: u8,
pub lfo3_wave: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct LfoParamsSetup2 {
pub lfo1_mult: u8,
pub lfo2_mult: u8,
pub lfo3_mult: u8,
pub lfo1_trig: u8,
pub lfo2_trig: u8,
pub lfo3_trig: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct AudioTrackAmpParamsSetup {
pub amp: u8,
pub sync: u8,
pub atck: u8,
pub fx1: u8,
pub fx2: u8,
pub unused: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct AudioTrackFxParamsSetup {
pub setting1: u8,
pub setting2: u8,
pub setting3: u8,
pub setting4: u8,
pub setting5: u8,
pub setting6: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
ArrayDefaults,
BoxedBigArrayDefaults,
)]
pub struct AudioTrackParamsSetup {
pub lfo_setup_1: LfoParamsSetup1,
pub amp: AudioTrackAmpParamsSetup,
pub fx1: AudioTrackFxParamsSetup,
pub fx2: AudioTrackFxParamsSetup,
pub lfo_setup_2: LfoParamsSetup2,
}
impl Default for AudioTrackParamsSetup {
fn default() -> Self {
Self {
lfo_setup_1: LfoParamsSetup1 {
lfo1_pmtr: 0,
lfo2_pmtr: 0,
lfo3_pmtr: 0,
lfo1_wave: 0,
lfo2_wave: 0,
lfo3_wave: 0,
},
amp: AudioTrackAmpParamsSetup {
amp: 1,
sync: 1,
atck: 0,
fx1: 0,
fx2: 0,
unused: 0,
},
fx1: AudioTrackFxParamsSetup {
setting1: 0,
setting2: 0,
setting3: 1,
setting4: 0,
setting5: 3,
setting6: 0,
},
fx2: AudioTrackFxParamsSetup {
setting1: 0,
setting2: 1,
setting3: 127,
setting4: 1,
setting5: 0,
setting6: 0,
},
lfo_setup_2: LfoParamsSetup2 {
lfo1_mult: 0,
lfo2_mult: 0,
lfo3_mult: 0,
lfo1_trig: 0,
lfo2_trig: 0,
lfo3_trig: 0,
},
}
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct MidiTrackMidiParamsValues {
pub note: u8,
pub vel: u8,
pub len: u8,
pub not2: u8,
pub not3: u8,
pub not4: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct MidiTrackArpParamsValues {
pub tran: u8,
pub leg: u8,
pub mode: u8,
pub spd: u8,
pub rnge: u8,
pub nlen: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct MidiTrackCc1ParamsValues {
pub pb: u8,
pub at: u8,
pub cc1: u8,
pub cc2: u8,
pub cc3: u8,
pub cc4: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct MidiTrackCc2ParamsValues {
pub cc5: u8,
pub cc6: u8,
pub cc7: u8,
pub cc8: u8,
pub cc9: u8,
pub cc10: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
ArrayDefaults,
BoxedBigArrayDefaults,
)]
pub struct MidiTrackParamsValues {
pub midi: MidiTrackMidiParamsValues,
pub lfo: LfoParamsValues,
pub arp: MidiTrackArpParamsValues,
pub ctrl1: MidiTrackCc1ParamsValues,
pub ctrl2: MidiTrackCc2ParamsValues,
#[serde(with = "BigArray")]
pub unknown: [u8; 2],
}
impl Default for MidiTrackParamsValues {
fn default() -> Self {
Self {
midi: MidiTrackMidiParamsValues {
note: 48,
vel: 100,
len: 6,
not2: 64,
not3: 64,
not4: 64,
},
lfo: LfoParamsValues {
spd1: 32,
spd2: 32,
spd3: 32,
dep1: 0,
dep2: 0,
dep3: 0,
},
arp: MidiTrackArpParamsValues {
tran: 64,
leg: 0,
mode: 0,
spd: 5,
rnge: 0,
nlen: 6,
},
ctrl1: MidiTrackCc1ParamsValues {
pb: 64,
at: 0,
cc1: 127,
cc2: 0,
cc3: 0,
cc4: 64,
},
ctrl2: MidiTrackCc2ParamsValues {
cc5: 0,
cc6: 0,
cc7: 0,
cc8: 0,
cc9: 0,
cc10: 0,
},
unknown: [0, 0],
}
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct MidiTrackNoteParamsSetup {
pub chan: u8,
pub bank: u8,
pub prog: u8,
pub unused_1: u8,
pub sbank: u8,
pub unused_2: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct MidiTrackArpParamsSetup {
pub unused_1: u8,
pub unused_2: u8,
pub len: u8,
pub unused_3: u8,
pub unused_4: u8,
pub key: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct MidiTrackCc1ParamsSetup {
pub unused_1: u8,
pub unused_2: u8,
pub cc1: u8,
pub cc2: u8,
pub cc3: u8,
pub cc4: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct MidiTrackCc2ParamsSetup {
pub cc5: u8,
pub cc6: u8,
pub cc7: u8,
pub cc8: u8,
pub cc9: u8,
pub cc10: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
ArrayDefaults,
BoxedBigArrayDefaults,
)]
pub struct MidiTrackParamsSetup {
pub note: MidiTrackNoteParamsSetup,
pub lfo1: LfoParamsSetup1,
pub arp: MidiTrackArpParamsSetup,
pub ctrl1: MidiTrackCc1ParamsSetup,
pub ctrl2: MidiTrackCc2ParamsSetup,
pub lfo2: LfoParamsSetup2,
}
impl Default for MidiTrackParamsSetup {
fn default() -> Self {
Self {
note: MidiTrackNoteParamsSetup {
chan: 0,
bank: 128,
prog: 128,
unused_1: 0,
sbank: 128,
unused_2: 0,
},
lfo1: LfoParamsSetup1 {
lfo1_pmtr: 0,
lfo2_pmtr: 0,
lfo3_pmtr: 0,
lfo1_wave: 0,
lfo2_wave: 0,
lfo3_wave: 0,
},
arp: MidiTrackArpParamsSetup {
unused_1: 0,
unused_2: 0,
len: 7,
unused_3: 0,
unused_4: 0,
key: 0,
},
ctrl1: MidiTrackCc1ParamsSetup {
unused_1: 0,
unused_2: 0,
cc1: 7,
cc2: 1,
cc3: 2,
cc4: 10,
},
ctrl2: MidiTrackCc2ParamsSetup {
cc5: 71,
cc6: 72,
cc7: 73,
cc8: 74,
cc9: 75,
cc10: 76,
},
lfo2: LfoParamsSetup2 {
lfo1_mult: 0,
lfo2_mult: 0,
lfo3_mult: 0,
lfo1_trig: 0,
lfo2_trig: 0,
lfo3_trig: 0,
},
}
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
ArrayDefaults,
BoxedBigArrayDefaults,
)]
pub struct CustomLfoDesign(pub [u8; 16]);
impl Default for CustomLfoDesign {
fn default() -> Self {
Self(from_fn(|_| 0))
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
ArrayDefaults,
BoxedBigArrayDefaults,
)]
pub struct CustomLfoInterpolationMask(pub [u8; 2]);
impl Default for CustomLfoInterpolationMask {
fn default() -> Self {
Self(from_fn(|_| 0))
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct RecorderSetupSources {
pub in_ab: u8,
pub in_cd: u8,
pub rlen: u8,
pub trig: u8,
pub src3: u8,
pub xloop: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct RecorderSetupProcessing {
pub fin: u8,
pub fout: u8,
pub ab: u8,
pub qrec: u8,
pub qpl: u8,
pub cd: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
ArrayDefaults,
BoxedBigArrayDefaults,
)]
pub struct RecorderSetup {
pub src: RecorderSetupSources,
pub proc: RecorderSetupProcessing,
}
impl Default for RecorderSetup {
fn default() -> Self {
Self {
src: RecorderSetupSources {
in_ab: 1,
in_cd: 1,
rlen: 64,
trig: 0,
src3: 0,
xloop: 1,
},
proc: RecorderSetupProcessing {
fin: 0,
fout: 0,
ab: 0,
qrec: 255,
qpl: 255,
cd: 0,
},
}
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct AudioTrackSceneLockPlayback {
pub param1: u8,
pub param2: u8,
pub param3: u8,
pub param4: u8,
pub param5: u8,
pub param6: u8,
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
ArrayDefaults,
BoxedBigArrayDefaults,
IsDefaultCheck,
)]
pub struct SceneParams {
pub machine: AudioTrackSceneLockPlayback,
pub lfo: LfoParamsValues,
pub amp: AudioTrackAmpParamsValues,
pub fx1: AudioTrackFxParamsValues,
pub fx2: AudioTrackFxParamsValues,
pub unknown_1: u8,
pub unknown_2: u8,
}
impl Default for SceneParams {
fn default() -> Self {
Self {
machine: AudioTrackSceneLockPlayback {
param1: 255,
param2: 255,
param3: 255,
param4: 255,
param5: 255,
param6: 255,
},
lfo: LfoParamsValues {
spd1: 255,
spd2: 255,
spd3: 255,
dep1: 255,
dep2: 255,
dep3: 255,
},
amp: AudioTrackAmpParamsValues {
atk: 255,
hold: 255,
rel: 255,
vol: 255,
bal: 255,
f: 255,
},
fx1: AudioTrackFxParamsValues {
param_1: 255,
param_2: 255,
param_3: 255,
param_4: 255,
param_5: 255,
param_6: 255,
},
fx2: AudioTrackFxParamsValues {
param_1: 255,
param_2: 255,
param_3: 255,
param_4: 255,
param_5: 255,
param_6: 255,
},
unknown_1: 255,
unknown_2: 255,
}
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
ArrayDefaults,
BoxedBigArrayDefaults,
IsDefaultCheck,
ContainerArrayMethods,
)]
pub struct SceneParamsArray(pub [SceneParams; 8]);
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
ArrayDefaults,
BoxedBigArrayDefaults,
)]
pub struct SceneXlvAssignments {
#[serde(with = "BigArray")]
pub track_xlvs: [u8; 8],
#[serde(with = "BigArray")]
pub unknown: [u8; 2],
}
impl Default for SceneXlvAssignments {
fn default() -> Self {
Self {
track_xlvs: from_fn(|_| 255),
unknown: from_fn(|_| 255),
}
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
ArrayDefaults,
BoxedBigArrayDefaults,
)]
pub struct MidiArpSequence(pub [u8; 16]);
impl Default for MidiArpSequence {
fn default() -> Self {
Self(from_fn(|_| 0))
}
}
#[derive(
Copy,
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
BoxedBigArrayDefaults,
)]
pub struct Part {
#[serde(with = "BigArray")]
pub header: [u8; 4],
#[serde(with = "BigArray")]
pub data_block_1: [u8; 4],
pub part_id: u8,
#[serde(with = "BigArray")]
pub audio_track_fx1: [u8; 8],
#[serde(with = "BigArray")]
pub audio_track_fx2: [u8; 8],
pub active_scenes: ActiveScenes,
#[serde(with = "BigArray")]
pub audio_track_volumes: [AudioTrackVolume; 8],
#[serde(with = "BigArray")]
pub audio_track_machine_types: [u8; 8],
#[serde(with = "BigArray")]
pub audio_track_machine_params: [AudioTrackMachinesParamsValues; 8],
#[serde(with = "BigArray")]
pub audio_track_params_values: [AudioTrackParamsValues; 8],
#[serde(with = "BigArray")]
pub audio_track_machine_setup: [AudioTrackMachinesParamsSetup; 8],
#[serde(with = "BigArray")]
pub audio_track_machine_slots: [AudioTrackMachineSlot; 8],
#[serde(with = "BigArray")]
pub audio_track_params_setup: [AudioTrackParamsSetup; 8],
#[serde(with = "BigArray")]
pub midi_track_params_values: [MidiTrackParamsValues; 8],
#[serde(with = "BigArray")]
pub midi_track_params_setup: [MidiTrackParamsSetup; 8],
#[serde(with = "BigArray")]
pub recorder_setup: [RecorderSetup; 8],
#[serde(with = "BigArray")]
pub scenes: [SceneParamsArray; 16],
#[serde(with = "BigArray")]
pub scene_xlvs: [SceneXlvAssignments; 16],
#[serde(with = "BigArray")]
pub audio_tracks_custom_lfo_designs: [CustomLfoDesign; 8],
#[serde(with = "BigArray")]
pub audio_tracks_custom_lfos_interpolation_masks: [CustomLfoInterpolationMask; 8],
#[serde(with = "BigArray")]
pub midi_tracks_custom_lfos: [CustomLfoDesign; 8],
#[serde(with = "BigArray")]
pub midi_tracks_custom_lfos_interpolation_masks: [CustomLfoInterpolationMask; 8],
#[serde(with = "BigArray")]
pub midi_tracks_arp_mute_masks: [u8; 16],
pub midi_tracks_arp_seqs: [MidiArpSequence; 8],
}
impl Default for Part {
fn default() -> Self {
Self {
header: PART_HEADER,
data_block_1: from_fn(|_| 0),
part_id: 0,
audio_track_fx1: from_fn(|_| 4),
audio_track_fx2: from_fn(|_| 8),
active_scenes: ActiveScenes::default(),
audio_track_volumes: AudioTrackVolume::defaults(),
audio_track_machine_types: from_fn(|_| 0),
audio_track_machine_params: AudioTrackMachinesParamsValues::defaults(),
audio_track_params_values: AudioTrackParamsValues::defaults(),
audio_track_machine_setup: AudioTrackMachinesParamsSetup::defaults(),
audio_track_machine_slots: AudioTrackMachineSlot::defaults(),
audio_track_params_setup: AudioTrackParamsSetup::defaults(),
midi_track_params_values: MidiTrackParamsValues::defaults(),
midi_track_params_setup: MidiTrackParamsSetup::defaults(),
recorder_setup: RecorderSetup::defaults(),
scenes: SceneParamsArray::defaults(),
scene_xlvs: SceneXlvAssignments::defaults(),
audio_tracks_custom_lfo_designs: CustomLfoDesign::defaults(),
audio_tracks_custom_lfos_interpolation_masks: CustomLfoInterpolationMask::defaults(),
midi_tracks_custom_lfos: CustomLfoDesign::defaults(),
midi_tracks_custom_lfos_interpolation_masks: CustomLfoInterpolationMask::defaults(),
midi_tracks_arp_mute_masks: from_fn(|_| 255),
midi_tracks_arp_seqs: MidiArpSequence::defaults(),
}
}
}
impl crate::IsDefault for Part {
fn is_default(&self) -> bool
where
Self: Default + PartialEq,
{
let x = Self {
part_id: self.part_id,
..Default::default()
};
self == &x
}
}
#[cfg(test)]
mod is_default {
use crate::parts::Part;
use crate::IsDefault;
use crate::OtToolsIoError;
#[test]
fn valid_part_1() -> Result<(), OtToolsIoError> {
let p = Part::default();
assert!(p.is_default());
Ok(())
}
#[test]
fn valid_part_2() -> Result<(), OtToolsIoError> {
assert!(Part {
part_id: 1,
..Default::default()
}
.is_default());
Ok(())
}
#[test]
fn valid_part_3() -> Result<(), OtToolsIoError> {
assert!(Part {
part_id: 2,
..Default::default()
}
.is_default());
Ok(())
}
#[test]
fn valid_part_4() -> Result<(), OtToolsIoError> {
assert!(Part {
part_id: 3,
..Default::default()
}
.is_default());
Ok(())
}
}
impl<const N: usize> Defaults<[Self; N]> for Part {
fn defaults() -> [Self; N]
where
Self: Default,
{
from_fn(|i| Self {
part_id: i as u8,
..Default::default()
})
}
}
impl HasHeaderField for Part {
fn check_header(&self) -> Result<bool, OtToolsIoError> {
Ok(self.header == PART_HEADER)
}
}
#[cfg(test)]
mod part_header_field {
use crate::{
test_utils::get_blank_proj_dirpath, BankFile, HasHeaderField, OctatrackFileIO,
OtToolsIoError,
};
#[test]
fn valid() -> Result<(), OtToolsIoError> {
let path = get_blank_proj_dirpath().join("bank01.work");
let parts = BankFile::from_data_file(&path)?.parts.saved.clone();
let part = parts[0];
assert!(part.check_header()?);
Ok(())
}
#[test]
fn invalid() -> Result<(), OtToolsIoError> {
let path = get_blank_proj_dirpath().join("bank01.work");
let parts = BankFile::from_data_file(&path)?.parts.saved.clone();
let mut part = parts[0];
part.header[0] = 255;
part.header[1] = 255;
part.header[2] = 255;
part.header[3] = 255;
assert!(!part.check_header()?);
Ok(())
}
}
#[derive(
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
)]
pub struct Parts {
pub unsaved: PartArray,
pub saved: PartArray,
}
#[allow(clippy::derivable_impls)]
impl Default for Parts {
fn default() -> Self {
Self {
unsaved: PartArray::default(),
saved: PartArray::default(),
}
}
}
impl HasHeaderField for Parts {
fn check_header(&self) -> Result<bool, OtToolsIoError> {
let unsaved = self
.unsaved
.iter()
.all(|x| x.check_header().is_ok_and(|x| x));
let saved = self.saved.iter().all(|x| x.check_header().is_ok_and(|x| x));
Ok(saved && unsaved)
}
}
#[cfg(test)]
mod parts_header_field {
use crate::{
test_utils::get_blank_proj_dirpath, BankFile, HasHeaderField, OctatrackFileIO,
OtToolsIoError,
};
#[test]
fn valid() -> Result<(), OtToolsIoError> {
let path = get_blank_proj_dirpath().join("bank01.work");
let parts = BankFile::from_data_file(&path)?.parts;
assert!(parts.check_header()?);
Ok(())
}
#[test]
fn invalid() -> Result<(), OtToolsIoError> {
let path = get_blank_proj_dirpath().join("bank01.work");
let mut parts = BankFile::from_data_file(&path)?.parts;
parts.saved[0].header[0] = 255;
parts.saved[0].header[1] = 255;
parts.saved[0].header[2] = 255;
parts.saved[0].header[3] = 255;
assert!(!parts.check_header()?);
Ok(())
}
}
#[derive(
Clone,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
Deserialize,
AsMutDerive,
AsRefDerive,
ContainerArrayMethods,
)]
pub struct PartArray(
Box<Array<Part, 4>>,
);
impl std::ops::Deref for PartArray {
type Target = Box<Array<Part, 4>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::ops::DerefMut for PartArray {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}