made quality-settings (internal processing samplerate, interpolation and so on) independent of audio-devices (final output) and added new qualitySettings-structure to mixer - might be still buggy and HQ-mode is currently not working, this is going to be fixed tomorrow, anyways important preparation for new project-export-dialog

git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@957 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
Tobias Doerffel
2008-05-05 23:14:48 +00:00
parent 2b7b813f2f
commit 5cfb1b2f96
57 changed files with 441 additions and 325 deletions

View File

@@ -1,7 +1,7 @@
/*
* audio_alsa.h - device-class that implements ALSA-PCM-output
*
* Copyright (c) 2004-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -51,8 +51,7 @@ class QLineEdit;
class audioALSA : public audioDevice, public QThread
{
public:
audioALSA( const sample_rate_t _sample_rate, bool & _success_ful,
mixer * _mixer );
audioALSA( bool & _success_ful, mixer * _mixer );
virtual ~audioALSA();
inline static QString name( void )
@@ -84,11 +83,9 @@ private:
virtual void stopProcessing( void );
virtual void run( void );
int FASTCALL setHWParams( const sample_rate_t _sample_rate,
const ch_cnt_t _channels,
snd_pcm_access_t _access );
int setHWParams( const ch_cnt_t _channels, snd_pcm_access_t _access );
int setSWParams( void );
int FASTCALL handleError( int _err );
int handleError( int _err );
snd_pcm_t * m_handle;

View File

@@ -1,7 +1,7 @@
/*
* audio_device.h - base-class for audio-devices, used by LMMS-mixer
*
* Copyright (c) 2004-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -34,13 +34,6 @@
#include <config.h>
#endif
#ifndef USE_3RDPARTY_LIBSRC
#include <samplerate.h>
#else
#include "src/3rdparty/samplerate/samplerate.h"
#endif
#include "mixer.h"
#include "tab_widget.h"
@@ -53,8 +46,7 @@ class audioPort;
class audioDevice
{
public:
audioDevice( const sample_rate_t _sample_rate,
const ch_cnt_t _channels, mixer * _mixer );
audioDevice( const ch_cnt_t _channels, mixer * _mixer );
virtual ~audioDevice();
inline void lock( void )
@@ -128,29 +120,29 @@ public:
protected:
// subclasses can re-implement this for being used in conjunction with
// processNextBuffer()
virtual void FASTCALL writeBuffer( const surroundSampleFrame * _ab,
virtual void writeBuffer( const surroundSampleFrame * _ab,
const fpp_t _frames,
const float _master_gain )
{
}
// called by according driver for fetching new sound-data
fpp_t FASTCALL getNextBuffer( surroundSampleFrame * _ab );
fpp_t getNextBuffer( surroundSampleFrame * _ab );
// convert a given audio-buffer to a buffer in signed 16-bit samples
// returns num of bytes in outbuf
Uint32 FASTCALL convertToS16( const surroundSampleFrame * _ab,
Uint32 convertToS16( const surroundSampleFrame * _ab,
const fpp_t _frames,
const float _master_gain,
int_sample_t * _output_buffer,
const bool _convert_endian = FALSE );
// clear given signed-int-16-buffer
void FASTCALL clearS16Buffer( int_sample_t * _outbuf,
void clearS16Buffer( int_sample_t * _outbuf,
const fpp_t _frames );
// resample given buffer from samplerate _src_sr to samplerate _dst_sr
void FASTCALL resample( const surroundSampleFrame * _src,
void resample( const surroundSampleFrame * _src,
const fpp_t _frames,
surroundSampleFrame * _dst,
const sample_rate_t _src_sr,

View File

@@ -1,7 +1,7 @@
/*
* audio_dummy.h - dummy-audio-device
*
* Copyright (c) 2004-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -33,9 +33,8 @@
class audioDummy : public audioDevice, public QThread
{
public:
audioDummy( const sample_rate_t _sample_rate, bool & _success_ful,
mixer * _mixer ) :
audioDevice( _sample_rate, DEFAULT_CHANNELS, _mixer )
audioDummy( bool & _success_ful, mixer * _mixer ) :
audioDevice( DEFAULT_CHANNELS, _mixer )
{
_success_ful = TRUE;
}
@@ -48,7 +47,7 @@ public:
inline static QString name( void )
{
return( QT_TRANSLATE_NOOP( "setupWidget",
"Dummy (no sound output)" ) );
"Dummy (no sound output)" ) );
}
@@ -110,7 +109,8 @@ private:
const Sint32 microseconds = static_cast<Sint32>(
getMixer()->framesPerPeriod() *
1000000.0f / getMixer()->sampleRate() -
1000000.0f /
getMixer()->processingSampleRate() -
timer.elapsed() );
if( microseconds > 0 )
{

View File

@@ -2,7 +2,7 @@
* audio_file_device.h - base-class for audio-device-classes which write
* their output into a file
*
* Copyright (c) 2004-2006 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*

View File

@@ -1,7 +1,7 @@
/*
* audio_jack.h - support for JACK-transport
*
* Copyright (c) 2005-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2005-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -52,8 +52,7 @@ class lcdSpinBox;
class audioJACK : public audioDevice
{
public:
audioJACK( const sample_rate_t _sample_rate, bool & _success_ful,
mixer * _mixer );
audioJACK( bool & _success_ful, mixer * _mixer );
virtual ~audioJACK();
inline static QString name( void )

View File

@@ -1,7 +1,7 @@
/*
* audio_oss.h - device-class that implements OSS-PCM-output
*
* Copyright (c) 2004-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -46,8 +46,7 @@ class QLineEdit;
class audioOSS : public audioDevice, public QThread
{
public:
audioOSS( const sample_rate_t _sample_rate, bool & _success_ful,
mixer * _mixer );
audioOSS( bool & _success_ful, mixer * _mixer );
virtual ~audioOSS();
inline static QString name( void )

View File

@@ -3,7 +3,7 @@
* surround-audio-buffers into RAM, maybe later
* also harddisk
*
* Copyright (c) 2004-2006 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -41,17 +41,16 @@ class sampleBuffer;
class audioSampleRecorder : public audioDevice
{
public:
audioSampleRecorder( const sample_rate_t _sample_rate,
const ch_cnt_t _channels, bool & _success_ful,
audioSampleRecorder( const ch_cnt_t _channels, bool & _success_ful,
mixer * _mixer );
virtual ~audioSampleRecorder();
f_cnt_t framesRecorded( void ) const;
void FASTCALL createSampleBuffer( sampleBuffer * * _sample_buf );
void createSampleBuffer( sampleBuffer * * _sample_buf );
private:
virtual void FASTCALL writeBuffer( const surroundSampleFrame * _ab,
virtual void writeBuffer( const surroundSampleFrame * _ab,
const fpp_t _frames,
const float _master_gain );

View File

@@ -1,7 +1,7 @@
/*
* audio_sdl.h - device-class that performs PCM-output via SDL
*
* Copyright (c) 2004-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -50,14 +50,13 @@ class QLineEdit;
class audioSDL : public audioDevice
{
public:
audioSDL( const sample_rate_t _sample_rate, bool & _success_ful,
mixer * _mixer );
audioSDL( bool & _success_ful, mixer * _mixer );
virtual ~audioSDL();
inline static QString name( void )
{
return( QT_TRANSLATE_NOOP( "setupWidget",
"SDL (Simple DirectMedia Layer)" ) );
"SDL (Simple DirectMedia Layer)" ) );
}

View File

@@ -52,7 +52,9 @@ public:
inline bool isSampleExact( void ) const
{
return m_sampleExact || engine::getMixer()->highQuality();
return m_sampleExact ||
engine::getMixer()->qualitySettings().
sampleExactControllers;
}
void setSampleExact( bool _exact )

View File

@@ -109,7 +109,8 @@ public:
inline f_cnt_t getTimeout( void ) const
{
const float samples = engine::getMixer()->sampleRate() *
const float samples =
engine::getMixer()->processingSampleRate() *
m_autoQuitModel.value() / 1000.0f;
return( 1 + ( static_cast<Uint32>( samples ) /
engine::getMixer()->framesPerPeriod() ) );

View File

@@ -30,6 +30,13 @@
#include <config.h>
#endif
#ifndef USE_3RDPARTY_LIBSRC
#include <samplerate.h>
#else
#include "src/3rdparty/samplerate/samplerate.h"
#endif
#include <QtCore/QMutex>
#include <QtCore/QSemaphore>
#include <QtCore/QThread>
@@ -58,16 +65,6 @@ const ch_cnt_t SURROUND_CHANNELS =
#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];
@@ -96,8 +93,103 @@ class 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,
Oversampling_16x
} ;
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( void ) const
{
switch( oversampling )
{
case Oversampling_None: return 1;
case Oversampling_2x: return 2;
case Oversampling_4x: return 4;
case Oversampling_8x: return 8;
case Oversampling_16x: return 16;
}
return( 1 );
}
int libsrcInterpolation( void ) const
{
switch( interpolation )
{
case Interpolation_Linear:
return( SRC_LINEAR );
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 );
void FASTCALL clear( void );
void clear( void );
// audio-device-stuff
@@ -106,7 +198,7 @@ public:
return( m_audioDevName );
}
void FASTCALL setAudioDevice( audioDevice * _dev, bool _hq );
void setAudioDevice( audioDevice * _dev );
void restoreAudioDevice( void );
inline audioDevice * audioDev( void )
{
@@ -199,16 +291,15 @@ public:
return( m_cpuLoad );
}
inline bool highQuality( void ) const
const qualitySettings & qualitySettings( void ) const
{
return( m_qualityLevel > DEFAULT_QUALITY_LEVEL );
return( m_qualitySettings );
}
inline sample_rate_t sampleRate( void ) const
{
return( SAMPLE_RATES[m_qualityLevel] );
}
sample_rate_t baseSampleRate( void ) const;
sample_rate_t outputSampleRate( void ) const;
sample_rate_t processingSampleRate( void ) const;
inline float masterGain( void ) const
@@ -268,7 +359,7 @@ public:
}
// audio-buffer-mgm
void FASTCALL bufferToPort( const sampleFrame * _buf,
void bufferToPort( const sampleFrame * _buf,
const fpp_t _frames,
const f_cnt_t _offset,
stereoVolumeVector _volume_vector,
@@ -295,11 +386,11 @@ public:
}
public slots:
void setHighQuality( bool _hq_on = FALSE );
void changeQuality( const struct qualitySettings & _qs );
signals:
void qualitySettingsChanged( void );
void sampleRateChanged( void );
void nextAudioBuffer( void );
@@ -371,7 +462,7 @@ private:
playHandleVector m_playHandles;
constPlayHandleVector m_playHandlesToRemove;
qualityLevels m_qualityLevel;
struct qualitySettings m_qualitySettings;
float m_masterGain;

View File

@@ -80,13 +80,12 @@ public:
virtual ~sampleBuffer();
bool FASTCALL play( sampleFrame * _ab, handleState * _state,
bool play( sampleFrame * _ab, handleState * _state,
const fpp_t _frames,
const float _freq = BaseFreq,
const bool _looped = FALSE ) const;
void FASTCALL visualize( QPainter & _p, const QRect & _dr,
const QRect & _clip );
void visualize( QPainter & _p, const QRect & _dr, const QRect & _clip );
inline void visualize( QPainter & _p, const QRect & _dr )
{
visualize( _p, _dr, _dr );
@@ -157,13 +156,12 @@ public:
QString & toBase64( QString & _dst ) const;
static sampleBuffer * FASTCALL resample( sampleFrame * _data,
static sampleBuffer * resample( sampleFrame * _data,
const f_cnt_t _frames,
const sample_rate_t _src_sr,
const sample_rate_t _dst_sr );
static inline sampleBuffer * FASTCALL resample(
sampleBuffer * _buf,
static inline sampleBuffer * resample( sampleBuffer * _buf,
const sample_rate_t _src_sr,
const sample_rate_t _dst_sr )
{
@@ -171,7 +169,7 @@ public:
_dst_sr ) );
}
void normalize_sample_rate( const sample_rate_t _src_sr,
void normalizeSampleRate( const sample_rate_t _src_sr,
bool _keep_settings = FALSE );
inline sample_t userWaveSample( const float _sample ) const
@@ -209,29 +207,25 @@ public slots:
private:
void FASTCALL update( bool _keep_settings = FALSE );
void update( bool _keep_settings = FALSE );
#ifdef SDL_SDL_SOUND_H
f_cnt_t FASTCALL decodeSampleSDL( const char * _f,
int_sample_t * & _buf,
f_cnt_t decodeSampleSDL( const char * _f, int_sample_t * & _buf,
ch_cnt_t _channels,
sample_rate_t _sample_rate );
#endif
#ifdef HAVE_SNDFILE_H
f_cnt_t FASTCALL decodeSampleSF( const char * _f,
int_sample_t * & _buf,
f_cnt_t decodeSampleSF( const char * _f, int_sample_t * & _buf,
ch_cnt_t & _channels,
sample_rate_t & _sample_rate );
#endif
#ifdef HAVE_VORBIS_VORBISFILE_H
f_cnt_t FASTCALL decodeSampleOGGVorbis( const char * _f,
int_sample_t * & _buf,
f_cnt_t decodeSampleOGGVorbis( const char * _f, int_sample_t * & _buf,
ch_cnt_t & _channels,
sample_rate_t & _sample_rate );
#endif
f_cnt_t FASTCALL decodeSampleDS( const char * _f,
int_sample_t * & _buf,
f_cnt_t decodeSampleDS( const char * _f, int_sample_t * & _buf,
ch_cnt_t & _channels,
sample_rate_t & _sample_rate );

View File

@@ -95,24 +95,24 @@ public:
void processNextBuffer( void );
inline bool paused( void ) const
inline bool isPaused( void ) const
{
return( m_paused );
}
inline bool playing( void ) const
inline bool isPlaying( void ) const
{
return( m_playing && m_exporting == FALSE );
}
inline bool exporting( void ) const
inline bool isExporting( void ) const
{
return( m_exporting );
}
bool realTimeTask( void ) const;
inline bool exportDone( void ) const
inline bool isExportDone( void ) const
{
return( m_exporting == TRUE &&
m_playPos[Mode_PlaySong].getTact() >= length() + 1 );
@@ -194,7 +194,7 @@ public slots:
void exportProject( void );
void startExport( void );
void stopExport( void );
void cancelExport( void );
void setModified( void );