Do the same changes for midi

This commit is contained in:
Gwilym Inzani 2024-06-05 17:14:39 +01:00
parent 3a755107aa
commit f452070154
4 changed files with 71 additions and 67 deletions

View file

@ -8,10 +8,6 @@ description = "Library for converting MIDI files for use with agb-tracker on the
repository = "https://github.com/agbrs/agb"
[dependencies]
proc-macro-error = "1"
proc-macro2 = "1"
quote = "1"
syn = "2"
rustysynth = "1.3"
midly = { version = "0.5", default-features = false, features = [
"alloc",

View file

@ -10,63 +10,7 @@ use std::{
use agb_fixnum::Num;
use agb_tracker_interop::{Envelope, Pattern, PatternEffect, PatternSlot, Sample, Track};
use midly::{Format, MetaMessage, Smf, Timing, TrackEventKind};
use proc_macro2::TokenStream;
use proc_macro_error::abort;
use quote::quote;
use rustysynth::SoundFont;
use syn::{
parse::{Parse, ParseStream},
LitStr, Token,
};
struct MidiCoreInput {
sf2_file: LitStr,
_comma: Token![,],
midi_file: LitStr,
}
impl Parse for MidiCoreInput {
fn parse(input: ParseStream) -> syn::Result<Self> {
Ok(Self {
sf2_file: input.parse()?,
_comma: input.parse()?,
midi_file: input.parse()?,
})
}
}
pub fn agb_midi_core(args: TokenStream) -> TokenStream {
let input: MidiCoreInput = match syn::parse2(args.clone()) {
Ok(input) => input,
Err(e) => abort!(args, e),
};
let sf2_file = input.sf2_file.value();
let midi_file = input.midi_file.value();
let root = std::env::var("CARGO_MANIFEST_DIR").expect("Failed to get cargo manifest dir");
let sf2_file = Path::new(&root).join(&*sf2_file);
let midi_file = Path::new(&root).join(&*midi_file);
let sf2_include_path = sf2_file.to_string_lossy();
let midi_file_include_path = midi_file.to_string_lossy();
let midi_info = match MidiInfo::load_from_file(&sf2_file, &midi_file) {
Ok(track) => track,
Err(e) => abort!(args, e),
};
let parsed = parse_midi(&midi_info);
quote! {
{
const _: &[u8] = include_bytes!(#sf2_include_path);
const _: &[u8] = include_bytes!(#midi_file_include_path);
#parsed
}
}
}
pub struct MidiInfo {
sound_font: SoundFont,
@ -88,7 +32,7 @@ impl MidiInfo {
}
}
pub fn parse_midi(midi_info: &MidiInfo) -> TokenStream {
pub fn parse_midi(midi_info: &MidiInfo) -> Track {
let mut samples = vec![];
let sf2 = &midi_info.sound_font;
let sf2_data = sf2.get_wave_data();
@ -417,7 +361,7 @@ pub fn parse_midi(midi_info: &MidiInfo) -> TokenStream {
})
.collect();
let track = Track {
Track {
samples: samples.into(),
envelopes: envelopes.into(),
patterns: Cow::from(vec![Pattern {
@ -430,9 +374,7 @@ pub fn parse_midi(midi_info: &MidiInfo) -> TokenStream {
frames_per_tick: Num::from_f64(frames_per_tick),
ticks_per_step: 1,
repeat: 0,
};
quote!(#track)
}
}
#[derive(Clone, Default)]

View file

@ -14,3 +14,11 @@ proc-macro = true
agb_midi_core = { version = "0.20.5", path = "../agb-midi-core" }
proc-macro-error = "1"
proc-macro2 = "1"
quote = "1"
syn = "2"
rustysynth = "1.3"
midly = { version = "0.5", default-features = false, features = [
"alloc",
"std",
] }

View file

@ -1,8 +1,66 @@
use std::path::Path;
use agb_midi_core::{parse_midi, MidiInfo};
use proc_macro::TokenStream;
use proc_macro_error::proc_macro_error;
use proc_macro_error::{abort, proc_macro_error};
use quote::quote;
use syn::{
parse::{Parse, ParseStream},
LitStr, Token,
};
#[proc_macro_error]
#[proc_macro]
pub fn include_midi(args: TokenStream) -> TokenStream {
agb_midi_core::agb_midi_core(args.into()).into()
agb_midi_core(args)
}
struct MidiCoreInput {
sf2_file: LitStr,
_comma: Token![,],
midi_file: LitStr,
}
impl Parse for MidiCoreInput {
fn parse(input: ParseStream) -> syn::Result<Self> {
Ok(Self {
sf2_file: input.parse()?,
_comma: input.parse()?,
midi_file: input.parse()?,
})
}
}
fn agb_midi_core(args: TokenStream) -> TokenStream {
let input: MidiCoreInput = match syn::parse(args.clone()) {
Ok(input) => input,
Err(e) => abort!(proc_macro2::TokenStream::from(args), e),
};
let sf2_file = input.sf2_file.value();
let midi_file = input.midi_file.value();
let root = std::env::var("CARGO_MANIFEST_DIR").expect("Failed to get cargo manifest dir");
let sf2_file = Path::new(&root).join(&*sf2_file);
let midi_file = Path::new(&root).join(&*midi_file);
let sf2_include_path = sf2_file.to_string_lossy();
let midi_file_include_path = midi_file.to_string_lossy();
let midi_info = match MidiInfo::load_from_file(&sf2_file, &midi_file) {
Ok(track) => track,
Err(e) => abort!(proc_macro2::TokenStream::from(args), e),
};
let parsed = parse_midi(&midi_info);
quote! {
{
const _: &[u8] = include_bytes!(#sf2_include_path);
const _: &[u8] = include_bytes!(#midi_file_include_path);
#parsed
}
}
.into()
}