From a7b14c66607ae9b54b25ae4386a50f0e8f04eb9c Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Wed, 27 Feb 2008 17:49:35 +0000 Subject: [PATCH] lock audioPort-buffers before writing them git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/branches/lmms-mv@725 0778d3d1-df1d-0410-868b-ea421aaaa00d --- include/audio_port.h | 30 +++++++++++++++++++++++++++++- src/audio/audio_port.cpp | 9 ++++++--- src/core/mixer.cpp | 15 +++++++++------ 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/include/audio_port.h b/include/audio_port.h index a7177772d..357c7ae8a 100644 --- a/include/audio_port.h +++ b/include/audio_port.h @@ -27,6 +27,8 @@ #define _AUDIO_PORT_H #include +#include +#include #include "effect_chain.h" @@ -46,6 +48,26 @@ public: return( m_secondBuffer ); } + inline void lockFirstBuffer( void ) + { + m_firstBufferLock.lock(); + } + + inline void lockSecondBuffer( void ) + { + m_secondBufferLock.lock(); + } + + inline void unlockFirstBuffer( void ) + { + m_firstBufferLock.unlock(); + } + + inline void unlockSecondBuffer( void ) + { + m_secondBufferLock.unlock(); + } + void nextPeriod( void ); @@ -85,11 +107,14 @@ public: enum bufferUsages { - NONE, FIRST, BOTH + NoUsage, + FirstBuffer, + BothBuffers } m_bufferUsage; inline bool processEffects( void ) { + QMutexLocker m( &m_firstBufferLock ); return( m_effects.processAudioBuffer( m_firstBuffer, m_frames ) ); } @@ -97,6 +122,9 @@ public: private: surroundSampleFrame * m_firstBuffer; surroundSampleFrame * m_secondBuffer; + QMutex m_firstBufferLock; + QMutex m_secondBufferLock; + bool m_extOutputEnabled; fx_ch_t m_nextFxChannel; diff --git a/src/audio/audio_port.cpp b/src/audio/audio_port.cpp index 7b9bafd1a..00510aa13 100644 --- a/src/audio/audio_port.cpp +++ b/src/audio/audio_port.cpp @@ -35,7 +35,7 @@ audioPort::audioPort( const QString & _name, track * _track ) : - m_bufferUsage( NONE ), + m_bufferUsage( NoUsage ), m_firstBuffer( new surroundSampleFrame[ engine::getMixer()->framesPerPeriod()] ), m_secondBuffer( new surroundSampleFrame[ @@ -70,12 +70,15 @@ audioPort::~audioPort() void audioPort::nextPeriod( void ) { + m_firstBufferLock.lock(); engine::getMixer()->clearAudioBuffer( m_firstBuffer, engine::getMixer()->framesPerPeriod() ); qSwap( m_firstBuffer, m_secondBuffer ); + m_firstBufferLock.unlock(); // this is how we decrease state of buffer-usage ;-) - m_bufferUsage = ( m_bufferUsage != NONE ) ? - ( ( m_bufferUsage == FIRST ) ? NONE : FIRST ) : NONE; + m_bufferUsage = ( m_bufferUsage != NoUsage ) ? + ( ( m_bufferUsage == FirstBuffer ) ? + NoUsage : FirstBuffer ) : NoUsage; } diff --git a/src/core/mixer.cpp b/src/core/mixer.cpp index b9ad6229d..40dab8160 100644 --- a/src/core/mixer.cpp +++ b/src/core/mixer.cpp @@ -170,7 +170,7 @@ private: { audioPort * a = (audioPort *) it->job; bool me = a->processEffects(); - if( a->m_bufferUsage != audioPort::NONE || me ) + if( a->m_bufferUsage != audioPort::NoUsage || me ) { m_mixer->processBuffer( a->firstBuffer(), @@ -567,7 +567,7 @@ const surroundSampleFrame * mixer::renderNextBuffer( void ) it != m_audioPorts.end(); ++it ) { more_effects = ( *it )->processEffects(); - if( ( *it )->m_bufferUsage != audioPort::NONE || + if( ( *it )->m_bufferUsage != audioPort::NoUsage || more_effects ) { processBuffer( ( *it )->firstBuffer(), @@ -648,6 +648,7 @@ void FASTCALL mixer::bufferToPort( const sampleFrame * _buf, fpp_t end_frame = start_frame + _frames; const fpp_t loop1_frame = tMin( end_frame, m_framesPerPeriod ); + _port->lockFirstBuffer(); for( fpp_t frame = start_frame; frame < loop1_frame; ++frame ) { for( ch_cnt_t chnl = 0; chnl < m_audioDev->channels(); ++chnl ) @@ -658,7 +659,9 @@ void FASTCALL mixer::bufferToPort( const sampleFrame * _buf, _volume_vector.vol[chnl]; } } + _port->unlockFirstBuffer(); + _port->lockSecondBuffer(); if( end_frame > m_framesPerPeriod ) { fpp_t frames_done = m_framesPerPeriod - start_frame; @@ -676,14 +679,14 @@ void FASTCALL mixer::bufferToPort( const sampleFrame * _buf, } } // we used both buffers so set flags - _port->m_bufferUsage = audioPort::BOTH; + _port->m_bufferUsage = audioPort::BothBuffers; } - else if( _port->m_bufferUsage == audioPort::NONE ) + else if( _port->m_bufferUsage == audioPort::NoUsage ) { // only first buffer touched - _port->m_bufferUsage = audioPort::FIRST; + _port->m_bufferUsage = audioPort::FirstBuffer; } - + _port->unlockSecondBuffer(); }