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:
@@ -30,7 +30,7 @@
|
||||
|
||||
#include "song.h"
|
||||
#include "engine.h"
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
#include "Controller.h"
|
||||
#include "ControllerConnection.h"
|
||||
#include "ControllerDialog.h"
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
|
||||
#include "song.h"
|
||||
#include "engine.h"
|
||||
#include "mixer.h"
|
||||
#include "ControllerConnection.h"
|
||||
|
||||
|
||||
|
||||
@@ -23,11 +23,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <QtXml/QDomElement>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "AudioOutputContext.h"
|
||||
#include "Effect.h"
|
||||
#include "engine.h"
|
||||
#include "DummyEffect.h"
|
||||
@@ -168,8 +168,8 @@ void Effect::reinitSRC()
|
||||
}
|
||||
int error;
|
||||
if( ( m_srcState[i] = src_new(
|
||||
engine::getMixer()->currentQualitySettings().
|
||||
libsrcInterpolation(),
|
||||
engine::mixer()->audioOutputContext()->
|
||||
qualitySettings().libsrcInterpolation(),
|
||||
DEFAULT_CHANNELS, &error ) ) == NULL )
|
||||
{
|
||||
fprintf( stderr, "Error: src_new() failed in effect.cpp!\n" );
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "EnvelopeAndLfoParameters.h"
|
||||
#include "debug.h"
|
||||
#include "engine.h"
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
#include "mmp.h"
|
||||
#include "Oscillator.h"
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
|
||||
#include "song.h"
|
||||
#include "engine.h"
|
||||
#include "mixer.h"
|
||||
#include "LfoController.h"
|
||||
#include "ControllerDialog.h"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* mixer.cpp - audio-device-independent mixer for LMMS
|
||||
* Mixer.cpp - Mixer for audio processing and rendering
|
||||
*
|
||||
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
@@ -24,7 +24,8 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "mixer.h"
|
||||
#include "AudioOutputContext.h"
|
||||
#include "Mixer.h"
|
||||
#include "FxMixer.h"
|
||||
#include "play_handle.h"
|
||||
#include "song.h"
|
||||
@@ -117,7 +118,7 @@ public:
|
||||
|
||||
static JobQueue s_jobQueue;
|
||||
|
||||
MixerWorkerThread( int _worker_num, mixer * _mixer ) :
|
||||
MixerWorkerThread( int _worker_num, Mixer * _mixer ) :
|
||||
QThread( _mixer ),
|
||||
m_workingBuf( CPU::allocFrames( _mixer->framesPerPeriod() ) ),
|
||||
m_workerNum( _worker_num ),
|
||||
@@ -166,7 +167,7 @@ private:
|
||||
sampleFrame * m_workingBuf;
|
||||
int m_workerNum;
|
||||
volatile bool m_quit;
|
||||
mixer * m_mixer;
|
||||
Mixer * m_mixer;
|
||||
QWaitCondition * m_queueReadyWaitCond;
|
||||
|
||||
} ;
|
||||
@@ -268,8 +269,11 @@ void MixerWorkerThread::processJobQueue()
|
||||
|
||||
|
||||
|
||||
mixer::mixer() :
|
||||
m_framesPerPeriod( DEFAULT_BUFFER_SIZE ),
|
||||
|
||||
Mixer::Mixer() :
|
||||
m_framesPerPeriod( qBound<int>( 32,
|
||||
configManager::inst()->value( "mixer", "framesperaudiobuffer" ).toInt(),
|
||||
DEFAULT_BUFFER_SIZE ) ),
|
||||
m_workingBuf( NULL ),
|
||||
m_inputBufferRead( 0 ),
|
||||
m_inputBufferWrite( 1 ),
|
||||
@@ -279,17 +283,16 @@ mixer::mixer() :
|
||||
m_workers(),
|
||||
m_numWorkers( QThread::idealThreadCount()-1 ),
|
||||
m_queueReadyWaitCond(),
|
||||
m_qualitySettings( qualitySettings::Mode_Draft ),
|
||||
m_masterGain( 1.0f ),
|
||||
m_audioDev( NULL ),
|
||||
m_oldAudioDev( NULL ),
|
||||
m_audioOutputContext( NULL ),
|
||||
m_defaultAudioOutputContext( NULL ),
|
||||
m_globalMutex( QMutex::Recursive )
|
||||
{
|
||||
for( int i = 0; i < 2; ++i )
|
||||
{
|
||||
m_inputBufferFrames[i] = 0;
|
||||
m_inputBufferSize[i] = DEFAULT_BUFFER_SIZE * 100;
|
||||
m_inputBuffer[i] = CPU::allocFrames(
|
||||
m_inputBuffer[i] = CPU::allocFrames(
|
||||
DEFAULT_BUFFER_SIZE * 100 );
|
||||
clearAudioBuffer( m_inputBuffer[i], m_inputBufferSize[i] );
|
||||
}
|
||||
@@ -299,38 +302,6 @@ mixer::mixer() :
|
||||
__fx_channel_jobs[i-1] = (fx_ch_t) i;
|
||||
}
|
||||
|
||||
// just rendering?
|
||||
if( !engine::hasGUI() )
|
||||
{
|
||||
m_framesPerPeriod = DEFAULT_BUFFER_SIZE;
|
||||
m_fifo = new fifo( 1 );
|
||||
}
|
||||
else if( configManager::inst()->value( "mixer", "framesperaudiobuffer"
|
||||
).toInt() >= 32 )
|
||||
{
|
||||
m_framesPerPeriod =
|
||||
(fpp_t) configManager::inst()->value( "mixer",
|
||||
"framesperaudiobuffer" ).toInt();
|
||||
|
||||
if( m_framesPerPeriod > DEFAULT_BUFFER_SIZE )
|
||||
{
|
||||
m_fifo = new fifo( m_framesPerPeriod
|
||||
/ DEFAULT_BUFFER_SIZE );
|
||||
m_framesPerPeriod = DEFAULT_BUFFER_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fifo = new fifo( 1 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
configManager::inst()->setValue( "mixer",
|
||||
"framesperaudiobuffer",
|
||||
QString::number( m_framesPerPeriod ) );
|
||||
m_fifo = new fifo( 1 );
|
||||
}
|
||||
|
||||
m_workingBuf = CPU::allocFrames( m_framesPerPeriod );
|
||||
for( Uint8 i = 0; i < 3; i++ )
|
||||
{
|
||||
@@ -352,12 +323,17 @@ mixer::mixer() :
|
||||
m_poolDepth = 2;
|
||||
m_readBuffer = 0;
|
||||
m_writeBuffer = 1;
|
||||
|
||||
// initialize default AudioOutputContext
|
||||
m_defaultAudioOutputContext = new AudioOutputContext( this, NULL,
|
||||
AudioOutputContext::QualitySettings::Preset_Draft );
|
||||
m_audioOutputContext = m_defaultAudioOutputContext;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
mixer::~mixer()
|
||||
Mixer::~Mixer()
|
||||
{
|
||||
// distribute an empty job-queue so that worker-threads
|
||||
// get out of their processing-loop
|
||||
@@ -372,13 +348,7 @@ mixer::~mixer()
|
||||
m_workers[w]->wait( 500 );
|
||||
}
|
||||
|
||||
while( m_fifo->available() )
|
||||
{
|
||||
delete[] m_fifo->read();
|
||||
}
|
||||
delete m_fifo;
|
||||
|
||||
delete m_audioDev;
|
||||
delete m_audioOutputContext;
|
||||
delete m_midiClient;
|
||||
|
||||
for( Uint8 i = 0; i < 3; i++ )
|
||||
@@ -392,54 +362,54 @@ mixer::~mixer()
|
||||
|
||||
|
||||
|
||||
void mixer::initDevices()
|
||||
void Mixer::initDevices()
|
||||
{
|
||||
m_audioDev = tryAudioDevices();
|
||||
audioOutputContext()->setAudioBackend( tryAudioBackends() );
|
||||
m_midiClient = tryMidiClients();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void mixer::startProcessing( bool _needs_fifo )
|
||||
void Mixer::setAudioOutputContext( AudioOutputContext * context )
|
||||
{
|
||||
if( _needs_fifo )
|
||||
{
|
||||
m_fifoWriter = new fifoWriter( this, m_fifo );
|
||||
m_fifoWriter->start( QThread::HighPriority );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fifoWriter = NULL;
|
||||
}
|
||||
stopProcessing();
|
||||
|
||||
m_audioDev->startProcessing();
|
||||
m_audioOutputContext = context;
|
||||
|
||||
//m_audioDev->applyQualitySettings();
|
||||
|
||||
emit sampleRateChanged();
|
||||
|
||||
startProcessing();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void mixer::stopProcessing()
|
||||
void Mixer::startProcessing()
|
||||
{
|
||||
if( m_fifoWriter != NULL )
|
||||
if( m_audioOutputContext )
|
||||
{
|
||||
m_fifoWriter->finish();
|
||||
m_audioDev->stopProcessing();
|
||||
m_fifoWriter->wait( 1000 );
|
||||
m_fifoWriter->terminate();
|
||||
delete m_fifoWriter;
|
||||
m_fifoWriter = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_audioDev->stopProcessing();
|
||||
m_audioOutputContext->startProcessing();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
sample_rate_t mixer::baseSampleRate() const
|
||||
void Mixer::stopProcessing()
|
||||
{
|
||||
if( m_audioOutputContext )
|
||||
{
|
||||
m_audioOutputContext->stopProcessing();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
sample_rate_t Mixer::baseSampleRate() const
|
||||
{
|
||||
sample_rate_t sr =
|
||||
configManager::inst()->value( "mixer", "samplerate" ).toInt();
|
||||
@@ -453,33 +423,36 @@ sample_rate_t mixer::baseSampleRate() const
|
||||
|
||||
|
||||
|
||||
sample_rate_t mixer::outputSampleRate() const
|
||||
sample_rate_t Mixer::outputSampleRate() const
|
||||
{
|
||||
return m_audioDev != NULL ? m_audioDev->sampleRate() :
|
||||
baseSampleRate();
|
||||
if( audioOutputContext()->audioBackend() )
|
||||
{
|
||||
return audioOutputContext()->audioBackend()->sampleRate();
|
||||
}
|
||||
return baseSampleRate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
sample_rate_t mixer::inputSampleRate() const
|
||||
sample_rate_t Mixer::inputSampleRate() const
|
||||
{
|
||||
return m_audioDev != NULL ? m_audioDev->sampleRate() :
|
||||
baseSampleRate();
|
||||
return outputSampleRate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
sample_rate_t mixer::processingSampleRate() const
|
||||
sample_rate_t Mixer::processingSampleRate() const
|
||||
{
|
||||
return outputSampleRate() * m_qualitySettings.sampleRateMultiplier();
|
||||
return outputSampleRate() *
|
||||
audioOutputContext()->qualitySettings().sampleRateMultiplier();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool mixer::criticalXRuns() const
|
||||
bool Mixer::criticalXRuns() const
|
||||
{
|
||||
return m_cpuLoad >= 99 && engine::getSong()->realTimeTask() == true;
|
||||
}
|
||||
@@ -487,14 +460,14 @@ bool mixer::criticalXRuns() const
|
||||
|
||||
|
||||
|
||||
void mixer::pushInputFrames( sampleFrame * _ab, const f_cnt_t _frames )
|
||||
void Mixer::pushInputFrames( sampleFrame * _ab, const f_cnt_t _frames )
|
||||
{
|
||||
lockInputFrames();
|
||||
|
||||
f_cnt_t frames = m_inputBufferFrames[ m_inputBufferWrite ];
|
||||
int size = m_inputBufferSize[ m_inputBufferWrite ];
|
||||
sampleFrame * buf = m_inputBuffer[ m_inputBufferWrite ];
|
||||
|
||||
|
||||
if( frames + _frames > size )
|
||||
{
|
||||
size = qMax( size * 2, frames + _frames );
|
||||
@@ -507,17 +480,17 @@ void mixer::pushInputFrames( sampleFrame * _ab, const f_cnt_t _frames )
|
||||
|
||||
buf = ab;
|
||||
}
|
||||
|
||||
|
||||
CPU::memCpy( &buf[ frames ], _ab, _frames * sizeof( sampleFrame ) );
|
||||
m_inputBufferFrames[ m_inputBufferWrite ] += _frames;
|
||||
|
||||
|
||||
unlockInputFrames();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
sampleFrameA * mixer::renderNextBuffer()
|
||||
sampleFrameA * Mixer::renderNextBuffer()
|
||||
{
|
||||
MicroTimer timer;
|
||||
static song::playPos last_metro_pos = -1;
|
||||
@@ -649,7 +622,7 @@ sampleFrameA * mixer::renderNextBuffer()
|
||||
|
||||
// removes all play-handles. this is neccessary, when the song is stopped ->
|
||||
// all remaining notes etc. would be played until their end
|
||||
void mixer::clear()
|
||||
void Mixer::clear()
|
||||
{
|
||||
// TODO: m_midiClient->noteOffAll();
|
||||
lock();
|
||||
@@ -669,7 +642,7 @@ void mixer::clear()
|
||||
|
||||
|
||||
|
||||
void mixer::bufferToPort( const sampleFrame * _buf,
|
||||
void Mixer::bufferToPort( const sampleFrame * _buf,
|
||||
const fpp_t _frames,
|
||||
const f_cnt_t _offset,
|
||||
stereoVolumeVector _vv,
|
||||
@@ -709,7 +682,7 @@ void mixer::bufferToPort( const sampleFrame * _buf,
|
||||
|
||||
|
||||
|
||||
void mixer::clearAudioBuffer( sampleFrame * _ab, const f_cnt_t _frames,
|
||||
void Mixer::clearAudioBuffer( sampleFrame * _ab, const f_cnt_t _frames,
|
||||
const f_cnt_t _offset )
|
||||
{
|
||||
if( likely( (size_t)( _ab+_offset ) % 16 == 0 && _frames % 8 == 0 ) )
|
||||
@@ -724,18 +697,8 @@ void mixer::clearAudioBuffer( sampleFrame * _ab, const f_cnt_t _frames,
|
||||
|
||||
|
||||
|
||||
#ifndef LMMS_DISABLE_SURROUND
|
||||
void 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( sampleFrame * _ab, const f_cnt_t _frames )
|
||||
float Mixer::peakValueLeft( sampleFrame * _ab, const f_cnt_t _frames )
|
||||
{
|
||||
float p = 0.0f;
|
||||
for( f_cnt_t f = 0; f < _frames; ++f )
|
||||
@@ -755,7 +718,7 @@ float mixer::peakValueLeft( sampleFrame * _ab, const f_cnt_t _frames )
|
||||
|
||||
|
||||
|
||||
float mixer::peakValueRight( sampleFrame * _ab, const f_cnt_t _frames )
|
||||
float Mixer::peakValueRight( sampleFrame * _ab, const f_cnt_t _frames )
|
||||
{
|
||||
float p = 0.0f;
|
||||
for( f_cnt_t f = 0; f < _frames; ++f )
|
||||
@@ -775,97 +738,7 @@ float mixer::peakValueRight( sampleFrame * _ab, const f_cnt_t _frames )
|
||||
|
||||
|
||||
|
||||
void mixer::changeQuality( const struct qualitySettings & _qs )
|
||||
{
|
||||
// don't delete the audio-device
|
||||
stopProcessing();
|
||||
|
||||
m_qualitySettings = _qs;
|
||||
m_audioDev->applyQualitySettings();
|
||||
|
||||
emit sampleRateChanged();
|
||||
emit qualitySettingsChanged();
|
||||
|
||||
startProcessing();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void mixer::setAudioDevice( AudioDevice * _dev )
|
||||
{
|
||||
stopProcessing();
|
||||
|
||||
m_oldAudioDev = m_audioDev;
|
||||
|
||||
if( _dev == NULL )
|
||||
{
|
||||
printf( "param _dev == NULL in mixer::setAudioDevice(...). "
|
||||
"Trying any working audio-device\n" );
|
||||
m_audioDev = tryAudioDevices();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_audioDev = _dev;
|
||||
}
|
||||
|
||||
emit sampleRateChanged();
|
||||
|
||||
startProcessing();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void mixer::setAudioDevice( AudioDevice * _dev,
|
||||
const struct qualitySettings & _qs,
|
||||
bool _needs_fifo )
|
||||
{
|
||||
// don't delete the audio-device
|
||||
stopProcessing();
|
||||
|
||||
m_qualitySettings = _qs;
|
||||
m_oldAudioDev = m_audioDev;
|
||||
|
||||
if( _dev == NULL )
|
||||
{
|
||||
printf( "param _dev == NULL in mixer::setAudioDevice(...). "
|
||||
"Trying any working audio-device\n" );
|
||||
m_audioDev = tryAudioDevices();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_audioDev = _dev;
|
||||
}
|
||||
|
||||
emit qualitySettingsChanged();
|
||||
emit sampleRateChanged();
|
||||
|
||||
startProcessing( _needs_fifo );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void mixer::restoreAudioDevice()
|
||||
{
|
||||
if( m_oldAudioDev != NULL )
|
||||
{
|
||||
stopProcessing();
|
||||
delete m_audioDev;
|
||||
|
||||
m_audioDev = m_oldAudioDev;
|
||||
emit sampleRateChanged();
|
||||
|
||||
m_oldAudioDev = NULL;
|
||||
startProcessing();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void mixer::removeAudioPort( AudioPort * _port )
|
||||
void Mixer::removeAudioPort( AudioPort * _port )
|
||||
{
|
||||
QVector<AudioPort *>::Iterator it = qFind( m_audioPorts.begin(),
|
||||
m_audioPorts.end(),
|
||||
@@ -881,7 +754,7 @@ void mixer::removeAudioPort( AudioPort * _port )
|
||||
|
||||
|
||||
|
||||
void mixer::removePlayHandle( playHandle * _ph )
|
||||
void Mixer::removePlayHandle( playHandle * _ph )
|
||||
{
|
||||
lock();
|
||||
// check thread affinity as we must not delete play-handles
|
||||
@@ -908,7 +781,7 @@ void mixer::removePlayHandle( playHandle * _ph )
|
||||
|
||||
|
||||
|
||||
void mixer::removePlayHandles( track * _track, playHandle::Type _type )
|
||||
void Mixer::removePlayHandles( track * _track, playHandle::Type _type )
|
||||
{
|
||||
lock();
|
||||
PlayHandleList::Iterator it = m_playHandles.begin();
|
||||
@@ -932,10 +805,10 @@ void mixer::removePlayHandles( track * _track, playHandle::Type _type )
|
||||
|
||||
|
||||
|
||||
AudioDevice * mixer::tryAudioDevices()
|
||||
AudioBackend * Mixer::tryAudioBackends()
|
||||
{
|
||||
bool success_ful = false;
|
||||
AudioDevice * dev = NULL;
|
||||
AudioBackend * dev = NULL;
|
||||
QString dev_name = configManager::inst()->value( "mixer", "audiodev" );
|
||||
|
||||
if( dev_name == AudioDummy::name() )
|
||||
@@ -946,7 +819,7 @@ AudioDevice * mixer::tryAudioDevices()
|
||||
#ifdef LMMS_HAVE_ALSA
|
||||
if( dev_name == AudioAlsa::name() || dev_name == "" )
|
||||
{
|
||||
dev = new AudioAlsa( success_ful, this );
|
||||
dev = new AudioAlsa( success_ful, audioOutputContext() );
|
||||
if( success_ful )
|
||||
{
|
||||
m_audioDevName = AudioAlsa::name();
|
||||
@@ -960,7 +833,7 @@ AudioDevice * mixer::tryAudioDevices()
|
||||
#ifdef LMMS_HAVE_PORTAUDIO
|
||||
if( dev_name == AudioPortAudio::name() || dev_name == "" )
|
||||
{
|
||||
dev = new AudioPortAudio( success_ful, this );
|
||||
dev = new AudioPortAudio( success_ful, audioOutputContext() );
|
||||
if( success_ful )
|
||||
{
|
||||
m_audioDevName = AudioPortAudio::name();
|
||||
@@ -974,7 +847,7 @@ AudioDevice * mixer::tryAudioDevices()
|
||||
#ifdef LMMS_HAVE_PULSEAUDIO
|
||||
if( dev_name == AudioPulseAudio::name() || dev_name == "" )
|
||||
{
|
||||
dev = new AudioPulseAudio( success_ful, this );
|
||||
dev = new AudioPulseAudio( success_ful, audioOutputContext() );
|
||||
if( success_ful )
|
||||
{
|
||||
m_audioDevName = AudioPulseAudio::name();
|
||||
@@ -988,7 +861,7 @@ AudioDevice * mixer::tryAudioDevices()
|
||||
#ifdef LMMS_HAVE_OSS
|
||||
if( dev_name == AudioOss::name() || dev_name == "" )
|
||||
{
|
||||
dev = new AudioOss( success_ful, this );
|
||||
dev = new AudioOss( success_ful, audioOutputContext() );
|
||||
if( success_ful )
|
||||
{
|
||||
m_audioDevName = AudioOss::name();
|
||||
@@ -1002,7 +875,7 @@ AudioDevice * mixer::tryAudioDevices()
|
||||
#ifdef LMMS_HAVE_JACK
|
||||
if( dev_name == AudioJack::name() || dev_name == "" )
|
||||
{
|
||||
dev = new AudioJack( success_ful, this );
|
||||
dev = new AudioJack( success_ful, audioOutputContext() );
|
||||
if( success_ful )
|
||||
{
|
||||
m_audioDevName = AudioJack::name();
|
||||
@@ -1016,7 +889,7 @@ AudioDevice * mixer::tryAudioDevices()
|
||||
#ifdef LMMS_HAVE_SDL
|
||||
if( dev_name == AudioSdl::name() || dev_name == "" )
|
||||
{
|
||||
dev = new AudioSdl( success_ful, this );
|
||||
dev = new AudioSdl( success_ful, audioOutputContext() );
|
||||
if( success_ful )
|
||||
{
|
||||
m_audioDevName = AudioSdl::name();
|
||||
@@ -1027,7 +900,7 @@ AudioDevice * mixer::tryAudioDevices()
|
||||
#endif
|
||||
|
||||
// add more device-classes here...
|
||||
//dev = new audioXXXX( SAMPLE_RATES[m_qualityLevel], success_ful, this );
|
||||
//dev = new audioXXXX( SAMPLE_RATES[m_qualityLevel], success_ful, audioOutputContext() );
|
||||
//if( sucess_ful )
|
||||
//{
|
||||
// return dev;
|
||||
@@ -1040,13 +913,13 @@ AudioDevice * mixer::tryAudioDevices()
|
||||
|
||||
m_audioDevName = AudioDummy::name();
|
||||
|
||||
return new AudioDummy( success_ful, this );
|
||||
return new AudioDummy( success_ful, audioOutputContext() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
MidiClient * mixer::tryMidiClients()
|
||||
MidiClient * Mixer::tryMidiClients()
|
||||
{
|
||||
QString client_name = configManager::inst()->value( "mixer",
|
||||
"mididev" );
|
||||
@@ -1111,57 +984,5 @@ MidiClient * mixer::tryMidiClients()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
mixer::fifoWriter::fifoWriter( mixer * _mixer, fifo * _fifo ) :
|
||||
m_mixer( _mixer ),
|
||||
m_fifo( _fifo ),
|
||||
m_writing( true )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void mixer::fifoWriter::finish()
|
||||
{
|
||||
m_writing = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void mixer::fifoWriter::run()
|
||||
{
|
||||
#if 0
|
||||
#ifdef LMMS_BUILD_LINUX
|
||||
#ifdef LMMS_HAVE_PTHREAD_H
|
||||
cpu_set_t mask;
|
||||
CPU_ZERO( &mask );
|
||||
CPU_SET( 0, &mask );
|
||||
pthread_setaffinity_np( pthread_self(), sizeof( mask ), &mask );
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const fpp_t frames = m_mixer->framesPerPeriod();
|
||||
while( m_writing )
|
||||
{
|
||||
sampleFrameA * buffer = CPU::allocFrames( frames );
|
||||
const sampleFrameA * b = m_mixer->renderNextBuffer();
|
||||
CPU::memCpy( buffer, b, frames * sizeof( sampleFrameA ) );
|
||||
m_fifo->write( buffer );
|
||||
}
|
||||
|
||||
m_fifo->write( NULL );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include "moc_mixer.cxx"
|
||||
#include "moc_Mixer.cxx"
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#include "Oscillator.h"
|
||||
#include "engine.h"
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
#include "AutomatableModel.h"
|
||||
|
||||
|
||||
@@ -55,9 +55,9 @@ Oscillator::Oscillator( const IntModel * _wave_shape_model,
|
||||
void Oscillator::update( sampleFrame * _ab, const fpp_t _frames,
|
||||
const ch_cnt_t _chnl )
|
||||
{
|
||||
if( m_freq >= engine::getMixer()->processingSampleRate() / 2 )
|
||||
if( m_freq >= engine::mixer()->processingSampleRate() / 2 )
|
||||
{
|
||||
mixer::clearAudioBuffer( _ab, _frames );
|
||||
Mixer::clearAudioBuffer( _ab, _frames );
|
||||
return;
|
||||
}
|
||||
if( m_subOsc != NULL )
|
||||
@@ -456,7 +456,7 @@ void Oscillator::updateFM( sampleFrame * _ab, const fpp_t _frames,
|
||||
recalcPhase();
|
||||
const float osc_coeff = m_freq * m_detuning;
|
||||
const float sampleRateCorrection = 44100.0f /
|
||||
engine::getMixer()->processingSampleRate();
|
||||
engine::mixer()->processingSampleRate();
|
||||
|
||||
for( fpp_t frame = 0; frame < _frames; ++frame )
|
||||
{
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
#include "song.h"
|
||||
#include "engine.h"
|
||||
#include "mixer.h"
|
||||
#include "PeakController.h"
|
||||
#include "ControllerDialog.h"
|
||||
#include "plugins/peak_controller_effect/peak_controller_effect.h"
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "Plugin.h"
|
||||
#include "embed.h"
|
||||
#include "engine.h"
|
||||
#include "mixer.h"
|
||||
#include "config_mgr.h"
|
||||
#include "DummyPlugin.h"
|
||||
#include "AutomatableModel.h"
|
||||
|
||||
@@ -77,17 +77,19 @@ FileEncodeDevice __fileEncodeDevices[] =
|
||||
const char * ProjectRenderer::EFF_ext[] = {"wav", "ogg", "mp3", "flac"};
|
||||
|
||||
|
||||
ProjectRenderer::ProjectRenderer( const mixer::qualitySettings & _qs,
|
||||
ProjectRenderer::ProjectRenderer(
|
||||
const AudioOutputContext::QualitySettings & _qs,
|
||||
const OutputSettings & _os,
|
||||
ExportFileFormats _file_format,
|
||||
const QString & _out_file ) :
|
||||
QThread( engine::getMixer() ),
|
||||
m_fileDev( NULL ),
|
||||
m_qualitySettings( _qs ),
|
||||
m_oldQualitySettings( engine::getMixer()->currentQualitySettings() ),
|
||||
m_progress( 0 ),
|
||||
m_abort( false )
|
||||
{
|
||||
m_context = new AudioOutputContext( engine::getMixer(),
|
||||
NULL,
|
||||
_qs );
|
||||
if( __fileEncodeDevices[_file_format].m_getDevInst == NULL )
|
||||
{
|
||||
return;
|
||||
@@ -100,13 +102,15 @@ ProjectRenderer::ProjectRenderer( const mixer::qualitySettings & _qs,
|
||||
_os.bitrate, _os.bitrate - 64, _os.bitrate + 64,
|
||||
_os.depth == Depth_32Bit ? 32 :
|
||||
( _os.depth == Depth_24Bit ? 24 : 16 ),
|
||||
engine::getMixer() );
|
||||
m_context );
|
||||
if( success_ful == false )
|
||||
{
|
||||
delete m_fileDev;
|
||||
m_fileDev = NULL;
|
||||
}
|
||||
|
||||
m_context->setAudioBackend( m_fileDev );
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -114,6 +118,7 @@ ProjectRenderer::ProjectRenderer( const mixer::qualitySettings & _qs,
|
||||
|
||||
ProjectRenderer::~ProjectRenderer()
|
||||
{
|
||||
delete m_fileDev;
|
||||
}
|
||||
|
||||
|
||||
@@ -129,12 +134,12 @@ ProjectRenderer::ExportFileFormats ProjectRenderer::getFileFormatFromExtension(
|
||||
{
|
||||
if( QString( __fileEncodeDevices[idx].m_extension ) == _ext )
|
||||
{
|
||||
return( __fileEncodeDevices[idx].m_fileFormat );
|
||||
return __fileEncodeDevices[idx].m_fileFormat;
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
|
||||
return( WaveFile ); // default
|
||||
return WaveFile; // default
|
||||
}
|
||||
|
||||
|
||||
@@ -144,11 +149,12 @@ void ProjectRenderer::startProcessing()
|
||||
{
|
||||
if( isReady() )
|
||||
{
|
||||
connect( this, SIGNAL( finished() ), this, SLOT( finishProcessing() ) );
|
||||
|
||||
// have to do mixer stuff with GUI-thread-affinity in order to
|
||||
// make slots connected to sampleRateChanged()-signals being
|
||||
// called immediately
|
||||
engine::getMixer()->setAudioDevice( m_fileDev,
|
||||
m_qualitySettings, false );
|
||||
engine::mixer()->setAudioOutputContext( m_context );
|
||||
|
||||
start(
|
||||
#ifndef LMMS_BUILD_WIN32
|
||||
@@ -160,6 +166,49 @@ void ProjectRenderer::startProcessing()
|
||||
|
||||
|
||||
|
||||
|
||||
void ProjectRenderer::abortProcessing()
|
||||
{
|
||||
m_abort = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void ProjectRenderer::updateConsoleProgress()
|
||||
{
|
||||
const int cols = 50;
|
||||
static int rot = 0;
|
||||
char buf[80];
|
||||
char prog[cols+1];
|
||||
|
||||
if( m_fileDev == NULL ){
|
||||
qWarning("Error occured. Aborting render.");
|
||||
m_consoleUpdateTimer->stop();
|
||||
delete m_consoleUpdateTimer;
|
||||
// TODO: kill the program. I can't figure out how to do it...
|
||||
return;
|
||||
}
|
||||
|
||||
for( int i = 0; i < cols; ++i )
|
||||
{
|
||||
prog[i] = ( i*100/cols <= m_progress ? '-' : ' ' );
|
||||
}
|
||||
prog[cols] = 0;
|
||||
|
||||
const char * activity = (const char *) "|/-\\";
|
||||
memset( buf, 0, sizeof( buf ) );
|
||||
sprintf( buf, "\r|%s| %3d%% %c ", prog, m_progress,
|
||||
activity[rot] );
|
||||
rot = ( rot+1 ) % 4;
|
||||
|
||||
fprintf( stderr, "%s", buf );
|
||||
fflush( stderr );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void ProjectRenderer::run()
|
||||
{
|
||||
#if 0
|
||||
@@ -194,11 +243,17 @@ void ProjectRenderer::run()
|
||||
}
|
||||
|
||||
engine::getSong()->stopExport();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void ProjectRenderer::finishProcessing()
|
||||
{
|
||||
const QString f = m_fileDev->outputFile();
|
||||
|
||||
engine::getMixer()->restoreAudioDevice(); // also deletes audio-dev
|
||||
engine::getMixer()->changeQuality( m_oldQualitySettings );
|
||||
engine::mixer()->setAudioOutputContext(
|
||||
engine::mixer()->defaultAudioOutputContext() );
|
||||
|
||||
// if the user aborted export-process, the file has to be deleted
|
||||
if( m_abort )
|
||||
@@ -209,46 +264,5 @@ void ProjectRenderer::run()
|
||||
|
||||
|
||||
|
||||
|
||||
void ProjectRenderer::abortProcessing()
|
||||
{
|
||||
m_abort = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ProjectRenderer::updateConsoleProgress()
|
||||
{
|
||||
const int cols = 50;
|
||||
static int rot = 0;
|
||||
char buf[80];
|
||||
char prog[cols+1];
|
||||
|
||||
if( m_fileDev == NULL ){
|
||||
qWarning("Error occured. Aborting render.");
|
||||
m_consoleUpdateTimer->stop();
|
||||
delete m_consoleUpdateTimer;
|
||||
// TODO: kill the program. I can't figure out how to do it...
|
||||
return;
|
||||
}
|
||||
|
||||
for( int i = 0; i < cols; ++i )
|
||||
{
|
||||
prog[i] = ( i*100/cols <= m_progress ? '-' : ' ' );
|
||||
}
|
||||
prog[cols] = 0;
|
||||
|
||||
const char * activity = (const char *) "|/-\\";
|
||||
memset( buf, 0, sizeof( buf ) );
|
||||
sprintf( buf, "\r|%s| %3d%% %c ", prog, m_progress,
|
||||
activity[rot] );
|
||||
rot = ( rot+1 ) % 4;
|
||||
|
||||
fprintf( stderr, "%s", buf );
|
||||
fflush( stderr );
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "moc_ProjectRenderer.cxx"
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#endif
|
||||
|
||||
#include "RemotePlugin.h"
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
#include "engine.h"
|
||||
#include "config_mgr.h"
|
||||
|
||||
|
||||
@@ -40,11 +40,11 @@
|
||||
|
||||
|
||||
|
||||
AudioAlsa::AudioAlsa( bool & _success_ful, mixer * _mixer ) :
|
||||
AudioDevice( tLimit<ch_cnt_t>(
|
||||
AudioAlsa::AudioAlsa( bool & _success_ful, AudioOutputContext * context ) :
|
||||
AudioBackend( tLimit<ch_cnt_t>(
|
||||
configManager::inst()->value( "audioalsa", "channels" ).toInt(),
|
||||
DEFAULT_CHANNELS, SURROUND_CHANNELS ),
|
||||
_mixer ),
|
||||
context ),
|
||||
m_handle( NULL ),
|
||||
m_hwParams( NULL ),
|
||||
m_swParams( NULL ),
|
||||
@@ -201,7 +201,7 @@ void AudioAlsa::applyQualitySettings()
|
||||
{
|
||||
if( hqAudio() )
|
||||
{
|
||||
setSampleRate( engine::getMixer()->processingSampleRate() );
|
||||
setSampleRate( mixer()->processingSampleRate() );
|
||||
|
||||
if( m_handle != NULL )
|
||||
{
|
||||
@@ -233,8 +233,6 @@ void AudioAlsa::applyQualitySettings()
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
AudioDevice::applyQualitySettings();
|
||||
}
|
||||
|
||||
|
||||
@@ -242,16 +240,15 @@ void AudioAlsa::applyQualitySettings()
|
||||
|
||||
void AudioAlsa::run()
|
||||
{
|
||||
sampleFrameA * temp = CPU::allocFrames(
|
||||
getMixer()->framesPerPeriod() );
|
||||
sampleFrameA * temp = CPU::allocFrames( mixer()->framesPerPeriod() );
|
||||
intSampleFrameA * outbuf = (intSampleFrameA *)
|
||||
CPU::memAlloc( sizeof( intSampleFrameA ) * channels() /
|
||||
DEFAULT_CHANNELS * getMixer()->framesPerPeriod() );
|
||||
DEFAULT_CHANNELS * mixer()->framesPerPeriod() );
|
||||
|
||||
int_sample_t * pcmbuf = new int_sample_t[m_periodSize * channels()];
|
||||
|
||||
|
||||
int outbuf_size = getMixer()->framesPerPeriod() * channels();
|
||||
int outbuf_size = mixer()->framesPerPeriod() * channels();
|
||||
int outbuf_pos = 0;
|
||||
int pcmbuf_size = m_periodSize * channels();
|
||||
|
||||
@@ -274,7 +271,7 @@ void AudioAlsa::run()
|
||||
outbuf_size = frames * channels();
|
||||
|
||||
CPU::convertToS16( temp, outbuf, frames,
|
||||
getMixer()->masterGain(),
|
||||
mixer()->masterGain(),
|
||||
m_convertEndian );
|
||||
}
|
||||
int min_len = qMin( len, outbuf_size - outbuf_pos );
|
||||
@@ -374,7 +371,7 @@ int AudioAlsa::setHWParams( const ch_cnt_t _channels, snd_pcm_access_t _access )
|
||||
sampleRate(), 0 ) ) < 0 )
|
||||
{
|
||||
if( ( err = snd_pcm_hw_params_set_rate( m_handle, m_hwParams,
|
||||
getMixer()->baseSampleRate(), 0 ) ) < 0 )
|
||||
mixer()->baseSampleRate(), 0 ) ) < 0 )
|
||||
{
|
||||
printf( "Could not set sample rate: %s\n",
|
||||
snd_strerror( err ) );
|
||||
@@ -382,7 +379,7 @@ int AudioAlsa::setHWParams( const ch_cnt_t _channels, snd_pcm_access_t _access )
|
||||
}
|
||||
}
|
||||
|
||||
m_periodSize = getMixer()->framesPerPeriod();
|
||||
m_periodSize = mixer()->framesPerPeriod();
|
||||
m_bufferSize = m_periodSize * 8;
|
||||
dir = 0;
|
||||
err = snd_pcm_hw_params_set_period_size_near( m_handle, m_hwParams,
|
||||
@@ -493,7 +490,7 @@ int AudioAlsa::setSWParams()
|
||||
|
||||
|
||||
AudioAlsa::setupWidget::setupWidget( QWidget * _parent ) :
|
||||
AudioDevice::setupWidget( AudioAlsa::name(), _parent )
|
||||
AudioBackend::setupWidget( AudioAlsa::name(), _parent )
|
||||
{
|
||||
|
||||
m_device = new QComboBox( this );
|
||||
|
||||
144
src/core/audio/AudioBackend.cpp
Normal file
144
src/core/audio/AudioBackend.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* AudioBackend.cpp - base-class for audio-devices used by LMMS-mixer
|
||||
*
|
||||
* Copyright (c) 2004-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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "AudioBackend.h"
|
||||
#include "AudioOutputContext.h"
|
||||
#include "config_mgr.h"
|
||||
#include "debug.h"
|
||||
#include "Cpu.h"
|
||||
|
||||
|
||||
|
||||
AudioBackend::AudioBackend( const ch_cnt_t _channels,
|
||||
AudioOutputContext * context ) :
|
||||
m_supportsCapture( false ),
|
||||
m_context( context ),
|
||||
m_sampleRate( mixer()->processingSampleRate() ),
|
||||
m_channels( _channels ),
|
||||
m_buffer( CPU::allocFrames( mixer()->framesPerPeriod() ) )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
AudioBackend::~AudioBackend()
|
||||
{
|
||||
CPU::freeFrames( m_buffer );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int AudioBackend::processNextBuffer()
|
||||
{
|
||||
const int frames = getNextBuffer( m_buffer );
|
||||
if( frames )
|
||||
{
|
||||
writeBuffer( m_buffer, frames, mixer()->masterGain() );
|
||||
}
|
||||
return frames;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int AudioBackend::getNextBuffer( sampleFrameA * _ab )
|
||||
{
|
||||
return outputContext()->getCurrentOutputBuffer( _ab, sampleRate() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioBackend::stopProcessing()
|
||||
{
|
||||
// flush AudioOutputContext's FIFO
|
||||
while( processNextBuffer() )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioBackend::applyQualitySettings()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioBackend::registerPort( AudioPort * )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioBackend::unregisterPort( AudioPort * _port )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioBackend::renamePort( AudioPort * )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioBackend::clearS16Buffer( intSampleFrameA * _outbuf, const fpp_t _frames )
|
||||
{
|
||||
CPU::memClear( _outbuf, _frames * sizeof( *_outbuf ) );
|
||||
// memset( _outbuf, 0, _frames * channels() * BYTES_PER_INT_SAMPLE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool AudioBackend::hqAudio() const
|
||||
{
|
||||
return configManager::inst()->value( "mixer", "hqaudio" ).toInt();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const Mixer * AudioBackend::mixer() const
|
||||
{
|
||||
return outputContext()->mixer();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Mixer * AudioBackend::mixer()
|
||||
{
|
||||
return outputContext()->mixer();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,208 +0,0 @@
|
||||
/*
|
||||
* AudioDevice.cpp - base-class for audio-devices used by LMMS-mixer
|
||||
*
|
||||
* Copyright (c) 2004-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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "AudioDevice.h"
|
||||
#include "config_mgr.h"
|
||||
#include "debug.h"
|
||||
#include "Cpu.h"
|
||||
|
||||
|
||||
|
||||
AudioDevice::AudioDevice( const ch_cnt_t _channels, mixer * _mixer ) :
|
||||
m_supportsCapture( false ),
|
||||
m_sampleRate( _mixer->processingSampleRate() ),
|
||||
m_channels( _channels ),
|
||||
m_mixer( _mixer ),
|
||||
m_buffer( CPU::allocFrames( getMixer()->framesPerPeriod() ) )
|
||||
{
|
||||
int error;
|
||||
if( ( m_srcState = src_new(
|
||||
getMixer()->currentQualitySettings().libsrcInterpolation(),
|
||||
SURROUND_CHANNELS, &error ) ) == NULL )
|
||||
{
|
||||
printf( "Error: src_new() failed in audio_device.cpp!\n" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
AudioDevice::~AudioDevice()
|
||||
{
|
||||
src_delete( m_srcState );
|
||||
CPU::freeFrames( m_buffer );
|
||||
|
||||
m_devMutex.tryLock();
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioDevice::processNextBuffer()
|
||||
{
|
||||
const fpp_t frames = getNextBuffer( m_buffer );
|
||||
if( frames )
|
||||
{
|
||||
writeBuffer( m_buffer, frames, getMixer()->masterGain() );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_inProcess = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
fpp_t AudioDevice::getNextBuffer( sampleFrameA * _ab )
|
||||
{
|
||||
fpp_t frames = getMixer()->framesPerPeriod();
|
||||
sampleFrameA * b = getMixer()->nextBuffer();
|
||||
if( !b )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// make sure, no other thread is accessing device
|
||||
lock();
|
||||
|
||||
// resample if neccessary
|
||||
if( getMixer()->processingSampleRate() != m_sampleRate )
|
||||
{
|
||||
resample( b, frames, _ab, getMixer()->processingSampleRate(),
|
||||
m_sampleRate );
|
||||
frames = frames * m_sampleRate /
|
||||
getMixer()->processingSampleRate();
|
||||
}
|
||||
else
|
||||
{
|
||||
CPU::memCpy( _ab, b, frames * sizeof( surroundSampleFrame ) );
|
||||
}
|
||||
|
||||
// release lock
|
||||
unlock();
|
||||
|
||||
if( getMixer()->hasFifoWriter() )
|
||||
{
|
||||
CPU::freeFrames( b );
|
||||
}
|
||||
|
||||
return frames;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioDevice::stopProcessing()
|
||||
{
|
||||
if( getMixer()->hasFifoWriter() )
|
||||
{
|
||||
while( m_inProcess )
|
||||
{
|
||||
processNextBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioDevice::applyQualitySettings()
|
||||
{
|
||||
src_delete( m_srcState );
|
||||
|
||||
int error;
|
||||
if( ( m_srcState = src_new(
|
||||
getMixer()->currentQualitySettings().libsrcInterpolation(),
|
||||
SURROUND_CHANNELS, &error ) ) == NULL )
|
||||
{
|
||||
printf( "Error: src_new() failed in audio_device.cpp!\n" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioDevice::registerPort( AudioPort * )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioDevice::unregisterPort( AudioPort * _port )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioDevice::renamePort( AudioPort * )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioDevice::resample( const sampleFrame * _src, const fpp_t _frames,
|
||||
sampleFrame * _dst,
|
||||
const sample_rate_t _src_sr,
|
||||
const sample_rate_t _dst_sr )
|
||||
{
|
||||
if( m_srcState == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_srcData.input_frames = _frames;
|
||||
m_srcData.output_frames = _frames;
|
||||
m_srcData.data_in = (float *) _src[0];
|
||||
m_srcData.data_out = _dst[0];
|
||||
m_srcData.src_ratio = (double) _dst_sr / _src_sr;
|
||||
m_srcData.end_of_input = 0;
|
||||
int error;
|
||||
if( ( error = src_process( m_srcState, &m_srcData ) ) )
|
||||
{
|
||||
printf( "AudioDevice::resample(): error while resampling: %s\n",
|
||||
src_strerror( error ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AudioDevice::clearS16Buffer( intSampleFrameA * _outbuf, const fpp_t _frames )
|
||||
{
|
||||
CPU::memClear( _outbuf, _frames * sizeof( *_outbuf ) );
|
||||
// memset( _outbuf, 0, _frames * channels() * BYTES_PER_INT_SAMPLE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool AudioDevice::hqAudio() const
|
||||
{
|
||||
return configManager::inst()->value( "mixer", "hqaudio" ).toInt();
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,8 @@ AudioFileDevice::AudioFileDevice( const sample_rate_t _sample_rate,
|
||||
const bitrate_t _min_bitrate,
|
||||
const bitrate_t _max_bitrate,
|
||||
const int _depth,
|
||||
mixer * _mixer ) :
|
||||
AudioDevice( _channels, _mixer ),
|
||||
AudioOutputContext * context ) :
|
||||
AudioBackend( _channels, context ),
|
||||
m_outputFile( _file ),
|
||||
m_useVbr( _use_vbr ),
|
||||
m_nomBitrate( _nom_bitrate ),
|
||||
|
||||
@@ -37,9 +37,9 @@ AudioFileFlac::AudioFileFlac( const sample_rate_t _sample_rate,
|
||||
const ch_cnt_t _channels, bool & _success_ful, const QString & _file,
|
||||
const bool _use_vbr, const bitrate_t _nom_bitrate,
|
||||
const bitrate_t _min_bitrate, const bitrate_t _max_bitrate,
|
||||
const int _depth, mixer * _mixer ) :
|
||||
const int _depth, AudioOutputContext * context ) :
|
||||
AudioFileDevice( _sample_rate, _channels, _file, _use_vbr, _nom_bitrate,
|
||||
_min_bitrate, _max_bitrate, _depth, _mixer )
|
||||
_min_bitrate, _max_bitrate, _depth, context )
|
||||
{
|
||||
_success_ful = startEncoding();
|
||||
}
|
||||
|
||||
@@ -38,9 +38,9 @@ AudioFileMp3::AudioFileMp3( const sample_rate_t _sample_rate,
|
||||
const ch_cnt_t _channels, bool & _success_ful, const QString & _file,
|
||||
const bool _use_vbr, const bitrate_t _nom_bitrate,
|
||||
const bitrate_t _min_bitrate, const bitrate_t _max_bitrate,
|
||||
const int _depth, mixer * _mixer ) :
|
||||
const int _depth, AudioOutputContext * context ) :
|
||||
AudioFileDevice( _sample_rate, _channels, _file, _use_vbr, _nom_bitrate,
|
||||
_min_bitrate, _max_bitrate, _depth, _mixer ),
|
||||
_min_bitrate, _max_bitrate, _depth, context ),
|
||||
m_lgf( NULL ),
|
||||
m_lame( LameLibrary() ),
|
||||
m_outfile( NULL ),
|
||||
|
||||
@@ -44,10 +44,10 @@ AudioFileOgg::AudioFileOgg( const sample_rate_t _sample_rate,
|
||||
const bitrate_t _min_bitrate,
|
||||
const bitrate_t _max_bitrate,
|
||||
const int _depth,
|
||||
mixer * _mixer ) :
|
||||
AudioOutputContext * context ) :
|
||||
AudioFileDevice( _sample_rate, _channels, _file, _use_vbr,
|
||||
_nom_bitrate, _min_bitrate, _max_bitrate,
|
||||
_depth, _mixer )
|
||||
_depth, context )
|
||||
{
|
||||
m_ok = _success_ful = startEncoding();
|
||||
}
|
||||
|
||||
@@ -36,10 +36,10 @@ AudioFileWave::AudioFileWave( const sample_rate_t _sample_rate,
|
||||
const bitrate_t _min_bitrate,
|
||||
const bitrate_t _max_bitrate,
|
||||
const int _depth,
|
||||
mixer * _mixer ) :
|
||||
AudioOutputContext * context ) :
|
||||
AudioFileDevice( _sample_rate, _channels, _file, _use_vbr,
|
||||
_nom_bitrate, _min_bitrate, _max_bitrate,
|
||||
_depth, _mixer )
|
||||
_depth, context )
|
||||
{
|
||||
_success_ful = startEncoding();
|
||||
}
|
||||
@@ -59,7 +59,7 @@ bool AudioFileWave::startEncoding()
|
||||
{
|
||||
m_si.samplerate = sampleRate();
|
||||
m_si.channels = channels();
|
||||
m_si.frames = getMixer()->framesPerPeriod();
|
||||
m_si.frames = mixer()->framesPerPeriod();
|
||||
m_si.sections = 1;
|
||||
m_si.seekable = 0;
|
||||
|
||||
|
||||
@@ -45,15 +45,15 @@
|
||||
|
||||
|
||||
|
||||
AudioJack::AudioJack( bool & _success_ful, mixer * _mixer ) :
|
||||
AudioDevice( tLimit<int>( configManager::inst()->value(
|
||||
AudioJack::AudioJack( bool & _success_ful, AudioOutputContext * context ) :
|
||||
AudioBackend( tLimit<int>( configManager::inst()->value(
|
||||
"audiojack", "channels" ).toInt(),
|
||||
DEFAULT_CHANNELS, SURROUND_CHANNELS ),
|
||||
_mixer ),
|
||||
context ),
|
||||
m_client( NULL ),
|
||||
m_active( false ),
|
||||
m_stopSemaphore( 1 ),
|
||||
m_outBuf( CPU::allocFrames( getMixer()->framesPerPeriod() ) ),
|
||||
m_outBuf( CPU::allocFrames( mixer()->framesPerPeriod() ) ),
|
||||
m_framesDoneInCurBuf( 0 ),
|
||||
m_framesToDoInCurBuf( 0 )
|
||||
{
|
||||
@@ -210,7 +210,7 @@ void AudioJack::startProcessing()
|
||||
|
||||
|
||||
// try to sync JACK's and LMMS's buffer-size
|
||||
// jack_set_buffer_size( m_client, getMixer()->framesPerPeriod() );
|
||||
// jack_set_buffer_size( m_client, mixer()->framesPerPeriod() );
|
||||
|
||||
|
||||
|
||||
@@ -255,15 +255,13 @@ void AudioJack::applyQualitySettings()
|
||||
{
|
||||
if( hqAudio() )
|
||||
{
|
||||
setSampleRate( engine::getMixer()->processingSampleRate() );
|
||||
setSampleRate( mixer()->processingSampleRate() );
|
||||
|
||||
if( jack_get_sample_rate( m_client ) != sampleRate() )
|
||||
{
|
||||
setSampleRate( jack_get_sample_rate( m_client ) );
|
||||
}
|
||||
}
|
||||
|
||||
AudioDevice::applyQualitySettings();
|
||||
}
|
||||
|
||||
|
||||
@@ -343,7 +341,7 @@ int AudioJack::processCallback( jack_nframes_t _nframes, void * _udata )
|
||||
|
||||
#ifdef AUDIO_PORT_SUPPORT
|
||||
const Uint32 frames = qMin<Uint32>( _nframes,
|
||||
getMixer()->framesPerPeriod() );
|
||||
mixer()->framesPerPeriod() );
|
||||
for( jackPortMap::iterator it = m_portMap.begin();
|
||||
it != m_portMap.end(); ++it )
|
||||
{
|
||||
@@ -372,7 +370,7 @@ int AudioJack::processCallback( jack_nframes_t _nframes, void * _udata )
|
||||
_nframes,
|
||||
m_framesToDoInCurBuf -
|
||||
m_framesDoneInCurBuf );
|
||||
const float gain = getMixer()->masterGain();
|
||||
const float gain = mixer()->masterGain();
|
||||
for( ch_cnt_t chnl = 0; chnl < channels(); ++chnl )
|
||||
{
|
||||
jack_default_audio_sample_t * o = outbufs[chnl];
|
||||
@@ -434,7 +432,7 @@ void AudioJack::shutdownCallback( void * _udata )
|
||||
|
||||
|
||||
AudioJack::setupWidget::setupWidget( QWidget * _parent ) :
|
||||
AudioDevice::setupWidget( AudioJack::name(), _parent )
|
||||
AudioBackend::setupWidget( AudioJack::name(), _parent )
|
||||
{
|
||||
QString cn = configManager::inst()->value( "audiojack", "clientname" );
|
||||
if( cn.isEmpty() )
|
||||
|
||||
@@ -74,11 +74,11 @@
|
||||
|
||||
|
||||
|
||||
AudioOss::AudioOss( bool & _success_ful, mixer * _mixer ) :
|
||||
AudioDevice( tLimit<ch_cnt_t>(
|
||||
AudioOss::AudioOss( bool & _success_ful, AudioOutputContext * context ) :
|
||||
AudioBackend( tLimit<ch_cnt_t>(
|
||||
configManager::inst()->value( "audiooss", "channels" ).toInt(),
|
||||
DEFAULT_CHANNELS, SURROUND_CHANNELS ),
|
||||
_mixer ),
|
||||
context ),
|
||||
m_convertEndian( false )
|
||||
{
|
||||
_success_ful = false;
|
||||
@@ -106,7 +106,7 @@ AudioOss::AudioOss( bool & _success_ful, mixer * _mixer ) :
|
||||
|
||||
int frag_spec;
|
||||
for( frag_spec = 0; static_cast<int>( 0x01 << frag_spec ) <
|
||||
getMixer()->framesPerPeriod() * channels() *
|
||||
mixer()->framesPerPeriod() * channels() *
|
||||
BYTES_PER_INT_SAMPLE;
|
||||
++frag_spec )
|
||||
{
|
||||
@@ -178,7 +178,7 @@ AudioOss::AudioOss( bool & _success_ful, mixer * _mixer ) :
|
||||
}
|
||||
if( value != sampleRate() )
|
||||
{
|
||||
value = getMixer()->baseSampleRate();
|
||||
value = mixer()->baseSampleRate();
|
||||
if ( ioctl( m_audioFD, SNDCTL_DSP_SPEED, &value ) < 0 )
|
||||
{
|
||||
perror( "SNDCTL_DSP_SPEED" );
|
||||
@@ -271,7 +271,7 @@ void AudioOss::applyQualitySettings()
|
||||
{
|
||||
if( hqAudio() )
|
||||
{
|
||||
setSampleRate( engine::getMixer()->processingSampleRate() );
|
||||
setSampleRate( mixer()->processingSampleRate() );
|
||||
|
||||
unsigned int value = sampleRate();
|
||||
if ( ioctl( m_audioFD, SNDCTL_DSP_SPEED, &value ) < 0 )
|
||||
@@ -282,7 +282,7 @@ void AudioOss::applyQualitySettings()
|
||||
}
|
||||
if( value != sampleRate() )
|
||||
{
|
||||
value = getMixer()->baseSampleRate();
|
||||
value = mixer()->baseSampleRate();
|
||||
if ( ioctl( m_audioFD, SNDCTL_DSP_SPEED, &value ) < 0 )
|
||||
{
|
||||
perror( "SNDCTL_DSP_SPEED" );
|
||||
@@ -292,8 +292,6 @@ void AudioOss::applyQualitySettings()
|
||||
setSampleRate( value );
|
||||
}
|
||||
}
|
||||
|
||||
AudioDevice::applyQualitySettings();
|
||||
}
|
||||
|
||||
|
||||
@@ -302,10 +300,10 @@ void AudioOss::applyQualitySettings()
|
||||
void AudioOss::run()
|
||||
{
|
||||
sampleFrameA * temp = CPU::allocFrames(
|
||||
getMixer()->framesPerPeriod() );
|
||||
mixer()->framesPerPeriod() );
|
||||
intSampleFrameA * outbuf = (intSampleFrameA *)
|
||||
CPU::memAlloc( sizeof( intSampleFrameA ) *
|
||||
getMixer()->framesPerPeriod() );
|
||||
mixer()->framesPerPeriod() );
|
||||
|
||||
while( true )
|
||||
{
|
||||
@@ -316,7 +314,7 @@ void AudioOss::run()
|
||||
}
|
||||
|
||||
int bytes = CPU::convertToS16( temp, outbuf, frames,
|
||||
getMixer()->masterGain(),
|
||||
mixer()->masterGain(),
|
||||
m_convertEndian );
|
||||
if( write( m_audioFD, outbuf, bytes ) != bytes )
|
||||
{
|
||||
@@ -332,7 +330,7 @@ void AudioOss::run()
|
||||
|
||||
|
||||
AudioOss::setupWidget::setupWidget( QWidget * _parent ) :
|
||||
AudioDevice::setupWidget( AudioOss::name(), _parent )
|
||||
AudioBackend::setupWidget( AudioOss::name(), _parent )
|
||||
{
|
||||
m_device = new QLineEdit( probeDevice(), this );
|
||||
m_device->setGeometry( 10, 20, 160, 20 );
|
||||
|
||||
311
src/core/audio/AudioOutputContext.cpp
Normal file
311
src/core/audio/AudioOutputContext.cpp
Normal file
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* AudioOutputContext.cpp - 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "AudioBackend.h"
|
||||
#include "AudioOutputContext.h"
|
||||
#include "Cpu.h"
|
||||
|
||||
#include "config_mgr.h"
|
||||
#include "engine.h"
|
||||
|
||||
AudioOutputContext::BufferFifo::BufferFifo( int _size, int _bufferSize ) :
|
||||
m_readerSem( _size ),
|
||||
m_writerSem( _size ),
|
||||
m_readerIndex( 0 ),
|
||||
m_writerIndex( 0 ),
|
||||
m_size( _size ),
|
||||
m_bufferSize( _bufferSize )
|
||||
{
|
||||
m_buffers = new sampleFrameA *[m_size];
|
||||
for( int i = 0; i < m_size; ++i )
|
||||
{
|
||||
m_buffers[i] = CPU::allocFrames( m_bufferSize );
|
||||
}
|
||||
|
||||
m_bufferStates = new BufferState[m_size];
|
||||
|
||||
m_readerSem.acquire( _size );
|
||||
}
|
||||
|
||||
|
||||
|
||||
AudioOutputContext::BufferFifo::~BufferFifo()
|
||||
{
|
||||
for( int i = 0; i < m_size; ++i )
|
||||
{
|
||||
CPU::freeFrames( m_buffers[i] );
|
||||
}
|
||||
|
||||
delete[] m_buffers;
|
||||
delete[] m_bufferStates;
|
||||
|
||||
m_readerSem.release( m_size );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioOutputContext::BufferFifo::write( sampleFrameA * _buffer )
|
||||
{
|
||||
m_writerSem.acquire();
|
||||
|
||||
if( _buffer != NULL )
|
||||
{
|
||||
CPU::memCpy( m_buffers[m_writerIndex], _buffer,
|
||||
m_bufferSize * sizeof( sampleFrameA ) );
|
||||
m_bufferStates[m_writerIndex] = Running;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bufferStates[m_writerIndex] = NullBuffer;
|
||||
}
|
||||
|
||||
m_writerIndex = ( m_writerIndex + 1 ) % m_size;
|
||||
|
||||
m_readerSem.release();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioOutputContext::BufferFifo::startRead()
|
||||
{
|
||||
m_readerSem.acquire();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioOutputContext::BufferFifo::finishRead()
|
||||
{
|
||||
m_readerIndex = ( m_readerIndex + 1 ) % m_size;
|
||||
m_writerSem.release();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AudioOutputContext::AudioOutputContext( Mixer * mixer,
|
||||
AudioBackend * audioBackend,
|
||||
const QualitySettings & qualitySettings ) :
|
||||
m_mixer( mixer ),
|
||||
m_qualitySettings( qualitySettings ),
|
||||
m_audioBackend( audioBackend ),
|
||||
m_fifo( NULL ),
|
||||
m_fifoWriter( NULL )
|
||||
{
|
||||
int error;
|
||||
if( ( m_srcState = src_new(
|
||||
qualitySettings.libsrcInterpolation(),
|
||||
SURROUND_CHANNELS, &error ) ) == NULL )
|
||||
{
|
||||
qWarning( "src_new() failed in AudioOutputContext::AudioOutputContext()" );
|
||||
}
|
||||
//m_audioBackend->applyQualitySettings();
|
||||
|
||||
int framesPerPeriod = m_mixer->framesPerPeriod();
|
||||
|
||||
// just rendering?
|
||||
if( !engine::hasGUI() )
|
||||
{
|
||||
m_fifo = new BufferFifo( 1, framesPerPeriod );
|
||||
}
|
||||
else if( configManager::inst()->value( "mixer", "framesperaudiobuffer"
|
||||
).toInt() >= 32 )
|
||||
{
|
||||
framesPerPeriod =
|
||||
(fpp_t) configManager::inst()->value( "mixer",
|
||||
"framesperaudiobuffer" ).toInt();
|
||||
|
||||
if( framesPerPeriod > DEFAULT_BUFFER_SIZE )
|
||||
{
|
||||
m_fifo = new BufferFifo( framesPerPeriod / DEFAULT_BUFFER_SIZE,
|
||||
DEFAULT_BUFFER_SIZE );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fifo = new BufferFifo( 1, framesPerPeriod );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
configManager::inst()->setValue( "mixer",
|
||||
"framesperaudiobuffer",
|
||||
QString::number( framesPerPeriod ) );
|
||||
m_fifo = new BufferFifo( 1, framesPerPeriod );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
AudioOutputContext::~AudioOutputContext()
|
||||
{
|
||||
while( m_fifo->isEmpty() == false )
|
||||
{
|
||||
m_fifo->startRead();
|
||||
m_fifo->finishRead();
|
||||
}
|
||||
delete m_fifo;
|
||||
|
||||
src_delete( m_srcState );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioOutputContext::startProcessing()
|
||||
{
|
||||
if( !isProcessing() )
|
||||
{
|
||||
m_fifoWriter = new FifoWriter( this );
|
||||
m_fifoWriter->start( QThread::HighPriority );
|
||||
|
||||
m_audioBackend->startProcessing();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioOutputContext::stopProcessing()
|
||||
{
|
||||
if( isProcessing() )
|
||||
{
|
||||
m_fifoWriter->finish();
|
||||
m_audioBackend->stopProcessing();
|
||||
m_fifoWriter->wait();
|
||||
|
||||
delete m_fifoWriter;
|
||||
m_fifoWriter = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool AudioOutputContext::isProcessing() const
|
||||
{
|
||||
return m_fifoWriter && m_fifoWriter->isRunning();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int AudioOutputContext::getCurrentOutputBuffer( sampleFrameA * _destBuf,
|
||||
sample_rate_t _destSampleRate )
|
||||
{
|
||||
int frames = mixer()->framesPerPeriod();
|
||||
m_fifo->startRead();
|
||||
if( m_fifo->currentReadBufferState() == BufferFifo::NullBuffer )
|
||||
{
|
||||
m_fifo->finishRead();
|
||||
return 0;
|
||||
}
|
||||
sampleFrameA * srcBuf = m_fifo->currentReadBuffer();
|
||||
|
||||
if( mixer()->processingSampleRate() != _destSampleRate )
|
||||
{
|
||||
if( m_srcState == NULL )
|
||||
{
|
||||
m_fifo->finishRead();
|
||||
return 0;
|
||||
}
|
||||
m_srcData.input_frames = frames;
|
||||
m_srcData.output_frames = frames;
|
||||
m_srcData.data_in = (float *) srcBuf;
|
||||
m_srcData.data_out = (float *) _destBuf;
|
||||
m_srcData.src_ratio = (double) _destSampleRate /
|
||||
mixer()->processingSampleRate();
|
||||
m_srcData.end_of_input = 0;
|
||||
int error;
|
||||
if( ( error = src_process( m_srcState, &m_srcData ) ) )
|
||||
{
|
||||
qWarning( "AudioBackend::resample(): error while resampling: %s",
|
||||
src_strerror( error ) );
|
||||
}
|
||||
frames = frames * _destSampleRate / mixer()->processingSampleRate();
|
||||
}
|
||||
else
|
||||
{
|
||||
CPU::memCpy( _destBuf, srcBuf, frames * sizeof( sampleFrameA ) );
|
||||
}
|
||||
|
||||
// tell BufferFifo to release current read buffer
|
||||
m_fifo->finishRead();
|
||||
|
||||
return frames;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AudioOutputContext::FifoWriter::FifoWriter( AudioOutputContext * context ) :
|
||||
m_context( context ),
|
||||
m_writing( true )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioOutputContext::FifoWriter::finish()
|
||||
{
|
||||
m_writing = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioOutputContext::FifoWriter::run()
|
||||
{
|
||||
#if 0
|
||||
#ifdef LMMS_BUILD_LINUX
|
||||
#ifdef LMMS_HAVE_PTHREAD_H
|
||||
cpu_set_t mask;
|
||||
CPU_ZERO( &mask );
|
||||
CPU_SET( 0, &mask );
|
||||
pthread_setaffinity_np( pthread_self(), sizeof( mask ), &mask );
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
while( m_writing )
|
||||
{
|
||||
m_context->fifo()->write( m_context->mixer()->renderNextBuffer() );
|
||||
}
|
||||
|
||||
// write a NULL in order to signal the AudioBackend that the FifoWriter has
|
||||
// finished
|
||||
m_context->fifo()->write( NULL );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
*/
|
||||
|
||||
#include "AudioPort.h"
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioBackend.h"
|
||||
#include "AudioOutputContext.h"
|
||||
#include "EffectChain.h"
|
||||
#include "engine.h"
|
||||
#include "Cpu.h"
|
||||
@@ -88,11 +89,13 @@ void AudioPort::setExtOutputEnabled( bool _enabled )
|
||||
m_extOutputEnabled = _enabled;
|
||||
if( m_extOutputEnabled )
|
||||
{
|
||||
engine::getMixer()->audioDev()->registerPort( this );
|
||||
engine::mixer()->audioOutputContext()->
|
||||
audioBackend()->registerPort( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
engine::getMixer()->audioDev()->unregisterPort( this );
|
||||
engine::mixer()->audioOutputContext()->
|
||||
audioBackend()->unregisterPort( this );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,7 +106,7 @@ void AudioPort::setExtOutputEnabled( bool _enabled )
|
||||
void AudioPort::setName( const QString & _name )
|
||||
{
|
||||
m_name = _name;
|
||||
engine::getMixer()->audioDev()->renamePort( this );
|
||||
engine::mixer()->audioOutputContext()->audioBackend()->renamePort( this );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ void AudioPortAudioSetupUtil::updateChannels()
|
||||
|
||||
|
||||
AudioPortAudio::AudioPortAudio( bool & _success_ful, mixer * _mixer ) :
|
||||
AudioDevice( tLimit<ch_cnt_t>(
|
||||
AudioBackend( tLimit<ch_cnt_t>(
|
||||
configManager::inst()->value( "audioportaudio",
|
||||
"channels" ).toInt(),
|
||||
DEFAULT_CHANNELS, SURROUND_CHANNELS ),
|
||||
@@ -284,8 +284,6 @@ void AudioPortAudio::applyQualitySettings()
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
audioDevice::applyQualitySettings();
|
||||
}
|
||||
|
||||
int AudioPortAudio::process_callback(
|
||||
|
||||
@@ -46,11 +46,11 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata)
|
||||
|
||||
|
||||
|
||||
AudioPulseAudio::AudioPulseAudio( bool & _success_ful, mixer * _mixer ) :
|
||||
AudioDevice( tLimit<ch_cnt_t>(
|
||||
AudioPulseAudio::AudioPulseAudio( bool & _success_ful, AudioOutputContext * context ) :
|
||||
AudioBackend( tLimit<ch_cnt_t>(
|
||||
configManager::inst()->value( "audiopa", "channels" ).toInt(),
|
||||
DEFAULT_CHANNELS, SURROUND_CHANNELS ),
|
||||
_mixer ),
|
||||
context ),
|
||||
m_s( NULL ),
|
||||
m_quit( false ),
|
||||
m_convertEndian( false )
|
||||
@@ -119,11 +119,9 @@ void AudioPulseAudio::applyQualitySettings()
|
||||
{
|
||||
if( hqAudio() )
|
||||
{
|
||||
// setSampleRate( engine::getMixer()->processingSampleRate() );
|
||||
// setSampleRate( mixer()->processingSampleRate() );
|
||||
|
||||
}
|
||||
|
||||
AudioDevice::applyQualitySettings();
|
||||
}
|
||||
|
||||
|
||||
@@ -139,12 +137,12 @@ static void stream_state_callback( pa_stream *s, void * userdata )
|
||||
break;
|
||||
|
||||
case PA_STREAM_READY:
|
||||
qDebug( "Stream successfully created\n" );
|
||||
qDebug( "Stream successfully created" );
|
||||
break;
|
||||
|
||||
case PA_STREAM_FAILED:
|
||||
default:
|
||||
qCritical( "Stream errror: %s\n",
|
||||
qCritical( "Stream errror: %s",
|
||||
pa_strerror(pa_context_errno(
|
||||
pa_stream_get_context( s ) ) ) );
|
||||
}
|
||||
@@ -166,7 +164,7 @@ static void context_state_callback(pa_context *c, void *userdata)
|
||||
case PA_CONTEXT_READY:
|
||||
{
|
||||
pa_cvolume cv;
|
||||
qDebug( "Connection established.\n" );
|
||||
qDebug( "Connection established." );
|
||||
_this->m_s = pa_stream_new( c, "lmms", &_this->m_sampleSpec, NULL);
|
||||
pa_stream_set_state_callback( _this->m_s, stream_state_callback, _this );
|
||||
pa_stream_set_write_callback( _this->m_s, stream_write_callback, _this );
|
||||
@@ -181,7 +179,8 @@ static void context_state_callback(pa_context *c, void *userdata)
|
||||
buffer_attr.minreq = (uint32_t)(-1);
|
||||
buffer_attr.fragsize = (uint32_t)(-1);
|
||||
|
||||
double latency = (double)( engine::getMixer()->framesPerPeriod() ) /
|
||||
double latency = (double)( ( (const AudioPulseAudio *) _this )->
|
||||
mixer()->framesPerPeriod() ) /
|
||||
(double)_this->sampleRate();
|
||||
|
||||
// ask PulseAudio for the desired latency (which might not be approved)
|
||||
@@ -201,7 +200,7 @@ static void context_state_callback(pa_context *c, void *userdata)
|
||||
|
||||
case PA_CONTEXT_FAILED:
|
||||
default:
|
||||
qCritical( "Connection failure: %s\n", pa_strerror( pa_context_errno( c ) ) );
|
||||
qCritical( "Connection failure: %s", pa_strerror( pa_context_errno( c ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,7 +212,7 @@ void AudioPulseAudio::run()
|
||||
pa_mainloop * mainLoop = pa_mainloop_new();
|
||||
if( !mainLoop )
|
||||
{
|
||||
qCritical( "pa_mainloop_new() failed.\n" );
|
||||
qCritical( "pa_mainloop_new() failed." );
|
||||
return;
|
||||
}
|
||||
pa_mainloop_api * mainloop_api = pa_mainloop_get_api( mainLoop );
|
||||
@@ -250,7 +249,7 @@ void AudioPulseAudio::run()
|
||||
|
||||
void AudioPulseAudio::streamWriteCallback( pa_stream *s, size_t length )
|
||||
{
|
||||
const fpp_t fpp = getMixer()->framesPerPeriod();
|
||||
const fpp_t fpp = mixer()->framesPerPeriod();
|
||||
sampleFrameA * temp = CPU::allocFrames( fpp );
|
||||
Sint16 * pcmbuf = (Sint16*)CPU::memAlloc( fpp * channels() *
|
||||
sizeof(Sint16) );
|
||||
@@ -267,7 +266,7 @@ void AudioPulseAudio::streamWriteCallback( pa_stream *s, size_t length )
|
||||
int bytes = CPU::convertToS16( temp,
|
||||
(intSampleFrameA *) pcmbuf,
|
||||
frames,
|
||||
getMixer()->masterGain(),
|
||||
mixer()->masterGain(),
|
||||
m_convertEndian );
|
||||
if( bytes > 0 )
|
||||
{
|
||||
@@ -285,7 +284,7 @@ void AudioPulseAudio::streamWriteCallback( pa_stream *s, size_t length )
|
||||
|
||||
|
||||
AudioPulseAudio::setupWidget::setupWidget( QWidget * _parent ) :
|
||||
AudioDevice::setupWidget( AudioPulseAudio::name(), _parent )
|
||||
AudioBackend::setupWidget( AudioPulseAudio::name(), _parent )
|
||||
{
|
||||
m_device = new QLineEdit( AudioPulseAudio::probeDevice(), this );
|
||||
m_device->setGeometry( 10, 20, 160, 20 );
|
||||
|
||||
@@ -26,14 +26,14 @@
|
||||
|
||||
#include "AudioSampleRecorder.h"
|
||||
#include "sample_buffer.h"
|
||||
#include "debug.h"
|
||||
#include "Cpu.h"
|
||||
|
||||
|
||||
|
||||
AudioSampleRecorder::AudioSampleRecorder( const ch_cnt_t _channels,
|
||||
bool & _success_ful,
|
||||
mixer * _mixer ) :
|
||||
AudioDevice( _channels, _mixer ),
|
||||
AudioOutputContext * context ) :
|
||||
AudioBackend( _channels, context ),
|
||||
m_buffers()
|
||||
{
|
||||
_success_ful = true;
|
||||
@@ -46,7 +46,7 @@ AudioSampleRecorder::~AudioSampleRecorder()
|
||||
{
|
||||
while( !m_buffers.empty() )
|
||||
{
|
||||
delete[] m_buffers.front().first;
|
||||
CPU::freeFrames( m_buffers.front().first );
|
||||
m_buffers.erase( m_buffers.begin() );
|
||||
}
|
||||
}
|
||||
@@ -72,9 +72,9 @@ void AudioSampleRecorder::createSampleBuffer( sampleBuffer * * _sample_buf )
|
||||
{
|
||||
const f_cnt_t frames = framesRecorded();
|
||||
// create buffer to store all recorded buffers in
|
||||
sampleFrame * data = new sampleFrame[frames];
|
||||
sampleFrameA * data = CPU::allocFrames( frames );
|
||||
// make sure buffer is cleaned up properly at the end...
|
||||
sampleFrame * data_ptr = data;
|
||||
sampleFrameA * data_ptr = data;
|
||||
|
||||
#ifdef LMMS_DEBUG
|
||||
assert( data != NULL );
|
||||
@@ -83,30 +83,24 @@ void AudioSampleRecorder::createSampleBuffer( sampleBuffer * * _sample_buf )
|
||||
for( BufferList::ConstIterator it = m_buffers.begin();
|
||||
it != m_buffers.end(); ++it )
|
||||
{
|
||||
memcpy( data_ptr, ( *it ).first, ( *it ).second *
|
||||
sizeof( sampleFrame ) );
|
||||
CPU::memCpy( data_ptr, ( *it ).first, ( *it ).second *
|
||||
sizeof( sampleFrameA ) );
|
||||
data_ptr += ( *it ).second;
|
||||
}
|
||||
// create according sample-buffer out of big buffer
|
||||
*_sample_buf = new sampleBuffer( data, frames );
|
||||
( *_sample_buf )->setSampleRate( sampleRate() );
|
||||
delete[] data;
|
||||
CPU::freeFrames( data );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioSampleRecorder::writeBuffer( const surroundSampleFrame * _ab,
|
||||
void AudioSampleRecorder::writeBuffer( const sampleFrameA * srcBuf,
|
||||
const fpp_t _frames, const float )
|
||||
{
|
||||
sampleFrame * buf = new sampleFrame[_frames];
|
||||
for( fpp_t frame = 0; frame < _frames; ++frame )
|
||||
{
|
||||
for( ch_cnt_t chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
|
||||
{
|
||||
buf[frame][chnl] = _ab[frame][chnl];
|
||||
}
|
||||
}
|
||||
sampleFrameA * buf = CPU::allocFrames( _frames );
|
||||
CPU::memCpy( buf, srcBuf, _frames*sizeof( sampleFrameA ) );
|
||||
m_buffers.push_back( qMakePair( buf, _frames ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -38,16 +38,16 @@
|
||||
|
||||
|
||||
|
||||
AudioSdl::AudioSdl( bool & _success_ful, mixer * _mixer ) :
|
||||
AudioDevice( DEFAULT_CHANNELS, _mixer ),
|
||||
m_outBuf( CPU::allocFrames( getMixer()->framesPerPeriod() ) ),
|
||||
AudioSdl::AudioSdl( bool & _success_ful, AudioOutputContext * context ) :
|
||||
AudioBackend( DEFAULT_CHANNELS, context ),
|
||||
m_outBuf( CPU::allocFrames( mixer()->framesPerPeriod() ) ),
|
||||
m_convertedBufPos( 0 ),
|
||||
m_convertEndian( false ),
|
||||
m_stopSemaphore( 1 )
|
||||
{
|
||||
_success_ful = false;
|
||||
|
||||
m_convertedBufSize = getMixer()->framesPerPeriod() *
|
||||
m_convertedBufSize = mixer()->framesPerPeriod() *
|
||||
sizeof( intSampleFrameA );
|
||||
m_convertedBuf = (intSampleFrameA *) CPU::memAlloc( m_convertedBufSize );
|
||||
|
||||
@@ -63,7 +63,7 @@ AudioSdl::AudioSdl( bool & _success_ful, mixer * _mixer ) :
|
||||
// of system, so we don't have
|
||||
// to convert the buffers
|
||||
m_audioHandle.channels = channels();
|
||||
m_audioHandle.samples = qMax( 1024, getMixer()->framesPerPeriod()*2 );
|
||||
m_audioHandle.samples = qMax( 1024, mixer()->framesPerPeriod()*2 );
|
||||
|
||||
m_audioHandle.callback = sdlAudioCallback;
|
||||
m_audioHandle.userdata = this;
|
||||
@@ -131,7 +131,7 @@ void AudioSdl::applyQualitySettings()
|
||||
{
|
||||
SDL_CloseAudio();
|
||||
|
||||
setSampleRate( engine::getMixer()->processingSampleRate() );
|
||||
setSampleRate( mixer()->processingSampleRate() );
|
||||
|
||||
m_audioHandle.freq = sampleRate();
|
||||
|
||||
@@ -143,8 +143,6 @@ void AudioSdl::applyQualitySettings()
|
||||
qCritical( "Couldn't open SDL-audio: %s\n", SDL_GetError() );
|
||||
}
|
||||
}
|
||||
|
||||
AudioDevice::applyQualitySettings();
|
||||
}
|
||||
|
||||
|
||||
@@ -186,7 +184,7 @@ void AudioSdl::sdlAudioCallback( Uint8 * _buf, int _len )
|
||||
CPU::convertToS16( m_outBuf,
|
||||
m_convertedBuf,
|
||||
frames,
|
||||
getMixer()->masterGain(),
|
||||
mixer()->masterGain(),
|
||||
m_convertEndian );
|
||||
}
|
||||
const int min_len = qMin( _len, m_convertedBufSize
|
||||
@@ -203,7 +201,7 @@ void AudioSdl::sdlAudioCallback( Uint8 * _buf, int _len )
|
||||
|
||||
|
||||
AudioSdl::setupWidget::setupWidget( QWidget * _parent ) :
|
||||
AudioDevice::setupWidget( AudioSdl::name(), _parent )
|
||||
AudioBackend::setupWidget( AudioSdl::name(), _parent )
|
||||
{
|
||||
QString dev = configManager::inst()->value( "audiosdl", "device" );
|
||||
m_device = new QLineEdit( dev, this );
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#include "InstrumentTrack.h"
|
||||
#include "ladspa_2_lmms.h"
|
||||
#include "MainWindow.h"
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
#include "pattern.h"
|
||||
#include "piano_roll.h"
|
||||
#include "ProjectJournal.h"
|
||||
@@ -56,7 +56,7 @@
|
||||
bool engine::s_hasGUI = true;
|
||||
bool engine::s_suppressMessages = false;
|
||||
float engine::s_framesPerTick;
|
||||
mixer * engine::s_mixer = NULL;
|
||||
Mixer * engine::s_mixer = NULL;
|
||||
FxMixer * engine::s_fxMixer = NULL;
|
||||
FxMixerView * engine::s_fxMixerView = NULL;
|
||||
MainWindow * engine::s_mainWindow = NULL;
|
||||
@@ -89,9 +89,11 @@ void engine::init( const bool _has_gui )
|
||||
initPluginFileHandling();
|
||||
|
||||
s_projectJournal = new ProjectJournal;
|
||||
s_mixer = new mixer;
|
||||
s_mixer = new Mixer;
|
||||
|
||||
s_song = new song;
|
||||
|
||||
s_mixer->initDevices();
|
||||
|
||||
// init resource framework
|
||||
s_workingDirResourceDB =
|
||||
@@ -119,8 +121,6 @@ void engine::init( const bool _has_gui )
|
||||
|
||||
s_projectJournal->setJournalling( true );
|
||||
|
||||
s_mixer->initDevices();
|
||||
|
||||
s_midiControlListener = new MidiControlListener();
|
||||
|
||||
s_automationRecorder = new AutomationRecorder;
|
||||
|
||||
@@ -126,7 +126,8 @@ int main( int argc, char * * argv )
|
||||
new QApplication( argc, argv ) ;
|
||||
|
||||
|
||||
mixer::qualitySettings qs( mixer::qualitySettings::Mode_HighQuality );
|
||||
AudioOutputContext::QualitySettings qs(
|
||||
AudioOutputContext::QualitySettings::Preset_HighQuality );
|
||||
ProjectRenderer::OutputSettings os( 44100, false, 160,
|
||||
ProjectRenderer::Depth_16Bit );
|
||||
ProjectRenderer::ExportFileFormats eff = ProjectRenderer::WaveFile;
|
||||
@@ -284,19 +285,23 @@ int main( int argc, char * * argv )
|
||||
const QString ip = QString( argv[i + 1] );
|
||||
if( ip == "linear" )
|
||||
{
|
||||
qs.interpolation = mixer::qualitySettings::Interpolation_Linear;
|
||||
qs.setInterpolation( AudioOutputContext::QualitySettings::
|
||||
Interpolation_Linear );
|
||||
}
|
||||
else if( ip == "sincfastest" )
|
||||
{
|
||||
qs.interpolation = mixer::qualitySettings::Interpolation_SincFastest;
|
||||
qs.setInterpolation( AudioOutputContext::QualitySettings::
|
||||
Interpolation_SincFastest );
|
||||
}
|
||||
else if( ip == "sincmedium" )
|
||||
{
|
||||
qs.interpolation = mixer::qualitySettings::Interpolation_SincMedium;
|
||||
qs.setInterpolation( AudioOutputContext::QualitySettings::
|
||||
Interpolation_SincMedium );
|
||||
}
|
||||
else if( ip == "sincbest" )
|
||||
{
|
||||
qs.interpolation = mixer::qualitySettings::Interpolation_SincBest;
|
||||
qs.setInterpolation( AudioOutputContext::QualitySettings::
|
||||
Interpolation_SincBest );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -314,21 +319,25 @@ int main( int argc, char * * argv )
|
||||
switch( o )
|
||||
{
|
||||
case 1:
|
||||
qs.oversampling = mixer::qualitySettings::Oversampling_None;
|
||||
break;
|
||||
qs.setOversampling( AudioOutputContext::QualitySettings::
|
||||
Oversampling_None );
|
||||
break;
|
||||
case 2:
|
||||
qs.oversampling = mixer::qualitySettings::Oversampling_2x;
|
||||
break;
|
||||
qs.setOversampling( AudioOutputContext::QualitySettings::
|
||||
Oversampling_2x );
|
||||
break;
|
||||
case 4:
|
||||
qs.oversampling = mixer::qualitySettings::Oversampling_4x;
|
||||
break;
|
||||
qs.setOversampling( AudioOutputContext::QualitySettings::
|
||||
Oversampling_4x );
|
||||
break;
|
||||
case 8:
|
||||
qs.oversampling = mixer::qualitySettings::Oversampling_8x;
|
||||
break;
|
||||
qs.setOversampling( AudioOutputContext::QualitySettings::
|
||||
Oversampling_8x );
|
||||
break;
|
||||
default:
|
||||
printf( "\nInvalid oversampling %s.\n\n"
|
||||
printf( "\nInvalid oversampling %s.\n\n"
|
||||
"Try \"%s --help\" for more information.\n\n", argv[i + 1], argv[0] );
|
||||
return( EXIT_FAILURE );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include <QtXml/QDomNodeList>
|
||||
|
||||
#include "MidiControlListener.h"
|
||||
#include "mixer.h"
|
||||
#include "MidiClient.h"
|
||||
#include "MidiPort.h"
|
||||
#include "engine.h"
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
#include "song.h"
|
||||
#include "engine.h"
|
||||
#include "mixer.h"
|
||||
#include "MidiClient.h"
|
||||
#include "MidiController.h"
|
||||
#include "automation_recorder.h"
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
|
||||
#include "sample_buffer.h"
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
|
||||
|
||||
#include <QtCore/QBuffer>
|
||||
|
||||
@@ -146,11 +146,12 @@ void ExportProjectDialog::startBtnClicked()
|
||||
ui->progressBar->setEnabled( true );
|
||||
|
||||
|
||||
mixer::qualitySettings qs = mixer::qualitySettings(
|
||||
static_cast<mixer::qualitySettings::Interpolation>(
|
||||
ui->interpolationCB->currentIndex() ),
|
||||
static_cast<mixer::qualitySettings::Oversampling>(
|
||||
ui->oversamplingCB->currentIndex() ),
|
||||
AudioOutputContext::QualitySettings qs =
|
||||
AudioOutputContext::QualitySettings(
|
||||
static_cast<AudioOutputContext::QualitySettings::Interpolation>(
|
||||
ui->interpolationCB->currentIndex() ),
|
||||
static_cast<AudioOutputContext::QualitySettings::Oversampling>(
|
||||
ui->oversamplingCB->currentIndex() ),
|
||||
ui->sampleExactControllersCB->isChecked(),
|
||||
ui->aliasFreeOscillatorsCB->isChecked() );
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
#include "plugin_browser.h"
|
||||
#include "SideBar.h"
|
||||
#include "config_mgr.h"
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
#include "project_notes.h"
|
||||
#include "setup_dialog.h"
|
||||
#include "AudioDummy.h"
|
||||
@@ -1470,9 +1470,9 @@ void MainWindow::browseHelp()
|
||||
|
||||
void MainWindow::setHighQuality( bool _hq )
|
||||
{
|
||||
engine::getMixer()->changeQuality( mixer::qualitySettings(
|
||||
_hq ? mixer::qualitySettings::Mode_HighQuality :
|
||||
mixer::qualitySettings::Mode_Draft ) );
|
||||
/*engine::getMixer()->changeQuality( Mixer::qualitySettings(
|
||||
_hq ? Mixer::qualitySettings::Mode_HighQuality :
|
||||
Mixer::qualitySettings::Mode_Draft ) );*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
#include "tab_button.h"
|
||||
#include "tab_widget.h"
|
||||
#include "gui_templates.h"
|
||||
#include "mixer.h"
|
||||
#include "ProjectJournal.h"
|
||||
#include "config_mgr.h"
|
||||
#include "embed.h"
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "AudioOutputContext.h"
|
||||
#include "song_editor.h"
|
||||
#include "combobox.h"
|
||||
#include "embed.h"
|
||||
@@ -43,7 +44,7 @@
|
||||
#include "timeline.h"
|
||||
#include "tool_button.h"
|
||||
#include "tooltip.h"
|
||||
#include "AudioDevice.h"
|
||||
#include "AudioBackend.h"
|
||||
#include "piano_roll.h"
|
||||
|
||||
|
||||
@@ -130,7 +131,7 @@ songEditor::songEditor( song * _song, songEditor * & _engine_ptr ) :
|
||||
m_recordButton->setDisabled( true );
|
||||
|
||||
// disable record buttons if capturing is not supported
|
||||
if( !engine::getMixer()->audioDev()->supportsCapture() )
|
||||
if( !engine::mixer()->audioOutputContext()->audioBackend()->supportsCapture() )
|
||||
{
|
||||
m_recordButton->setDisabled( true );
|
||||
m_recordAccompanyButton->setDisabled( true );
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "gui_templates.h"
|
||||
#include "knob.h"
|
||||
#include "led_checkbox.h"
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
#include "mmp.h"
|
||||
#include "Oscillator.h"
|
||||
#include "pixmap_button.h"
|
||||
@@ -482,7 +482,7 @@ void EnvelopeAndLfoView::paintEvent( QPaintEvent * )
|
||||
int graphYBase = LFO_GRAPH_Y + 3 + lfoGraphHeight / 2;
|
||||
|
||||
const float framesForGraph = SECS_PER_LFO_OSCILLATION *
|
||||
engine::getMixer()->baseSampleRate() / 10;
|
||||
engine::mixer()->baseSampleRate() / 10;
|
||||
|
||||
const float lfoGrayAmount = fabsf( m_lfoAmountKnob->value<float>() );
|
||||
p.setPen( QPen( QColor::fromHsvF(
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "gui_templates.h"
|
||||
#include "lcd_spinbox.h"
|
||||
#include "MidiClient.h"
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
#include "tooltip.h"
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ InstrumentMidiIOView::InstrumentMidiIOView( QWidget * _parent ) :
|
||||
m_outputProgramSpinBox, SLOT( setEnabled( bool ) ) );
|
||||
|
||||
|
||||
if( !engine::getMixer()->midiClient()->isRaw() )
|
||||
if( !engine::mixer()->midiClient()->isRaw() )
|
||||
{
|
||||
m_rpBtn = new QToolButton( m_midiInputGroupBox );
|
||||
m_rpBtn->setText( tr( "MIDI devices to receive MIDI events from" ) );
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
* cpuload_widget.cpp - widget for displaying CPU-load (partly based on
|
||||
* Hydrogen's CPU-load-widget)
|
||||
*
|
||||
* Copyright (c) 2005-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* Copyright (c) 2005-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
|
||||
@@ -29,7 +29,7 @@
|
||||
#include "cpuload_widget.h"
|
||||
#include "embed.h"
|
||||
#include "engine.h"
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
|
||||
|
||||
cpuloadWidget::cpuloadWidget( QWidget * _parent ) :
|
||||
@@ -90,7 +90,7 @@ void cpuloadWidget::paintEvent( QPaintEvent * )
|
||||
void cpuloadWidget::updateCpuLoad()
|
||||
{
|
||||
// smooth load-values a bit
|
||||
Uint8 new_load = ( m_currentLoad + engine::getMixer()->cpuLoad() ) / 2;
|
||||
int new_load = ( m_currentLoad + engine::mixer()->cpuLoad() ) / 2;
|
||||
if( new_load != m_currentLoad )
|
||||
{
|
||||
m_currentLoad = new_load;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "visualization_widget.h"
|
||||
#include "gui_templates.h"
|
||||
#include "MainWindow.h"
|
||||
#include "Mixer.h"
|
||||
#include "embed.h"
|
||||
#include "engine.h"
|
||||
#include "tooltip.h"
|
||||
@@ -40,16 +41,16 @@ visualizationWidget::visualizationWidget( const QPixmap & _bg, QWidget * _p,
|
||||
visualizationTypes _vtype ) :
|
||||
QWidget( _p ),
|
||||
s_background( _bg ),
|
||||
m_points( new QPointF[engine::getMixer()->framesPerPeriod()] ),
|
||||
m_points( new QPointF[engine::mixer()->framesPerPeriod()] ),
|
||||
m_active( false )
|
||||
{
|
||||
setFixedSize( s_background.width(), s_background.height() );
|
||||
setAttribute( Qt::WA_OpaquePaintEvent, true );
|
||||
|
||||
const fpp_t frames = engine::getMixer()->framesPerPeriod();
|
||||
const fpp_t frames = engine::mixer()->framesPerPeriod();
|
||||
m_buffer = new sampleFrame[frames];
|
||||
|
||||
engine::getMixer()->clearAudioBuffer( m_buffer, frames );
|
||||
engine::mixer()->clearAudioBuffer( m_buffer, frames );
|
||||
|
||||
|
||||
toolTip::add( this, tr( "click to enable/disable visualization of "
|
||||
@@ -72,12 +73,11 @@ void visualizationWidget::updateAudioBuffer()
|
||||
{
|
||||
if( !engine::getSong()->isExporting() )
|
||||
{
|
||||
engine::getMixer()->lock();
|
||||
const surroundSampleFrame * c = engine::getMixer()->
|
||||
currentReadBuffer();
|
||||
const fpp_t fpp = engine::getMixer()->framesPerPeriod();
|
||||
engine::mixer()->lock();
|
||||
const surroundSampleFrame * c = engine::mixer()->currentReadBuffer();
|
||||
const fpp_t fpp = engine::mixer()->framesPerPeriod();
|
||||
memcpy( m_buffer, c, sizeof( surroundSampleFrame ) * fpp );
|
||||
engine::getMixer()->unlock();
|
||||
engine::mixer()->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ void visualizationWidget::setActive( bool _active )
|
||||
connect( engine::mainWindow(),
|
||||
SIGNAL( periodicUpdate() ),
|
||||
this, SLOT( update() ) );
|
||||
connect( engine::getMixer(),
|
||||
connect( engine::mixer(),
|
||||
SIGNAL( nextAudioBuffer() ),
|
||||
this, SLOT( updateAudioBuffer() ) );
|
||||
}
|
||||
@@ -101,7 +101,7 @@ void visualizationWidget::setActive( bool _active )
|
||||
disconnect( engine::mainWindow(),
|
||||
SIGNAL( periodicUpdate() ),
|
||||
this, SLOT( update() ) );
|
||||
disconnect( engine::getMixer(),
|
||||
disconnect( engine::mixer(),
|
||||
SIGNAL( nextAudioBuffer() ),
|
||||
this, SLOT( updateAudioBuffer() ) );
|
||||
// we have to update (remove last waves),
|
||||
@@ -121,7 +121,7 @@ void visualizationWidget::paintEvent( QPaintEvent * )
|
||||
|
||||
if( m_active && !engine::getSong()->isExporting() )
|
||||
{
|
||||
float master_output = engine::getMixer()->masterGain();
|
||||
float master_output = engine::mixer()->masterGain();
|
||||
int w = width()-4;
|
||||
const float half_h = -( height() - 6 ) / 3.0 * master_output - 1;
|
||||
int x_base = 2;
|
||||
@@ -131,10 +131,10 @@ void visualizationWidget::paintEvent( QPaintEvent * )
|
||||
|
||||
|
||||
const fpp_t frames =
|
||||
engine::getMixer()->framesPerPeriod();
|
||||
engine::mixer()->framesPerPeriod();
|
||||
const float max_level = qMax<float>(
|
||||
mixer::peakValueLeft( m_buffer, frames ),
|
||||
mixer::peakValueRight( m_buffer, frames ) );
|
||||
Mixer::peakValueLeft( m_buffer, frames ),
|
||||
Mixer::peakValueRight( m_buffer, frames ) );
|
||||
|
||||
// and set color according to that...
|
||||
LmmsStyle::ColorRole levelColor;
|
||||
@@ -165,7 +165,7 @@ void visualizationWidget::paintEvent( QPaintEvent * )
|
||||
{
|
||||
m_points[frame] = QPointF(
|
||||
x_base + (float) frame * xd,
|
||||
y_base + ( mixer::clip(
|
||||
y_base + ( Mixer::clip(
|
||||
m_buffer[frame][ch] ) *
|
||||
half_h ) );
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "embed.h"
|
||||
#include "engine.h"
|
||||
#include "gui_templates.h"
|
||||
#include "mixer.h"
|
||||
#include "Mixer.h"
|
||||
#include "rename_dialog.h"
|
||||
#include "song.h"
|
||||
#include "song_editor.h"
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <QtGui/QPushButton>
|
||||
#include <QtAlgorithms>
|
||||
|
||||
#include "AudioOutputContext.h"
|
||||
#include "pattern.h"
|
||||
#include "InstrumentTrack.h"
|
||||
#include "templates.h"
|
||||
@@ -735,15 +736,14 @@ patternFreezeThread::~patternFreezeThread()
|
||||
|
||||
void patternFreezeThread::run()
|
||||
{
|
||||
// create and install audio-sample-recorder
|
||||
AudioOutputContext context( engine::mixer(), NULL,
|
||||
engine::mixer()->defaultAudioOutputContext()->qualitySettings() );
|
||||
|
||||
// create and install AudioSampleRecorder
|
||||
bool b;
|
||||
// we cannot create local copy, because at a later stage
|
||||
// mixer::restoreAudioDevice(...) deletes old audio-dev and thus
|
||||
// AudioSampleRecorder would be destroyed two times...
|
||||
AudioSampleRecorder * freeze_recorder = new AudioSampleRecorder(
|
||||
DEFAULT_CHANNELS, b,
|
||||
engine::getMixer() );
|
||||
engine::getMixer()->setAudioDevice( freeze_recorder );
|
||||
AudioSampleRecorder freezeRecorder( DEFAULT_CHANNELS, b, &context );
|
||||
context.setAudioBackend( &freezeRecorder );
|
||||
engine::mixer()->setAudioOutputContext( &context );
|
||||
|
||||
// prepare stuff for playing correct things later
|
||||
engine::getSong()->playPattern( m_pattern, false );
|
||||
@@ -761,7 +761,7 @@ void patternFreezeThread::run()
|
||||
while( ppp < m_pattern->length() &&
|
||||
m_pattern->m_freezeAborted == false )
|
||||
{
|
||||
freeze_recorder->processNextBuffer();
|
||||
freezeRecorder.processNextBuffer();
|
||||
m_statusDlg->setProgress( ppp * 100 / m_pattern->length() );
|
||||
}
|
||||
m_statusDlg->setProgress( 100 );
|
||||
@@ -769,7 +769,7 @@ void patternFreezeThread::run()
|
||||
while( engine::getMixer()->hasPlayHandles() &&
|
||||
m_pattern->m_freezeAborted == false )
|
||||
{
|
||||
freeze_recorder->processNextBuffer();
|
||||
freezeRecorder.processNextBuffer();
|
||||
}
|
||||
|
||||
|
||||
@@ -782,12 +782,13 @@ void patternFreezeThread::run()
|
||||
// create final sample-buffer if freezing was successful
|
||||
if( m_pattern->m_freezeAborted == false )
|
||||
{
|
||||
freeze_recorder->createSampleBuffer(
|
||||
freezeRecorder.createSampleBuffer(
|
||||
&m_pattern->m_frozenPattern );
|
||||
}
|
||||
|
||||
// restore original audio-device
|
||||
engine::getMixer()->restoreAudioDevice();
|
||||
engine::mixer()->setAudioOutputContext(
|
||||
engine::mixer()->defaultAudioOutputContext() );
|
||||
|
||||
m_statusDlg->setProgress( -1 ); // we're finished
|
||||
|
||||
|
||||
Reference in New Issue
Block a user