hilbert_image_to_sound/
lib.rs1#![deny(missing_docs)]
2
3pub fn play(file: &str) {
13 use cpal::traits::{DeviceTrait, HostTrait, EventLoopTrait};
14
15 let image = image::open(file).unwrap().to_rgba();
16
17 let n = 16;
19 let mut hilbert: Vec<Vec<usize>> = vec![vec![0; n]; n];
21 let n2 = n as usize * n as usize;
23 for i in 0..n2 {
24 let (x, y) = hilbert_curve::convert_1d_to_2d(i, n2);
25 hilbert[y][x] = i;
26 }
27
28 let mut amplitudes: Vec<f64> = vec![0.0; n2];
30 let (w, h) = image.dimensions();
31 let cell = w.min(h) / n as u32;
32 for (x, y, pixel) in image.enumerate_pixels() {
33 let x = x / cell;
34 let y = y / cell;
35 if x >= n as u32 || y >= n as u32 {continue}
36 let image::Rgba([r, g, b, _]) = pixel;
37 let frequency = hilbert[y as usize][x as usize];
38 let amplitude = (*r as f64 + *g as f64 + *b as f64) / 255.0 / 3.0;
39 amplitudes[frequency] += amplitude / (cell as f64 * cell as f64);
40 }
41
42 let host = cpal::default_host();
43 let event_loop = host.event_loop();
44 let device = host.default_output_device().expect("no output device available");
45
46 let mut supported_formats_range = device.supported_output_formats()
47 .expect("error while querying formats");
48 let format = supported_formats_range.next()
49 .expect("no supported format?!")
50 .with_max_sample_rate();
51
52 let stream_id = event_loop.build_output_stream(&device, &format).unwrap();
53 event_loop.play_stream(stream_id).expect("failed to play_stream");
54
55 let tau: f64 = 6.283185307179586;
56 let mut t: f64 = 0.0;
57 let volume = 0.2;
58 std::thread::spawn(move || {
59
60 event_loop.run(move |stream_id, stream_result| {
61 use cpal::{StreamData, UnknownTypeOutputBuffer};
62
63 let stream_data = match stream_result {
64 Ok(data) => data,
65 Err(err) => {
66 eprintln!("an error occurred on stream {:?}: {}", stream_id, err);
67 return;
68 }
69 };
70
71 match stream_data {
72 StreamData::Output { buffer: UnknownTypeOutputBuffer::F32(mut buffer) } => {
73 for elem in buffer.iter_mut() {
74 let mut s: f64 = 0.0;
75 for (i, amp) in amplitudes.iter().enumerate() {
76 let fi = i as f64 / n2 as f64;
77 let f = 4.5 * fi + 0.25;
78 s += *amp * (t * f * tau + i as f64).sin();
79 }
80 *elem = volume * s as f32;
81
82 t += 0.005;
83 }
84 },
85 _ => (),
86 }
87 });
88 });
89
90 std::thread::sleep(std::time::Duration::from_secs_f64(2.0))
91}