Files
lmms/include/mixer.h
Tobias Doerffel d88b2959ce 0.2.1 release
git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@272 0778d3d1-df1d-0410-868b-ea421aaaa00d
2006-07-28 08:42:40 +00:00

368 lines
6.9 KiB
C++

/*
* mixer.h - audio-device-independent mixer for LMMS
*
* Copyright (c) 2004-2006 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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*/
#ifndef _MIXER_H
#define _MIXER_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "qt3support.h"
#ifdef QT4
#include <QtCore/QMutex>
#include <QtCore/QVector>
#else
#include <qobject.h>
#include <qmutex.h>
#include <qvaluevector.h>
#endif
#include "types.h"
#include "volume.h"
#include "panning.h"
#include "note.h"
#include "play_handle.h"
#include "effect_board.h"
#include "engine.h"
class audioDevice;
class midiClient;
class audioPort;
const fpab_t DEFAULT_BUFFER_SIZE = 512;
const ch_cnt_t DEFAULT_CHANNELS = 2;
const ch_cnt_t SURROUND_CHANNELS =
#ifndef DISABLE_SURROUND
4;
#else
2;
#endif
enum qualityLevels
{
DEFAULT_QUALITY_LEVEL,
HIGH_QUALITY_LEVEL,
QUALITY_LEVELS
} ;
extern sample_rate_t SAMPLE_RATES[QUALITY_LEVELS];
const sample_rate_t DEFAULT_SAMPLE_RATE = 44100;
typedef sample_t sampleFrame[DEFAULT_CHANNELS];
typedef sample_t surroundSampleFrame[SURROUND_CHANNELS];
typedef struct
{
float vol[SURROUND_CHANNELS];
} volumeVector;
const Uint8 BYTES_PER_SAMPLE = sizeof( sample_t );
const Uint8 BYTES_PER_INT_SAMPLE = sizeof( int_sample_t );
const Uint8 BYTES_PER_FRAME = sizeof( sampleFrame );
const Uint8 BYTES_PER_SURROUND_FRAME = sizeof( surroundSampleFrame );
const float OUTPUT_SAMPLE_MULTIPLIER = 32767.0f;
const float BASE_FREQ = 440.0f;
const tones BASE_TONE = A;
const octaves BASE_OCTAVE = OCTAVE_4;
class mixer : public QObject, public engineObject
{
Q_OBJECT
public:
void initDevices( void );
void FASTCALL clear( const bool _everything = FALSE );
// audio-device-stuff
inline const QString & audioDevName( void ) const
{
return( m_audioDevName );
}
void FASTCALL setAudioDevice( audioDevice * _dev, bool _hq );
void restoreAudioDevice( void );
inline audioDevice * audioDev( void )
{
return( m_audioDev );
}
// audio-port-stuff
inline void addAudioPort( audioPort * _port )
{
pause();
m_audioPorts.push_back( _port );
play();
}
inline void removeAudioPort( audioPort * _port )
{
vvector<audioPort *>::iterator it = qFind( m_audioPorts.begin(),
m_audioPorts.end(),
_port );
if( it != m_audioPorts.end() )
{
m_audioPorts.erase( it );
}
}
// MIDI-client-stuff
inline const QString & midiClientName( void ) const
{
return( m_midiClientName );
}
inline midiClient * getMIDIClient( void )
{
return( m_midiClient );
}
// play-handle stuff
inline bool addPlayHandle( playHandle * _ph )
{
if( criticalXRuns() == FALSE )
{
m_playHandles.push_back( _ph );
return( TRUE );
}
delete _ph;
return( FALSE );
}
inline void removePlayHandle( playHandle * _ph )
{
m_playHandlesToRemove.push_back( _ph );
}
inline const playHandleVector & playHandles( void ) const
{
return( m_playHandles );
}
void checkValidityOfPlayHandles( void );
inline bool haveNoRunningNotes( void ) const
{
return( m_playHandles.size() == 0 );
}
// methods providing information for other classes
inline fpab_t framesPerAudioBuffer( void ) const
{
return( m_framesPerAudioBuffer );
}
inline const surroundSampleFrame * currentAudioBuffer( void ) const
{
return( m_writeBuf );
}
inline Uint8 cpuLoad( void ) const
{
return( m_cpuLoad );
}
inline bool highQuality( void ) const
{
return( m_qualityLevel > DEFAULT_QUALITY_LEVEL );
}
inline sample_rate_t sampleRate( void ) const
{
return( SAMPLE_RATES[m_qualityLevel] );
}
inline float masterGain( void ) const
{
return( m_masterGain );
}
inline void setMasterGain( const float _mo )
{
m_masterGain = _mo;
}
static inline sample_t clip( const sample_t _s )
{
if( _s > 1.0f )
{
return( 1.0f );
}
else if( _s < -1.0f )
{
return( -1.0f );
}
return( _s );
}
// methods for controlling mixer-state
void pause( void )
{
if( m_mixMutexLockLevel == 0 )
{
m_mixMutex.lock();
}
++m_mixMutexLockLevel;
}
void play( void )
{
if( m_mixMutexLockLevel == 1 )
{
m_mixMutex.unlock();
}
--m_mixMutexLockLevel;
}
// audio-buffer-mgm
void FASTCALL bufferToPort( const sampleFrame * _buf,
const fpab_t _frames,
const fpab_t _framesAhead,
const volumeVector & _volumeVector,
audioPort * _port );
void FASTCALL clearAudioBuffer( sampleFrame * _ab,
const f_cnt_t _frames );
#ifndef DISABLE_SURROUND
void FASTCALL clearAudioBuffer( surroundSampleFrame * _ab,
const f_cnt_t _frames );
#endif
bool criticalXRuns( void ) const;
const surroundSampleFrame * renderNextBuffer( void );
public slots:
void setHighQuality( bool _hq_on = FALSE );
void setClipScaling( bool _state );
signals:
void sampleRateChanged( void );
void nextAudioBuffer( const surroundSampleFrame *, int _frames );
private:
mixer( engine * _engine );
~mixer();
void startProcessing( void );
void stopProcessing( void );
// we don't allow to create mixer by using copy-ctor
mixer( const mixer & ) :
engineObject( NULL )
{
}
audioDevice * tryAudioDevices( void );
midiClient * tryMIDIClients( void );
void processBuffer( const surroundSampleFrame * _buf,
const fx_ch_t _fx_chnl );
void FASTCALL scaleClip( fpab_t _frame, ch_cnt_t _chnl );
vvector<audioPort *> m_audioPorts;
fpab_t m_framesPerAudioBuffer;
surroundSampleFrame * m_readBuf;
surroundSampleFrame * m_writeBuf;
vvector<surroundSampleFrame *> m_bufferPool;
Uint8 m_readBuffer;
Uint8 m_writeBuffer;
Uint8 m_analBuffer;
Uint8 m_poolDepth;
bool m_scaleClip;
surroundSampleFrame m_maxClip;
surroundSampleFrame m_previousSample;
fpab_t m_halfStart[SURROUND_CHANNELS];
bool m_clipped[SURROUND_CHANNELS];
bool m_oldBuffer[SURROUND_CHANNELS];
bool m_newBuffer[SURROUND_CHANNELS];
Uint8 m_cpuLoad;
playHandleVector m_playHandles;
playHandleVector m_playHandlesToRemove;
qualityLevels m_qualityLevel;
float m_masterGain;
audioDevice * m_audioDev;
audioDevice * m_oldAudioDev;
QString m_audioDevName;
midiClient * m_midiClient;
QString m_midiClientName;
QMutex m_mixMutex;
Uint8 m_mixMutexLockLevel;
friend class engine;
} ;
#endif