use std::sync::Arc;
use super::super::soundfont::{Preset, SoundFont};
use crate::core::tuning::Tuning;
use crate::core::utils::TypedIndex;
type MidiControlChange = u32;
const ALL_SOUND_OFF: MidiControlChange = 120;
const RPN_MSB: MidiControlChange = 101;
const RPN_LSB: MidiControlChange = 100;
const NRPN_MSB: MidiControlChange = 99;
const NRPN_LSB: MidiControlChange = 98;
const EFFECTS_DEPTH5: MidiControlChange = 95;
const EFFECTS_DEPTH1: MidiControlChange = 91;
const SOUND_CTRL10: MidiControlChange = 79;
const SOUND_CTRL1: MidiControlChange = 70;
const EXPRESSION_LSB: MidiControlChange = 43;
const PAN_LSB: MidiControlChange = 42;
const VOLUME_LSB: MidiControlChange = 39;
const BANK_SELECT_LSB: MidiControlChange = 32;
const EXPRESSION_MSB: MidiControlChange = 11;
const PAN_MSB: MidiControlChange = 10;
const VOLUME_MSB: MidiControlChange = 7;
const BANK_SELECT_MSB: MidiControlChange = 0;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum InterpolationMethod {
None = 0,
Linear = 1,
FourthOrder = 4,
SeventhOrder = 7,
}
impl Default for InterpolationMethod {
fn default() -> Self {
Self::FourthOrder
}
}
#[derive(Clone)]
pub struct Channel {
id: usize,
sfontnum: Option<TypedIndex<SoundFont>>,
banknum: u32,
prognum: u8,
preset: Option<Arc<Preset>>,
key_pressure: [i8; 128],
channel_pressure: u8,
pitch_bend: u16,
pitch_wheel_sensitivity: u8,
cc: [u8; 128],
bank_msb: u8,
interp_method: InterpolationMethod,
tuning: Option<Tuning>,
nrpn_select: i16,
nrpn_active: i16,
gen: [f32; 60],
gen_abs: [i8; 60],
}
impl Channel {
pub fn new(id: usize, preset: Option<Arc<Preset>>) -> Self {
let mut chan = Self {
id,
sfontnum: None,
banknum: 0,
prognum: 0,
preset,
key_pressure: [0; 128],
channel_pressure: 0,
pitch_bend: 0,
pitch_wheel_sensitivity: 0,
cc: [0; 128],
bank_msb: 0,
interp_method: Default::default(),
tuning: None,
nrpn_select: 0,
nrpn_active: 0,
gen: [0f32; 60],
gen_abs: [0; 60],
};
chan.init_ctrl(0);
chan
}
pub fn init(&mut self, preset: Option<Arc<Preset>>) {
self.prognum = 0;
self.banknum = 0;
self.sfontnum = None;
self.preset = preset;
self.interp_method = Default::default();
self.tuning = None;
self.nrpn_select = 0;
self.nrpn_active = 0;
}
pub fn init_ctrl(&mut self, is_all_ctrl_off: i32) {
self.channel_pressure = 0;
self.pitch_bend = 0x2000;
for i in 0..60 {
self.gen[i as usize] = 0.0;
self.gen_abs[i as usize] = 0;
}
if is_all_ctrl_off != 0 {
for i in 0..ALL_SOUND_OFF {
if !(i >= EFFECTS_DEPTH1 && i <= EFFECTS_DEPTH5) {
if !(i >= SOUND_CTRL1 && i <= SOUND_CTRL10) {
if !(i == BANK_SELECT_MSB
|| i == BANK_SELECT_LSB
|| i == VOLUME_MSB
|| i == VOLUME_LSB
|| i == PAN_MSB
|| i == PAN_LSB)
{
self.cc[i as usize] = 0;
}
}
}
}
} else {
for i in 0..128 {
self.cc[i] = 0;
}
}
for i in 0..128 {
self.key_pressure[i] = 0;
}
self.cc[RPN_LSB as usize] = 127;
self.cc[RPN_MSB as usize] = 127;
self.cc[NRPN_LSB as usize] = 127;
self.cc[NRPN_MSB as usize] = 127;
self.cc[EXPRESSION_MSB as usize] = 127;
self.cc[EXPRESSION_LSB as usize] = 127;
if is_all_ctrl_off == 0 {
self.pitch_wheel_sensitivity = 2;
let mut i = SOUND_CTRL1;
while i <= SOUND_CTRL10 {
self.cc[i as usize] = 64;
i += 1
}
self.cc[VOLUME_MSB as usize] = 100;
self.cc[VOLUME_LSB as usize] = 0;
self.cc[PAN_MSB as usize] = 64;
self.cc[PAN_LSB as usize] = 0;
};
}
}
impl Channel {
pub fn id(&self) -> usize {
self.id
}
pub fn sfontnum(&self) -> Option<TypedIndex<SoundFont>> {
self.sfontnum
}
pub fn set_sfontnum(&mut self, sfontnum: Option<TypedIndex<SoundFont>>) {
self.sfontnum = sfontnum;
}
pub fn banknum(&self) -> u32 {
self.banknum
}
pub fn set_banknum(&mut self, banknum: u32) {
self.banknum = banknum;
}
pub fn prognum(&self) -> u8 {
self.prognum
}
pub fn set_prognum(&mut self, prognum: u8) {
self.prognum = prognum;
}
pub fn preset(&self) -> Option<&Arc<Preset>> {
self.preset.as_ref()
}
pub fn set_preset(&mut self, preset: Option<Arc<Preset>>) {
self.preset = preset;
}
pub fn key_pressure(&self, id: usize) -> i8 {
self.key_pressure[id]
}
pub fn set_key_pressure(&mut self, id: usize, val: i8) {
self.key_pressure[id] = val;
}
pub fn channel_pressure(&self) -> u8 {
self.channel_pressure
}
pub fn set_channel_pressure(&mut self, val: u8) {
self.channel_pressure = val;
}
pub fn pitch_bend(&self) -> u16 {
self.pitch_bend
}
pub fn set_pitch_bend(&mut self, val: u16) {
self.pitch_bend = val;
}
pub fn pitch_wheel_sensitivity(&self) -> u8 {
self.pitch_wheel_sensitivity
}
pub fn set_pitch_wheel_sensitivity(&mut self, val: u8) {
self.pitch_wheel_sensitivity = val;
}
pub fn cc(&self, id: usize) -> u8 {
if id < 128 {
self.cc[id]
} else {
0
}
}
pub fn cc_mut(&mut self, id: usize) -> &mut u8 {
&mut self.cc[id]
}
pub fn bank_msb(&self) -> u8 {
self.bank_msb
}
pub fn set_bank_msb(&mut self, val: u8) {
self.bank_msb = val;
}
pub fn interp_method(&self) -> InterpolationMethod {
self.interp_method
}
pub fn set_interp_method(&mut self, new_method: InterpolationMethod) {
self.interp_method = new_method;
}
pub fn tuning(&self) -> Option<&Tuning> {
self.tuning.as_ref()
}
pub fn set_tuning(&mut self, val: Option<Tuning>) {
self.tuning = val;
}
pub fn nrpn_select(&self) -> i16 {
self.nrpn_select
}
pub fn set_nrpn_select(&mut self, value: i16) {
self.nrpn_select = value;
}
pub fn nrpn_active(&self) -> i16 {
self.nrpn_active
}
pub fn set_nrpn_active(&mut self, value: i16) {
self.nrpn_active = value;
}
pub fn gen(&self, id: usize) -> f32 {
self.gen[id]
}
pub fn set_gen(&mut self, id: usize, val: f32) {
self.gen[id] = val;
}
pub fn gen_abs(&self, id: usize) -> i8 {
self.gen_abs[id]
}
pub fn set_gen_abs(&mut self, id: usize, val: i8) {
self.gen_abs[id] = val;
}
}