diff options
-rw-r--r-- | dgedit/canvastoollisten.cc | 29 | ||||
-rw-r--r-- | dgedit/canvastoollisten.h | 1 | ||||
-rw-r--r-- | dgedit/mainwindow.cc | 28 | ||||
-rw-r--r-- | dgedit/mainwindow.h | 2 | ||||
-rw-r--r-- | dgedit/player.cc | 104 | ||||
-rw-r--r-- | dgedit/player.h | 27 | ||||
-rw-r--r-- | dgedit/selection.h | 8 |
7 files changed, 133 insertions, 66 deletions
diff --git a/dgedit/canvastoollisten.cc b/dgedit/canvastoollisten.cc index bd16b15..847c32d 100644 --- a/dgedit/canvastoollisten.cc +++ b/dgedit/canvastoollisten.cc @@ -39,7 +39,6 @@ bool CanvasToolListen::mousePressEvent(QMouseEvent *event) { if(!isActive()) return false; player.setPosition(canvas->unmapX(event->x())); - player.playing = true; canvas->update(); connect(&player, SIGNAL(positionUpdate(size_t)), this, SLOT(update(size_t))); return true; @@ -48,7 +47,7 @@ bool CanvasToolListen::mousePressEvent(QMouseEvent *event) bool CanvasToolListen::mouseReleaseEvent(QMouseEvent *event) { if(!isActive()) return false; - player.playing = false; + player.stop(); disconnect(&player, SIGNAL(positionUpdate(size_t)), this, SLOT(update(size_t))); lastpos = 0; @@ -60,7 +59,7 @@ void CanvasToolListen::paintEvent(QPaintEvent *event, QPainter &painter) { if(!isActive()) return; - if(player.playing) { + if(player.pos < player.end) { painter.setPen(QColor(0, 127, 127)); painter.drawLine(canvas->mapX(pos), event->rect().y(), @@ -80,27 +79,3 @@ void CanvasToolListen::update(size_t pos) canvas->update(r); lastpos = pos; } - -void CanvasToolListen::setVolume(int v) -{ - player.setGainScalar(v); -} - -/* - * UGLY HACK: This method is in dire need of a rewrite! - */ -#include <unistd.h> -void CanvasToolListen::playRange(unsigned int from, unsigned int to) -{ - player.pos = from; - player.playing = true; - canvas->update(); - connect(&player, SIGNAL(positionUpdate(size_t)), this, SLOT(update(size_t))); - while(player.pos < to) { - qApp->processEvents(); - usleep(10000); - } - disconnect(&player, SIGNAL(positionUpdate(size_t)), - this, SLOT(update(size_t))); - player.playing = false; -} diff --git a/dgedit/canvastoollisten.h b/dgedit/canvastoollisten.h index 810e7cb..bfb2d41 100644 --- a/dgedit/canvastoollisten.h +++ b/dgedit/canvastoollisten.h @@ -48,7 +48,6 @@ public: public slots: void update(size_t position); - void setVolume(int v); private: Canvas *canvas; diff --git a/dgedit/mainwindow.cc b/dgedit/mainwindow.cc index d573ff4..9f877bf 100644 --- a/dgedit/mainwindow.cc +++ b/dgedit/mainwindow.cc @@ -42,12 +42,12 @@ #include <QIntValidator> #include <QTabWidget> #include <QProgressBar> +#include <QTime> -#include <unistd.h> +//#include <unistd.h> #include "canvastool.h" #include "canvastoolthreshold.h" -#include "canvastoollisten.h" #include "volumefader.h" #include "selectioneditor.h" @@ -65,7 +65,6 @@ static void addTool(QToolBar *toolbar, Canvas *canvas, CanvasTool *tool) canvas->tools.push_back(tool); } -static CanvasToolListen *g_listen; MainWindow::MainWindow() { { @@ -84,8 +83,7 @@ MainWindow::MainWindow() canvas = new Canvas(this); QToolBar *toolbar = addToolBar("Tools"); - g_listen = new CanvasToolListen(canvas, player); - CanvasTool *listen = g_listen; + listen = new CanvasToolListen(canvas, player); addTool(toolbar, canvas, listen); threshold = new CanvasToolThreshold(canvas); canvas->tools.push_back(threshold);//addTool(toolbar, canvas, threshold); @@ -426,8 +424,6 @@ void MainWindow::setVolumeLineEd(int value) void MainWindow::playSamples() { - //unsigned int length = 44100 / 4; // 0.25 seconds in 44k1Hz - QVector<sel_id_t> ids = selections.ids(); for(int v1 = 0; v1 < ids.size(); v1++) { for(int v2 = 0; v2 < ids.size(); v2++) { @@ -452,15 +448,25 @@ void MainWindow::playSamples() unsigned int sample_length = sel.to - sel.from; unsigned int to = sel.to; - unsigned int sleep = 0; if(sample_length > length) to = sel.from + length; - else sleep = length - sample_length; selections.setActive(*i); - g_listen->playRange(sel.from, to); - usleep(1000000 * sleep / 44100); + connect(&player, SIGNAL(positionUpdate(size_t)), + listen, SLOT(update(size_t))); + + player.playSelection(sel, to - sel.from); + QTime t; + t.start(); + while(t.elapsed() < sb_playsamples->value()) { + qApp->processEvents(); + usleep(25 * 1000); + } + player.stop(); + + disconnect(&player, SIGNAL(positionUpdate(size_t)), + listen, SLOT(update(size_t))); i++; } } diff --git a/dgedit/mainwindow.h b/dgedit/mainwindow.h index 620c116..6fef5db 100644 --- a/dgedit/mainwindow.h +++ b/dgedit/mainwindow.h @@ -40,6 +40,7 @@ #include "filelist.h" #include "canvastoolselections.h" #include "canvastoolthreshold.h" +#include "canvastoollisten.h" #include "selection.h" #include "player.h" @@ -88,6 +89,7 @@ private: Canvas *canvas; CanvasToolSelections *tool_selections; CanvasToolThreshold *threshold; + CanvasToolListen *listen; AudioExtractor *extractor; FileList *filelist; QScrollBar *yoffset; diff --git a/dgedit/player.cc b/dgedit/player.cc index baaf975..745052e 100644 --- a/dgedit/player.cc +++ b/dgedit/player.cc @@ -28,17 +28,17 @@ #include <math.h> -#define BUFSZ 1024 * 2 +#define BUFSZ 512 Player::Player() { - playing = false; - peak = 0; pos = 0; gain_scalar = 1.0; pcm_data = NULL; pcm_size = 0; + end = 0; + new_selection = false; connect(&report_timer, SIGNAL(timeout()), this, SLOT(reportTimeout())); report_timer.start(50); // Update 25 times per second @@ -52,8 +52,11 @@ Player::~Player() wait(); // Wait for player thread to stop. } +#define _MIN(a, b) (a<b?a:b) void Player::run() { + Selection sel; + ao_initialize(); ao_sample_format sf; @@ -69,31 +72,75 @@ void Player::run() short s[BUFSZ]; while(running) { - if(playing) { - for(size_t i = 0; i < BUFSZ; i++) { - double sample = 0.0; - if(i + pos < pcm_size) { - sample = pcm_data[pos + i] * gain_scalar; - } else { - playing = false; - } - if(abs(sample) > peak) peak = abs(sample); - s[i] = sample * SHRT_MAX; + + { // Check for new Selection. + QMutexLocker lock(&mutex); + if(new_selection) { + sel = selection; + pos = sel.from; + end = sel_end; + new_selection = false; } + } - ao_play(dev, (char*)s, BUFSZ * sizeof(short)); + for(size_t i = 0; i < BUFSZ; i++) { + double sample = 0.0; + size_t p = i + pos; + if(p < sel.to && p < end && p < pcm_size) { + double fade = 1; + if(p < (sel.from + sel.fadein)) { + // Apply linear fade-in + double fp = p - sel.from; + fade = fp / (double)sel.fadeout; + } - pos += BUFSZ; + if(p > (sel.to - sel.fadeout)) { + // Apply linear fade-out + double fp = (double)(((int)sel.to - (int)sel.fadeout) - (int)p); + fade = 1 + (fp / (double)sel.fadeout); + } - } else { - msleep(22); + sample = pcm_data[p] * fade * gain_scalar; + } + if(abs(sample) > peak) peak = abs(sample); + s[i] = _MIN(sample * SHRT_MAX, SHRT_MAX); } + + ao_play(dev, (char*)s, BUFSZ * sizeof(short)); + + pos += BUFSZ; } ao_close(dev); ao_shutdown(); } +bool Player::playSelectionDone() +{ + return pos >= sel_end || pos >= selection.to; +} + +void Player::playSelection(Selection s, int len) +{ + { // Enqueue new Selection for player consumation + QMutexLocker lock(&mutex); + + selection = s; + + if(len > 0) sel_end = len; + else sel_end = selection.to - selection.from; + + sel_end += selection.from; + + new_selection = true; + } + + // Wait until player actually consumed the new Selection. + while(new_selection) { + msleep(1); + } +} + void Player::setGainScalar(double g) { gain_scalar = g; @@ -120,7 +167,22 @@ void Player::setPcmData(float *data, size_t size) pcm_size = size; } - void Player::setPosition(size_t position) - { - pos = position; - } +void Player::setPosition(size_t position) +{ + Selection s; + s.from = position; + s.to = pcm_size; + s.fadein = 0; + s.fadeout = 0; + playSelection(s); +} + +void Player::stop() +{ + Selection s; + s.from = 0; + s.to = 0; + s.fadein = 0; + s.fadeout = 0; + playSelection(s, pos); +} diff --git a/dgedit/player.h b/dgedit/player.h index 2977103..60b2ccb 100644 --- a/dgedit/player.h +++ b/dgedit/player.h @@ -29,10 +29,11 @@ #include <QThread> #include <QTimer> +#include <QMutex> #include <ao/ao.h> -#include "canvas.h" +#include "selection.h" class Player : public QThread { Q_OBJECT @@ -45,8 +46,9 @@ public: // TODO: Make these private. // These two need to be public in order for the ugly hack in // CanvasToolListen::playRange to work... - volatile bool playing; + // volatile bool playing; volatile size_t pos; + volatile size_t end; public slots: /** @@ -72,6 +74,22 @@ public slots: */ void setPosition(size_t position); + /** + * Play range based on selection including fade-in/out. + * @param length Stop playing after length samples. -1 means play all. + */ + void playSelection(Selection selection, int length = -1); + + /** + * Return true if last selection is done playing. + */ + bool playSelectionDone(); + + /** + * Stop playing + */ + void stop(); + signals: /** * The absolute maximum of samples seen since last update. @@ -103,6 +121,11 @@ private: double peak; bool running; + + QMutex mutex; + volatile bool new_selection; + size_t sel_end; + Selection selection; }; #endif/*__DRUMGIZMO_PLAYER_H__*/ diff --git a/dgedit/selection.h b/dgedit/selection.h index 08b897b..c6c7ecc 100644 --- a/dgedit/selection.h +++ b/dgedit/selection.h @@ -40,10 +40,10 @@ public: this->fadein = fadein; this->fadeout = fadeout; } - int from; - int to; - int fadein; - int fadeout; + size_t from; + size_t to; + size_t fadein; + size_t fadeout; double energy; |