mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 08:11:33 +11:00
emit sound directly as a single token
This commit is contained in:
parent
99af3e2b17
commit
d0a238da9e
|
@ -1,15 +1,9 @@
|
|||
#![deny(clippy::all)]
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use std::{
|
||||
collections::hash_map::DefaultHasher,
|
||||
fs,
|
||||
fs::File,
|
||||
hash::{Hash, Hasher},
|
||||
io::Write,
|
||||
path::Path,
|
||||
};
|
||||
use proc_macro2::Literal;
|
||||
use quote::{quote, ToTokens};
|
||||
use std::path::Path;
|
||||
use syn::parse_macro_input;
|
||||
|
||||
#[cfg(all(not(feature = "freq18157"), not(feature = "freq32768")))]
|
||||
|
@ -21,6 +15,14 @@ const FREQUENCY: u32 = 32768;
|
|||
#[cfg(all(feature = "freq18157", feature = "freq32768"))]
|
||||
compile_error!("Must have at most one of freq18157 or freq32768 features enabled");
|
||||
|
||||
use quote::TokenStreamExt;
|
||||
struct ByteString<'a>(&'a [u8]);
|
||||
impl ToTokens for ByteString<'_> {
|
||||
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
|
||||
tokens.append(Literal::byte_string(self.0));
|
||||
}
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn include_wav(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as syn::LitStr);
|
||||
|
@ -32,47 +34,18 @@ pub fn include_wav(input: TokenStream) -> TokenStream {
|
|||
|
||||
let include_path = path.to_string_lossy();
|
||||
|
||||
let out_file_path_include = {
|
||||
let out_dir = std::env::var("OUT_DIR").expect("Expected OUT_DIR");
|
||||
let out_filename = get_out_filename(&path);
|
||||
let wav_reader = hound::WavReader::open(&path)
|
||||
.unwrap_or_else(|_| panic!("Failed to load file {}", include_path));
|
||||
|
||||
let out_file_path = Path::new(&out_dir).with_file_name(&out_filename);
|
||||
assert_eq!(
|
||||
wav_reader.spec().sample_rate,
|
||||
FREQUENCY,
|
||||
"agb currently only supports sample rate of {}Hz",
|
||||
FREQUENCY
|
||||
);
|
||||
|
||||
let out_file_mtime = fs::metadata(&out_file_path).and_then(|metadata| metadata.modified());
|
||||
let in_file_mtime = fs::metadata(&path).and_then(|metadata| metadata.modified());
|
||||
|
||||
let should_write = match (out_file_mtime, in_file_mtime) {
|
||||
(Ok(out_file_mtime), Ok(in_file_mtime)) => out_file_mtime <= in_file_mtime,
|
||||
_ => true,
|
||||
};
|
||||
|
||||
if should_write {
|
||||
let wav_reader = hound::WavReader::open(&path)
|
||||
.unwrap_or_else(|_| panic!("Failed to load file {}", include_path));
|
||||
|
||||
assert_eq!(
|
||||
wav_reader.spec().sample_rate,
|
||||
FREQUENCY,
|
||||
"agb currently only supports sample rate of {}Hz",
|
||||
FREQUENCY
|
||||
);
|
||||
|
||||
let samples = samples_from_reader(wav_reader);
|
||||
|
||||
let mut out_file =
|
||||
File::create(&out_file_path).expect("Failed to open file for writing");
|
||||
|
||||
out_file
|
||||
.write_all(&samples.collect::<Vec<_>>())
|
||||
.expect("Failed to write to temporary file");
|
||||
}
|
||||
|
||||
out_file_path
|
||||
}
|
||||
.canonicalize()
|
||||
.expect("Failed to canonicalize");
|
||||
|
||||
let out_file_path_include = out_file_path_include.to_string_lossy();
|
||||
let samples: Vec<u8> = samples_from_reader(wav_reader).collect();
|
||||
let samples = ByteString(&samples);
|
||||
|
||||
let result = quote! {
|
||||
{
|
||||
|
@ -81,7 +54,7 @@ pub fn include_wav(input: TokenStream) -> TokenStream {
|
|||
|
||||
const _: &[u8] = include_bytes!(#include_path);
|
||||
|
||||
&AlignmentWrapper(*include_bytes!(#out_file_path_include)).0
|
||||
&AlignmentWrapper(*#samples).0
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -108,10 +81,3 @@ where
|
|||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_out_filename(path: &Path) -> String {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
path.hash(&mut hasher);
|
||||
|
||||
format!("{}.raw", hasher.finish())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue