use std::{
fs::File,
io::{BufReader, Error},
};
use hound::{WavSpec, WavWriter};
use rodio::{Decoder, OutputStream, Sink};
use crate::{waveform::generate_sample, Song};
impl Song {
pub fn export_to_wav(&self, filename: String) -> Result<(), Box<dyn std::error::Error>> {
let spec = WavSpec {
channels: 1,
sample_rate: 44100, bits_per_sample: 16, sample_format: hound::SampleFormat::Int,
};
let mut writer = match WavWriter::create(filename, spec) {
Ok(e) => e,
Err(e) => {
panic!("RS-AUDIO: Error while creating file: {e}");
}
};
for note in &self.notes {
let total_samples = (note.dur * 44100.0) as usize;
for i in 0..total_samples {
let phase = (i as f64 * note.freq / 44100.0) % 1.0; let sample = generate_sample(¬e.wave, phase) * note.vol as f64; writer.write_sample((sample * i16::MAX as f64) as i16)?; }
}
writer.finalize()?;
Ok(())
}
pub fn play_wav(file_path: &str) -> Result<(), Error> {
let (_stream, handle) = match OutputStream::try_default() {
Ok(e) => e,
Err(e) => return Err(Error::other(e.to_string())),
};
let sink = match Sink::try_new(&handle) {
Ok(e) => e,
Err(e) => return Err(Error::other(e.to_string())),
};
let file = File::open(file_path)?;
let source = match Decoder::new(BufReader::new(file)) {
Ok(e) => e,
Err(e) => return Err(Error::other(e.to_string())),
};
sink.append(source);
sink.sleep_until_end();
Ok(())
}
}