use std::fmt;
use crate::k5000::control::{
VelocitySwitchSettings,
ModulationSettings,
PanSettings
};
use crate::{
SystemExclusiveData,
ParseError
};
use crate::k5000::osc::*;
use crate::k5000::filter::*;
use crate::k5000::amp::*;
use crate::k5000::lfo::*;
use crate::k5000::{
Volume,
BenderPitch,
BenderCutoff,
KeyOnDelay
};
use pretty_hex::*;
#[derive(Debug, Eq, PartialEq)]
pub struct Key {
pub note: u8,
}
static NOTE_NAMES: &str = "C C#D D#E F F#G G#A A#B ";
impl Key {
pub fn name(&self) -> String {
let octave = (self.note as f32 / 12 as f32).floor() - 1.0;
let name_index = (self.note as usize % 12) * 2;
let slice = if NOTE_NAMES.as_bytes()[name_index + 1] == ' ' as u8 {
&NOTE_NAMES[name_index..(name_index + 1)]
} else {
&NOTE_NAMES[name_index..(name_index + 2)]
};
format!("{}{}", slice, octave)
}
}
impl fmt::Display for Key {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.name())
}
}
#[derive(Debug)]
pub struct Zone {
pub low: Key,
pub high: Key,
}
impl fmt::Display for Zone {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} to {}", self.low, self.high)
}
}
impl SystemExclusiveData for Zone {
fn from_bytes(data: &[u8]) -> Result<Self, ParseError> {
Ok(Zone { low: Key { note: data[0] }, high: Key { note: data[1] } })
}
fn to_bytes(&self) -> Vec<u8> {
vec![
self.low.note,
self.high.note,
]
}
fn data_size() -> usize { 2 }
}
#[derive(Debug)]
pub struct SourceControl {
pub zone: Zone,
pub vel_sw: VelocitySwitchSettings,
pub effect_path: u8,
pub volume: Volume,
pub bender_pitch: BenderPitch,
pub bender_cutoff: BenderCutoff,
pub modulation: ModulationSettings,
pub key_on_delay: KeyOnDelay,
pub pan: PanSettings,
}
impl Default for SourceControl {
fn default() -> Self {
SourceControl {
zone: Zone { low: Key { note: 0 }, high: Key { note: 127 } },
vel_sw: Default::default(),
effect_path: 0,
volume: Volume::new(100),
bender_pitch: BenderPitch::new(0),
bender_cutoff: BenderCutoff::new(0),
modulation: Default::default(),
key_on_delay: KeyOnDelay::new(0),
pan: Default::default(),
}
}
}
impl fmt::Display for SourceControl {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Zone={}\nVel. switch: {}\nEffect Path={}\nVolume={}\nBender: Pitch={} Cutoff={}\nKey On Delay={}\nPan: Type={} Value={}\n",
self.zone, self.vel_sw, self.effect_path, self.volume, self.bender_pitch, self.bender_cutoff, self.key_on_delay, self.pan.pan_type, self.pan.pan_value
)
}
}
impl SystemExclusiveData for SourceControl {
fn from_bytes(data: &[u8]) -> Result<Self, ParseError> {
eprintln!("Source control data = {}", simple_hex(&data));
Ok(SourceControl {
zone: Zone { low: Key { note: data[0] }, high: Key { note: data[1] } },
vel_sw: VelocitySwitchSettings::from_bytes(&[data[2]])?,
effect_path: data[3],
volume: Volume::from(data[4]),
bender_pitch: BenderPitch::from(data[5]),
bender_cutoff: BenderCutoff::from(data[6]),
modulation: ModulationSettings::from_bytes(&data[7..25])?,
key_on_delay: KeyOnDelay::from(data[25]),
pan: PanSettings::from_bytes(&data[26..28])?,
})
}
fn to_bytes(&self) -> Vec<u8> {
let mut result: Vec<u8> = Vec::new();
result.extend(self.zone.to_bytes());
result.extend(self.vel_sw.to_bytes());
result.push(self.effect_path);
result.push(self.volume.into());
result.push(self.bender_pitch.into());
result.push(self.bender_cutoff.into());
result.extend(self.modulation.to_bytes());
result.push(self.key_on_delay.into());
result.extend(self.pan.to_bytes());
result
}
fn data_size() -> usize { Zone::data_size()
+ VelocitySwitchSettings::data_size()
+ 4 + ModulationSettings::data_size()
+ 1 + PanSettings::data_size()
}
}
#[derive(Default, Debug)]
pub struct Source {
pub oscillator: Oscillator,
pub filter: Filter,
pub amplifier: Amplifier,
pub lfo: Lfo,
pub control: SourceControl,
}
impl Source {
pub fn pcm() -> Source {
Default::default()
}
pub fn is_additive(&self) -> bool {
self.oscillator.wave.is_additive()
}
pub fn is_pcm(&self) -> bool {
!self.is_additive()
}
pub fn additive() -> Source {
Source {
oscillator: Oscillator::additive(),
filter: Default::default(),
amplifier: Default::default(),
lfo: Default::default(),
control: Default::default(),
}
}
}
impl fmt::Display for Source {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}\n\nDCO:\n{}\n\nDCF:\n{}\n\nDCA:\n{}\n\nLFO:\n{}\n",
self.control, self.oscillator, self.filter, self.amplifier, self.lfo)
}
}
impl SystemExclusiveData for Source {
fn from_bytes(data: &[u8]) -> Result<Self, ParseError> {
eprintln!("Source data size = {} bytes", data.len());
eprintln!("Reported sizes:");
let source_control_size = SourceControl::data_size();
eprintln!("Source control = {} bytes",
source_control_size);
let amplifier_size = Amplifier::data_size();
eprintln!("Amplifier data = {} bytes",
amplifier_size);
let oscillator_size = Oscillator::data_size();
eprintln!("Oscillator data = {} bytes",
oscillator_size);
let filter_size = Filter::data_size();
eprintln!("Filter data = {} bytes",
filter_size);
let lfo_size = Lfo::data_size();
eprintln!("LFO data = {} bytes",
lfo_size);
let total_size = source_control_size + amplifier_size + oscillator_size
+ filter_size + lfo_size;
eprintln!("Total = {} bytes", total_size);
Ok(Source {
control: SourceControl::from_bytes(&data[..28])?,
oscillator: Oscillator::from_bytes(&data[28..40])?,
filter: Filter::from_bytes(&data[40..60])?,
amplifier: Amplifier::from_bytes(&data[60..75])?,
lfo: Lfo::from_bytes(&data[75..86])?,
})
}
fn to_bytes(&self) -> Vec<u8> {
let mut result: Vec<u8> = Vec::new();
result.extend(self.control.to_bytes());
result.extend(self.oscillator.to_bytes());
result.extend(self.filter.to_bytes());
result.extend(self.amplifier.to_bytes());
result.extend(self.lfo.to_bytes());
result
}
fn data_size() -> usize {
SourceControl::data_size()
+ Oscillator::data_size()
+ Filter::data_size()
+ Amplifier::data_size()
+ Lfo::data_size()
}
}
#[cfg(test)]
mod tests {
use super::{*};
#[test]
fn test_key_name() {
let key = Key { note: 60 };
assert_eq!(key.name(), "C4");
}
#[test]
fn test_source_control_from_bytes() {
let data = vec![
0x00, 0x7f, 0x10, 0x00, 0x78, 0x02, 0x0c, 0x01, 0x4f, 0x03, 0x40, 0x03, 0x59, 0x01, 0x40, 0x02, 0x5f, 0x00, 0x40, 0x02, 0x0d, 0x40, 0x02, 0x09, 0x40, 0x00, 0x00, 0x40, ];
let source_control = SourceControl::from_bytes(&data);
assert_eq!(source_control.as_ref().unwrap().zone.low.note, 0x00);
assert_eq!(source_control.as_ref().unwrap().zone.high.note, 0x7f);
assert_eq!(source_control.as_ref().unwrap().volume.value(), 0x78);
}
#[test]
fn test_source_from_bytes() {
let data = vec![
0x00, 0x7f, 0x10, 0x00, 0x78, 0x02, 0x0c, 0x01, 0x4f, 0x03, 0x40, 0x03, 0x59, 0x01, 0x40, 0x02, 0x5f, 0x00, 0x40, 0x02, 0x0d, 0x40, 0x02, 0x09, 0x40, 0x00, 0x00, 0x40, 0x04, 0x00, 0x40, 0x40, 0x00, 0x00, 0x40, 0x04, 0x40, 0x40, 0x40, 0x40,
0x00, 0x00, 0x04, 0x00, 0x00, 0x37, 0x60, 0x40, 0x59, 0x00, 0x78, 0x7f, 0x50, 0x7f, 0x14, 0x40, 0x40, 0x5e, 0x40, 0x40,
0x04, 0x01, 0x5e, 0x7f, 0x3f, 0x7f, 0x0f, 0x40, 0x40, 0x40, 0x40, 0x14, 0x40, 0x40, 0x40, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, ];
let source = Source::from_bytes(&data);
assert_eq!(source.unwrap().lfo.speed.value(), 0x5d);
}
}