Skip to content

Commit

Permalink
Change the window function
Browse files Browse the repository at this point in the history
And add Blackman-Harris in addition to Hann and Hamming.

References alexkay#94.
  • Loading branch information
alexkay committed Apr 3, 2016
1 parent df59b4d commit 70ecaae
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 6 deletions.
3 changes: 3 additions & 0 deletions MANUAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ On OS X use the Command key instead of Ctrl.
`Ctrl-Shift-up`, `Ctrl-Shift-down`
: Change the upper limit of the dynamic range in dBFS.

`f`, `F`
: Change the DFT window function.

`s`, `S`
: Change the DFT window size.

Expand Down
22 changes: 17 additions & 5 deletions src/spek-pipeline.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ struct spek_pipeline
{
std::unique_ptr<AudioFile> file;
std::unique_ptr<FFTPlan> fft;
enum window_function window_function;
int samples;
spek_pipeline_cb cb;
void *cb_data;
Expand Down Expand Up @@ -60,6 +61,7 @@ static void reader_sync(struct spek_pipeline *p, int pos);
struct spek_pipeline * spek_pipeline_open(
std::unique_ptr<AudioFile> file,
std::unique_ptr<FFTPlan> fft,
enum window_function window_function,
int samples,
spek_pipeline_cb cb,
void *cb_data
Expand All @@ -68,6 +70,7 @@ struct spek_pipeline * spek_pipeline_open(
spek_pipeline *p = new spek_pipeline();
p->file = std::move(file);
p->fft = std::move(fft);
p->window_function = window_function;
p->samples = samples;
p->cb = cb;
p->cb_data = cb_data;
Expand Down Expand Up @@ -319,6 +322,19 @@ static void reader_sync(struct spek_pipeline *p, int pos)
pthread_mutex_unlock(&p->worker_mutex);
}

static float get_window(enum window_function f, int i, float *coss, int n) {
switch (f) {
case WINDOW_HANN:
return 0.5f * (1.0f - coss[i]);
case WINDOW_HAMMING:
return 0.53836f - 0.46164f * coss[i];
case WINDOW_BLACKMAN_HARRIS:
return 0.35875f - 0.48829f * coss[i] + 0.14128f * coss[2*i % n] - 0.01168f * coss[3*i % n];
default:
assert(false);
}
}

static void * worker_func(void *pp)
{
struct spek_pipeline *p = (spek_pipeline*)pp;
Expand Down Expand Up @@ -370,11 +386,7 @@ static void * worker_func(void *pp)
prev_head = head;
for (int i = 0; i < p->nfft; i++) {
float val = p->input[(p->input_size + head - p->nfft + i) % p->input_size];
// TODO: allow the user to chose the window function
// Hamming window.
// val *= 0.53836f - 0.46164f * coss[i];
// Hann window.
val *= 0.5f * (1.0f - p->coss[i]);
val *= get_window(p->window_function, i, p->coss, p->nfft);
p->fft->set_input(i, val);
}
p->fft->execute();
Expand Down
9 changes: 9 additions & 0 deletions src/spek-pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,20 @@ class AudioFile;
class FFTPlan;
struct spek_pipeline;

enum window_function {
WINDOW_HANN,
WINDOW_HAMMING,
WINDOW_BLACKMAN_HARRIS,
WINDOW_COUNT,
WINDOW_DEFAULT = WINDOW_HANN,
};

typedef void (*spek_pipeline_cb)(int bands, int sample, float *values, void *cb_data);

struct spek_pipeline * spek_pipeline_open(
std::unique_ptr<AudioFile> file,
std::unique_ptr<FFTPlan> fft,
enum window_function window_function,
int samples,
spek_pipeline_cb cb,
void *cb_data
Expand Down
8 changes: 7 additions & 1 deletion src/spek-spectrogram.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include "spek-audio.h"
#include "spek-events.h"
#include "spek-fft.h"
#include "spek-pipeline.h"
#include "spek-platform.h"
#include "spek-ruler.h"
#include "spek-utils.h"
Expand Down Expand Up @@ -48,6 +47,7 @@ SpekSpectrogram::SpekSpectrogram(wxFrame *parent) :
audio(new Audio()), // TODO: refactor
fft(new FFT()),
pipeline(NULL),
window_function(WINDOW_DEFAULT),
duration(0.0),
sample_rate(0),
palette(PALETTE_DEFAULT),
Expand Down Expand Up @@ -102,6 +102,11 @@ void SpekSpectrogram::on_char(wxKeyEvent& evt)
this->urange = spek_min(this->urange + 1, MAX_RANGE);
} else if (CS && D) {
this->urange = spek_max(this->urange - 1, this->lrange + 1);
} else if (S && evt.GetKeyCode() == 'F') {
this->window_function = (enum window_function) ((this->window_function + 1) % WINDOW_COUNT);
} else if (N && evt.GetKeyCode() == 'f') {
this->window_function =
(enum window_function) ((this->window_function - 1 + WINDOW_COUNT) % WINDOW_COUNT);
} else if (S && evt.GetKeyCode() == 'S') {
this->fft_bits = spek_min(this->fft_bits + 1, MAX_FFT_BITS);
this->create_palette();
Expand Down Expand Up @@ -358,6 +363,7 @@ void SpekSpectrogram::start()
this->pipeline = spek_pipeline_open(
this->audio->open(std::string(this->path.utf8_str())),
this->fft->create(this->fft_bits),
this->window_function,
samples,
pipeline_cb,
this
Expand Down
2 changes: 2 additions & 0 deletions src/spek-spectrogram.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <wx/wx.h>

#include "spek-palette.h"
#include "spek-pipeline.h"

class Audio;
class FFT;
Expand Down Expand Up @@ -34,6 +35,7 @@ class SpekSpectrogram : public wxWindow
std::unique_ptr<Audio> audio;
std::unique_ptr<FFT> fft;
spek_pipeline *pipeline;
enum window_function window_function;
wxString path;
wxString desc;
double duration;
Expand Down

0 comments on commit 70ecaae

Please sign in to comment.