rustwav/
lib.rs

1mod errors;
2mod savagestr;
3mod readwrite;
4mod copiablebuf;
5mod filehasher;
6mod adpcm;
7mod xlaw;
8mod wavcore;
9mod wavreader;
10mod wavwriter;
11mod hacks;
12
13/// ## The utility for both you and me to convert waveform format.
14pub mod utils;
15
16/// ## The encoders for the `WaveWriter`, each of these provides the same API for it to use. You can use it too.
17pub mod encoders;
18
19/// ## The decoders for the `WaveReader`, each of these provides the same API for it to use. You can use it too.
20pub mod decoders;
21
22#[doc(hidden)]
23pub use sampletypes::{i24, u24};
24
25pub use sampletypes::{SampleType, SampleFrom};
26pub use readwrite::{Reader, Writer, ReadBridge, WriteBridge, SharedReader, SharedWriter, string_io};
27pub use wavcore::{Spec, SampleFormat, DataFormat};
28pub use wavreader::{WaveDataSource, WaveReader, FrameIter, StereoIter, MonoIter, FrameIntoIter, StereoIntoIter, MonoIntoIter};
29pub use wavwriter::{FileSizeOption, WaveWriter};
30pub use resampler::Resampler;
31pub use errors::{AudioReadError, AudioError, AudioWriteError};
32pub use wavcore::{AdpcmSubFormat};
33pub use wavcore::{FlacEncoderParams, FlacCompression};
34
35#[doc(inline)]
36pub use encoders::{Mp3EncoderOptions, Mp3Channels, Mp3Quality, Mp3Bitrate, Mp3VbrMode};
37
38#[doc(inline)]
39pub use encoders::{OpusEncoderOptions, OpusBitrate, OpusEncoderSampleDuration};
40
41#[doc(inline)]
42pub use encoders::{VorbisEncoderParams, VorbisBitrateStrategy};
43
44/// ## The list for the command line program to parse the argument and we have the pre-filled encoder initializer parameter structs for each format.
45pub const FORMATS: [(&str, DataFormat); 10] = [
46    ("pcm", DataFormat::Pcm),
47    ("pcm-alaw", DataFormat::PcmALaw),
48    ("pcm-ulaw", DataFormat::PcmMuLaw),
49    ("adpcm-ms", DataFormat::Adpcm(AdpcmSubFormat::Ms)),
50    ("adpcm-ima", DataFormat::Adpcm(AdpcmSubFormat::Ima)),
51    ("adpcm-yamaha", DataFormat::Adpcm(AdpcmSubFormat::Yamaha)),
52    ("mp3", DataFormat::Mp3(Mp3EncoderOptions{
53        channels: Mp3Channels::NotSet,
54        quality: Mp3Quality::Best,
55        bitrate: Mp3Bitrate::Kbps320,
56        vbr_mode: Mp3VbrMode::Off,
57        id3tag: None,
58    })),
59    ("opus", DataFormat::Opus(OpusEncoderOptions{
60        bitrate: OpusBitrate::Max,
61        encode_vbr: false,
62        samples_cache_duration: OpusEncoderSampleDuration::MilliSec60,
63    })),
64    ("flac", DataFormat::Flac(FlacEncoderParams{
65        verify_decoded: false,
66        compression: FlacCompression::Level8,
67        channels: 2,
68        sample_rate: 44100,
69        bits_per_sample: 32,
70        total_samples_estimate: 0,
71    })),
72    ("vorbis", DataFormat::Vorbis(VorbisEncoderParams{
73        channels: 2,
74        sample_rate: 44100,
75        stream_serial: None,
76        bitrate: None,
77        minimum_page_data_size: None,
78    }))
79];
80
81/// ## Transfer audio from the decoder to the encoder with resampling.
82/// * This allows to transfer of audio from the decoder to a different sample rate encoder.
83pub fn transfer_audio_from_decoder_to_encoder(decoder: &mut WaveReader, encoder: &mut WaveWriter) {
84    // The fft size can be any number greater than the sample rate of the encoder or the decoder.
85    // It is for the resampler. A greater number results in better resample quality, but the process could be slower.
86    // In most cases, the audio sampling rate is about 11025 to 48000, so 65536 is the best number for the resampler.
87    const FFT_SIZE: usize = 65536;
88
89    // This is the resampler, if the decoder's sample rate is different than the encode sample rate, use the resampler to help stretch or compress the waveform.
90    // Otherwise, it's not needed there.
91    let resampler = Resampler::new(FFT_SIZE);
92
93    // The decoding audio spec
94    let decode_spec = decoder.spec();
95
96    // The encoding audio spec
97    let encode_spec = encoder.spec();
98
99    let decode_channels = decode_spec.channels;
100    let encode_channels = encode_spec.channels;
101    let decode_sample_rate = decode_spec.sample_rate;
102    let encode_sample_rate = encode_spec.sample_rate;
103
104    // The number of channels must match
105    assert_eq!(encode_channels, decode_channels);
106
107    // Process size is for the resampler to process the waveform, it is the length of the source waveform slice.
108    let process_size = resampler.get_process_size(FFT_SIZE, decode_sample_rate, encode_sample_rate);
109
110    // There are three types of iterators for three types of audio channels: mono, stereo, and more than 2 channels of audio.
111    // Usually, the third iterator can handle all numbers of channels, but it's the slowest iterator.
112    match encode_channels {
113        1 => {
114            let mut iter = decoder.mono_iter::<f32>().unwrap();
115            loop {
116                let block: Vec<f32> = iter.by_ref().take(process_size).collect();
117                if block.is_empty() {
118                    break;
119                }
120                let block = utils::do_resample_mono(&resampler, &block, decode_sample_rate, encode_sample_rate);
121                encoder.write_mono_channel(&block).unwrap();
122            }
123        },
124        2 => {
125            let mut iter = decoder.stereo_iter::<f32>().unwrap();
126            loop {
127                let block: Vec<(f32, f32)> = iter.by_ref().take(process_size).collect();
128                if block.is_empty() {
129                    break;
130                }
131                let block = utils::do_resample_stereo(&resampler, &block, decode_sample_rate, encode_sample_rate);
132                encoder.write_stereos(&block).unwrap();
133            }
134        },
135        _ => {
136            let mut iter = decoder.frame_iter::<f32>().unwrap();
137            loop {
138                let block: Vec<Vec<f32>> = iter.by_ref().take(process_size).collect();
139                if block.is_empty() {
140                    break;
141                }
142                let block = utils::do_resample_frames(&resampler, &block, decode_sample_rate, encode_sample_rate);
143                encoder.write_frames(&block).unwrap();
144            }
145        }
146    }
147}
148
149use std::{env::args, process::ExitCode, error::Error};
150
151/// ## The `test()` function
152/// * arg1: the format, e.g. "pcm"
153/// * arg2: the input file to parse and decode, tests the decoder for the input file.
154/// * arg3: the output file to encode, test the encoder.
155/// * arg4: re-decode arg3 and encode to pcm to test the decoder.
156pub fn test(arg1: &str, arg2: &str, arg3: &str, arg4: &str) -> Result<(), Box<dyn Error>> {
157    let mut data_format = DataFormat::Unspecified;
158    for format in FORMATS {
159        if arg1 == format.0 {
160            data_format = format.1;
161            break;
162        }
163    }
164
165    // Failed to match the data format
166    if data_format == DataFormat::Unspecified {
167        return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, format!("Unknown format `{arg1}`. Please input one of these:\n{}", FORMATS.iter().map(|(s, _v)|{s.to_string()}).collect::<Vec<String>>().join(", "))).into());
168    }
169
170    println!("======== TEST 1 ========");
171    println!("{:?}", data_format);
172
173    // This is the decoder
174    let mut wavereader = WaveReader::open(arg2).unwrap();
175
176    let orig_spec = wavereader.spec();
177
178    // The spec for the encoder
179    let mut spec = Spec {
180        channels: orig_spec.channels,
181        channel_mask: 0,
182        sample_rate: orig_spec.sample_rate,
183        bits_per_sample: 16,
184        sample_format: SampleFormat::Int,
185    };
186
187    match data_format {
188        DataFormat::Mp3(ref mut options) => {
189            match spec.channels {
190                1 => options.channels = Mp3Channels::Mono,
191                2 => options.channels = Mp3Channels::JointStereo,
192                o => panic!("MP3 format can't encode {o} channels audio."),
193            }
194        },
195        DataFormat::Opus(ref options) => {
196            spec.sample_rate = options.get_rounded_up_sample_rate(spec.sample_rate);
197        },
198        DataFormat::Flac(ref mut options) => {
199            options.channels = spec.channels;
200            options.sample_rate = spec.sample_rate;
201            options.bits_per_sample = spec.bits_per_sample as u32;
202        },
203        _ => (),
204    }
205
206    // Just to let you know, WAV file can be larger than 4 GB
207	#[allow(unused_imports)]
208	use FileSizeOption::{NeverLargerThan4GB, AllowLargerThan4GB, ForceUse4GBFormat};
209
210    // This is the encoder
211    let mut wavewriter = WaveWriter::create(arg3, &spec, data_format, NeverLargerThan4GB).unwrap();
212
213    // Transfer audio samples from the decoder to the encoder
214    transfer_audio_from_decoder_to_encoder(&mut wavereader, &mut wavewriter);
215
216    // Get the metadata from the decoder
217    wavewriter.inherit_metadata_from_reader(&wavereader, true);
218
219    // Show debug info
220    dbg!(&wavereader);
221    dbg!(&wavewriter);
222
223    drop(wavereader);
224    drop(wavewriter);
225
226    println!("======== TEST 2 ========");
227
228    let spec2 = Spec {
229        channels: spec.channels,
230        channel_mask: 0,
231        sample_rate: orig_spec.sample_rate,
232        bits_per_sample: 16,
233        sample_format: SampleFormat::Int,
234    };
235
236    let mut wavereader_2 = WaveReader::open(arg3).unwrap();
237    let mut wavewriter_2 = WaveWriter::create(arg4, &spec2, DataFormat::Pcm, NeverLargerThan4GB).unwrap();
238
239    // Transfer audio samples from the decoder to the encoder
240    transfer_audio_from_decoder_to_encoder(&mut wavereader_2, &mut wavewriter_2);
241
242    // Get the metadata from the decoder
243    wavewriter_2.inherit_metadata_from_reader(&wavereader_2, true);
244
245
246    // Show debug info
247    dbg!(&wavereader_2);
248    dbg!(&wavewriter_2);
249
250    drop(wavereader_2);
251    drop(wavewriter_2);
252
253    Ok(())
254}
255
256/// ## A function dedicated to testing WAV encoding and decoding. This function is actually a `main()` function for a command-line program that parses `args` and returns an `ExitCode`.
257/// * The usage is `arg0 [format] [test.wav] [output.wav] [output2.wav]`
258/// * It decodes the `test.wav` and encodes it to `output.wav` by `format`
259/// * Then it re-decode `output.wav` to `output2.wav`
260/// * This can test both encoders and decoders with the specified format to see if they behave as they should.
261#[allow(dead_code)]
262pub fn test_wav() -> ExitCode {
263    let args: Vec<String> = args().collect();
264    if args.len() < 5 {return ExitCode::from(1);}
265    let input_wav = &args[1];
266    let output_wav = &args[2];
267    let reinput_wav = &args[3];
268    let reoutput_wav = &args[4];
269    match test(input_wav, output_wav, reinput_wav, reoutput_wav) {
270        Ok(_) => ExitCode::from(0),
271        Err(e) => {
272            eprintln!("{:?}", e);
273            ExitCode::from(2)
274        },
275    }
276}
277
278macro_rules! test_fn {
279	($name:ident, $index:expr) => {
280		#[test]
281		pub fn $name() {
282		    let fmt = FORMATS[$index].0;
283		    test(fmt, "test.wav", &format!("{fmt}_test_encode.wav"), &format!("{fmt}_test_decode.wav")).unwrap();
284		}
285	}
286}
287
288test_fn!(test0, 0);
289test_fn!(test1, 1);
290test_fn!(test2, 2);
291test_fn!(test3, 3);
292test_fn!(test4, 4);
293test_fn!(test5, 5);
294test_fn!(test6, 6);
295test_fn!(test7, 7);
296test_fn!(test8, 8);
297test_fn!(test9, 9);