Mixer: rewrote processing chain of rendered audio buffers
Until now, Mixer not only was responsible for rendering audio buffers but also managed writing them to audio backend (through a FIFO) and handled various quality related parameters. All this functionality has been moved into the new AudioOutputContext class. It glues together AudioBackend (formerly called AudioDevice), global quality settings and the Mixer. The AudioOutputContext class creates a FifoWriter which calls Mixer::renderNextBuffer() and writes the output into the BufferFifo of the AudioOutputContext it belongs to. The BufferFifo is read by the according AudioBackend which belongs to the AudioOutputContext as well. The AudioOutputContext also handles resampling in case the AudioBackend wants the buffers in a different samplerate. During this rewrite the Mixer class and the according source files have been renamed from "mixer" to "Mixer". This results in small changes all over LMMS' code base.
This commit is contained in:
@@ -34,17 +34,17 @@
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioBackend.h"
|
||||
|
||||
|
||||
class lcdSpinBox;
|
||||
class QComboBox;
|
||||
|
||||
|
||||
class AudioAlsa : public AudioDevice, public QThread
|
||||
class AudioAlsa : public AudioBackend, public QThread
|
||||
{
|
||||
public:
|
||||
AudioAlsa( bool & _success_ful, mixer * _mixer );
|
||||
AudioAlsa( bool & _success_ful, AudioOutputContext * context );
|
||||
virtual ~AudioAlsa();
|
||||
|
||||
inline static QString name()
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
static QString probeDevice();
|
||||
|
||||
|
||||
class setupWidget : public AudioDevice::setupWidget
|
||||
class setupWidget : public AudioBackend::setupWidget
|
||||
{
|
||||
public:
|
||||
setupWidget( QWidget * _parent );
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* AudioDevice.h - base-class for audio-devices, used by LMMS-mixer
|
||||
* AudioBackend.h - base-class for audio-devices, used by LMMS-mixer
|
||||
*
|
||||
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
@@ -26,37 +26,31 @@
|
||||
#define _AUDIO_DEVICE_H
|
||||
|
||||
#include <QtCore/QPair>
|
||||
#include <QtCore/QMutex>
|
||||
#include <QtCore/QThread>
|
||||
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
#include "tab_widget.h"
|
||||
|
||||
|
||||
class AudioPort;
|
||||
|
||||
|
||||
class AudioDevice
|
||||
/*! \brief The AudioBackend class is the base class for all kinds of AudioBackends.
|
||||
*
|
||||
* All classes derived from AudioBackend receive audio data so they can output
|
||||
* it.
|
||||
*/
|
||||
class AudioBackend
|
||||
{
|
||||
public:
|
||||
AudioDevice( const ch_cnt_t _channels, mixer * _mixer );
|
||||
virtual ~AudioDevice();
|
||||
/*! \brief Constructs an AudioBackend object for the given AudioOutputContext. */
|
||||
AudioBackend( const ch_cnt_t _channels, AudioOutputContext * context );
|
||||
virtual ~AudioBackend();
|
||||
|
||||
inline void lock()
|
||||
{
|
||||
m_devMutex.lock();
|
||||
}
|
||||
|
||||
inline void unlock()
|
||||
{
|
||||
m_devMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
// if audio-driver supports ports, classes inherting AudioPort
|
||||
// (e.g. channel-tracks) can register themselves for making
|
||||
// audio-driver able to collect their individual output and provide
|
||||
// them at a specific port - currently only supported by JACK
|
||||
/*! If the audio backend supports ports, classes creating an AudioPort
|
||||
* (e.g. InstrumentTrack) can register themselves for making
|
||||
* audio backend able to collect their individual output and provide
|
||||
* them at a specific port - currently only supported by JACK
|
||||
*/
|
||||
virtual void registerPort( AudioPort * _port );
|
||||
virtual void unregisterPort( AudioPort * _port );
|
||||
virtual void renamePort( AudioPort * _port );
|
||||
@@ -77,11 +71,14 @@ public:
|
||||
return m_channels;
|
||||
}
|
||||
|
||||
void processNextBuffer();
|
||||
/*! \brief Fetches one buffer and writes it to output device.
|
||||
*
|
||||
* \return Number of frames processed
|
||||
*/
|
||||
int processNextBuffer();
|
||||
|
||||
virtual void startProcessing()
|
||||
{
|
||||
m_inProcess = true;
|
||||
}
|
||||
|
||||
virtual void stopProcessing();
|
||||
@@ -115,41 +112,47 @@ public:
|
||||
} ;
|
||||
|
||||
|
||||
/*! \brief Returns const pointer to AudioOutputContext this AudioBackend acts for. */
|
||||
const AudioOutputContext * outputContext() const
|
||||
{
|
||||
return m_context;
|
||||
}
|
||||
|
||||
/*! \brief Returns const pointer to Mixer this AudioBackend acts for. */
|
||||
const Mixer * mixer() const;
|
||||
|
||||
|
||||
protected:
|
||||
// subclasses can re-implement this for being used in conjunction with
|
||||
// processNextBuffer()
|
||||
/*! \brief Writes given buffer to actual device.
|
||||
*
|
||||
* Subclasses can reimplement this for being used in conjunction with
|
||||
* processNextBuffer()
|
||||
*/
|
||||
virtual void writeBuffer( const sampleFrameA * /* _buf*/,
|
||||
const fpp_t /*_frames*/,
|
||||
const float /*_master_gain*/ )
|
||||
{
|
||||
}
|
||||
|
||||
// called by according driver for fetching new sound-data
|
||||
fpp_t getNextBuffer( sampleFrameA * _ab );
|
||||
/*! \brief Called by according backend for fetching new audio data. */
|
||||
int getNextBuffer( sampleFrameA * _ab );
|
||||
|
||||
// clear given signed-int-16-buffer
|
||||
/*! \brief Clears given signed-int-16-buffer. */
|
||||
void clearS16Buffer( intSampleFrameA * _outbuf, const fpp_t _frames );
|
||||
|
||||
// resample given buffer from samplerate _src_sr to samplerate _dst_sr
|
||||
void resample( const sampleFrameA * _src,
|
||||
const fpp_t _frames,
|
||||
sampleFrameA * _dst,
|
||||
const sample_rate_t _src_sr,
|
||||
const sample_rate_t _dst_sr );
|
||||
|
||||
inline void setSampleRate( const sample_rate_t _new_sr )
|
||||
{
|
||||
m_sampleRate = _new_sr;
|
||||
}
|
||||
|
||||
mixer * getMixer()
|
||||
{
|
||||
return m_mixer;
|
||||
}
|
||||
|
||||
bool hqAudio() const;
|
||||
|
||||
AudioOutputContext * outputContext()
|
||||
{
|
||||
return m_context;
|
||||
}
|
||||
|
||||
Mixer * mixer();
|
||||
|
||||
|
||||
protected:
|
||||
@@ -157,15 +160,9 @@ protected:
|
||||
|
||||
|
||||
private:
|
||||
AudioOutputContext * m_context;
|
||||
sample_rate_t m_sampleRate;
|
||||
ch_cnt_t m_channels;
|
||||
mixer * m_mixer;
|
||||
bool m_inProcess;
|
||||
|
||||
QMutex m_devMutex;
|
||||
|
||||
SRC_DATA m_srcData;
|
||||
SRC_STATE * m_srcState;
|
||||
|
||||
sampleFrameA * m_buffer;
|
||||
|
||||
@@ -25,16 +25,16 @@
|
||||
#ifndef _AUDIO_DUMMY_H
|
||||
#define _AUDIO_DUMMY_H
|
||||
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioBackend.h"
|
||||
#include "Cpu.h"
|
||||
#include "MicroTimer.h"
|
||||
|
||||
|
||||
class AudioDummy : public AudioDevice, public QThread
|
||||
class AudioDummy : public AudioBackend, public QThread
|
||||
{
|
||||
public:
|
||||
AudioDummy( bool & _success_ful, mixer * _mixer ) :
|
||||
AudioDevice( DEFAULT_CHANNELS, _mixer )
|
||||
AudioDummy( bool & _success_ful, AudioOutputContext * context ) :
|
||||
AudioBackend( DEFAULT_CHANNELS, context )
|
||||
{
|
||||
_success_ful = true;
|
||||
}
|
||||
@@ -50,11 +50,11 @@ public:
|
||||
}
|
||||
|
||||
|
||||
class setupWidget : public AudioDevice::setupWidget
|
||||
class setupWidget : public AudioBackend::setupWidget
|
||||
{
|
||||
public:
|
||||
setupWidget( QWidget * _parent ) :
|
||||
AudioDevice::setupWidget( AudioDummy::name(), _parent )
|
||||
AudioBackend::setupWidget( AudioDummy::name(), _parent )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -93,27 +93,25 @@ private:
|
||||
virtual void run()
|
||||
{
|
||||
MicroTimer timer;
|
||||
sampleFrameA * buf = CPU::allocFrames( mixer()->framesPerPeriod() );
|
||||
while( true )
|
||||
{
|
||||
timer.reset();
|
||||
surroundSampleFrame * b =
|
||||
getMixer()->nextBuffer();
|
||||
if( !b )
|
||||
int frames = getNextBuffer( buf );
|
||||
if( frames == 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
CPU::freeFrames( b );
|
||||
|
||||
const Sint32 microseconds = static_cast<Sint32>(
|
||||
getMixer()->framesPerPeriod() *
|
||||
1000000.0f /
|
||||
getMixer()->processingSampleRate() -
|
||||
timer.elapsed() );
|
||||
mixer()->framesPerPeriod() * 1000000.0f /
|
||||
mixer()->processingSampleRate() - timer.elapsed() );
|
||||
if( microseconds > 0 )
|
||||
{
|
||||
usleep( microseconds );
|
||||
}
|
||||
}
|
||||
CPU::freeFrames( buf );
|
||||
}
|
||||
|
||||
} ;
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
|
||||
#include <QtCore/QFile>
|
||||
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioBackend.h"
|
||||
|
||||
|
||||
class AudioFileDevice : public AudioDevice
|
||||
class AudioFileDevice : public AudioBackend
|
||||
{
|
||||
public:
|
||||
AudioFileDevice( const sample_rate_t _sample_rate,
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
const bitrate_t _min_bitrate,
|
||||
const bitrate_t _max_bitrate,
|
||||
const int _depth,
|
||||
mixer * _mixer );
|
||||
AudioOutputContext * context );
|
||||
virtual ~AudioFileDevice();
|
||||
|
||||
QString outputFile() const
|
||||
@@ -108,7 +108,7 @@ typedef AudioFileDevice * ( * AudioFileDeviceInstantiaton )
|
||||
const bitrate_t _min_bitrate,
|
||||
const bitrate_t _max_bitrate,
|
||||
const int _depth,
|
||||
mixer * _mixer );
|
||||
AudioOutputContext * mixer );
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
const bitrate_t _min_bitrate,
|
||||
const bitrate_t _max_bitrate,
|
||||
const int _depth,
|
||||
mixer * _mixer );
|
||||
AudioOutputContext * context );
|
||||
virtual ~AudioFileFlac();
|
||||
|
||||
static AudioFileDevice * getInst( const sample_rate_t _sample_rate,
|
||||
@@ -60,13 +60,12 @@ public:
|
||||
const bitrate_t _min_bitrate,
|
||||
const bitrate_t _max_bitrate,
|
||||
const int _depth,
|
||||
mixer * _mixer )
|
||||
AudioOutputContext * context )
|
||||
{
|
||||
return new AudioFileFlac( _sample_rate, _channels,
|
||||
_success_ful, _file, _use_vbr,
|
||||
_nom_bitrate, _min_bitrate,
|
||||
_max_bitrate, _depth,
|
||||
_mixer );
|
||||
_max_bitrate, _depth, context );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
const bitrate_t _min_bitrate,
|
||||
const bitrate_t _max_bitrate,
|
||||
const int _depth,
|
||||
mixer * _mixer );
|
||||
AudioOutputContext * context );
|
||||
virtual ~AudioFileMp3();
|
||||
|
||||
static AudioFileDevice * getInst( const sample_rate_t _sample_rate,
|
||||
@@ -56,13 +56,12 @@ public:
|
||||
const bitrate_t _min_bitrate,
|
||||
const bitrate_t _max_bitrate,
|
||||
const int _depth,
|
||||
mixer * _mixer )
|
||||
AudioOutputContext * context )
|
||||
{
|
||||
return new AudioFileMp3( _sample_rate, _channels,
|
||||
_success_ful, _file, _use_vbr,
|
||||
_nom_bitrate, _min_bitrate,
|
||||
_max_bitrate, _depth,
|
||||
_mixer );
|
||||
_max_bitrate, _depth, context );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
const bitrate_t _min_bitrate,
|
||||
const bitrate_t _max_bitrate,
|
||||
const int _depth,
|
||||
mixer * _mixer );
|
||||
AudioOutputContext * context );
|
||||
virtual ~AudioFileOgg();
|
||||
|
||||
static AudioFileDevice * getInst( const sample_rate_t _sample_rate,
|
||||
@@ -59,12 +59,11 @@ public:
|
||||
const bitrate_t _min_bitrate,
|
||||
const bitrate_t _max_bitrate,
|
||||
const int _depth,
|
||||
mixer * _mixer )
|
||||
AudioOutputContext * context )
|
||||
{
|
||||
return new AudioFileOgg( _sample_rate, _channels, _success_ful,
|
||||
_file, _use_vbr, _nom_bitrate,
|
||||
_min_bitrate, _max_bitrate,
|
||||
_depth, _mixer );
|
||||
_min_bitrate, _max_bitrate, _depth, context );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* AudioFileWave.h - AudioDevice which encodes wave-stream and writes it
|
||||
* AudioFileWave.h - AudioBackend which encodes wave-stream and writes it
|
||||
* into a WAVE-file. This is used for song-export.
|
||||
*
|
||||
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
const bitrate_t _min_bitrate,
|
||||
const bitrate_t _max_bitrate,
|
||||
const int _depth,
|
||||
mixer * _mixer );
|
||||
AudioOutputContext * context );
|
||||
virtual ~AudioFileWave();
|
||||
|
||||
static AudioFileDevice * getInst( const sample_rate_t _sample_rate,
|
||||
@@ -56,13 +56,12 @@ public:
|
||||
const bitrate_t _min_bitrate,
|
||||
const bitrate_t _max_bitrate,
|
||||
const int _depth,
|
||||
mixer * _mixer )
|
||||
AudioOutputContext * context )
|
||||
{
|
||||
return new AudioFileWave( _sample_rate, _channels,
|
||||
_success_ful, _file, _use_vbr,
|
||||
_nom_bitrate, _min_bitrate,
|
||||
_max_bitrate, _depth,
|
||||
_mixer );
|
||||
_max_bitrate, _depth, context );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -31,22 +31,22 @@
|
||||
#include <jack/jack.h>
|
||||
#endif
|
||||
|
||||
#include <QtCore/QVector>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QSemaphore>
|
||||
#include <QtCore/QVector>
|
||||
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioBackend.h"
|
||||
|
||||
|
||||
class QLineEdit;
|
||||
class lcdSpinBox;
|
||||
|
||||
|
||||
class AudioJack : public QObject, public AudioDevice
|
||||
class AudioJack : public QObject, public AudioBackend
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AudioJack( bool & _success_ful, mixer * _mixer );
|
||||
AudioJack( bool & _success_ful, AudioOutputContext * context );
|
||||
virtual ~AudioJack();
|
||||
|
||||
inline static QString name()
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
}
|
||||
|
||||
|
||||
class setupWidget : public AudioDevice::setupWidget
|
||||
class setupWidget : public AudioBackend::setupWidget
|
||||
{
|
||||
public:
|
||||
setupWidget( QWidget * _parent );
|
||||
|
||||
@@ -29,17 +29,17 @@
|
||||
|
||||
#ifdef LMMS_HAVE_OSS
|
||||
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioBackend.h"
|
||||
|
||||
|
||||
class lcdSpinBox;
|
||||
class QLineEdit;
|
||||
|
||||
|
||||
class AudioOss : public AudioDevice, public QThread
|
||||
class AudioOss : public AudioBackend, public QThread
|
||||
{
|
||||
public:
|
||||
AudioOss( bool & _success_ful, mixer * _mixer );
|
||||
AudioOss( bool & _success_ful, AudioOutputContext * context );
|
||||
virtual ~AudioOss();
|
||||
|
||||
inline static QString name()
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
static QString probeDevice();
|
||||
|
||||
|
||||
class setupWidget : public AudioDevice::setupWidget
|
||||
class setupWidget : public AudioBackend::setupWidget
|
||||
{
|
||||
public:
|
||||
setupWidget( QWidget * _parent );
|
||||
|
||||
377
include/AudioOutputContext.h
Normal file
377
include/AudioOutputContext.h
Normal file
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
* AudioOutputContext.h - centralize all audio output related functionality
|
||||
*
|
||||
* Copyright (c) 2009 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _AUDIO_OUTPUT_CONTEXT_H
|
||||
#define _AUDIO_OUTPUT_CONTEXT_H
|
||||
|
||||
#include <QtCore/QSemaphore>
|
||||
#include <QtCore/QThread>
|
||||
|
||||
#include "Mixer.h"
|
||||
|
||||
class AudioBackend;
|
||||
|
||||
/*! \brief The AudioOutputContext class centralizes all functionality
|
||||
* and data related to output of audio data.
|
||||
*
|
||||
* The process of audio output is rather complicated due to different kinds of
|
||||
* AudioBackend implementations, FIFO buffering and dedicated quality settings.
|
||||
* The AudioOutputContext class handles all this so the Mixer class can just
|
||||
* deal with actual audio rendering and processing.
|
||||
*/
|
||||
class AudioOutputContext
|
||||
{
|
||||
public:
|
||||
/*! \brief The QualitySettings class holds quality related settings.
|
||||
*
|
||||
* There's nothing special about it. It's just a data aggregration class.
|
||||
*/
|
||||
class QualitySettings
|
||||
{
|
||||
public:
|
||||
/*! Lists all quality presets. */
|
||||
enum Preset
|
||||
{
|
||||
Preset_Draft, /*!< Draft quality - used for editing project */
|
||||
Preset_HighQuality, /*!< High quality - standard setting for project export */
|
||||
Preset_FinalMix, /*!< Final mix quality - very slow, best quality */
|
||||
NumPresets
|
||||
} ;
|
||||
|
||||
/*! Lists all supported interpolation types. */
|
||||
enum Interpolation
|
||||
{
|
||||
Interpolation_Linear, /*!< Linear interpolation - fast */
|
||||
Interpolation_SincFastest, /*!< Fastest Sinc interpolation - good quality */
|
||||
Interpolation_SincMedium, /*!< Medium Sinc interpolation - better quality */
|
||||
Interpolation_SincBest /*!< High quality interpolation */
|
||||
} ;
|
||||
|
||||
/*! Lists all supported oversampling ratios. */
|
||||
enum Oversampling
|
||||
{
|
||||
Oversampling_None, /*!< No oversampling - fast */
|
||||
Oversampling_2x, /*!< 2x oversampling - good quality */
|
||||
Oversampling_4x, /*!< 4x oversampling - better quality */
|
||||
Oversampling_8x /*!< 8x oversampling - best quality but might break some filters */
|
||||
} ;
|
||||
|
||||
/*! \brief Constructs a QualitySettings object based on a given preset. */
|
||||
QualitySettings( Preset m )
|
||||
{
|
||||
switch( m )
|
||||
{
|
||||
case Preset_Draft:
|
||||
m_interpolation = Interpolation_Linear;
|
||||
m_oversampling = Oversampling_None;
|
||||
m_sampleExactControllers = false;
|
||||
m_aliasFreeOscillators = false;
|
||||
break;
|
||||
case Preset_HighQuality:
|
||||
m_interpolation = Interpolation_SincFastest;
|
||||
m_oversampling = Oversampling_2x;
|
||||
m_sampleExactControllers = true;
|
||||
m_aliasFreeOscillators = false;
|
||||
break;
|
||||
case Preset_FinalMix:
|
||||
m_interpolation = Interpolation_SincBest;
|
||||
m_oversampling = Oversampling_8x;
|
||||
m_sampleExactControllers = true;
|
||||
m_aliasFreeOscillators = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Constructs a QualitySettings object based on specific quality settings. */
|
||||
QualitySettings( Interpolation _i, Oversampling _o, bool _sec,
|
||||
bool _afo ) :
|
||||
m_interpolation( _i ),
|
||||
m_oversampling( _o ),
|
||||
m_sampleExactControllers( _sec ),
|
||||
m_aliasFreeOscillators( _afo )
|
||||
{
|
||||
}
|
||||
|
||||
/*! \brief Returns multiplier for sample rate based on oversampling settings. */
|
||||
int sampleRateMultiplier() const
|
||||
{
|
||||
switch( oversampling() )
|
||||
{
|
||||
case Oversampling_None: return 1;
|
||||
case Oversampling_2x: return 2;
|
||||
case Oversampling_4x: return 4;
|
||||
case Oversampling_8x: return 8;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*! \brief Maps interpolation setting to libsamplerate constants. */
|
||||
int libsrcInterpolation() const
|
||||
{
|
||||
switch( interpolation() )
|
||||
{
|
||||
case Interpolation_Linear:
|
||||
return SRC_ZERO_ORDER_HOLD;
|
||||
case Interpolation_SincFastest:
|
||||
return SRC_SINC_FASTEST;
|
||||
case Interpolation_SincMedium:
|
||||
return SRC_SINC_MEDIUM_QUALITY;
|
||||
case Interpolation_SincBest:
|
||||
return SRC_SINC_BEST_QUALITY;
|
||||
}
|
||||
return SRC_LINEAR;
|
||||
}
|
||||
|
||||
/*! \brief Returns current interpolation setting. */
|
||||
Interpolation interpolation() const
|
||||
{
|
||||
return m_interpolation;
|
||||
}
|
||||
|
||||
/*! \brief Sets a new interpolation method. */
|
||||
void setInterpolation( Interpolation interpolation )
|
||||
{
|
||||
m_interpolation = interpolation;
|
||||
}
|
||||
|
||||
/*! \brief Returns current oversampling setting. */
|
||||
Oversampling oversampling() const
|
||||
{
|
||||
return m_oversampling;
|
||||
}
|
||||
|
||||
/*! \brief Sets a new oversampling factor. */
|
||||
void setOversampling( Oversampling oversampling )
|
||||
{
|
||||
m_oversampling = oversampling;
|
||||
}
|
||||
|
||||
/*! \brief Returns whether to use sample exact controllers. */
|
||||
bool sampleExactControllers() const
|
||||
{
|
||||
return m_sampleExactControllers;
|
||||
}
|
||||
|
||||
/*! \brief Returns whether to use alias free oscillators. */
|
||||
bool aliasFreeOscillators() const
|
||||
{
|
||||
return m_aliasFreeOscillators;
|
||||
}
|
||||
|
||||
private:
|
||||
Interpolation m_interpolation;
|
||||
Oversampling m_oversampling;
|
||||
bool m_sampleExactControllers;
|
||||
bool m_aliasFreeOscillators;
|
||||
|
||||
} ;
|
||||
|
||||
/*! \brief The BufferFifo class provides an internal FIFO for rendered buffers.
|
||||
*
|
||||
* When working with buffer sizes greater than the default buffer size, one
|
||||
* big output buffer is still splitted into smaller chunks. This is
|
||||
* especially neccessary for automation which takes place once a buffer
|
||||
* period. Transitions would be anything else but smooth when adjusting a
|
||||
* control just 20 times per second. BufferFifo handles the queueing of
|
||||
* rendered buffers. */
|
||||
class BufferFifo
|
||||
{
|
||||
public:
|
||||
/*! Each buffer in the FIFO can have a special state. This is used
|
||||
* by FifoWriter to inject NULL buffers to indicate, the FIFO has
|
||||
* been emptied after FifoWriter was told to finish. */
|
||||
enum BufferStates
|
||||
{
|
||||
Running, /*!< Regular buffer */
|
||||
NullBuffer /*!< Even if the buffer returned by currentReadBuffer()
|
||||
* is not NULL, the FIFO input was NULL. FIFO reader can
|
||||
* use this information for own purposes. */
|
||||
} ;
|
||||
typedef BufferStates BufferState;
|
||||
|
||||
/*! \brief Constructs a new BufferFifo object.
|
||||
*
|
||||
* \param size The number of buffers in the FIFO
|
||||
* \param bufferSize The size of each buffer in the FIFO
|
||||
*/
|
||||
BufferFifo( int size, int bufferSize );
|
||||
~BufferFifo();
|
||||
|
||||
/*! \brief Pushes a new buffer into the FIFO.
|
||||
*
|
||||
* You can also push NULL which will set the according buffer state
|
||||
* to HasNullBuffer. */
|
||||
void write( sampleFrameA * buffer );
|
||||
|
||||
/*! \brief Prepares for reading next buffer (might block until one is available). */
|
||||
void startRead();
|
||||
|
||||
/*! \brief Returns current front buffer for reading. */
|
||||
sampleFrameA * currentReadBuffer() const
|
||||
{
|
||||
return m_buffers[m_readerIndex];
|
||||
}
|
||||
|
||||
/*! \brief Returns state of current front buffer. */
|
||||
BufferState currentReadBufferState() const
|
||||
{
|
||||
return m_bufferStates[m_readerIndex];
|
||||
}
|
||||
|
||||
/*! \brief Finish the current buffer read operation.
|
||||
*
|
||||
* The buffer returned by currentReadBuffer() is not guaranteed to
|
||||
* be valid anymore after calling this function. */
|
||||
void finishRead();
|
||||
|
||||
/*! \brief Returns whether FIFO is empty. */
|
||||
bool isEmpty() const
|
||||
{
|
||||
return m_readerSem.available() == false;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
QSemaphore m_readerSem;
|
||||
QSemaphore m_writerSem;
|
||||
int m_readerIndex;
|
||||
int m_writerIndex;
|
||||
int m_size;
|
||||
int m_bufferSize;
|
||||
sampleFrameA * * m_buffers;
|
||||
BufferState * m_bufferStates;
|
||||
|
||||
} ;
|
||||
|
||||
/*! \brief The FifoWriter class provides an internal thread for feeding
|
||||
* the FIFO read by the active AudioBackend */
|
||||
class FifoWriter : public QThread
|
||||
{
|
||||
public:
|
||||
FifoWriter( AudioOutputContext * context );
|
||||
|
||||
void finish();
|
||||
|
||||
|
||||
private:
|
||||
AudioOutputContext * m_context;
|
||||
volatile bool m_writing;
|
||||
|
||||
virtual void run();
|
||||
|
||||
} ;
|
||||
|
||||
/*! \brief Constructs an AudioOutputContext object for given AudioBackend.
|
||||
*
|
||||
* \param mixer The Mixer instance to fetch audio data from
|
||||
* \param audioBackend The AudioBackend to write audio data to
|
||||
* \param qualitySettings A QualitySettings object describing desired quality
|
||||
*/
|
||||
AudioOutputContext( Mixer * mixer,
|
||||
AudioBackend * audioBackend,
|
||||
const QualitySettings & qualitySettings );
|
||||
~AudioOutputContext();
|
||||
|
||||
/*! \brief Sets an AudioBackend for this context. */
|
||||
void setAudioBackend( AudioBackend * backend )
|
||||
{
|
||||
m_audioBackend = backend;
|
||||
}
|
||||
|
||||
/*! \brief Returns AudioBackend used by this context. */
|
||||
AudioBackend * audioBackend()
|
||||
{
|
||||
return m_audioBackend;
|
||||
}
|
||||
|
||||
/*! \brief Returns const AudioBackend used by this context. */
|
||||
const AudioBackend * audioBackend() const
|
||||
{
|
||||
return m_audioBackend;
|
||||
}
|
||||
|
||||
/*! \brief Returns Mixer used by this context. */
|
||||
Mixer * mixer()
|
||||
{
|
||||
return m_mixer;
|
||||
}
|
||||
|
||||
/*! \brief Returns const Mixer used by this context. */
|
||||
const Mixer * mixer() const
|
||||
{
|
||||
return m_mixer;
|
||||
}
|
||||
|
||||
/*! \brief Returns BufferFifo object used by this context. */
|
||||
BufferFifo * fifo()
|
||||
{
|
||||
return m_fifo;
|
||||
}
|
||||
|
||||
/*! \brief Returns current quality settings. */
|
||||
const QualitySettings & qualitySettings() const
|
||||
{
|
||||
return m_qualitySettings;
|
||||
}
|
||||
|
||||
/*! \brief Starts audio processing in this context. */
|
||||
void startProcessing();
|
||||
|
||||
/*! \brief Stops audio processing in this context. */
|
||||
void stopProcessing();
|
||||
|
||||
/*! \brief Returns whether audio processing in this context is running. */
|
||||
bool isProcessing() const;
|
||||
|
||||
/*! \brief Copies current output buffer to destination buffer and optionally
|
||||
* does resampling.
|
||||
*
|
||||
* If the Mixer has a running FifoWriter, it will make the FifoWriter start
|
||||
* rendering the next buffer so it can be read from the Fifo next period
|
||||
* without any delay. If the desired sample rate does not match current
|
||||
* processing sample rate, resampling will be done.
|
||||
* \param destBuffer The (aligned) destination buffer
|
||||
* \param destSampleRate The desired output sample rate */
|
||||
int getCurrentOutputBuffer( sampleFrameA * destBuffer,
|
||||
sample_rate_t destSampleRate );
|
||||
|
||||
|
||||
private:
|
||||
Mixer * m_mixer;
|
||||
QualitySettings m_qualitySettings;
|
||||
AudioBackend * m_audioBackend;
|
||||
BufferFifo * m_fifo;
|
||||
FifoWriter * m_fifoWriter;
|
||||
|
||||
// resample data
|
||||
SRC_DATA m_srcData;
|
||||
SRC_STATE * m_srcState;
|
||||
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <QtCore/QMutex>
|
||||
#include <QtCore/QMutexLocker>
|
||||
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
|
||||
class EffectChain;
|
||||
|
||||
@@ -134,7 +134,7 @@ private:
|
||||
EffectChain * m_effects;
|
||||
|
||||
|
||||
friend class mixer;
|
||||
friend class Mixer;
|
||||
friend class MixerWorkerThread;
|
||||
|
||||
} ;
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
|
||||
#include <portaudio.h>
|
||||
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioBackend.h"
|
||||
|
||||
#if defined paNeverDropInput || defined paNonInterleaved
|
||||
# define PORTAUDIO_V19
|
||||
@@ -60,7 +60,7 @@ class comboBox;
|
||||
class lcdSpinBox;
|
||||
|
||||
|
||||
class AudioPortAudio : public AudioDevice
|
||||
class AudioPortAudio : public AudioBackend
|
||||
{
|
||||
public:
|
||||
AudioPortAudio( bool & _success_ful, mixer * _mixer );
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
unsigned long _framesPerBuffer );
|
||||
|
||||
|
||||
class setupWidget : public AudioDevice::setupWidget
|
||||
class setupWidget : public AudioBackend::setupWidget
|
||||
{
|
||||
public:
|
||||
setupWidget( QWidget * _parent );
|
||||
|
||||
@@ -31,17 +31,17 @@
|
||||
|
||||
#include <pulse/pulseaudio.h>
|
||||
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioBackend.h"
|
||||
|
||||
|
||||
class lcdSpinBox;
|
||||
class QLineEdit;
|
||||
|
||||
|
||||
class AudioPulseAudio : public AudioDevice, public QThread
|
||||
class AudioPulseAudio : public AudioBackend, public QThread
|
||||
{
|
||||
public:
|
||||
AudioPulseAudio( bool & _success_ful, mixer * _mixer );
|
||||
AudioPulseAudio( bool & _success_ful, AudioOutputContext * context );
|
||||
virtual ~AudioPulseAudio();
|
||||
|
||||
inline static QString name()
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
static QString probeDevice();
|
||||
|
||||
|
||||
class setupWidget : public AudioDevice::setupWidget
|
||||
class setupWidget : public AudioBackend::setupWidget
|
||||
{
|
||||
public:
|
||||
setupWidget( QWidget * _parent );
|
||||
|
||||
@@ -29,16 +29,16 @@
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QPair>
|
||||
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioBackend.h"
|
||||
|
||||
class sampleBuffer;
|
||||
|
||||
|
||||
class AudioSampleRecorder : public AudioDevice
|
||||
class AudioSampleRecorder : public AudioBackend
|
||||
{
|
||||
public:
|
||||
AudioSampleRecorder( const ch_cnt_t _channels, bool & _success_ful,
|
||||
mixer * _mixer );
|
||||
AudioOutputContext * context );
|
||||
virtual ~AudioSampleRecorder();
|
||||
|
||||
f_cnt_t framesRecorded() const;
|
||||
@@ -46,11 +46,11 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
virtual void writeBuffer( const surroundSampleFrame * _ab,
|
||||
virtual void writeBuffer( const sampleFrameA * _ab,
|
||||
const fpp_t _frames,
|
||||
const float _master_gain );
|
||||
|
||||
typedef QList<QPair<sampleFrame *, fpp_t> > BufferList;
|
||||
typedef QList<QPair<sampleFrameA *, fpp_t> > BufferList;
|
||||
BufferList m_buffers;
|
||||
|
||||
} ;
|
||||
|
||||
@@ -29,18 +29,20 @@
|
||||
|
||||
#ifdef LMMS_HAVE_SDL
|
||||
|
||||
#include <QtCore/QSemaphore>
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL/SDL_audio.h>
|
||||
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioBackend.h"
|
||||
|
||||
class QLineEdit;
|
||||
|
||||
|
||||
class AudioSdl : public AudioDevice
|
||||
class AudioSdl : public AudioBackend
|
||||
{
|
||||
public:
|
||||
AudioSdl( bool & _success_ful, mixer * _mixer );
|
||||
AudioSdl( bool & _success_ful, AudioOutputContext * context );
|
||||
virtual ~AudioSdl();
|
||||
|
||||
inline static QString name()
|
||||
@@ -50,7 +52,7 @@ public:
|
||||
}
|
||||
|
||||
|
||||
class setupWidget : public AudioDevice::setupWidget
|
||||
class setupWidget : public AudioBackend::setupWidget
|
||||
{
|
||||
public:
|
||||
setupWidget( QWidget * _parent );
|
||||
|
||||
@@ -23,13 +23,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _CONTROLLER_H
|
||||
#define _CONTROLLER_H
|
||||
|
||||
#include "engine.h"
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
#include "Model.h"
|
||||
//#include "AudioOutputContext.h"
|
||||
#include "JournallingObject.h"
|
||||
|
||||
class ControllerDialog;
|
||||
@@ -64,9 +64,9 @@ public:
|
||||
|
||||
inline bool isSampleExact() const
|
||||
{
|
||||
return m_sampleExact ||
|
||||
engine::getMixer()->currentQualitySettings().
|
||||
sampleExactControllers;
|
||||
return m_sampleExact /*||
|
||||
engine::mixer()->audioOutputContext()->
|
||||
qualitySettings().sampleExactControllers()*/;
|
||||
}
|
||||
|
||||
void setSampleExact( bool _exact )
|
||||
@@ -76,7 +76,7 @@ public:
|
||||
|
||||
inline ControllerTypes type() const
|
||||
{
|
||||
return( m_type );
|
||||
return m_type;
|
||||
}
|
||||
|
||||
// return whether this controller updates models frequently - used for
|
||||
@@ -85,17 +85,17 @@ public:
|
||||
{
|
||||
switch( m_type )
|
||||
{
|
||||
case LfoController: return( true );
|
||||
case PeakController: return( true );
|
||||
case LfoController: return true;
|
||||
case PeakController: return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return( false );
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual const QString & name() const
|
||||
{
|
||||
return( m_name );
|
||||
return m_name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include "Plugin.h"
|
||||
#include "engine.h"
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
#include "AutomatableModel.h"
|
||||
#include "TempoSyncKnobModel.h"
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include "Model.h"
|
||||
#include "SerializingObject.h"
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
#include "AutomatableModel.h"
|
||||
|
||||
class Effect;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define _FX_MIXER_H
|
||||
|
||||
#include "Model.h"
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
#include "EffectChain.h"
|
||||
#include "JournallingObject.h"
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
#include "Plugin.h"
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
|
||||
|
||||
// forward-declarations
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#ifndef _INSTRUMENT_SOUND_SHAPING_H
|
||||
#define _INSTRUMENT_SOUND_SHAPING_H
|
||||
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
#include "ComboBoxModel.h"
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* mixer.h - audio-device-independent mixer for LMMS
|
||||
* Mixer.h - Mixer for audio processing and rendering
|
||||
*
|
||||
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
@@ -39,19 +39,18 @@
|
||||
|
||||
|
||||
#include <QtCore/QMutex>
|
||||
#include <QtCore/QThread>
|
||||
#include <QtCore/QVector>
|
||||
#include <QtCore/QWaitCondition>
|
||||
|
||||
|
||||
#include "lmms_basics.h"
|
||||
#include "note.h"
|
||||
#include "fifo_buffer.h"
|
||||
|
||||
|
||||
class AudioDevice;
|
||||
class MidiClient;
|
||||
class AudioBackend;
|
||||
class AudioOutputContext;
|
||||
class AudioPort;
|
||||
class MidiClient;
|
||||
|
||||
|
||||
const fpp_t DEFAULT_BUFFER_SIZE = 256;
|
||||
@@ -67,105 +66,11 @@ const Octaves BaseOctave = DefaultOctave;
|
||||
|
||||
class MixerWorkerThread;
|
||||
|
||||
|
||||
class EXPORT mixer : public QObject
|
||||
/*! \brief The Mixer class is responsible for processing and rendering audio chunks. */
|
||||
class EXPORT Mixer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
struct qualitySettings
|
||||
{
|
||||
enum Mode
|
||||
{
|
||||
Mode_Draft,
|
||||
Mode_HighQuality,
|
||||
Mode_FinalMix
|
||||
} ;
|
||||
|
||||
enum Interpolation
|
||||
{
|
||||
Interpolation_Linear,
|
||||
Interpolation_SincFastest,
|
||||
Interpolation_SincMedium,
|
||||
Interpolation_SincBest
|
||||
} ;
|
||||
|
||||
enum Oversampling
|
||||
{
|
||||
Oversampling_None,
|
||||
Oversampling_2x,
|
||||
Oversampling_4x,
|
||||
Oversampling_8x
|
||||
} ;
|
||||
|
||||
Interpolation interpolation;
|
||||
Oversampling oversampling;
|
||||
bool sampleExactControllers;
|
||||
bool aliasFreeOscillators;
|
||||
|
||||
qualitySettings( Mode _m )
|
||||
{
|
||||
switch( _m )
|
||||
{
|
||||
case Mode_Draft:
|
||||
interpolation = Interpolation_Linear;
|
||||
oversampling = Oversampling_None;
|
||||
sampleExactControllers = false;
|
||||
aliasFreeOscillators = false;
|
||||
break;
|
||||
case Mode_HighQuality:
|
||||
interpolation =
|
||||
Interpolation_SincFastest;
|
||||
oversampling = Oversampling_2x;
|
||||
sampleExactControllers = true;
|
||||
aliasFreeOscillators = false;
|
||||
break;
|
||||
case Mode_FinalMix:
|
||||
interpolation = Interpolation_SincBest;
|
||||
oversampling = Oversampling_8x;
|
||||
sampleExactControllers = true;
|
||||
aliasFreeOscillators = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
qualitySettings( Interpolation _i, Oversampling _o, bool _sec,
|
||||
bool _afo ) :
|
||||
interpolation( _i ),
|
||||
oversampling( _o ),
|
||||
sampleExactControllers( _sec ),
|
||||
aliasFreeOscillators( _afo )
|
||||
{
|
||||
}
|
||||
|
||||
int sampleRateMultiplier() const
|
||||
{
|
||||
switch( oversampling )
|
||||
{
|
||||
case Oversampling_None: return 1;
|
||||
case Oversampling_2x: return 2;
|
||||
case Oversampling_4x: return 4;
|
||||
case Oversampling_8x: return 8;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int libsrcInterpolation() const
|
||||
{
|
||||
switch( interpolation )
|
||||
{
|
||||
case Interpolation_Linear:
|
||||
return SRC_ZERO_ORDER_HOLD;
|
||||
case Interpolation_SincFastest:
|
||||
return SRC_SINC_FASTEST;
|
||||
case Interpolation_SincMedium:
|
||||
return SRC_SINC_MEDIUM_QUALITY;
|
||||
case Interpolation_SincBest:
|
||||
return SRC_SINC_BEST_QUALITY;
|
||||
}
|
||||
return SRC_LINEAR;
|
||||
}
|
||||
} ;
|
||||
|
||||
void initDevices();
|
||||
void clear();
|
||||
|
||||
@@ -176,16 +81,20 @@ public:
|
||||
return m_audioDevName;
|
||||
}
|
||||
|
||||
void setAudioDevice( AudioDevice * _dev );
|
||||
void setAudioDevice( AudioDevice * _dev,
|
||||
const struct qualitySettings & _qs,
|
||||
bool _needs_fifo );
|
||||
void restoreAudioDevice();
|
||||
inline AudioDevice * audioDev()
|
||||
/*! \brief Sets a specific AudioOutputContext to be the active context. */
|
||||
void setAudioOutputContext( AudioOutputContext * context );
|
||||
const AudioOutputContext * audioOutputContext() const
|
||||
{
|
||||
return m_audioDev;
|
||||
return m_audioOutputContext;
|
||||
}
|
||||
AudioOutputContext * audioOutputContext()
|
||||
{
|
||||
return m_audioOutputContext;
|
||||
}
|
||||
AudioOutputContext * defaultAudioOutputContext()
|
||||
{
|
||||
return m_defaultAudioOutputContext;
|
||||
}
|
||||
|
||||
|
||||
// audio-port-stuff
|
||||
inline void addAudioPort( AudioPort * _port )
|
||||
@@ -246,7 +155,7 @@ public:
|
||||
return m_framesPerPeriod;
|
||||
}
|
||||
|
||||
inline const surroundSampleFrame * currentReadBuffer() const
|
||||
inline const sampleFrameA * currentReadBuffer() const
|
||||
{
|
||||
return m_readBuf;
|
||||
}
|
||||
@@ -257,11 +166,6 @@ public:
|
||||
return m_cpuLoad;
|
||||
}
|
||||
|
||||
const qualitySettings & currentQualitySettings() const
|
||||
{
|
||||
return m_qualitySettings;
|
||||
}
|
||||
|
||||
|
||||
sample_rate_t baseSampleRate() const;
|
||||
sample_rate_t outputSampleRate() const;
|
||||
@@ -325,11 +229,6 @@ public:
|
||||
static void clearAudioBuffer( sampleFrame * _ab,
|
||||
const f_cnt_t _frames,
|
||||
const f_cnt_t _offset = 0 );
|
||||
#ifndef LMMS_DISABLE_SURROUND
|
||||
static void clearAudioBuffer( surroundSampleFrame * _ab,
|
||||
const f_cnt_t _frames,
|
||||
const f_cnt_t _offset = 0 );
|
||||
#endif
|
||||
|
||||
static float peakValueLeft( sampleFrame * _ab, const f_cnt_t _frames );
|
||||
static float peakValueRight( sampleFrame * _ab, const f_cnt_t _frames );
|
||||
@@ -337,13 +236,8 @@ public:
|
||||
|
||||
bool criticalXRuns() const;
|
||||
|
||||
inline bool hasFifoWriter() const
|
||||
{
|
||||
return m_fifoWriter != NULL;
|
||||
}
|
||||
|
||||
void pushInputFrames( sampleFrame * _ab, const f_cnt_t _frames );
|
||||
|
||||
|
||||
inline const sampleFrame * inputBuffer()
|
||||
{
|
||||
return m_inputBuffer[ m_inputBufferRead ];
|
||||
@@ -354,56 +248,27 @@ public:
|
||||
return m_inputBufferFrames[ m_inputBufferRead ];
|
||||
}
|
||||
|
||||
inline surroundSampleFrame * nextBuffer()
|
||||
{
|
||||
return hasFifoWriter() ? m_fifo->read() : renderNextBuffer();
|
||||
}
|
||||
|
||||
void changeQuality( const struct qualitySettings & _qs );
|
||||
/*! \brief Processes and renders next chunk of audio. */
|
||||
sampleFrameA * renderNextBuffer();
|
||||
|
||||
|
||||
signals:
|
||||
void qualitySettingsChanged();
|
||||
void sampleRateChanged();
|
||||
void nextAudioBuffer();
|
||||
|
||||
|
||||
private:
|
||||
typedef fifoBuffer<surroundSampleFrame *> fifo;
|
||||
Mixer();
|
||||
virtual ~Mixer();
|
||||
|
||||
class fifoWriter : public QThread
|
||||
{
|
||||
public:
|
||||
fifoWriter( mixer * _mixer, fifo * _fifo );
|
||||
|
||||
void finish();
|
||||
|
||||
|
||||
private:
|
||||
mixer * m_mixer;
|
||||
fifo * m_fifo;
|
||||
volatile bool m_writing;
|
||||
|
||||
virtual void run();
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
mixer();
|
||||
virtual ~mixer();
|
||||
|
||||
void startProcessing( bool _needs_fifo = true );
|
||||
void startProcessing();
|
||||
void stopProcessing();
|
||||
|
||||
|
||||
AudioDevice * tryAudioDevices();
|
||||
AudioBackend * tryAudioBackends();
|
||||
MidiClient * tryMidiClients();
|
||||
|
||||
|
||||
surroundSampleFrame * renderNextBuffer();
|
||||
|
||||
|
||||
|
||||
QVector<AudioPort *> m_audioPorts;
|
||||
|
||||
fpp_t m_framesPerPeriod;
|
||||
@@ -415,21 +280,21 @@ private:
|
||||
f_cnt_t m_inputBufferSize[2];
|
||||
int m_inputBufferRead;
|
||||
int m_inputBufferWrite;
|
||||
|
||||
surroundSampleFrame * m_readBuf;
|
||||
surroundSampleFrame * m_writeBuf;
|
||||
|
||||
QVector<surroundSampleFrame *> m_bufferPool;
|
||||
|
||||
sampleFrameA * m_readBuf;
|
||||
sampleFrameA * m_writeBuf;
|
||||
|
||||
QVector<sampleFrameA *> m_bufferPool;
|
||||
int m_readBuffer;
|
||||
int m_writeBuffer;
|
||||
int m_poolDepth;
|
||||
|
||||
surroundSampleFrame m_maxClip;
|
||||
surroundSampleFrame m_previousSample;
|
||||
sampleFrame m_maxClip;
|
||||
sampleFrame m_previousSample;
|
||||
fpp_t m_halfStart[SURROUND_CHANNELS];
|
||||
bool m_oldBuffer[SURROUND_CHANNELS];
|
||||
bool m_newBuffer[SURROUND_CHANNELS];
|
||||
|
||||
|
||||
int m_cpuLoad;
|
||||
QVector<MixerWorkerThread *> m_workers;
|
||||
int m_numWorkers;
|
||||
@@ -439,12 +304,11 @@ private:
|
||||
PlayHandleList m_playHandles;
|
||||
ConstPlayHandleList m_playHandlesToRemove;
|
||||
|
||||
struct qualitySettings m_qualitySettings;
|
||||
float m_masterGain;
|
||||
|
||||
|
||||
AudioDevice * m_audioDev;
|
||||
AudioDevice * m_oldAudioDev;
|
||||
AudioOutputContext * m_audioOutputContext;
|
||||
AudioOutputContext * m_defaultAudioOutputContext;
|
||||
QString m_audioDevName;
|
||||
|
||||
|
||||
@@ -456,10 +320,6 @@ private:
|
||||
QMutex m_inputFramesMutex;
|
||||
|
||||
|
||||
fifo * m_fifo;
|
||||
fifoWriter * m_fifoWriter;
|
||||
|
||||
|
||||
friend class engine;
|
||||
friend class MixerWorkerThread;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#define _PROJECT_RENDERER_H
|
||||
|
||||
#include "AudioFileDevice.h"
|
||||
#include "AudioOutputContext.h"
|
||||
#include "lmmsconfig.h"
|
||||
|
||||
class QTimer;
|
||||
@@ -71,7 +72,7 @@ public:
|
||||
} ;
|
||||
|
||||
|
||||
ProjectRenderer( const mixer::qualitySettings & _qs,
|
||||
ProjectRenderer( const AudioOutputContext::QualitySettings & _qs,
|
||||
const OutputSettings & _os,
|
||||
ExportFileFormats _file_format,
|
||||
const QString & _out_file );
|
||||
@@ -101,12 +102,15 @@ signals:
|
||||
void progressChanged( int );
|
||||
|
||||
|
||||
private slots:
|
||||
void finishProcessing();
|
||||
|
||||
|
||||
private:
|
||||
virtual void run();
|
||||
|
||||
AudioFileDevice * m_fileDev;
|
||||
mixer::qualitySettings m_qualitySettings;
|
||||
mixer::qualitySettings m_oldQualitySettings;
|
||||
AudioOutputContext * m_context;
|
||||
|
||||
volatile int m_progress;
|
||||
volatile bool m_abort;
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#include <math.h>
|
||||
|
||||
#include "lmms_basics.h"
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
#include "templates.h"
|
||||
#include "lmms_constants.h"
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ protected slots:
|
||||
|
||||
|
||||
private:
|
||||
Uint8 m_currentLoad;
|
||||
int m_currentLoad;
|
||||
|
||||
QPixmap m_temp;
|
||||
QPixmap m_background;
|
||||
|
||||
@@ -41,7 +41,7 @@ class FxMixer;
|
||||
class FxMixerView;
|
||||
class ProjectJournal;
|
||||
class MainWindow;
|
||||
class mixer;
|
||||
class Mixer;
|
||||
class pianoRoll;
|
||||
class projectNotes;
|
||||
class ResourceDB;
|
||||
@@ -75,7 +75,12 @@ public:
|
||||
}
|
||||
|
||||
// core
|
||||
static mixer * getMixer()
|
||||
static Mixer * getMixer()
|
||||
{
|
||||
return s_mixer;
|
||||
}
|
||||
|
||||
static Mixer * mixer()
|
||||
{
|
||||
return s_mixer;
|
||||
}
|
||||
@@ -207,7 +212,7 @@ private:
|
||||
static float s_framesPerTick;
|
||||
|
||||
// core
|
||||
static mixer * s_mixer;
|
||||
static Mixer * s_mixer;
|
||||
static FxMixer * s_fxMixer;
|
||||
static song * s_song;
|
||||
static ResourceDB * s_workingDirResourceDB;
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* fifo_buffer.h - FIFO fixed-size buffer
|
||||
*
|
||||
* Copyright (c) 2007 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _FIFO_BUFFER_H
|
||||
#define _FIFO_BUFFER_H
|
||||
|
||||
#include <QtCore/QSemaphore>
|
||||
|
||||
|
||||
template<typename T>
|
||||
class fifoBuffer
|
||||
{
|
||||
public:
|
||||
fifoBuffer( int _size ) :
|
||||
m_readerSem( _size ),
|
||||
m_writerSem( _size ),
|
||||
m_readerIndex( 0 ),
|
||||
m_writerIndex( 0 ),
|
||||
m_size( _size )
|
||||
{
|
||||
m_buffer = new T[_size];
|
||||
m_readerSem.acquire( _size );
|
||||
}
|
||||
|
||||
~fifoBuffer()
|
||||
{
|
||||
delete[] m_buffer;
|
||||
m_readerSem.release( m_size );
|
||||
}
|
||||
|
||||
void write( T _element )
|
||||
{
|
||||
m_writerSem.acquire();
|
||||
m_buffer[m_writerIndex++] = _element;
|
||||
m_writerIndex %= m_size;
|
||||
m_readerSem.release();
|
||||
}
|
||||
|
||||
T read()
|
||||
{
|
||||
m_readerSem.acquire();
|
||||
T element = m_buffer[m_readerIndex++];
|
||||
m_readerIndex %= m_size;
|
||||
m_writerSem.release();
|
||||
return element;
|
||||
}
|
||||
|
||||
bool available()
|
||||
{
|
||||
return m_readerSem.available();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
QSemaphore m_readerSem;
|
||||
QSemaphore m_writerSem;
|
||||
int m_readerIndex;
|
||||
int m_writerIndex;
|
||||
int m_size;
|
||||
T * m_buffer;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#define _NOTE_PLAY_HANDLE_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
#include "note.h"
|
||||
#include "engine.h"
|
||||
#include "track.h"
|
||||
|
||||
@@ -31,6 +31,6 @@
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#ifndef _SAMPLE_PLAY_HANDLE_H
|
||||
#define _SAMPLE_PLAY_HANDLE_H
|
||||
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
#include "sample_buffer.h"
|
||||
#include "AutomatableModel.h"
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include <QtCore/QPair>
|
||||
#include <qobject.h>
|
||||
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
#include "sample_buffer.h"
|
||||
|
||||
class bbTrack;
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <QtCore/QMap>
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioBackend.h"
|
||||
#include "MidiClient.h"
|
||||
#include "MidiPort.h"
|
||||
#include "MidiPortMenu.h"
|
||||
@@ -171,7 +171,7 @@ private:
|
||||
bool m_disableChActInd;
|
||||
bool m_manualChPiano;
|
||||
|
||||
typedef QMap<QString, AudioDevice::setupWidget *> AswMap;
|
||||
typedef QMap<QString, AudioBackend::setupWidget *> AswMap;
|
||||
typedef QMap<QString, MidiClient::setupWidget *> MswMap;
|
||||
typedef QMap<QString, QString> trMap;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
#include "AutomatableModel.h"
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
|
||||
|
||||
class QPixmap;
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <QtGui/QWidget>
|
||||
#include <QtGui/QPixmap>
|
||||
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
|
||||
|
||||
class visualizationWidget : public QWidget
|
||||
|
||||
Reference in New Issue
Block a user