emit sound directly as a single token

This commit is contained in:
Corwin 2022-08-04 22:53:25 +01:00
parent 99af3e2b17
commit d0a238da9e

View file

@ -1,15 +1,9 @@
#![deny(clippy::all)] #![deny(clippy::all)]
use proc_macro::TokenStream; use proc_macro::TokenStream;
use quote::quote; use proc_macro2::Literal;
use std::{ use quote::{quote, ToTokens};
collections::hash_map::DefaultHasher, use std::path::Path;
fs,
fs::File,
hash::{Hash, Hasher},
io::Write,
path::Path,
};
use syn::parse_macro_input; use syn::parse_macro_input;
#[cfg(all(not(feature = "freq18157"), not(feature = "freq32768")))] #[cfg(all(not(feature = "freq18157"), not(feature = "freq32768")))]
@ -21,6 +15,14 @@ const FREQUENCY: u32 = 32768;
#[cfg(all(feature = "freq18157", feature = "freq32768"))] #[cfg(all(feature = "freq18157", feature = "freq32768"))]
compile_error!("Must have at most one of freq18157 or freq32768 features enabled"); 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] #[proc_macro]
pub fn include_wav(input: TokenStream) -> TokenStream { pub fn include_wav(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as syn::LitStr); let input = parse_macro_input!(input as syn::LitStr);
@ -32,21 +34,6 @@ pub fn include_wav(input: TokenStream) -> TokenStream {
let include_path = path.to_string_lossy(); 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 out_file_path = Path::new(&out_dir).with_file_name(&out_filename);
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) let wav_reader = hound::WavReader::open(&path)
.unwrap_or_else(|_| panic!("Failed to load file {}", include_path)); .unwrap_or_else(|_| panic!("Failed to load file {}", include_path));
@ -57,22 +44,8 @@ pub fn include_wav(input: TokenStream) -> TokenStream {
FREQUENCY FREQUENCY
); );
let samples = samples_from_reader(wav_reader); let samples: Vec<u8> = samples_from_reader(wav_reader).collect();
let samples = ByteString(&samples);
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 result = quote! { let result = quote! {
{ {
@ -81,7 +54,7 @@ pub fn include_wav(input: TokenStream) -> TokenStream {
const _: &[u8] = include_bytes!(#include_path); 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())
}