mirror of
https://github.com/alexkay/spek.git
synced 2025-06-01 08:01:08 +03:00
Change the window function
And add Blackman-Harris in addition to Hann and Hamming. References #94.
This commit is contained in:
parent
df59b4d1e2
commit
70ecaae62e
@ -53,6 +53,9 @@ On OS X use the Command key instead of Ctrl.
|
|||||||
`Ctrl-Shift-up`, `Ctrl-Shift-down`
|
`Ctrl-Shift-up`, `Ctrl-Shift-down`
|
||||||
: Change the upper limit of the dynamic range in dBFS.
|
: Change the upper limit of the dynamic range in dBFS.
|
||||||
|
|
||||||
|
`f`, `F`
|
||||||
|
: Change the DFT window function.
|
||||||
|
|
||||||
`s`, `S`
|
`s`, `S`
|
||||||
: Change the DFT window size.
|
: Change the DFT window size.
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ struct spek_pipeline
|
|||||||
{
|
{
|
||||||
std::unique_ptr<AudioFile> file;
|
std::unique_ptr<AudioFile> file;
|
||||||
std::unique_ptr<FFTPlan> fft;
|
std::unique_ptr<FFTPlan> fft;
|
||||||
|
enum window_function window_function;
|
||||||
int samples;
|
int samples;
|
||||||
spek_pipeline_cb cb;
|
spek_pipeline_cb cb;
|
||||||
void *cb_data;
|
void *cb_data;
|
||||||
@ -60,6 +61,7 @@ static void reader_sync(struct spek_pipeline *p, int pos);
|
|||||||
struct spek_pipeline * spek_pipeline_open(
|
struct spek_pipeline * spek_pipeline_open(
|
||||||
std::unique_ptr<AudioFile> file,
|
std::unique_ptr<AudioFile> file,
|
||||||
std::unique_ptr<FFTPlan> fft,
|
std::unique_ptr<FFTPlan> fft,
|
||||||
|
enum window_function window_function,
|
||||||
int samples,
|
int samples,
|
||||||
spek_pipeline_cb cb,
|
spek_pipeline_cb cb,
|
||||||
void *cb_data
|
void *cb_data
|
||||||
@ -68,6 +70,7 @@ struct spek_pipeline * spek_pipeline_open(
|
|||||||
spek_pipeline *p = new spek_pipeline();
|
spek_pipeline *p = new spek_pipeline();
|
||||||
p->file = std::move(file);
|
p->file = std::move(file);
|
||||||
p->fft = std::move(fft);
|
p->fft = std::move(fft);
|
||||||
|
p->window_function = window_function;
|
||||||
p->samples = samples;
|
p->samples = samples;
|
||||||
p->cb = cb;
|
p->cb = cb;
|
||||||
p->cb_data = cb_data;
|
p->cb_data = cb_data;
|
||||||
@ -319,6 +322,19 @@ static void reader_sync(struct spek_pipeline *p, int pos)
|
|||||||
pthread_mutex_unlock(&p->worker_mutex);
|
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)
|
static void * worker_func(void *pp)
|
||||||
{
|
{
|
||||||
struct spek_pipeline *p = (spek_pipeline*)pp;
|
struct spek_pipeline *p = (spek_pipeline*)pp;
|
||||||
@ -370,11 +386,7 @@ static void * worker_func(void *pp)
|
|||||||
prev_head = head;
|
prev_head = head;
|
||||||
for (int i = 0; i < p->nfft; i++) {
|
for (int i = 0; i < p->nfft; i++) {
|
||||||
float val = p->input[(p->input_size + head - p->nfft + i) % p->input_size];
|
float val = p->input[(p->input_size + head - p->nfft + i) % p->input_size];
|
||||||
// TODO: allow the user to chose the window function
|
val *= get_window(p->window_function, i, p->coss, p->nfft);
|
||||||
// Hamming window.
|
|
||||||
// val *= 0.53836f - 0.46164f * coss[i];
|
|
||||||
// Hann window.
|
|
||||||
val *= 0.5f * (1.0f - p->coss[i]);
|
|
||||||
p->fft->set_input(i, val);
|
p->fft->set_input(i, val);
|
||||||
}
|
}
|
||||||
p->fft->execute();
|
p->fft->execute();
|
||||||
|
@ -7,11 +7,20 @@ class AudioFile;
|
|||||||
class FFTPlan;
|
class FFTPlan;
|
||||||
struct spek_pipeline;
|
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);
|
typedef void (*spek_pipeline_cb)(int bands, int sample, float *values, void *cb_data);
|
||||||
|
|
||||||
struct spek_pipeline * spek_pipeline_open(
|
struct spek_pipeline * spek_pipeline_open(
|
||||||
std::unique_ptr<AudioFile> file,
|
std::unique_ptr<AudioFile> file,
|
||||||
std::unique_ptr<FFTPlan> fft,
|
std::unique_ptr<FFTPlan> fft,
|
||||||
|
enum window_function window_function,
|
||||||
int samples,
|
int samples,
|
||||||
spek_pipeline_cb cb,
|
spek_pipeline_cb cb,
|
||||||
void *cb_data
|
void *cb_data
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include "spek-audio.h"
|
#include "spek-audio.h"
|
||||||
#include "spek-events.h"
|
#include "spek-events.h"
|
||||||
#include "spek-fft.h"
|
#include "spek-fft.h"
|
||||||
#include "spek-pipeline.h"
|
|
||||||
#include "spek-platform.h"
|
#include "spek-platform.h"
|
||||||
#include "spek-ruler.h"
|
#include "spek-ruler.h"
|
||||||
#include "spek-utils.h"
|
#include "spek-utils.h"
|
||||||
@ -48,6 +47,7 @@ SpekSpectrogram::SpekSpectrogram(wxFrame *parent) :
|
|||||||
audio(new Audio()), // TODO: refactor
|
audio(new Audio()), // TODO: refactor
|
||||||
fft(new FFT()),
|
fft(new FFT()),
|
||||||
pipeline(NULL),
|
pipeline(NULL),
|
||||||
|
window_function(WINDOW_DEFAULT),
|
||||||
duration(0.0),
|
duration(0.0),
|
||||||
sample_rate(0),
|
sample_rate(0),
|
||||||
palette(PALETTE_DEFAULT),
|
palette(PALETTE_DEFAULT),
|
||||||
@ -102,6 +102,11 @@ void SpekSpectrogram::on_char(wxKeyEvent& evt)
|
|||||||
this->urange = spek_min(this->urange + 1, MAX_RANGE);
|
this->urange = spek_min(this->urange + 1, MAX_RANGE);
|
||||||
} else if (CS && D) {
|
} else if (CS && D) {
|
||||||
this->urange = spek_max(this->urange - 1, this->lrange + 1);
|
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') {
|
} else if (S && evt.GetKeyCode() == 'S') {
|
||||||
this->fft_bits = spek_min(this->fft_bits + 1, MAX_FFT_BITS);
|
this->fft_bits = spek_min(this->fft_bits + 1, MAX_FFT_BITS);
|
||||||
this->create_palette();
|
this->create_palette();
|
||||||
@ -358,6 +363,7 @@ void SpekSpectrogram::start()
|
|||||||
this->pipeline = spek_pipeline_open(
|
this->pipeline = spek_pipeline_open(
|
||||||
this->audio->open(std::string(this->path.utf8_str())),
|
this->audio->open(std::string(this->path.utf8_str())),
|
||||||
this->fft->create(this->fft_bits),
|
this->fft->create(this->fft_bits),
|
||||||
|
this->window_function,
|
||||||
samples,
|
samples,
|
||||||
pipeline_cb,
|
pipeline_cb,
|
||||||
this
|
this
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <wx/wx.h>
|
#include <wx/wx.h>
|
||||||
|
|
||||||
#include "spek-palette.h"
|
#include "spek-palette.h"
|
||||||
|
#include "spek-pipeline.h"
|
||||||
|
|
||||||
class Audio;
|
class Audio;
|
||||||
class FFT;
|
class FFT;
|
||||||
@ -34,6 +35,7 @@ private:
|
|||||||
std::unique_ptr<Audio> audio;
|
std::unique_ptr<Audio> audio;
|
||||||
std::unique_ptr<FFT> fft;
|
std::unique_ptr<FFT> fft;
|
||||||
spek_pipeline *pipeline;
|
spek_pipeline *pipeline;
|
||||||
|
enum window_function window_function;
|
||||||
wxString path;
|
wxString path;
|
||||||
wxString desc;
|
wxString desc;
|
||||||
double duration;
|
double duration;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user