From 12b62ca84abab622889363b9b9f3215d52eb5167 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Tue, 15 Apr 2014 12:18:12 +0200 Subject: Player interface changes. Player moved to MainWindow for easier component sharing. --- dgedit/canvastoollisten.cc | 87 ++++++++----------------------------- dgedit/canvastoollisten.h | 33 +++----------- dgedit/mainwindow.cc | 10 ++++- dgedit/mainwindow.h | 3 ++ dgedit/player.cc | 106 +++++++++++++++++++++++++++++++++++++++++++++ dgedit/player.h | 82 +++++++++++++++++++++++++++++++++++ 6 files changed, 224 insertions(+), 97 deletions(-) create mode 100644 dgedit/player.cc create mode 100644 dgedit/player.h diff --git a/dgedit/canvastoollisten.cc b/dgedit/canvastoollisten.cc index 569a164..f842235 100644 --- a/dgedit/canvastoollisten.cc +++ b/dgedit/canvastoollisten.cc @@ -28,78 +28,19 @@ #include -#define BUFSZ 1024 * 2 - -Player::Player(Canvas *c) -{ - canvas = c; - playing = false; - pos = 0; - - ao_initialize(); - - ao_sample_format sf; - sf.bits = 16; - sf.rate = 44100; - sf.channels = 1; - sf.byte_format = AO_FMT_NATIVE; - - dev = ao_open_live(ao_default_driver_id(), &sf, 0); - - volume = 1000; -} - -Player::~Player() -{ - ao_close(dev); - ao_shutdown(); -} - -void Player::run() -{ - while(true) { - if(playing) { - short s[BUFSZ]; - for(size_t i = 0; i < BUFSZ; i++) { - if(i + pos < canvas->size) s[i] = canvas->data[pos + i] * volume; - else { - s[i] = 0; - playing = false; - } - } - - ao_play(dev, (char*)s, BUFSZ * sizeof(short)); - // canvas->update(); - - pos += BUFSZ; - - } else { - msleep(22); - } - } -} - -void Player::setVolume(double v) +CanvasToolListen::CanvasToolListen(Canvas *c, Player &p) + : player(p) { - volume = v; -} - -CanvasToolListen::CanvasToolListen(Canvas *c) - : player(c) -{ - lastpos = 0; + lastpos = pos = 0; canvas = c ; - player.start(); - QObject::connect(&timer, SIGNAL(timeout()), this, SLOT(update())); } bool CanvasToolListen::mousePressEvent(QMouseEvent *event) { if(!isActive()) return false; - player.pos = canvas->unmapX(event->x()); player.playing = true; canvas->update(); - timer.start(50); + connect(&player, SIGNAL(positionUpdate(size_t)), this, SLOT(update(size_t))); return true; } @@ -107,7 +48,8 @@ bool CanvasToolListen::mouseReleaseEvent(QMouseEvent *event) { if(!isActive()) return false; player.playing = false; - timer.stop(); + disconnect(&player, SIGNAL(positionUpdate(size_t)), + this, SLOT(update(size_t))); lastpos = 0; canvas->update(); return true; @@ -119,16 +61,16 @@ void CanvasToolListen::paintEvent(QPaintEvent *event, QPainter &painter) if(player.playing) { painter.setPen(QColor(0, 127, 127)); - painter.drawLine(canvas->mapX(player.pos), + painter.drawLine(canvas->mapX(pos), event->rect().y(), - canvas->mapX(player.pos), + canvas->mapX(pos), event->rect().y() + event->rect().height()); } } -void CanvasToolListen::update() +void CanvasToolListen::update(size_t pos) { - size_t pos = player.pos; + this->pos = pos; size_t last = canvas->mapX(lastpos); size_t x = canvas->mapX(player.pos); QRect r(last, 0, @@ -140,19 +82,24 @@ void CanvasToolListen::update() void CanvasToolListen::setVolume(int v) { - player.setVolume(v); + player.setGainScalar(v); } +/* + * UGLY HACK: This method is in dire need of a rewrite! + */ #include void CanvasToolListen::playRange(unsigned int from, unsigned int to) { player.pos = from; player.playing = true; canvas->update(); - timer.start(50); + 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 dccc3f9..810e7cb 100644 --- a/dgedit/canvastoollisten.h +++ b/dgedit/canvastoollisten.h @@ -29,35 +29,15 @@ #include "canvastool.h" -#include -#include - -#include +//#include #include "canvas.h" - -class Player : public QThread { -public: - Player(Canvas *canvas); - ~Player(); - - void run(); - - volatile bool playing; - volatile size_t pos; - - void setVolume(double v); - -private: - ao_device *dev; - Canvas *canvas; - double volume; -}; +#include "player.h" class CanvasToolListen : public CanvasTool { Q_OBJECT public: - CanvasToolListen(Canvas *canvas); + CanvasToolListen(Canvas *canvas, Player &player); QString name() { return "Listen"; } bool mousePressEvent(QMouseEvent *event); @@ -67,15 +47,16 @@ public: void playRange(unsigned int from, unsigned int to); public slots: - void update(); + void update(size_t position); void setVolume(int v); private: Canvas *canvas; - Player player; - QTimer timer; + Player &player; + size_t lastpos; + size_t pos; }; #endif/*__DRUMGIZMO_CANVASTOOLLISTEN_H__*/ diff --git a/dgedit/mainwindow.cc b/dgedit/mainwindow.cc index 412cd32..82eaaa6 100644 --- a/dgedit/mainwindow.cc +++ b/dgedit/mainwindow.cc @@ -73,8 +73,11 @@ MainWindow::MainWindow() extractor = new AudioExtractor(session, this); canvas = new Canvas(this); + player = new Player(canvas); + player->start(); + QToolBar *toolbar = addToolBar("Tools"); - g_listen = new CanvasToolListen(canvas); + g_listen = new CanvasToolListen(canvas, *player); CanvasTool *listen = g_listen; addTool(toolbar, canvas, listen); CanvasTool *threshold = new CanvasToolThreshold(canvas); @@ -298,6 +301,11 @@ MainWindow::MainWindow() statusBar()->showMessage("Ready"); } +MainWindow::~MainWindow() +{ + delete player; +} + void MainWindow::setAttackLengthLineEd(int value) { lineed_attacklength->setText(QString::number(value)); diff --git a/dgedit/mainwindow.h b/dgedit/mainwindow.h index 6758779..ccb2f07 100644 --- a/dgedit/mainwindow.h +++ b/dgedit/mainwindow.h @@ -40,6 +40,7 @@ #include "filelist.h" #include "canvastoolselections.h" #include "selection.h" +#include "player.h" class Preset { public: @@ -54,6 +55,7 @@ class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); + ~MainWindow(); public slots: void setXScale(int); @@ -96,6 +98,7 @@ private: // Session state information: Selections session; + Player *player; private slots: void setAttackLengthLineEd(int); diff --git a/dgedit/player.cc b/dgedit/player.cc new file mode 100644 index 0000000..a7f09c3 --- /dev/null +++ b/dgedit/player.cc @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * player.cc + * + * Tue Apr 15 10:34:18 CEST 2014 + * Copyright 2014 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "player.h" + +#include + +#define BUFSZ 1024 * 2 + +Player::Player(Canvas *c) +{ + canvas = c; + playing = false; + pos = 0; + + ao_initialize(); + + ao_sample_format sf; + sf.bits = 16; + sf.rate = 44100; + sf.channels = 1; + sf.byte_format = AO_FMT_NATIVE; + + dev = ao_open_live(ao_default_driver_id(), &sf, 0); + + gain_scalar = 1000; + + peak = 0; + + connect(&report_timer, SIGNAL(timeout()), this, SLOT(reportTimeout())); + report_timer.start(50); // Update 25 times per second +} + +Player::~Player() +{ + ao_close(dev); + ao_shutdown(); +} + +void Player::run() +{ + short s[BUFSZ]; + while(true) { + if(playing) { + for(size_t i = 0; i < BUFSZ; i++) { + double sample = 0.0; + if(i + pos < canvas->size) { + sample = canvas->data[pos + i] * gain_scalar; + } else { + playing = false; + } + if(abs(sample) > peak) peak = abs(sample); + s[i] = sample * SHRT_MAX; + } + + ao_play(dev, (char*)s, BUFSZ * sizeof(short)); + + pos += BUFSZ; + + } else { + msleep(22); + } + } +} + +void Player::setGainScalar(double g) +{ + gain_scalar = g / 10000.0; +} + +void Player::setGainDB(double gain_db) +{ + setGainScalar(20*log10(gain_db)); +} + +void Player::reportTimeout() +{ + emit peakUpdate(peak); + peak = 0.0; + + emit positionUpdate(pos); + peak = 0.0; +} diff --git a/dgedit/player.h b/dgedit/player.h new file mode 100644 index 0000000..af278f5 --- /dev/null +++ b/dgedit/player.h @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * player.h + * + * Tue Apr 15 10:34:18 CEST 2014 + * Copyright 2014 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_PLAYER_H__ +#define __DRUMGIZMO_PLAYER_H__ + +#include +#include + +#include + +#include "canvas.h" + +class Player : public QThread { +Q_OBJECT +public: + Player(Canvas *canvas); // TODO: Don't use canvas pointer here. Instead introduce setData slot or similar. + ~Player(); + + void run(); + + // 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 size_t pos; + +public slots: + /** + * Set gain scalar. + * This value is multiplied with each sample before it is played. + */ + void setGainScalar(double gain_scalar); + + /** + * Set gain is dB. + * Convenience method for setGainScalar. It simple recalculates the dB value + * to a scalar and sets the gain scalar accordingly. + */ + void setGainDB(double gain_db); + +signals: + void peakUpdate(double peak); + void positionUpdate(size_t position); + +private slots: + void reportTimeout(); + +private: + ao_device *dev; + Canvas *canvas; + + QTimer report_timer; + + double gain_scalar; + double peak; +}; + +#endif/*__DRUMGIZMO_PLAYER_H__*/ -- cgit v1.2.3