├── .DS_Store ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── sound ├── .DS_Store ├── tng.wav └── tng_convolved.wav ├── src └── main.rs └── workspace.code-workspace /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spluta/rust_convolve/efec07292633b5226398f63dda263decc650a57b/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | find . -size +100M | cat >> .gitignore -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "ansi_term" 5 | version = "0.11.0" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" 8 | dependencies = [ 9 | "winapi", 10 | ] 11 | 12 | [[package]] 13 | name = "atty" 14 | version = "0.2.14" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 17 | dependencies = [ 18 | "hermit-abi", 19 | "libc", 20 | "winapi", 21 | ] 22 | 23 | [[package]] 24 | name = "autocfg" 25 | version = "1.0.1" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" 28 | 29 | [[package]] 30 | name = "bitflags" 31 | version = "1.2.1" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 34 | 35 | [[package]] 36 | name = "bwavfile" 37 | version = "0.9.3" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "145a91fcaa60397c14559bc6c11ad11e7c2324c1c017c03d6abeb13a29e42712" 40 | dependencies = [ 41 | "byteorder", 42 | "clap", 43 | "encoding", 44 | "uuid", 45 | ] 46 | 47 | [[package]] 48 | name = "byteorder" 49 | version = "1.4.3" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 52 | 53 | [[package]] 54 | name = "cfg-if" 55 | version = "1.0.0" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 58 | 59 | [[package]] 60 | name = "chrono" 61 | version = "0.4.19" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" 64 | dependencies = [ 65 | "libc", 66 | "num-integer", 67 | "num-traits", 68 | "time", 69 | "winapi", 70 | ] 71 | 72 | [[package]] 73 | name = "clap" 74 | version = "2.33.3" 75 | source = "registry+https://github.com/rust-lang/crates.io-index" 76 | checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" 77 | dependencies = [ 78 | "ansi_term", 79 | "atty", 80 | "bitflags", 81 | "strsim", 82 | "textwrap", 83 | "unicode-width", 84 | "vec_map", 85 | ] 86 | 87 | [[package]] 88 | name = "convolve" 89 | version = "0.1.0" 90 | dependencies = [ 91 | "bwavfile", 92 | "chrono", 93 | "clap", 94 | "hound", 95 | "rand", 96 | "realfft", 97 | "rustfft", 98 | ] 99 | 100 | [[package]] 101 | name = "encoding" 102 | version = "0.2.33" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" 105 | dependencies = [ 106 | "encoding-index-japanese", 107 | "encoding-index-korean", 108 | "encoding-index-simpchinese", 109 | "encoding-index-singlebyte", 110 | "encoding-index-tradchinese", 111 | ] 112 | 113 | [[package]] 114 | name = "encoding-index-japanese" 115 | version = "1.20141219.5" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" 118 | dependencies = [ 119 | "encoding_index_tests", 120 | ] 121 | 122 | [[package]] 123 | name = "encoding-index-korean" 124 | version = "1.20141219.5" 125 | source = "registry+https://github.com/rust-lang/crates.io-index" 126 | checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" 127 | dependencies = [ 128 | "encoding_index_tests", 129 | ] 130 | 131 | [[package]] 132 | name = "encoding-index-simpchinese" 133 | version = "1.20141219.5" 134 | source = "registry+https://github.com/rust-lang/crates.io-index" 135 | checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" 136 | dependencies = [ 137 | "encoding_index_tests", 138 | ] 139 | 140 | [[package]] 141 | name = "encoding-index-singlebyte" 142 | version = "1.20141219.5" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" 145 | dependencies = [ 146 | "encoding_index_tests", 147 | ] 148 | 149 | [[package]] 150 | name = "encoding-index-tradchinese" 151 | version = "1.20141219.5" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" 154 | dependencies = [ 155 | "encoding_index_tests", 156 | ] 157 | 158 | [[package]] 159 | name = "encoding_index_tests" 160 | version = "0.1.4" 161 | source = "registry+https://github.com/rust-lang/crates.io-index" 162 | checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" 163 | 164 | [[package]] 165 | name = "getrandom" 166 | version = "0.2.3" 167 | source = "registry+https://github.com/rust-lang/crates.io-index" 168 | checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" 169 | dependencies = [ 170 | "cfg-if", 171 | "libc", 172 | "wasi", 173 | ] 174 | 175 | [[package]] 176 | name = "hermit-abi" 177 | version = "0.1.18" 178 | source = "registry+https://github.com/rust-lang/crates.io-index" 179 | checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" 180 | dependencies = [ 181 | "libc", 182 | ] 183 | 184 | [[package]] 185 | name = "hound" 186 | version = "3.4.0" 187 | source = "registry+https://github.com/rust-lang/crates.io-index" 188 | checksum = "8a164bb2ceaeff4f42542bdb847c41517c78a60f5649671b2a07312b6e117549" 189 | 190 | [[package]] 191 | name = "libc" 192 | version = "0.2.96" 193 | source = "registry+https://github.com/rust-lang/crates.io-index" 194 | checksum = "5600b4e6efc5421841a2138a6b082e07fe12f9aaa12783d50e5d13325b26b4fc" 195 | 196 | [[package]] 197 | name = "num-complex" 198 | version = "0.4.0" 199 | source = "registry+https://github.com/rust-lang/crates.io-index" 200 | checksum = "26873667bbbb7c5182d4a37c1add32cdf09f841af72da53318fdb81543c15085" 201 | dependencies = [ 202 | "num-traits", 203 | ] 204 | 205 | [[package]] 206 | name = "num-integer" 207 | version = "0.1.44" 208 | source = "registry+https://github.com/rust-lang/crates.io-index" 209 | checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" 210 | dependencies = [ 211 | "autocfg", 212 | "num-traits", 213 | ] 214 | 215 | [[package]] 216 | name = "num-traits" 217 | version = "0.2.14" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" 220 | dependencies = [ 221 | "autocfg", 222 | ] 223 | 224 | [[package]] 225 | name = "ppv-lite86" 226 | version = "0.2.10" 227 | source = "registry+https://github.com/rust-lang/crates.io-index" 228 | checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" 229 | 230 | [[package]] 231 | name = "primal-check" 232 | version = "0.3.1" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | checksum = "01419cee72c1a1ca944554e23d83e483e1bccf378753344e881de28b5487511d" 235 | dependencies = [ 236 | "num-integer", 237 | ] 238 | 239 | [[package]] 240 | name = "rand" 241 | version = "0.8.3" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" 244 | dependencies = [ 245 | "libc", 246 | "rand_chacha", 247 | "rand_core", 248 | "rand_hc", 249 | ] 250 | 251 | [[package]] 252 | name = "rand_chacha" 253 | version = "0.3.1" 254 | source = "registry+https://github.com/rust-lang/crates.io-index" 255 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 256 | dependencies = [ 257 | "ppv-lite86", 258 | "rand_core", 259 | ] 260 | 261 | [[package]] 262 | name = "rand_core" 263 | version = "0.6.2" 264 | source = "registry+https://github.com/rust-lang/crates.io-index" 265 | checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" 266 | dependencies = [ 267 | "getrandom", 268 | ] 269 | 270 | [[package]] 271 | name = "rand_hc" 272 | version = "0.3.0" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" 275 | dependencies = [ 276 | "rand_core", 277 | ] 278 | 279 | [[package]] 280 | name = "realfft" 281 | version = "2.0.1" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | checksum = "d7695c87f31dc3644760f23fb59a3fed47659703abf76cf2d111f03b9e712342" 284 | dependencies = [ 285 | "rustfft", 286 | ] 287 | 288 | [[package]] 289 | name = "rustfft" 290 | version = "6.0.1" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "b1d089e5c57521629a59f5f39bca7434849ff89bd6873b521afe389c1c602543" 293 | dependencies = [ 294 | "num-complex", 295 | "num-integer", 296 | "num-traits", 297 | "primal-check", 298 | "strength_reduce", 299 | "transpose", 300 | ] 301 | 302 | [[package]] 303 | name = "strength_reduce" 304 | version = "0.2.3" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "a3ff2f71c82567c565ba4b3009a9350a96a7269eaa4001ebedae926230bc2254" 307 | 308 | [[package]] 309 | name = "strsim" 310 | version = "0.8.0" 311 | source = "registry+https://github.com/rust-lang/crates.io-index" 312 | checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" 313 | 314 | [[package]] 315 | name = "textwrap" 316 | version = "0.11.0" 317 | source = "registry+https://github.com/rust-lang/crates.io-index" 318 | checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" 319 | dependencies = [ 320 | "unicode-width", 321 | ] 322 | 323 | [[package]] 324 | name = "time" 325 | version = "0.1.43" 326 | source = "registry+https://github.com/rust-lang/crates.io-index" 327 | checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" 328 | dependencies = [ 329 | "libc", 330 | "winapi", 331 | ] 332 | 333 | [[package]] 334 | name = "transpose" 335 | version = "0.2.1" 336 | source = "registry+https://github.com/rust-lang/crates.io-index" 337 | checksum = "95f9c900aa98b6ea43aee227fd680550cdec726526aab8ac801549eadb25e39f" 338 | dependencies = [ 339 | "num-integer", 340 | "strength_reduce", 341 | ] 342 | 343 | [[package]] 344 | name = "unicode-width" 345 | version = "0.1.8" 346 | source = "registry+https://github.com/rust-lang/crates.io-index" 347 | checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" 348 | 349 | [[package]] 350 | name = "uuid" 351 | version = "0.8.2" 352 | source = "registry+https://github.com/rust-lang/crates.io-index" 353 | checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" 354 | 355 | [[package]] 356 | name = "vec_map" 357 | version = "0.8.2" 358 | source = "registry+https://github.com/rust-lang/crates.io-index" 359 | checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" 360 | 361 | [[package]] 362 | name = "wasi" 363 | version = "0.10.2+wasi-snapshot-preview1" 364 | source = "registry+https://github.com/rust-lang/crates.io-index" 365 | checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" 366 | 367 | [[package]] 368 | name = "winapi" 369 | version = "0.3.9" 370 | source = "registry+https://github.com/rust-lang/crates.io-index" 371 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 372 | dependencies = [ 373 | "winapi-i686-pc-windows-gnu", 374 | "winapi-x86_64-pc-windows-gnu", 375 | ] 376 | 377 | [[package]] 378 | name = "winapi-i686-pc-windows-gnu" 379 | version = "0.4.0" 380 | source = "registry+https://github.com/rust-lang/crates.io-index" 381 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 382 | 383 | [[package]] 384 | name = "winapi-x86_64-pc-windows-gnu" 385 | version = "0.4.0" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 388 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "convolve" 3 | version = "0.1.0" 4 | authors = ["Sam "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | rustfft = "6.0.1" 11 | realfft = "2.0.1" 12 | rand="0.8.0" 13 | hound = "3.4.0" 14 | chrono = "0.4" 15 | clap = "2.33.3" 16 | bwavfile = "0.9.3" -------------------------------------------------------------------------------- /sound/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spluta/rust_convolve/efec07292633b5226398f63dda263decc650a57b/sound/.DS_Store -------------------------------------------------------------------------------- /sound/tng.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spluta/rust_convolve/efec07292633b5226398f63dda263decc650a57b/sound/tng.wav -------------------------------------------------------------------------------- /sound/tng_convolved.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spluta/rust_convolve/efec07292633b5226398f63dda263decc650a57b/sound/tng_convolved.wav -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use chrono::{DateTime, NaiveDateTime, TimeZone, Utc}; 2 | use clap::{App, Arg}; 3 | use rand::Rng; 4 | use realfft::RealFftPlanner; 5 | use rustfft::num_complex::Complex; 6 | use std::env; 7 | use std::f64::consts::PI; 8 | use std::fs::File; 9 | use std::iter::FromIterator; 10 | use std::path::Path; 11 | use std::time::SystemTime; 12 | 13 | fn main() { 14 | let matches = App::new("Convolve") 15 | .version("0.1.0") 16 | .author("Sam Pluta") 17 | .about("Convolve two sound files") 18 | .arg( 19 | Arg::with_name("file1") 20 | .short("f") 21 | .long("file1") 22 | .takes_value(true) 23 | .help("Audio File 1"), 24 | ) 25 | .arg( 26 | Arg::with_name("file2") 27 | .short("g") 28 | .long("file2") 29 | .takes_value(true) 30 | .help("Audio File 2"), 31 | ) 32 | .arg( 33 | Arg::with_name("file1_slice_size") 34 | .short("s") 35 | .long("slice") 36 | .takes_value(true) 37 | .help("The slice size (a power of two) used for input file 1 (optional - defaults to full file)."), 38 | ) 39 | .arg( 40 | Arg::with_name("out_file") 41 | .short("o") 42 | .long("out_file_name") 43 | .takes_value(true) 44 | .help("The name of the output file (optional - defaults to file1_file2.wav"), 45 | ) 46 | .get_matches(); 47 | let file_name0 = matches.value_of("file1").unwrap_or("sound/tng.wav"); 48 | println!("The input file1 is: {}", file_name0); 49 | 50 | let file_name1 = matches.value_of("file2").unwrap_or("sound/tng.wav"); 51 | println!("The input file2 is: {}", file_name1); 52 | 53 | let s_in = matches.value_of("file1_slice_size").unwrap_or("0"); 54 | let num_slices: usize = match s_in.parse() { 55 | Ok(n) => n, 56 | Err(_) => { 57 | eprintln!("error: slices argument not an integer"); 58 | return; 59 | } 60 | }; 61 | 62 | let path = Path::new(file_name0); 63 | let parent = path.parent(); 64 | let file_stem = path.file_stem(); 65 | let extension = path.extension(); 66 | 67 | // let path2 = Path::new(file_name1); 68 | // let file_stem2 = path2.file_stem().unwrap().to_str(); 69 | 70 | let temp_out_file = file_name0.replace(".wav", &format!("{}{}", "_convolved", ".wav")); 71 | let out_file = matches.value_of("out_file").unwrap_or(&temp_out_file); 72 | println!("The output file will be: {}", out_file); 73 | println!(""); 74 | //println!("If your output file exceeds the limitations of the WAV format, the OS will think the file is too short, but all of the data will be there and it will be readable with software like Reaper (by normal import) or Audacity (via import Raw Data)"); 75 | //let mut sound_file0 = hound::WavReader::open(file_name0).unwrap(); 76 | //let mut sound_file1 = hound::WavReader::open(file_name1).unwrap(); 77 | let mut channels0 = get_file_channels(file_name0); 78 | let mut channels1 = get_file_channels(file_name1); 79 | 80 | let npot = usize::next_power_of_two; 81 | let mut fft_size = std::cmp::min(npot(channels0[0].len()), npot(channels1[0].len())); 82 | 83 | if fft_size > usize::pow(2, 17) { 84 | fft_size = usize::pow(2, 17); 85 | } 86 | println!("fftSize: {}", fft_size); 87 | 88 | for index in 0..channels0.len() { 89 | make_whole (&mut channels0[index], fft_size); 90 | } 91 | for index in 0..channels1.len() { 92 | make_whole (&mut channels1[index], fft_size); 93 | } 94 | 95 | let out_length = (channels0[0].len()+channels1[0].len()) as usize; 96 | let num_out_chans = std::cmp::max(channels0.len(), channels1.len()) as usize; 97 | let mut out_channels: Vec> = 98 | vec![vec![0.0_f64; out_length]; num_out_chans]; 99 | 100 | println!("channels0 len: {}", channels0[0].len()); 101 | println!("channels1 len: {}", channels1[0].len()); 102 | 103 | let mut real_planner = RealFftPlanner::::new(); 104 | let fft = real_planner.plan_fft_forward(fft_size*2); 105 | let mut spectrum0 = fft.make_output_vec(); 106 | let mut spectrum1 = fft.make_output_vec(); 107 | let ifft = real_planner.plan_fft_inverse(fft_size*2); 108 | let mut out_frame = ifft.make_output_vec(); 109 | let mut conv = fft.make_output_vec();//vec![Complex{re:0.0, im:0.0}; fft_size*2]; 110 | 111 | let mut aseg = vec![0.0; fft_size*2]; 112 | let mut bseg = vec![0.0; fft_size*2]; 113 | 114 | println!("{}", fft_size); 115 | for chan in 0..num_out_chans { 116 | println!(""); 117 | print!("chan {}", chan); 118 | for i in 0..channels0[0].len()/fft_size { 119 | //aseg.clone_from_slice(&channels0[chan%channels0.len() as usize][fft_size*i..fft_size*(i+1)]); 120 | for num in 0..fft_size { 121 | aseg[num]=channels0[chan%channels0.len() as usize][fft_size*i + num]; 122 | aseg[fft_size+num]=0.0; 123 | } 124 | fft.process(&mut aseg, &mut spectrum0).unwrap(); 125 | for bi in 0..channels1[0].len()/fft_size { 126 | //bseg.clone_from_slice(&channels1[chan%channels0.len() as usize][fft_size*bi..fft_size*(bi+1)]); 127 | for num in 0..fft_size { 128 | bseg[num]=channels1[chan%channels1.len() as usize][fft_size*bi + num]; 129 | bseg[fft_size+num]=0.0; 130 | } 131 | print!("."); 132 | fft.process(&mut bseg, &mut spectrum1).unwrap(); 133 | for sp in 0..spectrum0.len() { 134 | conv[sp] = spectrum0[sp]*spectrum1[sp]/(fft_size as f64*2.0); 135 | } 136 | ifft.process(&mut conv, &mut out_frame); 137 | for i2 in 0..out_frame.len() { 138 | out_channels[chan][fft_size*(i+bi)+i2] += out_frame[i2]/(fft_size as f64*2.0).sqrt()/2.0; 139 | } 140 | } 141 | } 142 | } 143 | let mut max = 0.0; 144 | 145 | for i in 0..out_channels.len(){ 146 | for i2 in 0..out_channels[0].len() { 147 | if out_channels[i][i2]>max {max = out_channels[i][i2]} 148 | } 149 | } 150 | println!("{}", max); 151 | for i in 0..out_channels.len(){ 152 | for i2 in 0..out_channels[0].len() { 153 | out_channels[i][i2] /= max; 154 | } 155 | } 156 | 157 | let sound_file = hound::WavReader::open(file_name0).unwrap(); 158 | let spec = hound::WavSpec { 159 | channels: out_channels.len() as u16, 160 | sample_rate: sound_file.spec().sample_rate, 161 | bits_per_sample: 32, 162 | sample_format: hound::SampleFormat::Float, 163 | }; 164 | 165 | let mut writer = hound::WavWriter::create(out_file, spec).unwrap(); 166 | for samp in 0..(out_channels[0].len()) { 167 | for chan in 0..spec.channels { 168 | writer 169 | .write_sample(out_channels[chan as usize][samp] as f32) 170 | .unwrap(); 171 | } 172 | } 173 | writer.finalize().unwrap(); 174 | } 175 | 176 | fn make_whole (vec: &mut Vec, fft_size: usize) { 177 | let missing = (vec.len() as f64 /fft_size as f64).ceil() as usize *fft_size - vec.len(); 178 | vec.append(&mut vec![0.0; missing]); 179 | } 180 | 181 | fn get_file_channels(file_name: &str) -> Vec> { 182 | let mut sound_file = hound::WavReader::open(file_name).unwrap(); 183 | let mut intemp = vec![0.0; 0]; 184 | if sound_file.spec().sample_format == hound::SampleFormat::Float { 185 | intemp.append( 186 | &mut sound_file 187 | .samples::() 188 | .map(|x| x.unwrap() as f64) 189 | .collect::>(), 190 | ); 191 | } else { 192 | intemp.append( 193 | &mut sound_file 194 | .samples::() 195 | .map(|x| x.unwrap() as f64) 196 | .collect::>(), 197 | ); 198 | let bits = sound_file.spec().bits_per_sample; 199 | for iter in 0..intemp.len() { 200 | intemp[iter] = intemp[iter] / (f64::powf(2.0, bits as f64)); 201 | } 202 | }; 203 | let chunked: Vec> = intemp 204 | .chunks(sound_file.spec().channels as usize) 205 | .map(|x| x.to_vec()) 206 | .collect(); 207 | let mut channels = transpose(chunked); 208 | 209 | return channels; 210 | } 211 | 212 | fn transpose(v: Vec>) -> Vec> 213 | where 214 | T: Clone, 215 | { 216 | assert!(!v.is_empty()); 217 | (0..v[0].len()) 218 | .map(|i| v.iter().map(|inner| inner[i].clone()).collect::>()) 219 | .collect() 220 | } 221 | -------------------------------------------------------------------------------- /workspace.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ] 7 | } --------------------------------------------------------------------------------