midip/src/midi.rs

345 lines
9.9 KiB
Rust

use std::fs::File;
use std::io::prelude::*;
use std::io::Error;
fn buffer_u16(b: &[u8]) -> u16 {
(b[0] as u16) << 8 | b[1] as u16
}
fn buffer_u32(b: &[u8]) -> u32 {
(b[0] as u32) << 24 | (b[1] as u32) << 16 | (b[2] as u32) << 8 | (b[3] as u32)
}
struct MidiHeader {
tamanho: u32,
formato: u16,
tracks: u16,
divisao: u16,
}
fn ler_vlq(buffer_completo: Vec<u8>) -> (u32, Vec<u8>) {
let mut dt;
let mut dtb;
let (p, mut resto) = buffer_completo.split_at(1);
dt = p[0] as u32;
dtb = p[0];
while dtb & 0b10000000 != 0 {
dt &= 0x7f;
dt = dt << 7;
let tmp = resto.split_at(1);
dtb = tmp.0[0];
resto = tmp.1;
dt = dt | (dtb & 0x7f) as u32;
}
return (dt, Vec::from(resto));
}
///////////////////////////////////////////////////////////////////////////////
#[derive(Clone, Debug)]
enum TipoMetaEvento {
SequenceNumber,
TextEvent(String),
CopyrightNotice(String),
TrackName(String),
InstrumentName(String),
Lyric(String),
Marker(String),
CuePoint(String),
SetTempo(u32),
MIDIChannelPrefix,
EndofTrack,
SMTPEOffset,
TimeSignature,
KeySignature,
SequencerSpecificMetaEvent,
}
#[derive(Clone, Debug)]
struct MetaEvento {
tipo: u8,
tamanho: u32,
dados: Vec<u8>,
estrutura: TipoMetaEvento,
}
impl MetaEvento {
fn novo(tipo: u8, tamanho: u32, dados: Vec<u8>) -> Self {
unsafe {
let estrutura = match tipo {
0x00 => TipoMetaEvento::SequenceNumber,
0x01 => TipoMetaEvento::TextEvent(String::from_utf8(dados.clone()).unwrap()),
0x02 => TipoMetaEvento::CopyrightNotice(String::from_utf8_unchecked(dados.clone())),
0x03 => TipoMetaEvento::TrackName(String::from_utf8(dados.clone()).unwrap()),
0x04 => TipoMetaEvento::InstrumentName(String::from_utf8(dados.clone()).unwrap()),
0x05 => TipoMetaEvento::Lyric(String::from_utf8(dados.clone()).unwrap()),
0x06 => TipoMetaEvento::Marker(String::from_utf8(dados.clone()).unwrap()),
0x07 => TipoMetaEvento::CuePoint(String::from_utf8(dados.clone()).unwrap()),
0x20 => TipoMetaEvento::MIDIChannelPrefix,
0x2F => TipoMetaEvento::EndofTrack,
0x54 => TipoMetaEvento::SMTPEOffset,
0x58 => TipoMetaEvento::TimeSignature,
0x59 => TipoMetaEvento::KeySignature,
0x51 => TipoMetaEvento::SetTempo(
(dados[0] as u32) << 16 | (dados[1] as u32) << 8 | (dados[2] as u32),
),
_ => TipoMetaEvento::SequencerSpecificMetaEvent,
};
MetaEvento {
tamanho,
tipo,
dados,
estrutura,
}
}
}
}
//////////////////////////////////////////////////////////////////////////////
//#[derive(Clone)]
//struct SysexEvento {
// tipo: u8,
// tamanho: u32,
// dados: Vec<u8>,
//}
//////////////////////////////////////////////////////////////////////////////
#[derive(Clone, Debug)]
pub enum TipoMidiEvento {
NotaOn(u8, u8),
NotaOff(u8, u8),
Nenhum,
}
#[derive(Clone, Debug)]
pub struct MidiEvento {
estrutura: TipoMidiEvento,
}
impl MidiEvento {
fn novo(tipo: u8, _canal: u8, dados: Vec<u8>) -> Self {
let estrutura = match tipo {
0x8 => TipoMidiEvento::NotaOff(dados[0], dados[1]),
0x9 => TipoMidiEvento::NotaOn(dados[0], dados[1]),
_ => TipoMidiEvento::Nenhum,
};
MidiEvento { estrutura }
}
pub fn som(&self) -> (u8, u8) {
match self.estrutura {
TipoMidiEvento::NotaOn(n, v) => (n, v),
TipoMidiEvento::NotaOff(n, v) => (n, v),
_ => (0, 0),
}
}
}
//////////////////////////////////////////////////////////////////////////////
#[derive(Clone, Debug)]
pub enum Evento {
Vazio,
Meta(MetaEvento),
//Sysex(SysexEvento),
Midi(MidiEvento),
}
#[derive(Clone)]
struct MidiTrack {
tamanho: u32,
d_eventos: Vec<(u32, Evento)>,
buffer_eventos: Vec<u8>,
}
impl MidiTrack {
pub fn tt(&self) {
println!("{}", self.d_eventos.len());
}
fn processar(&mut self) -> Result<(), Error> {
let mut buffer_completo = self.buffer_eventos.clone();
loop {
if buffer_completo.is_empty() {
break;
}
let (dt, mut resto) = ler_vlq(buffer_completo);
let tmp = resto.split_at(1);
let status = tmp.0[0];
resto = tmp.1.to_vec();
let evento = match status {
0xff => {
//Meta evento
let tmp = resto.split_at(1);
let tipo = tmp.0[0];
resto = tmp.1.to_vec();
let tmp = ler_vlq(resto);
let tamanho = tmp.0;
resto = tmp.1;
let tmp = resto.split_at(tamanho as usize);
let dados = tmp.0.to_vec();
resto = tmp.1.to_vec();
Evento::Meta(MetaEvento::novo(tipo, tamanho, dados))
}
0x80..=0xef => {
//Evento midi
let tipo = (status & 0b11110000) >> 4;
let canal = status & 0b00001111;
let evento;
match tipo {
0x8 => {
let tmp = resto.split_at(2);
evento = Evento::Midi(MidiEvento::novo(tipo, canal, tmp.0.to_vec()));
resto = tmp.1.to_vec();
}
0x9 => {
let tmp = resto.split_at(2);
evento = Evento::Midi(MidiEvento::novo(tipo, canal, tmp.0.to_vec()));
resto = tmp.1.to_vec();
}
0xa | 0xb | 0xe => {
let tmp = resto.split_at(2);
resto = tmp.1.to_vec();
evento = Evento::Vazio;
}
0xc => {
let tmp = resto.split_at(1);
resto = tmp.1.to_vec();
evento = Evento::Vazio;
}
0xd => {
let tmp = resto.split_at(1);
resto = tmp.1.to_vec();
evento = Evento::Vazio;
}
_ => {
return Err(Error::new(
std::io::ErrorKind::InvalidInput,
format!("evento midi desconhecido : {}", status),
))
}
}
evento
}
0xf0 | 0xf7 => todo!("implementar eventos sysex tipo 0x{:x?}", status),
_ => {
return Err(Error::new(
std::io::ErrorKind::InvalidInput,
format!("evento desconhecido : {:x?}", status),
));
}
};
self.d_eventos.push((dt, evento));
buffer_completo = Vec::from(resto);
}
let mut nd_eventos = Vec::new();
for ev in self.d_eventos.clone() {
match ev.1 {
Evento::Vazio => {}
_ => {
nd_eventos.push(ev);
}
}
}
self.d_eventos = nd_eventos;
Ok(())
}
}
pub struct MIDI {
cabecalho: MidiHeader,
tracks: Vec<MidiTrack>,
}
impl MIDI {
pub fn tt(&self) {
let mut tn = 1;
self.tracks.iter().for_each(|i| {
print!("track num {} :", tn);
i.tt();
tn += 1;
});
}
pub fn prox(&mut self) -> Option<(u32, Evento)> {
self.tracks[1].d_eventos.pop()
}
pub fn novo(arquivo: &str) -> Result<Self, Error> {
let mut f = File::open(arquivo).expect("problema ao abrir o midi");
let mut buffer_cabecalho = [0; 4];
let mut buffer_tamanho = [0; 4];
let mut buffer_formato = [0; 2];
let mut buffer_tracks = [0; 2];
let mut buffer_divisao = [0; 2];
f.read_exact(&mut buffer_cabecalho)?;
f.read_exact(&mut buffer_tamanho)?;
f.read_exact(&mut buffer_formato)?;
f.read_exact(&mut buffer_tracks)?;
f.read_exact(&mut buffer_divisao)?;
let tamanho = buffer_u32(&buffer_tamanho);
let formato = buffer_u16(&buffer_formato);
let tracks = buffer_u16(&buffer_tracks);
let divisao = buffer_u16(&buffer_divisao);
let cabecalho = MidiHeader {
tamanho,
formato,
tracks,
divisao,
};
let tracks = Vec::new();
let mut midi_r = MIDI { cabecalho, tracks };
midi_r.processar_tracks(&mut f)?;
return Ok(midi_r);
}
fn processar_tracks(&mut self, reader: &mut File) -> Result<(), Error> {
for _ in 0..self.cabecalho.tracks {
let mut buffer_cabecalho = [0; 4];
let mut buffer_tamanho = [0; 4];
reader.read_exact(&mut buffer_cabecalho)?;
reader.read_exact(&mut buffer_tamanho)?;
let tamanho = buffer_u32(&buffer_tamanho);
let mut buffer_eventos: Vec<u8> = vec![0; tamanho as usize];
reader.read_exact(&mut buffer_eventos)?;
let d_eventos = Vec::new();
let mut track = MidiTrack {
tamanho,
d_eventos,
buffer_eventos,
};
track.processar()?;
track.d_eventos.reverse();
self.tracks.push(track);
}
Ok(())
}
}