/* -*- 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 512 Player::Player() { 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 start(); } Player::~Player() { running = false; // Signal player thread to stop wait(); // Wait for player thread to stop. } #define _MIN(a, b) (a (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); } sample = pcm_data[p] * fade * gain_scalar; } if(fabs(sample) > peak) { peak = fabs(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; } void Player::setGainDB(double gain_db) { setGainScalar(pow(10, gain_db/ 20.0)); } void Player::reportTimeout() { emit peakUpdate(peak); emit peakUpdateDB(20 * log10(peak)); peak = 0.0; emit positionUpdate(pos); peak = 0.0; } void Player::setPcmData(float *data, size_t size) { pcm_data = data; pcm_size = size; } 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); }