use super::slot::Slot;
use crate::cbin::{self, Cbin, Header};
use crate::components::{
Level, MasterTempo, ProgramCategory, ReverbType, RotorSpeed, Selector, SplitNote,
StageTranspose,
};
use crate::error::Error;
use std::io::{Read, Seek};
pub const FORMAT: &str = "ns2p";
pub const KNOWN_VERSIONS: &[u32] = &[2, 3, 4, 5, 6, 7];
pub const BODY_LEN: usize = 521;
#[nord_bits_derive::bitbody(521)]
pub struct Program {
#[bits(16..=17)]
pub slot_selection: Selector<2>,
#[bits(18..=18)]
pub dual_keyboard: bool,
#[bits(20..=23)]
pub split_low_note: SplitNote,
#[bits(24..=27)]
pub split_high_note: SplitNote,
#[bits(28..=28)]
pub split_three_zones: bool,
#[bits(29..=29)]
pub split_two_zones: bool,
#[bits(33..=33)]
pub organ_pitch_stick: bool,
#[bits(34..=34)]
pub transpose_enabled: bool,
#[bits(35..=38)]
pub transpose: StageTranspose,
#[bits(43..=50)]
pub master_clock: MasterTempo,
#[bits(64..=65)]
pub organ_model: Selector<2>,
#[bits(72..=74)]
pub organ_b3_vibrato_mode: Selector<3>,
#[bits(75..=75)]
pub organ_b3_harmonic_third: bool,
#[bits(76..=76)]
pub organ_b3_decay_fast: bool,
#[bits(77..=77)]
pub organ_b3_volume_soft: bool,
#[bits(89..=90)]
pub organ_vox_vibrato_mode: Selector<2>,
#[bits(91..=91)]
pub organ_vox_vibrato_on: bool,
#[bits(105..=106)]
pub organ_farfisa_vibrato_mode: Selector<2>,
#[bits(107..=107)]
pub organ_farfisa_vibrato_on: bool,
#[bits(120..=122)]
pub piano_slot_detune: Selector<3>,
#[bits(136..=136)]
pub reverb_on: bool,
#[bits(137..=139)]
pub reverb_type: ReverbType,
#[bits(140..=146)]
pub reverb_amount: Level,
#[bits(147..=147)]
pub compressor_on: bool,
#[bits(148..=154)]
pub compressor_amount: Level,
#[bits(155..=155)]
pub rotary_speaker_on: bool,
#[bits(156..=157)]
pub rotary_speaker_source: Selector<2>,
#[bits(158..=164)]
pub rotary_speaker_drive: Level,
#[bits(165..=165)]
pub rotary_speaker_stop_mode: bool,
#[bits(166..=166)]
pub rotary_speaker_speed: RotorSpeed,
#[bits(167..=167)]
pub rotary_speaker_speed_wheel: bool,
#[bits(168..=168)]
pub rotary_speaker_speed_aftertouch: bool,
#[bits(169..=169)]
pub rotary_speaker_speed_ctrl_pedal: bool,
#[at(23..272)]
pub slot_a: Slot,
#[at(272..521)]
pub slot_b: Slot,
}
impl Program {
pub fn split_enabled(&self) -> bool {
self.split_two_zones || self.split_three_zones
}
}
pub fn category(header: &Header) -> ProgramCategory {
use crate::bits::Packed;
ProgramCategory::from_bits((header.aux & 0xff) as u64).expect("decoding is total")
}
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)
}
pub type OctaveShift = crate::components::OctaveShift<7, -7, 8>;