spek

Acoustic spectrum analyser
git clone http://git.hanabi.in/repos/spek.git
Log | Files | Refs | README

commit 437dc2fe5b6adce984678e5d6f9d0d01a4569695
parent a00057b4c81eec5f76104c74d010867fa61d06e7
Author: Alexander Kojevnikov <alexander@kojevnikov.com>
Date:   Tue, 29 Mar 2016 11:33:04 -0700

Change DFT window size

Closes #97.

Diffstat:
M.gitignore | 1+
MMANUAL.md | 3+++
Msrc/spek-pipeline.cc | 4++--
Msrc/spek-pipeline.h | 2+-
Msrc/spek-spectrogram.cc | 69+++++++++++++++++++++++++++++++++++++++++++++------------------------
Msrc/spek-spectrogram.h | 3+++
6 files changed, 55 insertions(+), 27 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,4 +1,5 @@ *.a +*.core *.exe *.msi *.o diff --git a/MANUAL.md b/MANUAL.md @@ -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. +`s`, `S` +: Change the DFT window size. + # FILES *~/.config/spek/preferences* diff --git a/src/spek-pipeline.cc b/src/spek-pipeline.cc @@ -325,7 +325,7 @@ static void * reader_func(void *pp) pthread_join(p->worker_thread, NULL); // Notify the client. - p->cb(-1, NULL, p->cb_data); + p->cb(p->fft->get_output_size(), -1, NULL, p->cb_data); return NULL; } @@ -422,7 +422,7 @@ static void * worker_func(void *pp) } if (sample == p->samples) break; - p->cb(sample++, p->output, p->cb_data); + p->cb(p->fft->get_output_size(), sample++, p->output, p->cb_data); memset(p->output, 0, sizeof(float) * p->fft->get_output_size()); frames = 0; diff --git a/src/spek-pipeline.h b/src/spek-pipeline.h @@ -26,7 +26,7 @@ class AudioFile; class FFTPlan; struct spek_pipeline; -typedef void (*spek_pipeline_cb)(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( std::unique_ptr<AudioFile> file, diff --git a/src/spek-spectrogram.cc b/src/spek-spectrogram.cc @@ -40,12 +40,13 @@ END_EVENT_TABLE() enum { - MAX_RANGE = 0, MIN_RANGE = -140, + MAX_RANGE = 0, URANGE = -20, LRANGE = -120, FFT_BITS = 11, - BANDS = (1 << (FFT_BITS - 1)) + 1, + MIN_FFT_BITS = 8, + MAX_FFT_BITS = 14, LPAD = 60, TPAD = 60, RPAD = 90, @@ -56,6 +57,7 @@ enum // Forward declarations. static wxString trim(wxDC& dc, const wxString& s, int length, bool trim_end); +static int bits_to_bands(int bits); SpekSpectrogram::SpekSpectrogram(wxFrame *parent) : wxWindow( @@ -67,25 +69,17 @@ SpekSpectrogram::SpekSpectrogram(wxFrame *parent) : pipeline(NULL), duration(0.0), sample_rate(0), - palette(RULER, BANDS), + palette(), image(1, 1), prev_width(-1), + fft_bits(FFT_BITS), urange(URANGE), lrange(LRANGE) { + this->create_palette(); + SetBackgroundStyle(wxBG_STYLE_CUSTOM); SetFocus(); - - // Pre-draw the palette. - for (int y = 0; y < BANDS; y++) { - uint32_t color = spek_palette_spectrum(y / (double) BANDS); - this->palette.SetRGB( - wxRect(0, BANDS - y - 1, RULER, 1), - color >> 16, - (color >> 8) & 0xFF, - color & 0xFF - ); - } } SpekSpectrogram::~SpekSpectrogram() @@ -111,19 +105,27 @@ void SpekSpectrogram::save(const wxString& path) void SpekSpectrogram::on_char(wxKeyEvent& evt) { + bool N = evt.GetModifiers() == wxMOD_NONE; bool C = evt.GetModifiers() == wxMOD_CONTROL; + bool S = evt.GetModifiers() == wxMOD_SHIFT; bool CS = evt.GetModifiers() == (wxMOD_CONTROL | wxMOD_SHIFT); - bool dn = evt.GetKeyCode() == WXK_DOWN; - bool up = evt.GetKeyCode() == WXK_UP; + bool U = evt.GetKeyCode() == WXK_UP; + bool D = evt.GetKeyCode() == WXK_DOWN; - if (C && up) { + if (C && U) { this->lrange = spek_min(this->lrange + 1, this->urange - 1); - } else if (C && dn) { + } else if (C && D) { this->lrange = spek_max(this->lrange - 1, MIN_RANGE); - } else if (CS && up) { + } else if (CS && U) { this->urange = spek_min(this->urange + 1, MAX_RANGE); - } else if (CS && dn) { + } else if (CS && D) { this->urange = spek_max(this->urange - 1, this->lrange + 1); + } else if (S && evt.GetKeyCode() == 'S') { + this->fft_bits = spek_min(this->fft_bits + 1, MAX_FFT_BITS); + this->create_palette(); + } else if (N && evt.GetKeyCode() == 's') { + this->fft_bits = spek_max(this->fft_bits - 1, MIN_FFT_BITS); + this->create_palette(); } else { evt.Skip(); return; @@ -343,9 +345,9 @@ void SpekSpectrogram::render(wxDC& dc) } } -static void pipeline_cb(int sample, float *values, void *cb_data) +static void pipeline_cb(int bands, int sample, float *values, void *cb_data) { - SpekHaveSampleEvent event(BANDS, sample, values, false); + SpekHaveSampleEvent event(bands, sample, values, false); SpekSpectrogram *s = (SpekSpectrogram *)cb_data; wxPostEvent(s, event); } @@ -364,10 +366,10 @@ void SpekSpectrogram::start() wxSize size = GetClientSize(); int samples = size.GetWidth() - LPAD - RPAD; if (samples > 0) { - this->image.Create(samples, BANDS); + this->image.Create(samples, bits_to_bands(this->fft_bits)); this->pipeline = spek_pipeline_open( this->audio->open(std::string(this->path.utf8_str())), - this->fft->create(FFT_BITS), + this->fft->create(this->fft_bits), samples, pipeline_cb, this @@ -393,6 +395,20 @@ void SpekSpectrogram::stop() } } +void SpekSpectrogram::create_palette() +{ + this->palette.Create(RULER, bits_to_bands(this->fft_bits)); + for (int y = 0; y < bits_to_bands(this->fft_bits); y++) { + uint32_t color = spek_palette_spectrum(y / (double)bits_to_bands(this->fft_bits)); + this->palette.SetRGB( + wxRect(0, bits_to_bands(this->fft_bits) - y - 1, RULER, 1), + color >> 16, + (color >> 8) & 0xFF, + color & 0xFF + ); + } +} + // Trim `s` so that it fits into `length`. static wxString trim(wxDC& dc, const wxString& s, int length, bool trim_end) { @@ -422,3 +438,8 @@ static wxString trim(wxDC& dc, const wxString& s, int length, bool trim_end) return trim_end ? s.substr(0, i) + fix : fix + s.substr(k); } + +// TODO: test +static int bits_to_bands(int bits) { + return (1 << (bits - 1)) + 1; +} diff --git a/src/spek-spectrogram.h b/src/spek-spectrogram.h @@ -46,6 +46,8 @@ private: void start(); void stop(); + void create_palette(); + std::unique_ptr<Audio> audio; std::unique_ptr<FFT> fft; spek_pipeline *pipeline; @@ -56,6 +58,7 @@ private: wxImage palette; wxImage image; int prev_width; + int fft_bits; int urange; int lrange;