Skip to content

Commit

Permalink
Merge branch 'main' into wav-compressor-optimizer-integration
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniil-Golikov authored Oct 4, 2023
2 parents c2b7106 + 8964e05 commit b91ddb2
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 57 deletions.
37 changes: 18 additions & 19 deletions brro-compressor/src/compressor/constant.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::HashMap;
use bincode::{Decode, Encode};
use super::BinConfig;
use log::{info, debug};
use bincode::{Decode, Encode};
use log::{debug, info};
use std::collections::HashMap;

const CONSTANT_COMPRESSOR_ID: u8 = 0;

Expand Down Expand Up @@ -36,7 +36,7 @@ impl Constant {
}

/// returns the error value
pub fn get_error(self){
pub fn get_error(self) {
self.residuals.len();
}

Expand All @@ -52,7 +52,7 @@ impl Constant {
}

/// Compresses the data. Walks the data array and sets one value as the constant.
/// Performance consideration, we do O(3*n) in the worst case, best case is O(n).
/// Performance consideration, we do O(3*n) in the worst case, best case is O(n).
pub fn compress(&mut self, data: &[i64]) {
// Count occurrences of each value in the data
let mut seen_values = HashMap::new();
Expand All @@ -75,19 +75,21 @@ impl Constant {
// if there is more than 1 element in the map, we have to walk the initial array
if seen_values.len() > 1 {
// Walk the initial array (again) and push anything not matching the constant to the residuals
self.residuals = data.iter().enumerate()
.filter(|&(_,v)| *v != constant)
.map(|(k,v)| (k.try_into().unwrap(), *v))
.collect();
self.residuals = data
.iter()
.enumerate()
.filter(|&(_, v)| *v != constant)
.map(|(k, v)| (k.try_into().unwrap(), *v))
.collect();
}
}

/// Receives a data stream and generates a Constant
pub fn decompress(data: &Vec<u8>) -> Self {
pub fn decompress(data: &[u8]) -> Self {
let config = BinConfig::get();
match bincode::decode_from_slice(&data, config) {
match bincode::decode_from_slice(data, config) {
Ok((constant, _)) => constant,
Err(e) => panic!("{e}")
Err(e) => panic!("{e}"),
}
}

Expand All @@ -107,7 +109,6 @@ impl Constant {
}
data
}

}

pub fn constant(data: &[f64]) -> Vec<u8> {
Expand Down Expand Up @@ -137,7 +138,7 @@ mod tests {
c.compress(&Constant::optimize(&vector1));
let bin_data = c.to_bytes();
let c2 = Constant::decompress(&bin_data);

assert_eq!(bin_data, [0, 2, 0]);
assert_eq!(c.clone(), c2);
}
Expand All @@ -158,19 +159,17 @@ mod tests {
c.compress(&Constant::optimize(&vector1));

assert!(c.constant == 1);
assert_eq!(c.residuals, vec![(1,2),(4,3)]);
assert_eq!(c.residuals, vec![(1, 2), (4, 3)]);
}

#[test]
fn test_to_data() {
let vector1 = vec![1.0, 2.0, 1.0, 1.0, 3.0];
// Currently we are not dealing with floats
let out_vector1:Vec<i64> = vector1.iter()
.map(|&x| x as i64)
.collect();
let out_vector1: Vec<i64> = vector1.iter().map(|&x| x as i64).collect();
let frame_size = vector1.len();
let compressed_data = constant(&vector1);
let out = Constant::decompress(&compressed_data).to_data(frame_size);
assert_eq!(out_vector1, out);
}
}
}
27 changes: 14 additions & 13 deletions brro-compressor/src/compressor/fft.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use std::sync::Arc;

use bincode::{Decode, Encode};
use rustfft::{FftPlanner, num_complex::Complex};
use super::BinConfig;
use log::{error, debug, warn};
use bincode::{Decode, Encode};
use log::{debug, error, warn};
use rustfft::{num_complex::Complex, FftPlanner};

const CONSTANT_COMPRESSOR_ID: u8 = 15;

Expand Down Expand Up @@ -39,15 +37,18 @@ impl FFT {
// TODO: This actually seems to makes sense here. Call it convert?
fn optimize(data: &[f64]) -> Vec<Complex<f32>> {
data.iter()
.map(|x| Complex{re: FFT::f64_to_f32(*x), im: 0.0f32})
.map(|x| Complex {
re: FFT::f64_to_f32(*x),
im: 0.0f32,
})
.collect()
}

/// Compress data via FFT.
/// Compress data via FFT.
/// This picks a set of data, computes the FFT, and stores the most relevant frequencies, dropping
/// the remaining ones.
pub fn compress(&mut self, data: &[f64]) {
// First thing, always try to get the data len as a power of 2.
// First thing, always try to get the data len as a power of 2.
let v = data.len();
if !v.is_power_of_two() {
warn!("Slow FFT, data segment is not a power of 2!");
Expand All @@ -60,11 +61,11 @@ impl FFT {
}

/// Decompresses data
pub fn decompress(data: &Vec<u8>) -> Self {
pub fn decompress(data: &[u8]) -> Self {
let config = BinConfig::get();
match bincode::decode_from_slice(&data, config) {
match bincode::decode_from_slice(data, config) {
Ok((constant, _)) => constant,
Err(e) => panic!("{e}")
Err(e) => panic!("{e}"),
}
}

Expand All @@ -76,6 +77,6 @@ impl FFT {
/// Returns an array of data
/// Runs the ifft, and push residuals into place and/or adjusts max and mins accordingly
pub fn to_data(&self) -> Vec<f64> {
Vec::new()
Vec::new()
}
}
}
29 changes: 17 additions & 12 deletions brro-compressor/src/compressor/noop.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use log::{info, debug};
use super::BinConfig;
use bincode::{Decode, Encode};
use log::{debug, info};

// 250 to optimize bincode encoding, since it checks for <251 for u8
const NOOP_COMPRESSOR_ID:u8 = 250;
const NOOP_COMPRESSOR_ID: u8 = 250;
#[derive(Encode, Decode, PartialEq, Debug, Clone)]
pub struct Noop {
pub id: u8,
Expand All @@ -13,7 +13,10 @@ pub struct Noop {
impl Noop {
pub fn new(frame_size: usize) -> Self {
debug!("Noop compressor");
Noop { id: NOOP_COMPRESSOR_ID, data: Vec::with_capacity(frame_size) }
Noop {
id: NOOP_COMPRESSOR_ID,
data: Vec::with_capacity(frame_size),
}
}

/// Currently the data is provided in f64, this compressor needs i64. So the optimizer needs
Expand All @@ -33,11 +36,11 @@ impl Noop {
}

/// Receives a data stream and generates a Noop
pub fn decompress(data: &Vec<u8>) -> Self {
pub fn decompress(data: &[u8]) -> Self {
let config = BinConfig::get();
match bincode::decode_from_slice(&data, config) {
match bincode::decode_from_slice(data, config) {
Ok((constant, _)) => constant,
Err(e) => panic!("{e}")
Err(e) => panic!("{e}"),
}
}

Expand All @@ -51,17 +54,16 @@ impl Noop {
pub fn to_data(&self, _frame_size: usize) -> Vec<i64> {
self.data.clone()
}

}

pub fn noop(data: &[f64]) -> Vec<u8> {
info!("[Compressor] Initializing Noop Compressor");
let mut c = Noop::new(data.len());
c.compress(data);
c.to_bytes()
}
}

#[cfg(test)]
#[cfg(test)]
mod tests {
use super::*;

Expand All @@ -70,7 +72,7 @@ mod tests {
let vector1 = vec![1.0, 1.0, 1.0, 1.0, 1.0];
assert_eq!(noop(&vector1), [250, 5, 2, 2, 2, 2, 2]);
}

#[test]
fn test_compression() {
let vector1 = vec![1.0, 1.0, 1.0, 1.0, 1.0];
Expand All @@ -85,6 +87,9 @@ mod tests {
#[test]
fn test_decompression() {
let vector1 = vec![1.0, 2.0, 3.0, 4.0, 1.0];
assert_eq!(Noop::decompress(&noop(&vector1)).to_data(0), [1,2,3,4,1]);
assert_eq!(
Noop::decompress(&noop(&vector1)).to_data(0),
[1, 2, 3, 4, 1]
);
}
}
}
12 changes: 6 additions & 6 deletions brro-compressor/src/utils/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,14 @@ mod tests {
// Create a temporary file with a valid WAV header
let temp_file_path = "test.wav";
let header: [u8; 12] = [82, 73, 70, 70, 4, 0, 0, 0, 87, 65, 86, 69];
std::fs::write(temp_file_path, &header).expect("Failed to create temporary WAV file");
std::fs::write(temp_file_path, header).expect("Failed to create temporary WAV file");

// Check if the file is recognized as a WAV file
let path = Path::new(temp_file_path);
let result = is_wav_file(&path);
let result = is_wav_file(path);

// Assert that it should be recognized as a WAV file
assert!(result.is_ok() && result.unwrap() == true);
assert!(result.is_ok() && result.unwrap());

// Clean up the temporary file
std::fs::remove_file(temp_file_path).expect("Failed to remove temporary file");
Expand All @@ -165,14 +165,14 @@ mod tests {
// Create a temporary file with a non-WAV header
let temp_file_path = "test.txt";
let header: [u8; 12] = [84, 69, 83, 84, 32, 70, 73, 76, 69, 33, 33, 33];
std::fs::write(temp_file_path, &header).expect("Failed to create temporary non-WAV file");
std::fs::write(temp_file_path, header).expect("Failed to create temporary non-WAV file");

// Check if the file is recognized as a WAV file
let path = Path::new(temp_file_path);
let result = is_wav_file(&path);
let result = is_wav_file(path);

// Assert that it should not be recognized as a WAV file
assert!(result.is_ok() && result.unwrap() == false);
assert!(result.is_ok() && !result.unwrap());

// Clean up the temporary file
std::fs::remove_file(temp_file_path).expect("Failed to remove temporary file");
Expand Down
17 changes: 10 additions & 7 deletions brro-compressor/src/utils/writer.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::fs::{self, File};
use std::fs::File;
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use tempfile::TempDir; // Import the tempfile crate
use std::path::Path;

// Function to create a streaming writer for a file
pub fn create_streaming_writer(file_path: &Path) -> io::Result<File> {
Expand Down Expand Up @@ -36,7 +35,8 @@ pub fn replace_extension(filename: &String, new_extension: &str) -> String {
#[cfg(test)]
mod tests {
use super::*;

use tempfile::TempDir;

#[test]
fn test_stream_writer() {
// Create a temporary directory to hold the test file
Expand All @@ -46,18 +46,21 @@ mod tests {
// Write data to the streaming writer
let data_to_write = b"Hello, World!\n";
{
let mut writer = create_streaming_writer(&test_file_path).expect("Failed to create writer");
let mut writer =
create_streaming_writer(&test_file_path).expect("Failed to create writer");
write_data_to_stream(&mut writer, data_to_write).expect("Failed to write data");
writer.flush().expect("Failed to flush data");
}

// Read the contents of the written file
let file_contents = fs::read_to_string(&test_file_path).expect("Failed to read file");
let file_contents = std::fs::read_to_string(&test_file_path).expect("Failed to read file");

// Assert that the file contents match what was written
assert_eq!(file_contents.as_bytes(), data_to_write);

// Clean up the temporary directory and its contents
temp_dir.close().expect("Failed to remove temporary directory");
temp_dir
.close()
.expect("Failed to remove temporary directory");
}
}

0 comments on commit b91ddb2

Please sign in to comment.