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
}
}
-struct SwitchSpace {
- write_zone: Arc<Mutex<Vec<Complex<f32>>>>,
- read_zone: Arc<Mutex<Vec<Complex<f32>>>>,
- storage: [i16; WINDOW_SIZE*2],
- inverse_transform: Radix4::<f32>,
- scratch: Vec<Complex<f32>>,
- counter: Arc<Mutex<usize>>,
+struct SampleBuffer {
+ buffer: Arc<Mutex<[i16; 2 * SPECTOGRAM_AREA]>>,
+ index: usize,
tx: Sender<bool>
}
-impl SwitchSpace {
- fn new (write_zone: Arc<Mutex<Vec<Complex<f32>>>>, tx: Sender<bool>) -> Self {
+impl SampleBuffer {
+ fn new(buffer: Arc<Mutex<[i16; 2 * SPECTOGRAM_AREA]>>, tx: Sender<bool>) -> 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::<f32>::new(WINDOW_SIZE, FftDirection::Inverse),
-
- scratch: vec![
- Complex{re: 0f32, im: 0f32};
- Radix4::<f32>::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<dyn std::error::Error>> {
let forward_transform = Radix4::<f32>::new(WINDOW_SIZE, FftDirection::Forward);
+ let inverse_transform = Radix4::<f32>::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::<i16>() {
- 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,