commit f81ce84826b48f48c655bcf70343d99eb88bac74
parent 4df42e8258e98431392d4feeb06cdb67457aa221
Author: Alexander Kojevnikov <alexander@kojevnikov.com>
Date: Wed, 15 Aug 2012 00:56:20 -0700
Run the pipeline
Diffstat:
5 files changed, 77 insertions(+), 45 deletions(-)
diff --git a/src/spek-pipeline.c b/src/spek-pipeline.c
@@ -47,6 +47,7 @@ struct spek_pipeline
int samples;
int threshold;
spek_pipeline_cb cb;
+ void *cb_data;
struct spek_fft_plan *fft;
float *coss; // Pre-computed cos table.
@@ -79,7 +80,7 @@ static void reader_sync(struct spek_pipeline *p, int pos);
static float average_input(const struct spek_pipeline *p, void *buffer);
struct spek_pipeline * spek_pipeline_open(
- const char *path, int bands, int samples, int threshold, spek_pipeline_cb cb)
+ const char *path, int bands, int samples, int threshold, spek_pipeline_cb cb, void *cb_data)
{
struct spek_pipeline *p = malloc(sizeof(struct spek_pipeline));
p->cx = spek_audio_open(path);
@@ -88,6 +89,7 @@ struct spek_pipeline * spek_pipeline_open(
p->samples = samples;
p->threshold = threshold;
p->cb = cb;
+ p->cb_data = cb_data;
p->coss = NULL;
p->fft = NULL;
@@ -115,6 +117,11 @@ struct spek_pipeline * spek_pipeline_open(
}
}
+const struct spek_audio_properties * spek_pipeline_properties(struct spek_pipeline *pipeline)
+{
+ return pipeline->properties;
+}
+
void spek_pipeline_start(struct spek_pipeline *p)
{
if (!p->properties->error) return;
@@ -176,6 +183,7 @@ void spek_pipeline_close(struct spek_pipeline *p) {
spek_audio_close(p->cx);
p->cx = NULL;
}
+ free(p);
}
static void * reader_func (void *pp) {
@@ -310,7 +318,7 @@ static void * worker_func (void *pp) {
}
if (sample == p->samples) break;
- p->cb(sample++, p->output);
+ p->cb(sample++, p->output, p->cb_data);
memset(p->output, 0, sizeof(float) * p->bands);
frames = 0;
diff --git a/src/spek-pipeline.h b/src/spek-pipeline.h
@@ -26,15 +26,15 @@ extern "C" {
struct spek_pipeline;
struct spek_audio_properties;
-typedef void (*spek_pipeline_cb)(int sample, float *values);
+typedef void (*spek_pipeline_cb)(int sample, float *values, void *cb_data);
struct spek_pipeline * spek_pipeline_open(
- const char *path, int bands, int samples, int threshold, spek_pipeline_cb cb);
-
-void spek_pipeline_start(struct spek_pipeline *pipeline);
+ const char *path, int bands, int samples, int threshold, spek_pipeline_cb cb, void *cb_data);
const struct spek_audio_properties * spek_pipeline_properties(struct spek_pipeline *pipeline);
+void spek_pipeline_start(struct spek_pipeline *pipeline);
+
void spek_pipeline_close(struct spek_pipeline *pipeline);
#ifdef __cplusplus
diff --git a/src/spek-spectrogram.cc b/src/spek-spectrogram.cc
@@ -16,8 +16,12 @@
* along with Spek. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <cmath>
#include <wx/dcbuffer.h>
+#include "spek-audio-desc.hh"
+#include "spek-pipeline.h"
+
#include "spek-spectrogram.hh"
BEGIN_EVENT_TABLE(SpekSpectrogram, wxPanel)
@@ -39,7 +43,9 @@ enum
SpekSpectrogram::SpekSpectrogram(wxFrame *parent) :
wxPanel(parent, -1, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE),
- palette(RULER, BANDS)
+ pipeline(NULL),
+ palette(RULER, BANDS),
+ image()
{
SetBackgroundStyle(wxBG_STYLE_CUSTOM);
@@ -122,8 +128,57 @@ void SpekSpectrogram::render(wxDC& dc)
dc.DrawBitmap(bmp, w - RPAD + GAP, TPAD);
}
+void SpekSpectrogram::pipeline_cb(int sample, float *values, void *cb_data)
+{
+ static double log10_threshold = log10(-THRESHOLD);
+ SpekSpectrogram *s = (SpekSpectrogram *)cb_data;
+
+ for (int y = 0; y < BANDS; y++) {
+ double level = log10(1.0 - THRESHOLD + values[y]) / log10_threshold;
+ if (level > 1.0) level = 1.0;
+ uint32_t color = get_color(level);
+ s->image.SetRGB(
+ sample,
+ y,
+ color >> 16,
+ (color >> 8) & 0xFF,
+ color & 0xFF
+ );
+ }
+
+ s->Refresh(false); // TODO: refresh only one pixel column
+}
+
+
void SpekSpectrogram::start()
{
+ if(this->pipeline) {
+ spek_pipeline_close(this->pipeline);
+ this->pipeline = NULL;
+ }
+
+ // The number of samples is the number of pixels available for the image.
+ // The number of bands is fixed, FFT results are very different for
+ // different values but we need some consistency.
+ wxSize size = GetClientSize();
+ int samples = size.GetWidth() - LPAD - RPAD;
+ if (samples > 0) {
+ this->image.Create(samples, BANDS);
+ this->pipeline = spek_pipeline_open(
+ this->path.utf8_str(),
+ BANDS,
+ samples,
+ THRESHOLD,
+ pipeline_cb,
+ this
+ );
+ spek_pipeline_start(this->pipeline);
+ this->desc = spek_audio_desc(spek_pipeline_properties(this->pipeline));
+ } else {
+ this->image.Create(1, 1);
+ }
+
+ Refresh(false);
}
// Modified version of Dan Bruton's algorithm:
diff --git a/src/spek-spectrogram.hh b/src/spek-spectrogram.hh
@@ -21,6 +21,8 @@
#include <wx/wx.h>
+struct spek_pipeline;
+
class SpekSpectrogram : public wxPanel
{
public:
@@ -33,11 +35,14 @@ private:
void render(wxDC& dc);
void start();
- uint32_t get_color(double level);
+ static void pipeline_cb(int sample, float *values, void *cb_data);
+ static uint32_t get_color(double level);
+ spek_pipeline *pipeline;
wxString path;
- wxString info;
+ wxString desc;
wxImage palette;
+ wxImage image;
DECLARE_EVENT_TABLE()
};
diff --git a/src/spek-spectrogram.vala b/src/spek-spectrogram.vala
@@ -24,8 +24,6 @@ using Pango;
namespace Spek {
class Spectrogram : DrawingArea {
- private Pipeline pipeline;
-
private ImageSurface image;
public Spectrogram () {
@@ -38,30 +36,6 @@ namespace Spek {
surface.write_to_png (file_name);
}
- private void start () {
- if (pipeline != null) {
- pipeline.stop ();
- }
-
- // The number of samples is the number of pixels available for the image.
- // The number of bands is fixed, FFT results are very different for
- // different values but we need some consistency.
- Allocation allocation;
- get_allocation (out allocation);
- int samples = allocation.width - LPAD - RPAD;
- if (samples > 0) {
- image = new ImageSurface (Format.RGB24, samples, BANDS);
- pipeline = new Pipeline (file_name, BANDS, samples, THRESHOLD, data_cb);
- pipeline.start ();
- info = pipeline.description;
- } else {
- image = null;
- pipeline = null;
- }
-
- queue_draw ();
- }
-
private int prev_width = -1;
protected override void size_allocate (Gdk.Rectangle allocation) {
base.size_allocate (allocation);
@@ -74,16 +48,6 @@ namespace Spek {
}
}
- private double log10_threshold = Math.log10 (-THRESHOLD);
- private void data_cb (int sample, float[] values) {
- for (int y = 0; y < BANDS; y++) {
- var level = double.min (
- 1.0, Math.log10 (1.0 - THRESHOLD + values[y]) / log10_threshold);
- put_pixel (image, sample, y, get_color (level));
- }
- Idle.add (() => { queue_draw (); return false; });
- }
-
protected override bool expose_event (EventExpose event) {
var window = get_window ();
var cr = cairo_create (window);