mirror of
https://github.com/alexkay/spek.git
synced 2025-04-19 09:57:41 +03:00
Run the pipeline
This commit is contained in:
parent
4df42e8258
commit
f81ce84826
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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()
|
||||
};
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user