From 944ad49be84b71bc24b744f6055b8a70199900e6 Mon Sep 17 00:00:00 2001 From: will Date: Sat, 26 Oct 2024 15:07:58 +0100 Subject: [PATCH] Added build sript and started working on c++ perspective transformer --- .gitignore | 1 + Cargo.lock | 5 ++- Cargo.toml | 5 +++ src/build.rs | 7 +++ src/camera.cpp | 21 +++++++++ src/main.rs | 118 +++++++++++++++++++++---------------------------- 6 files changed, 88 insertions(+), 69 deletions(-) create mode 100644 src/build.rs create mode 100644 src/camera.cpp diff --git a/.gitignore b/.gitignore index ea8c4bf..9680458 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +camera.a diff --git a/Cargo.lock b/Cargo.lock index 4e4b4f3..ba08d99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -267,9 +267,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.18" +version = "1.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" dependencies = [ "jobserver", "libc", @@ -1503,6 +1503,7 @@ checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" name = "rust_fft" version = "0.1.0" dependencies = [ + "cc", "cpal", "hound", "rustfft", diff --git a/Cargo.toml b/Cargo.toml index 42c75ef..83fab88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,9 +2,14 @@ name = "rust_fft" version = "0.1.0" edition = "2021" +build = "src/build.rs" +include = ["src/camera.cpp"] [dependencies] rustfft = "6.2.0" show-image = "0.14.0" hound = "3.5.1" cpal = "0.15.3" + +[build-dependencies] +cc = "1.0" diff --git a/src/build.rs b/src/build.rs new file mode 100644 index 0000000..0f5bf50 --- /dev/null +++ b/src/build.rs @@ -0,0 +1,7 @@ +fn main() { + cc::Build::new() + .cpp(true) + .file("src/camera.cpp") + .compile("camera.a"); + println!("cargo:rerun-if-changed=src/camera.cpp"); +} diff --git a/src/camera.cpp b/src/camera.cpp new file mode 100644 index 0000000..74233cf --- /dev/null +++ b/src/camera.cpp @@ -0,0 +1,21 @@ +#include +#include + +using std::size_t; +using std::uint8_t; + +const size_t WINDOW_SIZE = 128; +const size_t CHUNK_SIZE = 72; +const size_t SPECTOGRAM_AREA = WINDOW_SIZE * CHUNK_SIZE; + +extern "C" { + uint8_t GetData(size_t *ptr) { + uint8_t image[SPECTOGRAM_AREA * 3]; + for (uint8_t i : image) { + i = *ptr; + ptr++; + } + uint8_t value = image[1]; + return value; + } +} diff --git a/src/main.rs b/src/main.rs index d74aa90..f9e048c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,12 +25,6 @@ const VOLUME_MAX: f32 = 100.0; // 60 - 65 const VOLUME_MIN: f32 = -40.0; const VOLUME_REL: f32 = VOLUME_MAX - VOLUME_MIN; -// have 2 image arrays that are read from and process line by line when neccicary -// increece the buffer size of the audio output to make it work -// mutex counter for the row that is currently to process -// when it reaches the last row it locks both images and switches them over -// then sends a message to the main thread to process -> show -> capture a new image - struct ImageArray { data: [u8; SPECTOGRAM_AREA * 3], chunks: usize @@ -100,126 +94,116 @@ impl ImageArray { } } -struct SwitchSpace { - write_zone: Arc>>>, - read_zone: Arc>>>, - storage: [i16; WINDOW_SIZE*2], - inverse_transform: Radix4::, - scratch: Vec>, - counter: Arc>, +struct SampleBuffer { + buffer: Arc>, + index: usize, tx: Sender } -impl SwitchSpace { - fn new (write_zone: Arc>>>, tx: Sender) -> Self { +impl SampleBuffer { + fn new(buffer: Arc>, tx: Sender) -> Self { Self { - write_zone, - read_zone: Arc::new(Mutex::new(vec![Complex{re: 0f32, im: 0f32}; SPECTOGRAM_AREA])), - storage: [0i16; WINDOW_SIZE*2], - - inverse_transform: Radix4::::new(WINDOW_SIZE, FftDirection::Inverse), - - scratch: vec![ - Complex{re: 0f32, im: 0f32}; - Radix4::::new( - WINDOW_SIZE, - FftDirection::Inverse - ).get_inplace_scratch_len() - ], - - counter: Arc::new(Mutex::new(0usize)), + buffer, + index: 0, tx } } - fn get_data(&mut self, data: &mut [i16], _: &cpal::OutputCallbackInfo) { - let mut counter = self.counter.lock().unwrap(); - - { - let mut read_chunk = self.read_zone.lock().unwrap(); - - self.inverse_transform.process_with_scratch(&mut read_chunk[*counter..*counter+WINDOW_SIZE], &mut self.scratch); + fn get_data(&mut self, data: &mut [i16]) { + let mut buffer = self.buffer.lock().unwrap(); + let length = data.len()/2; - println!("Writing {} data points...", data.len()); - for (i, x) in data.chunks_mut(2).enumerate() { - let value = read_chunk[*counter + i].re as i16; - for sample in x.iter_mut() { - *sample = value; - } - } + for i in 0..length { + data[i*2] = buffer[i + self.index]; } - if *counter == CHUNK_SIZE { - println!("Read space empty... Running switch..."); - let origional_write = self.write_zone.clone(); - self.write_zone = self.read_zone.clone(); - self.read_zone = origional_write.clone(); + self.index += length; + if self.index > SPECTOGRAM_AREA { + for i in 0..SPECTOGRAM_AREA { + buffer[i] = buffer[i + SPECTOGRAM_AREA]; + } + self.index -= SPECTOGRAM_AREA; - *counter = 0; let _ = self.tx.send(true); - } else { - *counter += 1; } } } +extern "C" { + fn GetData(ptr: usize) -> usize; +} + #[show_image::main] fn main () -> Result<(), Box> { let forward_transform = Radix4::::new(WINDOW_SIZE, FftDirection::Forward); + let inverse_transform = Radix4::::new(WINDOW_SIZE, FftDirection::Inverse); let scratch_size = forward_transform.get_inplace_scratch_len(); - let write_space = Arc::new(Mutex::new(vec![Complex{re: 0f32, im: 0f32}; SPECTOGRAM_AREA])); + let mut buffer = vec![Complex{re: 0f32, im: 0f32}; SPECTOGRAM_AREA]; let mut scratch = vec![Complex{re: 0f32, im: 0f32}; scratch_size]; + let (tx, rx) = mpsc::channel(); - let mut switch = SwitchSpace::new(write_space.clone(), tx); + let sample_buffer = Arc::new(Mutex::new([0i16; 2*SPECTOGRAM_AREA])); + let mut samples = SampleBuffer::new(sample_buffer.clone(), tx); let mut image_array = ImageArray::new(); let window = create_window("image", Default::default())?; + let mut reader = hound::WavReader::open("/home/will/Downloads/Adducci - Around the Horn.wav").unwrap(); + let file_rate = reader.spec().sample_rate; + let host = cpal::default_host(); let device = host.default_output_device().expect("No output device available"); let stream = device.build_output_stream( &StreamConfig{ channels: 2, - sample_rate: SampleRate{0: 22_050}, + sample_rate: SampleRate{0: file_rate}, buffer_size: BufferSize::Fixed(WINDOW_SIZE as u32) }, - move |data: &mut [i16], info: &cpal::OutputCallbackInfo| { - switch.get_data(data, info); + move |data: &mut [i16], _: &cpal::OutputCallbackInfo| { + samples.get_data(data); }, move |err| { eprintln!("an error occurred on the output audio stream: {}", err); }, None ).unwrap(); - stream.play().expect("Stream pay failed"); - let mut reader = hound::WavReader::open("/home/will/Downloads/Adducci - Around the Horn.wav").unwrap(); let mut i = 0; for sample in reader.samples::() { - let mut buffer = write_space.lock().unwrap(); if i == SPECTOGRAM_AREA { - forward_transform.process_with_scratch(&mut *buffer, &mut scratch); + forward_transform.process_with_scratch(&mut buffer, &mut scratch); for x in buffer.iter_mut() { *x *= 1f32 / WINDOW_SIZE as f32; } - image_array.from_buffer(&*buffer); + image_array.from_buffer(&mut buffer); let image = ImageView::new(ImageInfo::rgb8(WINDOW_SIZE as u32, CHUNK_SIZE as u32), &image_array.data); window.set_image ("image", image)?; - image_array.to_buffer(&mut *buffer); + unsafe{ + println!("First value: {}", image_array.data[1]); + println!("Origional: {}", image_array.data.as_ptr() as usize); + println!("Read first value: {}", GetData(image_array.data.as_ptr() as usize)); + } - i = 0; + image_array.to_buffer(&mut buffer); - println!("Waiting for signal..."); - if rx.recv().unwrap() {()} - println!("Signal recevied!"); + inverse_transform.process_with_scratch(&mut *buffer, &mut scratch); + + if rx.recv().unwrap() { + let mut write_buffer = sample_buffer.lock().unwrap(); + for (i, x) in write_buffer[SPECTOGRAM_AREA..].iter_mut().enumerate() { + *x = buffer[i].re as i16; + } + } + + i = 0; } let value = match sample { Ok(t) => t, -- 2.39.2