audio_visualizer/waveform/
png_file.rs1use crate::util::png::write_png_file_rgb_tuples;
27use crate::Channels;
28use std::fs;
29use std::path::PathBuf;
30
31pub fn waveform_static_png_visualize(
36 samples: &[i16],
37 channels: Channels,
38 directory: &str,
39 filename: &str,
40) {
41 let image_width = 1500;
42 let image_height = 200;
43 if channels.is_stereo() {
44 assert_eq!(
45 0,
46 samples.len() % 2,
47 "If stereo is provided, the length of the audio data must be even!"
48 );
49 let (left, right) = channels.stereo_interleavement().to_channel_data(samples);
50 waveform_static_png_visualize(
51 &left,
52 Channels::Mono,
53 directory,
54 &format!("left_{}", filename),
55 );
56 waveform_static_png_visualize(
57 &right,
58 Channels::Mono,
59 directory,
60 &format!("right_{}", filename),
61 );
62 return;
63 }
64
65 let width_per_sample = image_width as f64 / samples.len() as f64;
67 let height_per_max_amplitude = image_height as f64 / 2_f64 / i16::MAX as f64;
69
70 let mut image = vec![vec![(255, 255, 255); image_width]; image_height];
72 for (sample_index, sample_value) in samples.iter().enumerate() {
73 let x = (sample_index as f64 * width_per_sample) as usize;
75 let sample_value = *sample_value as f64 * -1.0; let mut y = ((image_height / 2) as f64 + sample_value * height_per_max_amplitude) as usize;
79
80 if y == image_height {
82 y -= 1;
83 }
84
85 image[y][x] = (0, 0, 0);
86 }
87
88 if !fs::exists(directory).unwrap() {
89 fs::create_dir(directory).unwrap();
90 }
91 let mut path = PathBuf::new();
92 path.push(directory);
93 path.push(filename);
94 write_png_file_rgb_tuples(&path, &image);
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100 use crate::tests::testutil::{decode_mp3, TEST_OUT_DIR, TEST_SAMPLES_DIR};
101 use crate::ChannelInterleavement;
102
103 #[test]
105 fn test_no_out_of_bounds_panic() {
106 let audio_data = vec![i16::MAX, i16::MIN];
107 waveform_static_png_visualize(
108 &audio_data,
109 Channels::Mono,
110 TEST_OUT_DIR,
111 "sample_1_waveform-test-out-of-bounds-check.png",
112 );
113 }
114
115 #[test]
116 fn test_visualize_png_output() {
117 let mut path = PathBuf::new();
118 path.push(TEST_SAMPLES_DIR);
119 path.push("sample_1.mp3");
120
121 let lrlr_mp3_samples = decode_mp3(path.as_path());
122
123 waveform_static_png_visualize(
124 &lrlr_mp3_samples,
125 Channels::Stereo(ChannelInterleavement::LRLR),
126 TEST_OUT_DIR,
127 "waveform_static_png_visualize_example.png",
128 );
129 }
130}