use crate::prelude::*;
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub enum VoiceEvent {
NoteOff {
key: Key,
velocity: Velocity,
},
NoteOn {
key: Key,
velocity: Velocity,
},
Aftertouch {
key: Key,
velocity: Velocity,
},
ControlChange {
controller: Controller,
value: DataByte,
},
ProgramChange {
program: Program,
},
ChannelPressureAfterTouch {
velocity: Velocity,
},
PitchBend(PitchBend),
}
impl VoiceEvent {
pub fn note_on(key: Key, velocity: Velocity) -> Self {
Self::NoteOn { key, velocity }
}
pub fn note_off(key: Key, velocity: Velocity) -> Self {
Self::NoteOff { key, velocity }
}
pub fn send_to_channel(self, channel: Channel) -> ChannelVoiceMessage {
ChannelVoiceMessage::new(channel, self)
}
pub fn program_change(program: Program) -> Self {
Self::ProgramChange { program }
}
pub fn is_note_on(&self) -> bool {
use VoiceEvent::*;
match self {
NoteOn { velocity, .. } => velocity.byte() != 0,
_ => false,
}
}
pub fn is_note_off(&self) -> bool {
use VoiceEvent::*;
match self {
NoteOff { .. } => true,
NoteOn { velocity, .. } => velocity.byte() == 0,
_ => false,
}
}
pub fn to_raw(&self) -> Vec<u8> {
match self {
VoiceEvent::NoteOff { key, velocity } => vec![key.byte(), velocity.byte()],
VoiceEvent::NoteOn { key, velocity } => vec![key.byte(), velocity.byte()],
VoiceEvent::Aftertouch { key, velocity } => {
vec![key.byte(), velocity.byte()]
}
VoiceEvent::ControlChange { controller, value } => {
vec![controller.byte(), value.0]
}
VoiceEvent::ProgramChange { program } => vec![program.byte()],
VoiceEvent::ChannelPressureAfterTouch { velocity } => vec![velocity.byte()],
VoiceEvent::PitchBend(bend) => {
vec![bend.lsb(), bend.msb()]
}
}
}
#[allow(dead_code)]
pub(crate) fn status_nibble(&self) -> u8 {
match self {
VoiceEvent::NoteOff { .. } => 0x8,
VoiceEvent::NoteOn { .. } => 0x9,
VoiceEvent::Aftertouch { .. } => 0xA,
VoiceEvent::ControlChange { .. } => 0xB,
VoiceEvent::ProgramChange { .. } => 0xC,
VoiceEvent::ChannelPressureAfterTouch { .. } => 0xD,
VoiceEvent::PitchBend { .. } => 0xE,
}
}
}