summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2014-04-18 13:16:03 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2014-04-18 13:16:03 +0200
commit68e4647e565519c57d76b95806dd9431a4ecfbb1 (patch)
treee7868dfa39dc886d21967dd6766072067d37636c
parent11b8e6db937f4c77942febb69f7b41e87ae0b6e0 (diff)
New player model (again).
-rw-r--r--dgedit/canvastoollisten.cc29
-rw-r--r--dgedit/canvastoollisten.h1
-rw-r--r--dgedit/mainwindow.cc28
-rw-r--r--dgedit/mainwindow.h2
-rw-r--r--dgedit/player.cc104
-rw-r--r--dgedit/player.h27
-rw-r--r--dgedit/selection.h8
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;