rs_audio/wav/exporter.rs
1use std::{
2 fs::File,
3 io::{BufReader, Error},
4};
5
6use hound::{WavSpec, WavWriter};
7use rodio::{Decoder, OutputStream, Sink};
8
9use crate::{waveform::generate_sample, BasicSong};
10
11impl BasicSong {
12 /**
13 # Deprecated
14 This feature has been deprecated in the latest update. Please use the new player, not the legacy one.<br><br>
15
16
17 Exports a Song struct to a .wav file.<br>It creates a .wav file in the current directory.<br>
18 Usage:
19 ```
20 use rs_audio::*;
21 use rs_audio::{legacyplayer::BasicSong};
22
23 let song = BasicSong::default();
24 song.export_to_wav("test.wav".to_string());
25 ```
26 */
27 pub fn export_to_wav(&self, filename: String) -> Result<(), Box<dyn std::error::Error>> {
28 // set up wave file specs
29 let spec = WavSpec {
30 channels: 1,
31 sample_rate: 44100, // 44.1k Hz
32 bits_per_sample: 16, // 16 bit depth
33 sample_format: hound::SampleFormat::Int,
34 };
35
36 // create writer for writing to files
37 let mut writer = match WavWriter::create(filename, spec) {
38 Ok(e) => e,
39 Err(e) => {
40 eprintln!("RS-AUDIO: Error while creating file: {e}");
41 std::process::exit(1);
42 }
43 };
44
45 for note in &self.notes {
46 let total_samples = (note.dur * 44100.0) as usize;
47 for i in 0..total_samples {
48 let phase = (i as f64 * note.freq / 44100.0) % 1.0; // generate phase
49 let sample = generate_sample(¬e.wave, phase) * note.vol as f64; // generate sample from waveform
50 writer.write_sample((sample * i16::MAX as f64) as i16)?; // add the sample
51 }
52 }
53
54 writer.finalize()?;
55
56 Ok(())
57 }
58
59 /**
60 # Deprecated
61 This feature has been deprecated in the latest update. Please use the new player, not the legacy one.<br><br>
62
63 Plays a .wav file.<br><br>
64
65
66 Usage:
67 ```
68 use rs_audio::*;
69 use rs_audio::{legacyplayer::BasicSong};
70
71 BasicSong::play_wav("test.wav").unwrap();
72 ```
73
74 */
75 pub fn play_wav(file_path: &str) -> Result<(), Error> {
76 let (_stream, handle) = OutputStream::try_default().unwrap();
77
78 let sink = match Sink::try_new(&handle) {
79 Ok(e) => e,
80
81 /* convert PlayError to std::io::Error */
82 Err(e) => return Err(Error::other(e.to_string())),
83 };
84
85 let file = File::open(file_path)?;
86 let source = Decoder::new(BufReader::new(file)).unwrap();
87
88 sink.append(source);
89 sink.sleep_until_end(); // blocks thread until finished
90
91 Ok(())
92 }
93}