2 * mixer.h - audio-device-independent mixer for LMMS
4 * Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
6 * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public
19 * License along with this program (see COPYING); if not, write to the
20 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301 USA.
28 #include "lmmsconfig.h"
30 #ifndef LMMS_USE_3RDPARTY_LIBSRC
31 #include <samplerate.h>
33 #ifndef OUT_OF_TREE_BUILD
34 #include "src/3rdparty/samplerate/samplerate.h"
36 #include <samplerate.h>
41 #include <QtCore/QMutex>
42 #include <QtCore/QThread>
43 #include <QtCore/QVector>
44 #include <QtCore/QWaitCondition>
47 #include "lmms_basics.h"
49 #include "fifo_buffer.h"
57 const fpp_t DEFAULT_BUFFER_SIZE
= 256;
59 const int BYTES_PER_SAMPLE
= sizeof( sample_t
);
60 const int BYTES_PER_INT_SAMPLE
= sizeof( int_sample_t
);
61 const int BYTES_PER_FRAME
= sizeof( sampleFrame
);
62 const int BYTES_PER_SURROUND_FRAME
= sizeof( surroundSampleFrame
);
64 const float OUTPUT_SAMPLE_MULTIPLIER
= 32767.0f
;
67 const float BaseFreq
= 440.0f
;
68 const Keys BaseKey
= Key_A
;
69 const Octaves BaseOctave
= DefaultOctave
;
72 #include "play_handle.h"
75 class MixerWorkerThread
;
78 class EXPORT mixer
: public QObject
82 struct qualitySettings
94 Interpolation_SincFastest
,
95 Interpolation_SincMedium
,
96 Interpolation_SincBest
107 Interpolation interpolation
;
108 Oversampling oversampling
;
109 bool sampleExactControllers
;
110 bool aliasFreeOscillators
;
112 qualitySettings( Mode _m
)
117 interpolation
= Interpolation_Linear
;
118 oversampling
= Oversampling_None
;
119 sampleExactControllers
= false;
120 aliasFreeOscillators
= false;
122 case Mode_HighQuality
:
124 Interpolation_SincFastest
;
125 oversampling
= Oversampling_2x
;
126 sampleExactControllers
= true;
127 aliasFreeOscillators
= false;
130 interpolation
= Interpolation_SincBest
;
131 oversampling
= Oversampling_8x
;
132 sampleExactControllers
= true;
133 aliasFreeOscillators
= true;
138 qualitySettings( Interpolation _i
, Oversampling _o
, bool _sec
,
142 sampleExactControllers( _sec
),
143 aliasFreeOscillators( _afo
)
147 int sampleRateMultiplier() const
149 switch( oversampling
)
151 case Oversampling_None
: return 1;
152 case Oversampling_2x
: return 2;
153 case Oversampling_4x
: return 4;
154 case Oversampling_8x
: return 8;
159 int libsrcInterpolation() const
161 switch( interpolation
)
163 case Interpolation_Linear
:
164 return SRC_ZERO_ORDER_HOLD
;
165 case Interpolation_SincFastest
:
166 return SRC_SINC_FASTEST
;
167 case Interpolation_SincMedium
:
168 return SRC_SINC_MEDIUM_QUALITY
;
169 case Interpolation_SincBest
:
170 return SRC_SINC_BEST_QUALITY
;
180 // audio-device-stuff
181 inline const QString
& audioDevName() const
183 return m_audioDevName
;
186 void setAudioDevice( AudioDevice
* _dev
);
187 void setAudioDevice( AudioDevice
* _dev
,
188 const struct qualitySettings
& _qs
,
190 void restoreAudioDevice();
191 inline AudioDevice
* audioDev()
198 inline void addAudioPort( AudioPort
* _port
)
201 m_audioPorts
.push_back( _port
);
205 void removeAudioPort( AudioPort
* _port
);
209 inline const QString
& midiClientName() const
211 return m_midiClientName
;
214 inline MidiClient
* midiClient()
221 inline bool addPlayHandle( playHandle
* _ph
)
223 if( criticalXRuns() == false )
226 m_playHandles
.push_back( _ph
);
234 void removePlayHandle( playHandle
* _ph
);
236 inline PlayHandleList
& playHandles()
238 return m_playHandles
;
241 void removePlayHandles( track
* _track
);
243 inline bool hasPlayHandles() const
245 return !m_playHandles
.empty();
249 // methods providing information for other classes
250 inline fpp_t
framesPerPeriod() const
252 return m_framesPerPeriod
;
255 inline const surroundSampleFrame
* currentReadBuffer() const
261 inline int cpuLoad() const
266 const qualitySettings
& currentQualitySettings() const
268 return m_qualitySettings
;
272 sample_rate_t
baseSampleRate() const;
273 sample_rate_t
outputSampleRate() const;
274 sample_rate_t
inputSampleRate() const;
275 sample_rate_t
processingSampleRate() const;
278 inline float masterGain() const
283 inline void setMasterGain( const float _mo
)
289 static inline sample_t
clip( const sample_t _s
)
295 else if( _s
< -1.0f
)
303 // methods needed by other threads to alter knob values, waveforms, etc
306 m_globalMutex
.lock();
311 m_globalMutex
.unlock();
314 void lockInputFrames()
316 m_inputFramesMutex
.lock();
319 void unlockInputFrames()
321 m_inputFramesMutex
.unlock();
325 void bufferToPort( const sampleFrame
* _buf
,
327 const f_cnt_t _offset
,
328 stereoVolumeVector _volume_vector
,
331 static void clearAudioBuffer( sampleFrame
* _ab
,
332 const f_cnt_t _frames
,
333 const f_cnt_t _offset
= 0 );
334 #ifndef LMMS_DISABLE_SURROUND
335 static void clearAudioBuffer( surroundSampleFrame
* _ab
,
336 const f_cnt_t _frames
,
337 const f_cnt_t _offset
= 0 );
340 static float peakValueLeft( sampleFrame
* _ab
, const f_cnt_t _frames
);
341 static float peakValueRight( sampleFrame
* _ab
, const f_cnt_t _frames
);
344 bool criticalXRuns() const;
346 inline bool hasFifoWriter() const
348 return m_fifoWriter
!= NULL
;
351 void pushInputFrames( sampleFrame
* _ab
, const f_cnt_t _frames
);
353 inline const sampleFrame
* inputBuffer()
355 return m_inputBuffer
[ m_inputBufferRead
];
358 inline f_cnt_t
inputBufferFrames() const
360 return m_inputBufferFrames
[ m_inputBufferRead
];
363 inline const surroundSampleFrame
* nextBuffer()
365 return hasFifoWriter() ? m_fifo
->read() : renderNextBuffer();
368 void changeQuality( const struct qualitySettings
& _qs
);
372 void qualitySettingsChanged();
373 void sampleRateChanged();
374 void nextAudioBuffer();
378 typedef fifoBuffer
<surroundSampleFrame
*> fifo
;
380 class fifoWriter
: public QThread
383 fifoWriter( mixer
* _mixer
, fifo
* _fifo
);
391 volatile bool m_writing
;
401 void startProcessing( bool _needs_fifo
= true );
402 void stopProcessing();
405 AudioDevice
* tryAudioDevices();
406 MidiClient
* tryMidiClients();
409 const surroundSampleFrame
* renderNextBuffer();
413 QVector
<AudioPort
*> m_audioPorts
;
415 fpp_t m_framesPerPeriod
;
417 sampleFrame
* m_workingBuf
;
419 sampleFrame
* m_inputBuffer
[2];
420 f_cnt_t m_inputBufferFrames
[2];
421 f_cnt_t m_inputBufferSize
[2];
422 int m_inputBufferRead
;
423 int m_inputBufferWrite
;
425 surroundSampleFrame
* m_readBuf
;
426 surroundSampleFrame
* m_writeBuf
;
428 QVector
<surroundSampleFrame
*> m_bufferPool
;
433 surroundSampleFrame m_maxClip
;
434 surroundSampleFrame m_previousSample
;
435 fpp_t m_halfStart
[SURROUND_CHANNELS
];
436 bool m_oldBuffer
[SURROUND_CHANNELS
];
437 bool m_newBuffer
[SURROUND_CHANNELS
];
440 QVector
<MixerWorkerThread
*> m_workers
;
442 QWaitCondition m_queueReadyWaitCond
;
445 PlayHandleList m_playHandles
;
446 ConstPlayHandleList m_playHandlesToRemove
;
448 struct qualitySettings m_qualitySettings
;
452 AudioDevice
* m_audioDev
;
453 AudioDevice
* m_oldAudioDev
;
454 QString m_audioDevName
;
457 MidiClient
* m_midiClient
;
458 QString m_midiClientName
;
461 QMutex m_globalMutex
;
462 QMutex m_inputFramesMutex
;
466 fifoWriter
* m_fifoWriter
;
470 friend class MixerWorkerThread
;