Add dedicated manager for noteplayhandles

This caches and reuses nph's independently of the generic memory manager.
This commit is contained in:
Vesa
2014-08-23 20:37:21 +03:00
parent 5e4308507b
commit 42e67d27a1
9 changed files with 175 additions and 37 deletions

View File

@@ -216,20 +216,7 @@ public:
// play-handle stuff
bool addPlayHandle( PlayHandle* handle )
{
if( criticalXRuns() == false )
{
m_playHandleMutex.lock();
m_newPlayHandles.append( handle );
m_playHandleMutex.unlock();
return true;
}
delete handle;
return false;
}
bool addPlayHandle( PlayHandle* handle );
void removePlayHandle( PlayHandle* handle );

View File

@@ -57,7 +57,7 @@ public:
OriginCount
};
typedef Origins Origin;
NotePlayHandle( InstrumentTrack* instrumentTrack,
const f_cnt_t offset,
const f_cnt_t frames,
@@ -65,7 +65,13 @@ public:
NotePlayHandle* parent = NULL,
int midiEventChannel = -1,
Origin origin = OriginPattern );
virtual ~NotePlayHandle();
virtual ~NotePlayHandle() {}
void done();
void * operator new ( size_t size, void * p )
{
return p;
}
virtual void setVolume( volume_t volume );
virtual void setPanning( panning_t panning );
@@ -292,7 +298,7 @@ private:
bpm_t m_origTempo; // original tempo
f_cnt_t m_origFrames; // original m_frames
const int m_origBaseNote;
int m_origBaseNote;
float m_frequency;
float m_unpitchedFrequency;
@@ -300,10 +306,37 @@ private:
BaseDetuning* m_baseDetuning;
MidiTime m_songGlobalParentOffset;
const int m_midiChannel;
const Origin m_origin;
int m_midiChannel;
Origin m_origin;
bool m_frequencyNeedsUpdate; // used to update pitch
} ;
const int INITIAL_NPH_CACHE = 256;
const int NPH_CACHE_INCREMENT = 16;
class NotePlayHandleManager
{
MM_OPERATORS
public:
static void init();
static NotePlayHandle * acquire( InstrumentTrack* instrumentTrack,
const f_cnt_t offset,
const f_cnt_t frames,
const note& noteToPlay,
NotePlayHandle* parent = NULL,
int midiEventChannel = -1,
NotePlayHandle::Origin origin = NotePlayHandle::OriginPattern );
static void release( NotePlayHandle * nph );
static void extend( int i );
static void cleanup();
private:
static NotePlayHandleList s_nphCache;
static NotePlayHandleList s_available;
static QMutex s_mutex;
};
#endif

View File

@@ -55,6 +55,14 @@ public:
{
}
PlayHandle & operator = ( PlayHandle & p )
{
m_type = p.m_type;
m_offset = p.m_offset;
m_affinity = p.m_affinity;
return *this;
}
virtual ~PlayHandle()
{
}
@@ -119,7 +127,7 @@ public:
private:
Type m_type;
f_cnt_t m_offset;
const QThread* m_affinity;
QThread* m_affinity;
QMutex m_processingLock;
} ;

View File

@@ -260,7 +260,7 @@ void InstrumentFunctionNoteStacking::processNote( NotePlayHandle * _n )
// create sub-note-play-handle, only note is
// different
new NotePlayHandle( _n->instrumentTrack(), _n->offset(), _n->frames(), note_copy,
NotePlayHandleManager::acquire( _n->instrumentTrack(), _n->offset(), _n->frames(), note_copy,
_n, -1, NotePlayHandle::OriginNoteStacking );
}
}
@@ -471,7 +471,7 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n )
// create sub-note-play-handle, only ptr to note is different
// and is_arp_note=true
new NotePlayHandle( _n->instrumentTrack(),
NotePlayHandleManager::acquire( _n->instrumentTrack(),
( ( m_arpModeModel.value() != FreeMode ) ? cnphv.first()->offset() : _n->offset() ) + frames_processed,
gated_frames,
note( MidiTime( 0 ), MidiTime( 0 ), sub_note_key, (volume_t) qRound( _n->getVolume() * vol_level ),

View File

@@ -355,7 +355,11 @@ const surroundSampleFrame * Mixer::renderNextBuffer()
if( it != m_playHandles.end() )
{
delete *it;
if( ( *it )->type() == PlayHandle::TypeNotePlayHandle )
{
NotePlayHandleManager::release( (NotePlayHandle*) *it );
}
else delete *it;
m_playHandles.erase( it );
}
@@ -406,7 +410,11 @@ const surroundSampleFrame * Mixer::renderNextBuffer()
}
if( ( *it )->isFinished() )
{
delete *it;
if( ( *it )->type() == PlayHandle::TypeNotePlayHandle )
{
NotePlayHandleManager::release( (NotePlayHandle*) *it );
}
else delete *it;
it = m_playHandles.erase( it );
}
else
@@ -652,6 +660,24 @@ void Mixer::removeAudioPort( AudioPort * _port )
}
bool Mixer::addPlayHandle( PlayHandle* handle )
{
if( criticalXRuns() == false )
{
m_playHandleMutex.lock();
m_newPlayHandles.append( handle );
m_playHandleMutex.unlock();
return true;
}
if( handle->type() == PlayHandle::TypeNotePlayHandle )
{
NotePlayHandleManager::release( (NotePlayHandle*)handle );
}
else delete handle;
return false;
}
void Mixer::removePlayHandle( PlayHandle * _ph )
@@ -668,7 +694,11 @@ void Mixer::removePlayHandle( PlayHandle * _ph )
if( it != m_playHandles.end() )
{
m_playHandles.erase( it );
delete _ph;
if( _ph->type() == PlayHandle::TypeNotePlayHandle )
{
NotePlayHandleManager::release( (NotePlayHandle*) _ph );
}
else delete _ph;
}
unlockPlayHandleRemoval();
}
@@ -689,7 +719,11 @@ void Mixer::removePlayHandles( track * _track, bool removeIPHs )
{
if( ( *it )->isFromTrack( _track ) && ( removeIPHs || ( *it )->type() != PlayHandle::TypeInstrumentPlayHandle ) )
{
delete *it;
if( ( *it )->type() == PlayHandle::TypeNotePlayHandle )
{
NotePlayHandleManager::release( (NotePlayHandle*) *it );
}
else delete *it;
it = m_playHandles.erase( it );
}
else

View File

@@ -120,9 +120,7 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack,
}
NotePlayHandle::~NotePlayHandle()
void NotePlayHandle::done()
{
lock();
noteOff( 0 );
@@ -149,7 +147,7 @@ NotePlayHandle::~NotePlayHandle()
foreach( NotePlayHandle * n, m_subNotes )
{
delete n;
NotePlayHandleManager::release( n );
}
m_subNotes.clear();
@@ -302,7 +300,7 @@ void NotePlayHandle::play( sampleFrame * _working_buffer )
n->play( _working_buffer );
if( n->isFinished() )
{
delete n;
NotePlayHandleManager::release( n );
}
}
@@ -548,3 +546,78 @@ void NotePlayHandle::resize( const bpm_t _new_tempo )
}
NotePlayHandleList NotePlayHandleManager::s_nphCache;
NotePlayHandleList NotePlayHandleManager::s_available;
QMutex NotePlayHandleManager::s_mutex;
void NotePlayHandleManager::init()
{
// make sure the containers have more room than we need so that they don't need to do reallocations
s_nphCache.reserve( 1024 );
s_available.reserve( 1024 );
NotePlayHandle * n = MM_ALLOC( NotePlayHandle, INITIAL_NPH_CACHE );
for( int i=0; i < INITIAL_NPH_CACHE; ++i )
{
s_nphCache += n;
s_available += n;
++n;
}
}
NotePlayHandle * NotePlayHandleManager::acquire( InstrumentTrack* instrumentTrack,
const f_cnt_t offset,
const f_cnt_t frames,
const note& noteToPlay,
NotePlayHandle* parent,
int midiEventChannel,
NotePlayHandle::Origin origin )
{
if( s_available.isEmpty() )
{
extend( NPH_CACHE_INCREMENT );
}
s_mutex.lock();
NotePlayHandle * nph = s_available.takeFirst();
s_mutex.unlock();
new( (void*)nph ) NotePlayHandle( instrumentTrack, offset, frames, noteToPlay, parent, midiEventChannel, origin );
return nph;
}
void NotePlayHandleManager::release( NotePlayHandle * nph )
{
nph->done();
s_mutex.lock();
s_available += nph;
s_mutex.unlock();
}
void NotePlayHandleManager::extend( int i )
{
NotePlayHandle * n = MM_ALLOC( NotePlayHandle, i );
s_mutex.lock();
for( int j=0; j < i; ++j )
{
s_nphCache += n;
s_available += n;
++n;
}
s_mutex.unlock();
}
void NotePlayHandleManager::cleanup()
{
foreach( NotePlayHandle * n, s_nphCache )
{
delete n;
}
}

View File

@@ -160,7 +160,7 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file,
midiPort()->setMode( MidiPort::Disabled );
// create note-play-handle for it
m_previewNote = new NotePlayHandle(
m_previewNote = NotePlayHandleManager::acquire(
s_previewTC->previewInstrumentTrack(), 0,
typeInfo<f_cnt_t>::max() / 2,
note( 0, 0, DefaultKey, 100 ) );
@@ -184,7 +184,7 @@ PresetPreviewPlayHandle::~PresetPreviewPlayHandle()
// then set according state
s_previewTC->setPreviewNote( NULL );
}
delete m_previewNote;
NotePlayHandleManager::release( m_previewNote );
s_previewTC->unlockData();
}

View File

@@ -66,6 +66,7 @@
#include "MemoryManager.h"
#include "ConfigManager.h"
#include "NotePlayHandle.h"
#include "embed.h"
#include "engine.h"
#include "LmmsStyle.h"
@@ -98,8 +99,9 @@ inline void loadTranslation( const QString & _tname,
int main( int argc, char * * argv )
{
// initialize memory manager
// initialize memory managers
MemoryManager::init();
NotePlayHandleManager::init();
// intialize RNG
srand( getpid() + time( 0 ) );
@@ -534,8 +536,9 @@ int main( int argc, char * * argv )
const int ret = app->exec();
delete app;
// cleanup memory manager
// cleanup memory managers
MemoryManager::cleanup();
NotePlayHandleManager::cleanup();
return( ret );
}

View File

@@ -278,7 +278,7 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& ti
m_notesMutex.lock();
if( m_notes[event.key()] == NULL )
{
nph = new NotePlayHandle( this, offset,
nph = NotePlayHandleManager::acquire( this, offset,
typeInfo<f_cnt_t>::max() / 2,
note( MidiTime(), MidiTime(), event.key(), event.volume( midiPort()->baseVelocity() ) ),
NULL, event.channel(),
@@ -668,7 +668,7 @@ bool InstrumentTrack::play( const MidiTime & _start, const fpp_t _frames,
cur_note->length().frames(
frames_per_tick );
NotePlayHandle* notePlayHandle = new NotePlayHandle( this, _offset, note_frames, *cur_note );
NotePlayHandle* notePlayHandle = NotePlayHandleManager::acquire( this, _offset, note_frames, *cur_note );
notePlayHandle->setBBTrack( bb_track );
// are we playing global song?
if( _tco_num < 0 )