audio_visualizer/waveform/
plotters_png_file.rs1use crate::Channels;
27use plotters::prelude::*;
28use std::path::PathBuf;
29
30pub fn waveform_static_plotters_png_visualize(
33 samples: &[i16],
34 channels: Channels,
35 directory: &str,
36 filename: &str,
37) {
38 if channels.is_stereo() {
39 assert_eq!(
40 0,
41 samples.len() % 2,
42 "If stereo is provided, the length of the audio data must be even!"
43 );
44 let (left, right) = channels.stereo_interleavement().to_channel_data(samples);
45 waveform_static_plotters_png_visualize(
46 &left,
47 Channels::Mono,
48 directory,
49 &format!("left_{}", filename),
50 );
51 waveform_static_plotters_png_visualize(
52 &right,
53 Channels::Mono,
54 directory,
55 &format!("right_{}", filename),
56 );
57 return;
58 }
59
60 let mut path = PathBuf::new();
61 path.push(directory);
62 path.push(filename);
63
64 let mut max = 0;
65 for sample in samples {
66 let sample = *sample as i32;
67 let sample = sample.abs();
68 if sample > max {
69 max = sample;
70 }
71 }
72
73 let width = (samples.len() / 5) as u32;
74 let width = if width > 4000 { 4000 } else { width };
75 let root = BitMapBackend::new(&path, (width, 1000)).into_drawing_area();
76 root.fill(&WHITE).unwrap();
77 let mut chart = ChartBuilder::on(&root)
78 .caption("y=music(t)", ("sans-serif", 50).into_font())
79 .margin(5)
80 .x_label_area_size(30)
81 .y_label_area_size(30)
82 .build_cartesian_2d(0.0..samples.len() as f32, -max as f32..max as f32)
83 .unwrap();
84
85 chart.configure_mesh().draw().unwrap();
86
87 chart
88 .draw_series(LineSeries::new(
89 samples
91 .iter()
92 .enumerate()
93 .map(|(sample_i, amplitude)| (sample_i as f32, *amplitude as f32)),
94 &RED,
95 ))
96 .unwrap()
97 .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], RED));
99
100 chart
101 .configure_series_labels()
102 .background_style(WHITE.mix(0.8))
103 .border_style(BLACK)
104 .draw()
105 .unwrap();
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111 use crate::tests::testutil::{TEST_OUT_DIR, TEST_SAMPLES_DIR};
112 use crate::ChannelInterleavement;
113 use minimp3::{Decoder as Mp3Decoder, Error as Mp3Error, Frame as Mp3Frame};
114 use std::fs::File;
115
116 #[test]
117 fn test_visualize_png_output() {
118 let mut path = PathBuf::new();
119 path.push(TEST_SAMPLES_DIR);
120 path.push("sample_1.mp3");
121 let mut decoder = Mp3Decoder::new(File::open(path).unwrap());
122
123 let mut lrlr_mp3_samples = vec![];
124 loop {
125 match decoder.next_frame() {
126 Ok(Mp3Frame {
127 data: samples_of_frame,
128 ..
129 }) => {
130 for sample in samples_of_frame {
131 lrlr_mp3_samples.push(sample);
132 }
133 }
134 Err(Mp3Error::Eof) => break,
135 Err(e) => panic!("{:?}", e),
136 }
137 }
138
139 waveform_static_plotters_png_visualize(
140 &lrlr_mp3_samples,
141 Channels::Stereo(ChannelInterleavement::LRLR),
142 TEST_OUT_DIR,
143 "waveform_static_plotters_png_visualize_example.png",
144 );
145 }
146}