diff options
author | Bent Bisballe Nyeng <deva@aasimon.org> | 2014-04-18 13:16:03 +0200 |
---|---|---|
committer | Bent Bisballe Nyeng <deva@aasimon.org> | 2014-04-18 13:16:03 +0200 |
commit | 68e4647e565519c57d76b95806dd9431a4ecfbb1 (patch) | |
tree | e7868dfa39dc886d21967dd6766072067d37636c /dgedit/player.cc | |
parent | 11b8e6db937f4c77942febb69f7b41e87ae0b6e0 (diff) |
New player model (again).
Diffstat (limited to 'dgedit/player.cc')
-rw-r--r-- | dgedit/player.cc | 104 |
1 files changed, 83 insertions, 21 deletions
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); +} |