use super::panel::Panel;
use crate::cbin::{self, Cbin};
use crate::components::{
sparse_enum, Level, MasterTempo, RotorSpeed, Selector, SplitNote, SplitWidth, StageTranspose,
SwitchMorph,
};
use crate::error::Error;
use std::io::{Read, Seek};
pub const FORMAT: &str = "ns3f";
pub const KNOWN_VERSIONS: &[u32] = &[300, 301, 302, 303, 304];
pub const BODY_LEN: usize = 548;
pub type OctaveShift = crate::components::OctaveShift<6, -6, 9>;
sparse_enum!(
PanelEnable, 2, {
0 => AOnly, "A only";
1 => BOnly, "B only";
2 => Both, "A & B";
}
);
sparse_enum!(
DualKeyboardStyle, 2, {
0 => Panel, "Panel";
1 => Organ, "Organ";
2 => Piano, "Piano";
3 => Synth, "Synth";
}
);
#[nord_bits_derive::bitbody(548)]
pub struct Program {
#[bits(40..=40)]
pub panel_b_selected: bool,
#[bits(41..=42)]
pub panel_enable: PanelEnable,
#[bits(43..=43)]
pub split_enabled: bool,
#[bits(44..=44)]
pub split_low_enabled: bool,
#[bits(45..=45)]
pub split_mid_enabled: bool,
#[bits(46..=46)]
pub split_high_enabled: bool,
#[bits(47..=50)]
pub split_low_note: SplitNote,
#[bits(51..=54)]
pub split_mid_note: SplitNote,
#[bits(55..=58)]
pub split_high_note: SplitNote,
#[bits(59..=60)]
pub split_low_width: SplitWidth,
#[bits(61..=62)]
pub split_mid_width: SplitWidth,
#[bits(63..=64)]
pub split_high_width: SplitWidth,
#[bits(65..=66)]
pub piano_layer_detune: PianoLayerDetune,
#[bits(67..=67)]
pub organ_pitch_stick: bool,
#[bits(68..=70)]
pub organ_vibrato_mode: OrganVibratoMode,
#[bits(71..=71)]
pub rotary_speaker_speed: RotorSpeed,
#[bits(72..=72)]
pub rotary_speaker_stop_mode: bool,
#[bits(73..=75)]
pub rotary_speaker_speed_wheel: SwitchMorph,
#[bits(76..=78)]
pub rotary_speaker_speed_aftertouch: SwitchMorph,
#[bits(79..=81)]
pub rotary_speaker_speed_ctrl_pedal: SwitchMorph,
#[bits(96..=96)]
pub transpose_enabled: bool,
#[bits(97..=100)]
pub transpose: StageTranspose,
#[bits(101..=108)]
pub master_clock: MasterTempo,
#[bits(109..=115)]
pub rotary_speaker_drive: Level,
#[bits(116..=116)]
pub dual_keyboard: bool,
#[bits(118..=119)]
pub dual_keyboard_style: DualKeyboardStyle,
#[bits(120..=123)]
pub synth_pitch_stick_range: Selector<4>,
#[at(22..285)]
pub panel_a: Panel,
#[at(285..548)]
pub panel_b: Panel,
}
pub fn location(file: &Cbin<Program>) -> (u16, u16) {
file.header.slot()
}
pub fn read_from(reader: &mut (impl Read + Seek)) -> Result<Cbin<Program>, Error> {
let file: Cbin<Program> = cbin::read(reader, FORMAT)?;
crate::formats::known_version(FORMAT, file.header.version, KNOWN_VERSIONS)?;
Ok(file)
}
sparse_enum!(
AmpSimEqAmpType, 3, {
0 => Clean, "Clean";
1 => Twin, "Twin";
2 => Jc, "JC";
3 => Small, "Small";
4 => Lp24, "LP24";
5 => Hp24, "HP24";
}
);
sparse_enum!(
ClavinetModel, 2, {
0 => Ca, "CA";
1 => Cb, "CB";
2 => Da, "DA";
3 => Db, "DB";
}
);
sparse_enum!(
OrganType, 3, {
0 => B3, "B3";
1 => Vox, "Vox";
2 => Farfisa, "Farfisa";
3 => Pipe1, "Pipe1";
4 => Pipe2, "Pipe2";
}
);
sparse_enum!(
OrganVibratoMode, 3, {
0 => V1, "V1";
1 => C1, "C1";
2 => V2, "V2";
3 => C2, "C2";
4 => V3, "V3";
5 => C3, "C3";
}
);
sparse_enum!(
PianoKbTouch, 2, {
0 => Normal, "Normal";
1 => KbTouch1, "KB Touch 1";
2 => Touch2, "Touch 2";
3 => Touch3, "Touch 3";
}
);
sparse_enum!(
PianoLayerDetune, 2, {
0 => V0, "Off";
1 => V1, "1";
2 => V2, "2";
3 => V3, "3";
}
);
sparse_enum!(
PianoTimbre, 3, {
0 => None, "None";
1 => Soft, "Soft";
2 => Treble, "Treble";
3 => SoftTreble, "Soft+Treble";
4 => Brilliant, "Brilliant";
5 => SoftBrill, "Soft+Brill";
6 => TrebleBrill, "Treble+Brill";
7 => SoftTrbBrill, "Soft+Trb+Brill";
}
);
sparse_enum!(
PianoType, 3, {
0 => Grand, "Grand";
1 => Upright, "Upright";
2 => Electric, "Electric";
3 => Clav, "Clav";
4 => Digital, "Digital";
5 => Misc, "Misc";
}
);
sparse_enum!(
SynthAmpEnvVelocity, 2, {
0 => V0, "Off";
1 => V1, "1";
2 => V2, "2";
3 => V3, "3";
}
);
sparse_enum!(
SynthArpPattern, 2, {
0 => Up, "Up";
1 => Down, "Down";
2 => UpDown, "Up/Down";
3 => Random, "Random";
}
);
sparse_enum!(
SynthArpRange, 2, {
0 => V1Octave, "1 Octave";
1 => V2Octaves, "2 Octaves";
2 => V3Octaves, "3 Octaves";
3 => V4Octaves, "4 Octaves";
}
);
sparse_enum!(
SynthFilterDrive, 2, {
0 => V0, "Off";
1 => V1, "1";
2 => V2, "2";
3 => V3, "3";
}
);
sparse_enum!(
SynthFilterKbTrack, 2, {
0 => V0, "Off";
1 => V1, "1/3";
2 => V2, "2/3";
3 => V3, "1";
}
);
sparse_enum!(
SynthFilterType, 3, {
0 => Lp12, "LP12";
1 => Lp24, "LP24";
2 => MiniMoog, "Mini Moog";
3 => LpHp, "LP+HP";
4 => Bp24, "BP24";
5 => Hp24, "HP24";
}
);
sparse_enum!(
SynthLfoWave, 3, {
0 => Triangle, "Triangle";
1 => Saw, "Saw";
2 => NegSaw, "Neg Saw";
3 => Square, "Square";
4 => SH, "S/H";
}
);
sparse_enum!(
SynthOscillatorConfig, 4, {
0 => None, "None";
1 => Pitch, "Pitch";
2 => Shape, "Shape";
3 => Sync, "Sync";
4 => Detune, "Detune";
5 => Mixsin, "MixSin";
6 => Mixtri, "MixTri";
7 => Mixsaw, "MixSaw";
8 => Mixsqr, "MixSqr";
9 => Mixbell, "MixBell";
10 => Mixns1, "MixNs1";
11 => Mixns2, "MixNs2";
12 => Fm1, "FM1";
13 => Fm2, "FM2";
14 => Rm, "RM";
}
);
sparse_enum!(
SynthOscillatorType, 3, {
0 => Classic, "Classic";
1 => Wave, "Wave";
2 => Formant, "Formant";
3 => Super, "Super";
4 => Sample, "Sample";
}
);
sparse_enum!(
SynthUnison, 2, {
0 => V0, "Off";
1 => V1, "1";
2 => V2, "2";
3 => V3, "3";
}
);
sparse_enum!(
SynthVibrato, 3, {
0 => Off, "Off";
1 => Delay1, "Delay 1";
2 => Delay2, "Delay 2";
3 => Delay3, "Delay 3";
4 => Wheel, "Wheel";
5 => AfterTouch, "After Touch";
}
);
sparse_enum!(
SynthVoice, 2, {
0 => Poly, "Poly";
1 => Legato, "Legato";
2 => Mono, "Mono";
}
);