added initial FX-mixer implementation - not perfect and very usable yet but the basics work so far

git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@789 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
Tobias Doerffel
2008-03-14 21:45:10 +00:00
parent a4f3d5d267
commit b682b30146
17 changed files with 864 additions and 67 deletions

View File

@@ -40,9 +40,9 @@ audioPort::audioPort( const QString & _name, track * _track ) :
m_secondBuffer( new surroundSampleFrame[
engine::getMixer()->framesPerPeriod()] ),
m_extOutputEnabled( FALSE ),
m_nextFxChannel( -1 ),
m_nextFxChannel( 0 ),
m_name( "unnamed port" ),
m_effects( this, _track ),
m_effects( _track ),
m_frames( engine::getMixer()->framesPerPeriod() )
{
engine::getMixer()->clearAudioBuffer( m_firstBuffer,

View File

@@ -33,9 +33,8 @@
effectChain::effectChain( audioPort * _port, track * _track ) :
effectChain::effectChain( track * _track ) :
model( /*_track*/ NULL ),
m_port( _port ),
m_track( _track ),
m_enabledModel( FALSE, FALSE, TRUE )
{

View File

@@ -29,6 +29,7 @@
#include "automation_editor.h"
#include "bb_editor.h"
#include "config_mgr.h"
#include "fx_mixer.h"
#include "ladspa_2_lmms.h"
#include "main_window.h"
#include "mixer.h"
@@ -44,6 +45,8 @@
bool engine::s_hasGUI = TRUE;
float engine::s_framesPerTact64th;
mixer * engine::s_mixer = NULL;
fxMixer * engine::s_fxMixer = NULL;
fxMixerView * engine::s_fxMixerView = NULL;
mainWindow * engine::s_mainWindow = NULL;
bbTrackContainer * engine::s_bbTrackContainer = NULL;
song * engine::s_song = NULL;
@@ -67,12 +70,14 @@ void engine::init( const bool _has_gui )
s_projectJournal = new projectJournal;
s_mixer = new mixer;
s_fxMixer = new fxMixer;
s_song = new song;
s_bbTrackContainer = new bbTrackContainer;
if( s_hasGUI )
{
s_mainWindow = new mainWindow;
s_fxMixerView = new fxMixerView;
s_songEditor = new songEditor( s_song );
s_projectNotes = new projectNotes;
s_bbEditor = new bbEditor( s_bbTrackContainer );

402
src/core/fx_mixer.cpp Normal file
View File

@@ -0,0 +1,402 @@
#ifndef SINGLE_SOURCE_COMPILE
/*
* fx_mixer.cpp - effect-mixer for LMMS
*
* Copyright (c) 2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* This program 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.
*
* This program 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 this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#include <QtGui/QInputDialog>
#include <QtGui/QLayout>
#include <QtGui/QMdiArea>
#include <QtGui/QPainter>
#include <QtGui/QScrollArea>
#include <QtGui/QScrollBar>
#include "fx_mixer.h"
#include "fader.h"
#include "effect_chain.h"
#include "effect_rack_view.h"
#include "embed.h"
#include "main_window.h"
#include "lcd_spinbox.h"
#include "gui_templates.h"
struct fxChannel
{
fxChannel( model * _parent ) :
m_fxChain( NULL ),
m_used( FALSE ),
m_peakLeft( 0.0f ),
m_peakRight( 0.0f ),
m_buffer( new surroundSampleFrame[
engine::getMixer()->framesPerPeriod()] ),
m_muteModel( FALSE, _parent ),
m_soloModel( FALSE, _parent ),
m_volumeModel( 1.0, 0.0, 2.0, 0.01, _parent ),
m_lock()
{
engine::getMixer()->clearAudioBuffer( m_buffer,
engine::getMixer()->framesPerPeriod() );
}
effectChain m_fxChain;
bool m_used;
float m_peakLeft;
float m_peakRight;
surroundSampleFrame * m_buffer;
boolModel m_muteModel;
boolModel m_soloModel;
floatModel m_volumeModel;
QMutex m_lock;
} ;
fxMixer::fxMixer() :
journallingObject(),
model( NULL )
{
for( int i = 0; i < NUM_FX_CHANNELS+1; ++i )
{
m_fxChannels[i] = new fxChannel( this );
}
}
fxMixer::~fxMixer()
{
}
void fxMixer::mixToChannel( const surroundSampleFrame * _buf, fx_ch_t _ch )
{
surroundSampleFrame * buf = m_fxChannels[_ch]->m_buffer;
for( f_cnt_t f = 0; f < engine::getMixer()->framesPerPeriod(); ++f )
{
buf[f][0] += _buf[f][0];
buf[f][1] += _buf[f][1];
}
m_fxChannels[_ch]->m_used = TRUE;
}
void fxMixer::processChannel( fx_ch_t _ch )
{
if( m_fxChannels[_ch]->m_used || _ch == 0 )
{
const fpp_t f = engine::getMixer()->framesPerPeriod();
m_fxChannels[_ch]->m_fxChain.startRunning();
m_fxChannels[_ch]->m_fxChain.processAudioBuffer(
m_fxChannels[_ch]->m_buffer, f );
m_fxChannels[_ch]->m_peakLeft = engine::getMixer()->peakValueLeft( m_fxChannels[_ch]->m_buffer, f ) * m_fxChannels[_ch]->m_volumeModel.value();
m_fxChannels[_ch]->m_peakRight = engine::getMixer()->peakValueRight( m_fxChannels[_ch]->m_buffer, f ) * m_fxChannels[_ch]->m_volumeModel.value();
}
else
{
m_fxChannels[_ch]->m_peakLeft =
m_fxChannels[_ch]->m_peakRight = 0.0f;
}
}
void fxMixer::prepareMasterMix( void )
{
engine::getMixer()->clearAudioBuffer( m_fxChannels[0]->m_buffer,
engine::getMixer()->framesPerPeriod() );
}
const surroundSampleFrame * fxMixer::masterMix( void )
{
surroundSampleFrame * buf = m_fxChannels[0]->m_buffer;
for( int i = 1; i < NUM_FX_CHANNELS+1; ++i )
{
if( m_fxChannels[i]->m_used )
{
surroundSampleFrame * _buf = m_fxChannels[i]->m_buffer;
for( f_cnt_t f = 0; f <
engine::getMixer()->framesPerPeriod(); ++f )
{
buf[f][0] += _buf[f][0]*m_fxChannels[i]->m_volumeModel.value();
buf[f][1] += _buf[f][1]*m_fxChannels[i]->m_volumeModel.value();
}
engine::getMixer()->clearAudioBuffer( _buf,
engine::getMixer()->framesPerPeriod() );
m_fxChannels[i]->m_used = FALSE;
}
}
processChannel( 0 );
for( f_cnt_t f = 0; f < engine::getMixer()->framesPerPeriod(); ++f )
{
buf[f][0] *= m_fxChannels[0]->m_volumeModel.value();
buf[f][1] *= m_fxChannels[0]->m_volumeModel.value();
}
m_fxChannels[0]->m_peakLeft *= engine::getMixer()->masterGain();
m_fxChannels[0]->m_peakRight *= engine::getMixer()->masterGain();
return( buf );
}
void fxMixer::saveSettings( QDomDocument & _doc, QDomElement & _this )
{
/* m_chordsEnabledModel.saveSettings( _doc, _this, "chord-enabled" );
m_chordsModel.saveSettings( _doc, _this, "chord" );
m_chordRangeModel.saveSettings( _doc, _this, "chordrange" );*/
}
void fxMixer::loadSettings( const QDomElement & _this )
{
/* m_chordsEnabledModel.loadSettings( _this, "chord-enabled" );
m_chordsModel.loadSettings( _this, "chord" );
m_chordRangeModel.loadSettings( _this, "chordrange" );*/
}
class fxLine : public QWidget
{
public:
fxLine( QWidget * _parent, fxMixerView * _mv ) :
QWidget( _parent ),
m_mv( _mv )
{
setFixedSize( 32, 200 );
setAttribute( Qt::WA_OpaquePaintEvent, TRUE );
}
virtual void setName( const QString & _name )
{
m_name = _name;
}
virtual void paintEvent( QPaintEvent * )
{
QPainter p( this );
p.fillRect( rect(), QColor( 72, 76, 88 ) );
/* p.setPen( QColor( 144, 152, 176 ) );
p.drawLine( 0, 0, width()-1, 0 );
p.drawLine( 0, 0, 0, height()-1 );
p.setPen( QColor( 36, 38, 44 ) );
p.drawLine( 0, height()-1, width()-1, height()-1 );
p.drawLine( width()-1, 0, width()-1, height()-1 );*/
p.setPen( QColor( 40, 42, 48 ) );
p.drawRect( 0, 0, width()-2, height()-2 );
p.setPen( QColor( 108, 114, 132 ) );
p.drawRect( 1, 1, width()-2, height()-2 );
p.setPen( QColor( 20, 24, 32 ) );
p.drawRect( 0, 0, width()-1, height()-1 );
p.rotate( -90 );
p.setPen( m_mv->currentFxLine() == this ?
QColor( 0, 255, 0 ) : Qt::white );
p.setFont( pointSizeF( font(), 7.5f ) );
p.drawText( -70, 20, m_name );
}
virtual void mousePressEvent( QMouseEvent * )
{
m_mv->setCurrentFxLine( this );
}
virtual void mouseDoubleClickEvent( QMouseEvent * )
{
bool ok;
QString new_name = QInputDialog::getText( this,
fxMixerView::tr( "Rename FX channel" ),
fxMixerView::tr( "Enter the new name for this "
"FX channel" ),
QLineEdit::Normal, m_name, &ok );
if( ok && !new_name.isEmpty() )
{
m_name = new_name;
update();
}
}
private:
fxMixerView * m_mv;
QString m_name;
} ;
fxMixerView::fxMixerView() :
QWidget(),
modelView( NULL )
{
fxMixer * m = engine::getFxMixer();
QPalette pal = palette();
pal.setColor( QPalette::Background, QColor( 72, 76, 88 ) );
setPalette( pal );
setAutoFillBackground( TRUE );
// setFixedHeight( 250+216 );
setWindowTitle( tr( "FX-Mixer" ) );
// setWindowIcon( embed::getIconPixmap( "fxmixer" ) );
engine::getMainWindow()->workspace()->addSubWindow( this );
parentWidget()->setAttribute( Qt::WA_DeleteOnClose, FALSE );
QVBoxLayout * ml = new QVBoxLayout( this );
ml->setMargin( 0 );
ml->setSpacing( 0 );
QScrollArea * a = new QScrollArea( this );
a->setFrameShape( QFrame::NoFrame );
a->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
a->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
a->setFixedHeight( 216 );
ml->addWidget( a );
m_fxRackArea = new QWidget( this );
m_fxRackArea->setFixedHeight( 250 );
ml->addWidget( m_fxRackArea );
ml->addStretch();
QWidget * base = new QWidget;
QHBoxLayout * bl = new QHBoxLayout( base );
bl->setSpacing( 0 );
bl->setMargin( 0 );
a->setWidget( base );
base->setFixedSize( (NUM_FX_CHANNELS+1)*33+6+10, 200 );
pal = base->palette();
pal.setColor( QPalette::Background, QColor( 72, 76, 88 ) );
base->setPalette( pal );
base->setAutoFillBackground( TRUE );
bl->addSpacing( 6 );
for( int i = 0; i < NUM_FX_CHANNELS+1; ++i )
{
fxChannelView * cv = &m_fxChannelViews[i];
cv->m_fxLine = new fxLine( base, this );
bl->addWidget( cv->m_fxLine );
if( i == 0 )
{
bl->addSpacing( 10 );
cv->m_fxLine->setName( tr( "Master" ).arg( i ) );
}
else
{
bl->addSpacing( 1 );
cv->m_fxLine->setName( tr( "FX %1" ).arg( i ) );
}
lcdSpinBox * l = new lcdSpinBox( 2, cv->m_fxLine );
l->model()->setRange( i, i );
l->model()->setValue( i );
l->update();
cv->m_fader = new fader( &m->m_fxChannels[i]->m_volumeModel,
cv->m_fxLine );
cv->m_fader->move( 15-cv->m_fader->width()/2, 80 );
cv->m_rackView = new effectRackView(
&m->m_fxChannels[i]->m_fxChain, m_fxRackArea );
cv->m_rackView->setFixedSize( 250, 250 );
}
show();
setCurrentFxLine( m_fxChannelViews[0].m_fxLine );
QTimer * t = new QTimer( this );
connect( t, SIGNAL( timeout() ), this, SLOT( updateFaders() ) );
t->start( 50 );
}
fxMixerView::~fxMixerView()
{
}
void fxMixerView::setCurrentFxLine( fxLine * _line )
{
m_currentFxLine = _line;
for( int i = 0; i < NUM_FX_CHANNELS+1; ++i )
{
if( m_fxChannelViews[i].m_fxLine == _line )
{
m_fxChannelViews[i].m_rackView->show();
}
else
{
m_fxChannelViews[i].m_rackView->hide();
}
m_fxChannelViews[i].m_fxLine->update();
}
}
void fxMixerView::updateFaders( void )
{
fxMixer * m = engine::getFxMixer();
for( int i = 0; i < NUM_FX_CHANNELS+1; ++i )
{
const float opl = m_fxChannelViews[i].m_fader->getPeak_L();
const float opr = m_fxChannelViews[i].m_fader->getPeak_R();
const float fall_off = 1.1;
if( m->m_fxChannels[i]->m_peakLeft > opl )
{
m_fxChannelViews[i].m_fader->setPeak_L(
m->m_fxChannels[i]->m_peakLeft );
}
else
{
m_fxChannelViews[i].m_fader->setPeak_L( opl/fall_off );
}
if( m->m_fxChannels[i]->m_peakRight > opr )
{
m_fxChannelViews[i].m_fader->setPeak_R(
m->m_fxChannels[i]->m_peakRight );
}
else
{
m_fxChannelViews[i].m_fader->setPeak_R( opr/fall_off );
}
}
}
#include "fx_mixer.moc"
#endif

View File

@@ -31,6 +31,7 @@
#include <math.h>
#include "mixer.h"
#include "fx_mixer.h"
#include "play_handle.h"
#include "song.h"
#include "templates.h"
@@ -495,6 +496,7 @@ const surroundSampleFrame * mixer::renderNextBuffer( void )
//printf("---------------------------next period\n");
// if( criticalXRuns() == FALSE )
{
engine::getFxMixer()->prepareMasterMix();
engine::getSong()->processNextBuffer();
lockPlayHandles();
@@ -605,6 +607,14 @@ if( COND_NPH )
}
}
}
for( int i = 1; i < NUM_FX_CHANNELS+1; ++i )
{
engine::getFxMixer()->processChannel( i );
}
const surroundSampleFrame * buf =
engine::getFxMixer()->masterMix();
memcpy( m_writeBuf, buf, m_framesPerPeriod *
sizeof( surroundSampleFrame ) );
}
unlock();
@@ -647,26 +657,6 @@ void mixer::clear( void )
void FASTCALL mixer::clearAudioBuffer( sampleFrame * _ab,
const f_cnt_t _frames,
const f_cnt_t _offset )
{
memset( _ab+_offset, 0, sizeof( *_ab ) * _frames );
}
#ifndef DISABLE_SURROUND
void FASTCALL mixer::clearAudioBuffer( surroundSampleFrame * _ab,
const f_cnt_t _frames,
const f_cnt_t _offset )
{
memset( _ab+_offset, 0, sizeof( *_ab ) * _frames );
}
#endif
void FASTCALL mixer::bufferToPort( const sampleFrame * _buf,
const fpp_t _frames,
const f_cnt_t _offset,
@@ -721,6 +711,59 @@ void FASTCALL mixer::bufferToPort( const sampleFrame * _buf,
void FASTCALL mixer::clearAudioBuffer( sampleFrame * _ab,
const f_cnt_t _frames,
const f_cnt_t _offset )
{
memset( _ab+_offset, 0, sizeof( *_ab ) * _frames );
}
#ifndef DISABLE_SURROUND
void FASTCALL mixer::clearAudioBuffer( surroundSampleFrame * _ab,
const f_cnt_t _frames,
const f_cnt_t _offset )
{
memset( _ab+_offset, 0, sizeof( *_ab ) * _frames );
}
#endif
float mixer::peakValueLeft( surroundSampleFrame * _ab, const f_cnt_t _frames )
{
float p = 0.0f;
for( f_cnt_t f = 0; f < _frames; ++f )
{
if( _ab[f][0] > p )
{
p = _ab[f][0];
}
}
return( p );
}
float mixer::peakValueRight( surroundSampleFrame * _ab, const f_cnt_t _frames )
{
float p = 0.0f;
for( f_cnt_t f = 0; f < _frames; ++f )
{
if( _ab[f][1] > p )
{
p = _ab[f][1];
}
}
return( p );
}
void mixer::setHighQuality( bool _hq_on )
{
// don't delete the audio-device
@@ -954,8 +997,7 @@ midiClient * mixer::tryMIDIClients( void )
void mixer::processBuffer( const surroundSampleFrame * _buf,
fx_ch_t/* _fx_chnl */ )
void mixer::processBuffer( const surroundSampleFrame * _buf, fx_ch_t _fx_chnl )
{
// TODO: process according effect-channel
@@ -968,22 +1010,7 @@ void mixer::processBuffer( const surroundSampleFrame * _buf,
m_newBuffer[chnl] = TRUE;
}
}*/
static QMutex m;
m.lock();
for( fpp_t frame = 0; frame < m_framesPerPeriod; ++frame )
{
for( ch_cnt_t chnl = 0; chnl < m_audioDev->channels(); ++chnl )
{
m_writeBuf[frame][chnl] += _buf[frame][chnl];
/*
if( m_scaleClip )
{
scaleClip( frame, chnl );
}*/
}
}
m.unlock();
engine::getFxMixer()->mixToChannel( _buf, _fx_chnl );
}

View File

@@ -108,7 +108,7 @@ instrumentTrack::instrumentTrack( trackContainer * _tc ) :
m_volumeModel( DEFAULT_VOLUME, MIN_VOLUME, MAX_VOLUME,
1.0f, this ),
m_surroundAreaModel( this, this ),
m_effectChannelModel( 1, 1, NUM_FX_CHANNELS, 1, this ),
m_effectChannelModel( 0, 0, NUM_FX_CHANNELS, 1, this ),
m_instrument( NULL ),
m_soundShaping( this ),
m_arpeggiator( this ),
@@ -189,6 +189,7 @@ void instrumentTrack::processAudioBuffer( sampleFrame * _buf,
}
volumeVector v = m_surroundAreaModel.getVolumeVector( v_scale );
m_audioPort.setNextFxChannel( m_effectChannelModel.value() );
engine::getMixer()->bufferToPort( _buf,
( _n != NULL ) ? tMin<f_cnt_t>(
_n->framesLeftForCurrentPeriod(), _frames ) :
@@ -1162,8 +1163,8 @@ void instrumentTrackWindow::modelChanged( void )
this, SLOT( updateInstrumentView() ),
Qt::QueuedConnection );
m_volumeKnob->setModel( &m_track->m_volumeModel );
m_volumeKnob->setModel( &m_track->m_volumeModel );
m_surroundArea->setModel( &m_track->m_surroundAreaModel );
m_effectChannelNumber->setModel( &m_track->m_effectChannelModel );
m_pianoView->setModel( &m_track->m_piano );
m_ssView->setModel( &m_track->m_soundShaping );

220
src/widgets/fader.cpp Normal file
View File

@@ -0,0 +1,220 @@
/*
* fader.cpp - fader-widget used in mixer - partly taken from Hydrogen
*
* Copyright (c) 2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* This program 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.
*
* This program 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 this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
/*
* Hydrogen
* Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
*
* http://www.hydrogen-music.org
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <QtGui/QMouseEvent>
#include <QtGui/QPaintEvent>
#include <QtGui/QPainter>
#include "fader.h"
#include "embed.h"
fader::fader( floatModel * _model, QWidget * _parent ) :
QWidget( _parent ),
floatModelView( _model ),
m_model( _model ),
m_fPeakValue_L( 0.0 ),
m_fPeakValue_R( 0.0 ),
m_fMinPeak( 0.01f ),
m_fMaxPeak( 1.1 ),
m_back( embed::getIconPixmap( "fader_background" ) ),
m_leds( embed::getIconPixmap( "fader_leds" ) ),
m_knob( embed::getIconPixmap( "fader_knob" ) )
{
setAttribute( Qt::WA_NoBackground );
setMinimumSize( 23, 116 );
setMaximumSize( 23, 116);
resize( 23, 116 );
setModel( _model );
}
fader::~fader()
{
}
void fader::mouseMoveEvent( QMouseEvent *ev )
{
float fVal = (float)( height() - ev->y() ) / (float)height();
fVal = fVal * ( m_model->maxValue() - m_model->minValue() );
fVal = fVal + m_model->minValue();
m_model->setValue( fVal );
}
void fader::mousePressEvent(QMouseEvent *ev)
{
mouseMoveEvent( ev );
}
void fader::wheelEvent ( QWheelEvent *ev )
{
ev->accept();
if ( ev->delta() > 0 )
{
m_model->incValue( 5 );
}
else
{
m_model->incValue( -5 );
}
}
///
/// Set peak value (0.0 .. 1.0)
///
void fader::setPeak_L( float fPeak )
{
if ( fPeak < m_fMinPeak ) {
fPeak = m_fMinPeak;
}
else if ( fPeak > m_fMaxPeak ) {
fPeak = m_fMaxPeak;
}
if ( m_fPeakValue_L != fPeak) {
m_fPeakValue_L = fPeak;
update();
}
}
///
/// Set peak value (0.0 .. 1.0)
///
void fader::setPeak_R( float fPeak )
{
if ( fPeak < m_fMinPeak ) {
fPeak = m_fMinPeak;
}
else if ( fPeak > m_fMaxPeak ) {
fPeak = m_fMaxPeak;
}
if ( m_fPeakValue_R != fPeak ) {
m_fPeakValue_R = fPeak;
update();
}
}
void fader::paintEvent( QPaintEvent * ev)
{
QPainter painter(this);
// background
// painter.drawPixmap( rect(), m_back, QRect( 0, 0, 23, 116 ) );
painter.drawPixmap( ev->rect(), m_back, ev->rect() );
// peak leds
//float fRange = abs( m_fMaxPeak ) + abs( m_fMinPeak );
float realPeak_L = m_fPeakValue_L - m_fMinPeak;
//int peak_L = 116 - ( realPeak_L / fRange ) * 116.0;
int peak_L = 116 - ( realPeak_L / ( m_fMaxPeak - m_fMinPeak ) ) * 116.0;
if ( peak_L > 116 ) {
peak_L = 116;
}
painter.drawPixmap( QRect( 0, peak_L, 11, 116 - peak_L ), m_leds, QRect( 0, peak_L, 11, 116 - peak_L ) );
float realPeak_R = m_fPeakValue_R - m_fMinPeak;
int peak_R = 116 - ( realPeak_R / ( m_fMaxPeak - m_fMinPeak ) ) * 116.0;
if ( peak_R > 116 ) {
peak_R = 116;
}
painter.drawPixmap( QRect( 11, peak_R, 11, 116 - peak_R ), m_leds, QRect( 11, peak_R, 11, 116 - peak_R ) );
// knob
static const uint knob_height = 29;
static const uint knob_width = 15;
float fRange = m_model->maxValue() - m_model->minValue();
float realVal = m_model->value() - m_model->minValue();
// uint knob_y = (uint)( 116.0 - ( 86.0 * ( m_model->value() / fRange ) ) );
uint knob_y = (uint)( 116.0 - ( 86.0 * ( realVal / fRange ) ) );
painter.drawPixmap( QRect( 4, knob_y - knob_height, knob_width, knob_height), m_knob, QRect( 0, 0, knob_width, knob_height ) );
}
void fader::setMaxPeak( float fMax )
{
m_fMaxPeak = fMax;
}
void fader::setMinPeak( float fMin )
{
m_fMinPeak = fMin;
}
#include "fader.moc"