Change DFT window size

Closes .
This commit is contained in:
Alexander Kojevnikov 2016-03-29 11:33:04 -07:00
parent a00057b4c8
commit 437dc2fe5b
6 changed files with 55 additions and 27 deletions

1
.gitignore vendored

@ -1,4 +1,5 @@
*.a
*.core
*.exe
*.msi
*.o

@ -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*

@ -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;

@ -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,

@ -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;
}

@ -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;