Skip to content

Commit

Permalink
Add dedicated manager for noteplayhandles
Browse files Browse the repository at this point in the history
This caches and reuses nph's independently of the generic memory manager.
  • Loading branch information
diizy committed Nov 18, 2014
1 parent 5e43085 commit 42e67d2
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 37 deletions.
15 changes: 1 addition & 14 deletions include/Mixer.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,20 +216,7 @@ class EXPORT Mixer : public QObject


// 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 );

Expand Down
43 changes: 38 additions & 5 deletions include/NotePlayHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,21 @@ class EXPORT NotePlayHandle : public PlayHandle, public note
OriginCount
};
typedef Origins Origin;

NotePlayHandle( InstrumentTrack* instrumentTrack,
const f_cnt_t offset,
const f_cnt_t frames,
const note& noteToPlay,
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 );
Expand Down Expand Up @@ -292,18 +298,45 @@ class EXPORT NotePlayHandle : public PlayHandle, public note
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;

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
10 changes: 9 additions & 1 deletion include/PlayHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ class PlayHandle : public ThreadableJob
{
}

PlayHandle & operator = ( PlayHandle & p )
{
m_type = p.m_type;
m_offset = p.m_offset;
m_affinity = p.m_affinity;
return *this;
}

virtual ~PlayHandle()
{
}
Expand Down Expand Up @@ -119,7 +127,7 @@ class PlayHandle : public ThreadableJob
private:
Type m_type;
f_cnt_t m_offset;
const QThread* m_affinity;
QThread* m_affinity;
QMutex m_processingLock;

} ;
Expand Down
4 changes: 2 additions & 2 deletions src/core/InstrumentFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
}
}
Expand Down Expand Up @@ -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 ),
Expand Down
42 changes: 38 additions & 4 deletions src/core/Mixer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 )
Expand All @@ -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();
}
Expand All @@ -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
Expand Down
83 changes: 78 additions & 5 deletions src/core/NotePlayHandle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,7 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack,
}




NotePlayHandle::~NotePlayHandle()
void NotePlayHandle::done()
{
lock();
noteOff( 0 );
Expand All @@ -149,7 +147,7 @@ NotePlayHandle::~NotePlayHandle()

foreach( NotePlayHandle * n, m_subNotes )
{
delete n;
NotePlayHandleManager::release( n );
}
m_subNotes.clear();

Expand Down Expand Up @@ -302,7 +300,7 @@ void NotePlayHandle::play( sampleFrame * _working_buffer )
n->play( _working_buffer );
if( n->isFinished() )
{
delete n;
NotePlayHandleManager::release( n );
}
}

Expand Down Expand Up @@ -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;
}
}
4 changes: 2 additions & 2 deletions src/core/PresetPreviewPlayHandle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) );
Expand All @@ -184,7 +184,7 @@ PresetPreviewPlayHandle::~PresetPreviewPlayHandle()
// then set according state
s_previewTC->setPreviewNote( NULL );
}
delete m_previewNote;
NotePlayHandleManager::release( m_previewNote );
s_previewTC->unlockData();
}

Expand Down
7 changes: 5 additions & 2 deletions src/core/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@

#include "MemoryManager.h"
#include "ConfigManager.h"
#include "NotePlayHandle.h"
#include "embed.h"
#include "engine.h"
#include "LmmsStyle.h"
Expand Down Expand Up @@ -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 ) );
Expand Down Expand Up @@ -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 );
}
Expand Down
4 changes: 2 additions & 2 deletions src/tracks/InstrumentTrack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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 )
Expand Down

0 comments on commit 42e67d2

Please sign in to comment.