Add dedicated manager for noteplayhandles
This caches and reuses nph's independently of the generic memory manager.
This commit is contained in:
@@ -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 );
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
} ;
|
||||
|
||||
@@ -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 ),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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 )
|
||||
|
||||
Reference in New Issue
Block a user