Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
target
**.DS_Store
Cargo.lock
.idea/
15 changes: 12 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,18 @@ name = "stft"
readme = "README.md"
repository = "https://github.com/snd/stft.git"
version = "0.2.0"
edition = "2018"

[dependencies]
apodize = "0.3.1"
num = "0.2.0"
rustfft = "3.0.0"
apodize = "1.0.0"
num = "0.4.0"
rustfft = "6.0.1"
strider = "0.1.3"

[dev-dependencies]
criterion = "0.3.4"
approx = "0.5.0"

[[bench]]
name = "lib"
harness = false
174 changes: 105 additions & 69 deletions benches/lib.rs
Original file line number Diff line number Diff line change
@@ -1,98 +1,134 @@
#![feature(test)]
extern crate test;

extern crate num;
use criterion::{criterion_group, criterion_main, Criterion};
use num::complex::Complex;

extern crate rustfft;
use rustfft::FFT;

extern crate stft;
use stft::{STFT, WindowType};
use rustfft::{FftDirection, FftPlanner};
use stft::{WindowType, STFT};

macro_rules! bench_fft_process {
($bencher:expr, $window_size:expr, $float:ty) => {{
let inverse = false;
let window_size = $window_size;
let mut fft = FFT::<$float>::new(window_size, inverse);
let input = std::iter::repeat(Complex::new(0., 0.))
.take(window_size)
.collect::<Vec<Complex<$float>>>();
($c:expr, $window_size:expr, $float:ty) => {{
let mut planner = FftPlanner::new();
let fft = planner.plan_fft($window_size, FftDirection::Forward);
// input is processed in-place
let mut output = std::iter::repeat(Complex::new(0., 0.))
.take(window_size)
.take($window_size)
.collect::<Vec<Complex<$float>>>();
$bencher.iter(|| {
fft.process(&input[..], &mut output[..])
});

}}
$c.bench_function(
concat!(
"bench_fft_process_",
stringify!($window_size),
"_",
stringify!($float)
),
|b| b.iter(|| fft.process(&mut output[..])),
);
}};
}

#[bench]
fn bench_fft_process_1024_f32(bencher: &mut test::Bencher) {
bench_fft_process!(bencher, 1024, f32);
fn bench_fft_process_1024_f32(c: &mut Criterion) {
bench_fft_process!(c, 1024, f32);
}

#[bench]
fn bench_fft_process_1024_f64(bencher: &mut test::Bencher) {
bench_fft_process!(bencher, 1024, f64);
fn bench_fft_process_1024_f64(c: &mut Criterion) {
bench_fft_process!(c, 1024, f64);
}

criterion_group!(
benches_fft_process,
bench_fft_process_1024_f32,
bench_fft_process_1024_f64
);

macro_rules! bench_stft_compute {
($bencher:expr, $window_size:expr, $float:ty) => {{
let mut stft = STFT::<$float>::new(WindowType::Hanning, $window_size, 0);
let input = std::iter::repeat(1.).take($window_size).collect::<Vec<$float>>();
let mut output = std::iter::repeat(0.).take(stft.output_size()).collect::<Vec<$float>>();
($c:expr, $window_size:expr, $float:ty) => {{
let step_size: usize = 512;
let mut stft = STFT::<$float>::new(WindowType::Hanning, $window_size, step_size);
let input = std::iter::repeat(1.)
.take($window_size)
.collect::<Vec<$float>>();
let mut output = std::iter::repeat(0.)
.take(stft.output_size())
.collect::<Vec<$float>>();
stft.append_samples(&input[..]);
$bencher.iter(|| {
stft.compute_column(&mut output[..])
});
}}
$c.bench_function(
concat!(
"bench_stft_compute_",
stringify!($window_size),
"_",
stringify!($float)
),
|b| b.iter(|| stft.compute_column(&mut output[..])),
);
}};
}

#[bench]
fn bench_stft_compute_1024_f32(bencher: &mut test::Bencher) {
bench_stft_compute!(bencher, 1024, f32);
fn bench_stft_compute_1024_f32(c: &mut Criterion) {
bench_stft_compute!(c, 1024, f32);
}

#[bench]
fn bench_stft_compute_1024_f64(bencher: &mut test::Bencher) {
bench_stft_compute!(bencher, 1024, f64);
fn bench_stft_compute_1024_f64(c: &mut Criterion) {
bench_stft_compute!(c, 1024, f64);
}

criterion_group!(
benches_stft_compute,
bench_stft_compute_1024_f32,
bench_stft_compute_1024_f64
);

macro_rules! bench_stft_audio {
($bencher:expr, $seconds:expr, $float:ty) => {{
($c:expr, $seconds:expr, $float:ty) => {{
// let's generate some fake audio
let sample_rate: usize = 44100;
let seconds: usize = $seconds;
let sample_count = sample_rate * seconds;
let all_samples = (0..sample_count).map(|x| x as $float).collect::<Vec<$float>>();
$bencher.iter(|| {
// let's initialize our short-time fourier transform
let window_type: WindowType = WindowType::Hanning;
let window_size: usize = 1024;
let step_size: usize = 512;
let mut stft = STFT::<$float>::new(window_type, window_size, step_size);
// we need a buffer to hold a computed column of the spectrogram
let mut spectrogram_column: Vec<$float> =
std::iter::repeat(0.).take(stft.output_size()).collect();
for some_samples in (&all_samples[..]).chunks(3000) {
stft.append_samples(some_samples);
while stft.contains_enough_to_compute() {
stft.compute_column(&mut spectrogram_column[..]);
stft.move_to_next_column();
}
}
});
}}
let all_samples = (0..sample_count)
.map(|x| x as $float)
.collect::<Vec<$float>>();
$c.bench_function(
concat!(
"bench_stft_audio_",
stringify!($windowsize),
"_",
stringify!($float)
),
|b| {
b.iter(|| {
// let's initialize our short-time fourier transform
let window_type: WindowType = WindowType::Hanning;
let window_size: usize = 1024;
let step_size: usize = 512;
let mut stft = STFT::<$float>::new(window_type, window_size, step_size);
// we need a buffer to hold a computed column of the spectrogram
let mut spectrogram_column: Vec<$float> =
std::iter::repeat(0.).take(stft.output_size()).collect();
for some_samples in (&all_samples[..]).chunks(3000) {
stft.append_samples(some_samples);
while stft.contains_enough_to_compute() {
stft.compute_column(&mut spectrogram_column[..]);
stft.move_to_next_column();
}
}
})
},
);
}};
}

#[bench]
fn bench_stft_10_seconds_audio_f32(bencher: &mut test::Bencher) {
bench_stft_audio!(bencher, 10, f32);
fn bench_stft_10_seconds_audio_f32(c: &mut Criterion) {
bench_stft_audio!(c, 10, f32);
}

#[bench]
fn bench_stft_10_seconds_audio_f64(bencher: &mut test::Bencher) {
bench_stft_audio!(bencher, 10, f64);
fn bench_stft_10_seconds_audio_f64(c: &mut Criterion) {
bench_stft_audio!(c, 10, f64);
}

criterion_group!(
benches_stft_audio,
bench_stft_10_seconds_audio_f32,
bench_stft_10_seconds_audio_f64
);

criterion_main!(
benches_fft_process,
benches_stft_compute,
benches_stft_audio
);
Loading