LMMS Memory Manager
This commit is contained in:
@@ -22,19 +22,21 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _AUDIO_PORT_H
|
||||
#define _AUDIO_PORT_H
|
||||
#ifndef AUDIO_PORT_H
|
||||
#define AUDIO_PORT_H
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QMutex>
|
||||
#include <QtCore/QMutexLocker>
|
||||
|
||||
#include "Mixer.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
class EffectChain;
|
||||
|
||||
class AudioPort : public ThreadableJob
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
AudioPort( const QString & _name, bool _has_effect_chain = true );
|
||||
virtual ~AudioPort();
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include <QtCore/QVector>
|
||||
|
||||
#include "export.h"
|
||||
|
||||
#include "MemoryManager.h"
|
||||
|
||||
class engine;
|
||||
|
||||
@@ -49,6 +49,7 @@ const QString LOCALE_PATH = "locale/";
|
||||
|
||||
class EXPORT ConfigManager
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
static inline ConfigManager * inst()
|
||||
{
|
||||
|
||||
@@ -23,14 +23,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DETUNING_HELPER_H
|
||||
#define _DETUNING_HELPER_H
|
||||
#ifndef DETUNING_HELPER_H
|
||||
#define DETUNING_HELPER_H
|
||||
|
||||
#include "InlineAutomation.h"
|
||||
|
||||
#include "MemoryManager.h"
|
||||
|
||||
class DetuningHelper : public InlineAutomation
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
DetuningHelper() :
|
||||
InlineAutomation()
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "Mixer.h"
|
||||
#include "AutomatableModel.h"
|
||||
#include "TempoSyncKnobModel.h"
|
||||
|
||||
#include "MemoryManager.h"
|
||||
|
||||
class EffectChain;
|
||||
class EffectControls;
|
||||
|
||||
130
include/MemoryManager.h
Normal file
130
include/MemoryManager.h
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* MemoryManager.h - A lightweight, generic memory manager for LMMS
|
||||
*
|
||||
* Copyright (c) 2014 Vesa Kivimäki
|
||||
* Copyright (c) 2007-2014 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MEMORY_MANAGER_H
|
||||
#define MEMORY_MANAGER_H
|
||||
|
||||
#include <new>
|
||||
#include <QtCore/QVector>
|
||||
#include <QtCore/QMutex>
|
||||
#include <QtCore/QMap>
|
||||
#include "MemoryHelper.h"
|
||||
|
||||
|
||||
const int MM_CHUNK_SIZE = 64; // granularity of managed memory
|
||||
const int MM_INITIAL_CHUNKS = 1024 * 1024; // how many chunks to allocate at startup - TODO: make configurable
|
||||
const int MM_INCREMENT_CHUNKS = 16 * 1024; // min. amount of chunks to increment at a time
|
||||
|
||||
struct MemoryPool
|
||||
{
|
||||
void * m_pool;
|
||||
char * m_free;
|
||||
int m_chunks;
|
||||
QMutex m_mutex;
|
||||
|
||||
MemoryPool() :
|
||||
m_pool( NULL ),
|
||||
m_free( NULL ),
|
||||
m_chunks( 0 )
|
||||
{}
|
||||
|
||||
MemoryPool( int chunks ) :
|
||||
m_chunks( chunks )
|
||||
{
|
||||
m_free = (char*) MemoryHelper::alignedMalloc( chunks );
|
||||
memset( m_free, 1, chunks );
|
||||
}
|
||||
|
||||
MemoryPool( const MemoryPool & mp ) :
|
||||
m_pool( mp.m_pool ),
|
||||
m_free( mp.m_free ),
|
||||
m_chunks( mp.m_chunks ),
|
||||
m_mutex()
|
||||
{}
|
||||
|
||||
MemoryPool & operator = ( const MemoryPool & mp )
|
||||
{
|
||||
m_pool = mp.m_pool;
|
||||
m_free = mp.m_free;
|
||||
m_chunks = mp.m_chunks;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void * getChunks( int chunksNeeded );
|
||||
void releaseChunks( void * ptr, int chunks );
|
||||
};
|
||||
|
||||
struct PtrInfo
|
||||
{
|
||||
int chunks;
|
||||
MemoryPool * memPool;
|
||||
};
|
||||
|
||||
typedef QVector<MemoryPool> MemoryPoolVector;
|
||||
typedef QMap<void*, PtrInfo> PointerInfoMap;
|
||||
|
||||
class MemoryManager
|
||||
{
|
||||
public:
|
||||
static bool init();
|
||||
static void * alloc( size_t size );
|
||||
static void free( void * ptr );
|
||||
static int extend( int chunks ); // returns index of created pool (for use by alloc)
|
||||
static void cleanup();
|
||||
|
||||
private:
|
||||
static MemoryPoolVector s_memoryPools;
|
||||
static QMutex s_poolMutex;
|
||||
|
||||
static PointerInfoMap s_pointerInfo;
|
||||
static QMutex s_pointerMutex;
|
||||
};
|
||||
|
||||
|
||||
#define MM_OPERATORS \
|
||||
public: \
|
||||
static void * operator new ( size_t size ) \
|
||||
{ \
|
||||
return MemoryManager::alloc( size ); \
|
||||
} \
|
||||
static void * operator new[] ( size_t size ) \
|
||||
{ \
|
||||
return MemoryManager::alloc( size ); \
|
||||
} \
|
||||
static void operator delete ( void * ptr ) \
|
||||
{ \
|
||||
MemoryManager::free( ptr ); \
|
||||
} \
|
||||
static void operator delete[] ( void * ptr ) \
|
||||
{ \
|
||||
MemoryManager::free( ptr ); \
|
||||
}
|
||||
|
||||
// for use in cases where overriding new/delete isn't a possibility
|
||||
#define MM_ALLOC( type, count ) (type*) MemoryManager::alloc( sizeof( type ) * count )
|
||||
// and just for symmetry...
|
||||
#define MM_FREE( ptr ) MemoryManager::free( ptr )
|
||||
|
||||
#endif
|
||||
@@ -29,9 +29,11 @@
|
||||
#include "Midi.h"
|
||||
#include "panning_constants.h"
|
||||
#include "volume.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
class MidiEvent
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
MidiEvent( MidiEventTypes type = MidiActiveSensing,
|
||||
int8_t channel = 0,
|
||||
|
||||
@@ -27,11 +27,12 @@
|
||||
|
||||
#include "MidiEvent.h"
|
||||
#include "MidiTime.h"
|
||||
|
||||
#include "MemoryManager.h"
|
||||
|
||||
// all classes being able to process MIDI-events should inherit from this
|
||||
class MidiEventProcessor
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
MidiEventProcessor()
|
||||
{
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "note.h"
|
||||
#include "PlayHandle.h"
|
||||
#include "track.h"
|
||||
|
||||
#include "MemoryManager.h"
|
||||
|
||||
class InstrumentTrack;
|
||||
class NotePlayHandle;
|
||||
@@ -42,6 +42,7 @@ typedef QList<const NotePlayHandle *> ConstNotePlayHandleList;
|
||||
|
||||
class EXPORT NotePlayHandle : public PlayHandle, public note
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
void * m_pluginData;
|
||||
basicFilters<> * m_filter;
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
|
||||
#include "JournallingObject.h"
|
||||
#include "Model.h"
|
||||
#include "base64.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
|
||||
class QWidget;
|
||||
@@ -42,6 +44,7 @@ class AutomatableModel;
|
||||
|
||||
class EXPORT Plugin : public JournallingObject, public Model
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
enum PluginTypes
|
||||
{
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "lmms_math.h"
|
||||
#include "shared_object.h"
|
||||
#include "Mixer.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
|
||||
class QPainter;
|
||||
@@ -59,6 +60,7 @@ public:
|
||||
};
|
||||
class EXPORT handleState
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
handleState( bool _varying_pitch = false, int interpolation_mode = SRC_LINEAR );
|
||||
virtual ~handleState();
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "templates.h"
|
||||
#include "lmms_constants.h"
|
||||
#include "interpolation.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
//#include <iostream>
|
||||
//#include <cstdlib>
|
||||
@@ -50,6 +51,7 @@
|
||||
template<ch_cnt_t CHANNELS/* = DEFAULT_CHANNELS*/>
|
||||
class basicFilters
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
enum FilterTypes
|
||||
{
|
||||
|
||||
@@ -23,10 +23,11 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _ENGINE_H
|
||||
#define _ENGINE_H
|
||||
#ifndef ENGINE_H
|
||||
#define ENGINE_H
|
||||
|
||||
#include "lmmsconfig.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
#include <QtCore/QMap>
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _BIT_INVADER_H
|
||||
#define _BIT_INVADER_H
|
||||
#ifndef BIT_INVADER_H
|
||||
#define BIT_INVADER_H
|
||||
|
||||
#include "Instrument.h"
|
||||
#include "InstrumentView.h"
|
||||
@@ -33,12 +33,14 @@
|
||||
#include "knob.h"
|
||||
#include "pixmap_button.h"
|
||||
#include "led_checkbox.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
class oscillator;
|
||||
class bitInvaderView;
|
||||
|
||||
class bSynth
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
bSynth( float * sample, int length, NotePlayHandle * _nph,
|
||||
bool _interpolation, float factor,
|
||||
|
||||
@@ -31,11 +31,13 @@
|
||||
|
||||
#include "lmms_math.h"
|
||||
#include "interpolation.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
|
||||
template<class FX = DspEffectLibrary::StereoBypass>
|
||||
class KickerOsc
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
KickerOsc( const FX & fx, const float start, const float end, const float noise, const float offset,
|
||||
const float slope, const float env, const float diststart, const float distend, const float length ) :
|
||||
|
||||
@@ -189,6 +189,7 @@ class MonstroView;
|
||||
|
||||
class MonstroSynth
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
MonstroSynth( MonstroInstrument * _i, NotePlayHandle * _nph );
|
||||
virtual ~MonstroSynth();
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "TempoSyncKnob.h"
|
||||
#include "NotePlayHandle.h"
|
||||
#include "pixmap_button.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
|
||||
#define makeknob( name, x, y, hint, unit, oname ) \
|
||||
@@ -80,6 +81,7 @@ class NesInstrument;
|
||||
|
||||
class NesObject
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
NesObject( NesInstrument * nes, const sample_rate_t samplerate, NotePlayHandle * nph );
|
||||
virtual ~NesObject();
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
|
||||
#include "gb_apu/Gb_Apu.h"
|
||||
#include "gb_apu/Multi_Buffer.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
class Basic_Gb_Apu {
|
||||
MM_OPERATORS
|
||||
public:
|
||||
Basic_Gb_Apu();
|
||||
~Basic_Gb_Apu();
|
||||
|
||||
@@ -23,14 +23,14 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _PATMAN_H_
|
||||
#define _PATMAN_H_
|
||||
#ifndef PATMAN_H_
|
||||
#define PATMAN_H_
|
||||
|
||||
#include "Instrument.h"
|
||||
#include "InstrumentView.h"
|
||||
#include "SampleBuffer.h"
|
||||
#include "AutomatableModel.h"
|
||||
|
||||
#include "MemoryManager.h"
|
||||
|
||||
class pixmapButton;
|
||||
|
||||
@@ -79,6 +79,7 @@ public slots:
|
||||
private:
|
||||
typedef struct
|
||||
{
|
||||
MM_OPERATORS
|
||||
SampleBuffer::handleState* state;
|
||||
bool tuned;
|
||||
SampleBuffer* sample;
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "led_checkbox.h"
|
||||
#include "fluidsynth.h"
|
||||
#include "SampleBuffer.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
class sf2InstrumentView;
|
||||
class sf2Font;
|
||||
@@ -173,6 +174,7 @@ signals:
|
||||
// A soundfont in our font-map
|
||||
class sf2Font
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
sf2Font( fluid_sfont_t * f ) :
|
||||
fluidFont( f ),
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "graph.h"
|
||||
#include "pixmap_button.h"
|
||||
#include "led_checkbox.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
|
||||
enum SfxrWaves
|
||||
@@ -69,6 +70,7 @@ class sfxrInstrument;
|
||||
|
||||
class SfxrSynth
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
SfxrSynth( const sfxrInstrument * s );
|
||||
virtual ~SfxrSynth();
|
||||
|
||||
@@ -27,11 +27,12 @@
|
||||
#include <QVector>
|
||||
|
||||
#include "vibrating_string.h"
|
||||
|
||||
#include "MemoryManager.h"
|
||||
|
||||
|
||||
class stringContainer
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
stringContainer(const float _pitch,
|
||||
const sample_rate_t _sample_rate,
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "NotePlayHandle.h"
|
||||
#include "pixmap_button.h"
|
||||
#include <samplerate.h>
|
||||
#include "MemoryManager.h"
|
||||
|
||||
|
||||
#define makeknob( name, x, y, hint, unit, oname ) \
|
||||
@@ -80,6 +81,7 @@ class WatsynInstrument;
|
||||
|
||||
class WatsynObject
|
||||
{
|
||||
MM_OPERATORS
|
||||
public:
|
||||
WatsynObject( float * _A1wave, float * _A2wave,
|
||||
float * _B1wave, float * _B2wave,
|
||||
|
||||
210
src/core/MemoryManager.cpp
Normal file
210
src/core/MemoryManager.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* MemoryManager.cpp - A lightweight, generic memory manager for LMMS
|
||||
*
|
||||
* Copyright (c) 2014 Vesa Kivimäki
|
||||
* Copyright (c) 2007-2014 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 "MemoryManager.h"
|
||||
#include <QtGlobal>
|
||||
|
||||
|
||||
MemoryPoolVector MemoryManager::s_memoryPools;
|
||||
QMutex MemoryManager::s_poolMutex;
|
||||
PointerInfoMap MemoryManager::s_pointerInfo;
|
||||
QMutex MemoryManager::s_pointerMutex;
|
||||
|
||||
|
||||
bool MemoryManager::init()
|
||||
{
|
||||
// construct first MemoryPool and allocate memory
|
||||
MemoryPool m ( MM_INITIAL_CHUNKS );
|
||||
m.m_pool = MemoryHelper::alignedMalloc( MM_INITIAL_CHUNKS * MM_CHUNK_SIZE );
|
||||
s_memoryPools.append( m );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void * MemoryManager::alloc( size_t size )
|
||||
{
|
||||
int requiredChunks = size / MM_CHUNK_SIZE + ( size % MM_CHUNK_SIZE > 0 ? 1 : 0 );
|
||||
|
||||
MemoryPool * mp = NULL;
|
||||
void * ptr = NULL;
|
||||
|
||||
MemoryPoolVector::iterator it = s_memoryPools.begin();
|
||||
|
||||
s_poolMutex.lock();
|
||||
while( it != s_memoryPools.end() && !ptr )
|
||||
{
|
||||
ptr = ( *it ).getChunks( requiredChunks );
|
||||
if( ptr )
|
||||
{
|
||||
mp = &( *it );
|
||||
}
|
||||
}
|
||||
s_poolMutex.unlock();
|
||||
|
||||
if( ptr )
|
||||
{
|
||||
s_pointerMutex.lock();
|
||||
PtrInfo p;
|
||||
p.chunks = requiredChunks;
|
||||
p.memPool = mp;
|
||||
s_pointerInfo[ptr] = p;
|
||||
s_pointerMutex.unlock();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// can't find enough chunks in existing pools, so
|
||||
// create a new pool that is guaranteed to have enough chunks
|
||||
int moreChunks = qMax( requiredChunks, MM_INCREMENT_CHUNKS );
|
||||
int i = MemoryManager::extend( moreChunks );
|
||||
|
||||
mp = &s_memoryPools[i];
|
||||
ptr = s_memoryPools[i].getChunks( requiredChunks );
|
||||
if( ptr )
|
||||
{
|
||||
s_pointerMutex.lock();
|
||||
PtrInfo p;
|
||||
p.chunks = requiredChunks;
|
||||
p.memPool = mp;
|
||||
s_pointerInfo[ptr] = p;
|
||||
s_pointerMutex.unlock();
|
||||
return ptr;
|
||||
}
|
||||
// still no luck? something is horribly wrong
|
||||
qFatal( "MemoryManager.cpp: Couldn't allocate memory: %d chunks asked", requiredChunks );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void MemoryManager::free( void * ptr )
|
||||
{
|
||||
if( ptr == NULL ) return; // let's not try to deallocate null pointers, ok?
|
||||
|
||||
// fetch info on the ptr and remove
|
||||
s_pointerMutex.lock();
|
||||
if( ! s_pointerInfo.contains( ptr ) ) // if we have no info on ptr, fail loudly
|
||||
{
|
||||
qFatal( "MemoryManager.cpp: Couldn't find pointer info for pointer: %d", (int)ptr );
|
||||
}
|
||||
PtrInfo p = s_pointerInfo[ptr];
|
||||
s_pointerInfo.remove( ptr );
|
||||
s_pointerMutex.unlock();
|
||||
|
||||
p.memPool->releaseChunks( ptr, p.chunks );
|
||||
}
|
||||
|
||||
|
||||
int MemoryManager::extend( int chunks )
|
||||
{
|
||||
MemoryPool m ( chunks );
|
||||
m.m_pool = MemoryHelper::alignedMalloc( chunks * MM_CHUNK_SIZE );
|
||||
|
||||
s_poolMutex.lock();
|
||||
s_memoryPools.append( m );
|
||||
int i = s_memoryPools.size() - 1;
|
||||
s_poolMutex.unlock();
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
void MemoryManager::cleanup()
|
||||
{
|
||||
for( MemoryPoolVector::iterator it = s_memoryPools.begin(); it != s_memoryPools.end(); ++it )
|
||||
{
|
||||
MemoryHelper::alignedFree( ( *it ).m_pool );
|
||||
MemoryHelper::alignedFree( ( *it ).m_free );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void * MemoryPool::getChunks( int chunksNeeded )
|
||||
{
|
||||
if( chunksNeeded > m_chunks ) // not enough chunks in this pool?
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_mutex.lock();
|
||||
|
||||
// now find out if we have a long enough sequence of chunks in this pool
|
||||
char last = 0;
|
||||
int n = 0;
|
||||
int index = -1;
|
||||
bool found = false;
|
||||
|
||||
for( int i = 0; i < m_chunks; ++i )
|
||||
{
|
||||
if( m_free[i] )
|
||||
{
|
||||
if( !last )
|
||||
{
|
||||
index = i;
|
||||
}
|
||||
|
||||
++n;
|
||||
if( n >= chunksNeeded )
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
n = 0;
|
||||
}
|
||||
|
||||
last = m_free[i];
|
||||
}
|
||||
|
||||
if( found ) // if enough chunks found, return pointer to chunks
|
||||
{
|
||||
// set chunk flags to false so we know the chunks are in use
|
||||
for( int i = 0; i < chunksNeeded; ++i )
|
||||
{
|
||||
m_free[ index + i ] = 0;
|
||||
}
|
||||
m_mutex.unlock();
|
||||
return (char*)m_pool + ( index * MM_CHUNK_SIZE );
|
||||
}
|
||||
m_mutex.unlock();
|
||||
return NULL; // out of stock, come again tomorrow!
|
||||
}
|
||||
|
||||
|
||||
void MemoryPool::releaseChunks( void * ptr, int chunks )
|
||||
{
|
||||
m_mutex.lock();
|
||||
|
||||
int start = ( (int)ptr - (int)m_pool ) / MM_CHUNK_SIZE;
|
||||
if( start < 0 )
|
||||
{
|
||||
qFatal( "MemoryManager: error at releaseChunks() - corrupt pointer info?" );
|
||||
}
|
||||
|
||||
memset( &m_free[ start ], 1, chunks );
|
||||
|
||||
m_mutex.unlock();
|
||||
}
|
||||
@@ -61,6 +61,7 @@
|
||||
#include "templates.h"
|
||||
|
||||
#include "FileDialog.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
|
||||
SampleBuffer::SampleBuffer( const QString & _audio_file,
|
||||
@@ -106,7 +107,7 @@ SampleBuffer::SampleBuffer( const sampleFrame * _data, const f_cnt_t _frames ) :
|
||||
{
|
||||
if( _frames > 0 )
|
||||
{
|
||||
m_origData = new sampleFrame[_frames];
|
||||
m_origData = MM_ALLOC( sampleFrame, _frames );
|
||||
memcpy( m_origData, _data, _frames * BYTES_PER_FRAME );
|
||||
m_origFrames = _frames;
|
||||
}
|
||||
@@ -133,7 +134,7 @@ SampleBuffer::SampleBuffer( const f_cnt_t _frames ) :
|
||||
{
|
||||
if( _frames > 0 )
|
||||
{
|
||||
m_origData = new sampleFrame[_frames];
|
||||
m_origData = MM_ALLOC( sampleFrame, _frames );
|
||||
memset( m_origData, 0, _frames * BYTES_PER_FRAME );
|
||||
m_origFrames = _frames;
|
||||
}
|
||||
@@ -145,8 +146,8 @@ SampleBuffer::SampleBuffer( const f_cnt_t _frames ) :
|
||||
|
||||
SampleBuffer::~SampleBuffer()
|
||||
{
|
||||
delete[] m_origData;
|
||||
delete[] m_data;
|
||||
MM_FREE( m_origData );
|
||||
MM_FREE( m_data );
|
||||
}
|
||||
|
||||
|
||||
@@ -160,14 +161,14 @@ void SampleBuffer::update( bool _keep_settings )
|
||||
if( lock )
|
||||
{
|
||||
engine::mixer()->lock();
|
||||
delete[] m_data;
|
||||
MM_FREE( m_data );
|
||||
}
|
||||
|
||||
if( m_audioFile.isEmpty() && m_origData != NULL && m_origFrames > 0 )
|
||||
{
|
||||
// TODO: reverse- and amplification-property is not covered
|
||||
// by following code...
|
||||
m_data = new sampleFrame[m_origFrames];
|
||||
m_data = MM_ALLOC( sampleFrame, m_origFrames );
|
||||
memcpy( m_data, m_origData, m_origFrames * BYTES_PER_FRAME );
|
||||
if( _keep_settings == false )
|
||||
{
|
||||
@@ -232,7 +233,7 @@ void SampleBuffer::update( bool _keep_settings )
|
||||
{
|
||||
// sample couldn't be decoded, create buffer containing
|
||||
// one sample-frame
|
||||
m_data = new sampleFrame[1];
|
||||
m_data = MM_ALLOC( sampleFrame, 1 );
|
||||
memset( m_data, 0, sizeof( *m_data ) );
|
||||
m_frames = 1;
|
||||
m_loopStartFrame = m_startFrame = 0;
|
||||
@@ -252,7 +253,7 @@ void SampleBuffer::update( bool _keep_settings )
|
||||
{
|
||||
// neither an audio-file nor a buffer to copy from, so create
|
||||
// buffer containing one sample-frame
|
||||
m_data = new sampleFrame[1];
|
||||
m_data = MM_ALLOC( sampleFrame, 1 );
|
||||
memset( m_data, 0, sizeof( *m_data ) );
|
||||
m_frames = 1;
|
||||
m_loopStartFrame = m_startFrame = 0;
|
||||
@@ -273,7 +274,7 @@ void SampleBuffer::convertIntToFloat ( int_sample_t * & _ibuf, f_cnt_t _frames,
|
||||
// following code transforms int-samples into
|
||||
// float-samples and does amplifying & reversing
|
||||
const float fac = 1 / OUTPUT_SAMPLE_MULTIPLIER;
|
||||
m_data = new sampleFrame[_frames];
|
||||
m_data = MM_ALLOC( sampleFrame, _frames );
|
||||
const int ch = ( _channels > 1 ) ? 1 : 0;
|
||||
|
||||
// if reversing is on, we also reverse when
|
||||
@@ -313,7 +314,7 @@ void SampleBuffer::directFloatWrite ( sample_t * & _fbuf, f_cnt_t _frames, int _
|
||||
|
||||
{
|
||||
|
||||
m_data = new sampleFrame[_frames];
|
||||
m_data = MM_ALLOC( sampleFrame, _frames );
|
||||
const int ch = ( _channels > 1 ) ? 1 : 0;
|
||||
|
||||
// if reversing is on, we also reverse when
|
||||
@@ -356,9 +357,9 @@ void SampleBuffer::normalizeSampleRate( const sample_rate_t _src_sr,
|
||||
{
|
||||
SampleBuffer * resampled = resample( this, _src_sr,
|
||||
engine::mixer()->baseSampleRate() );
|
||||
delete[] m_data;
|
||||
MM_FREE( m_data );
|
||||
m_frames = resampled->frames();
|
||||
m_data = new sampleFrame[m_frames];
|
||||
m_data = MM_ALLOC( sampleFrame, m_frames );
|
||||
memcpy( m_data, resampled->data(), m_frames *
|
||||
sizeof( sampleFrame ) );
|
||||
delete resampled;
|
||||
@@ -1336,15 +1337,15 @@ void SampleBuffer::loadFromBase64( const QString & _data )
|
||||
printf("%d\n", (int) orig_data.size() );
|
||||
|
||||
m_origFrames = orig_data.size() / sizeof( sampleFrame );
|
||||
delete[] m_origData;
|
||||
m_origData = new sampleFrame[m_origFrames];
|
||||
MM_FREE( m_origData );
|
||||
m_origData = MM_ALLOC( sampleFrame, m_origFrames );
|
||||
memcpy( m_origData, orig_data.data(), orig_data.size() );
|
||||
|
||||
#else /* LMMS_HAVE_FLAC_STREAM_DECODER_H */
|
||||
|
||||
m_origFrames = dsize / sizeof( sampleFrame );
|
||||
delete[] m_origData;
|
||||
m_origData = new sampleFrame[m_origFrames];
|
||||
MM_FREE( m_origData );
|
||||
m_origData = MM_ALLOC( sampleFrame, m_origFrames );
|
||||
memcpy( m_origData, dst, dsize );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "MemoryManager.h"
|
||||
#include "ConfigManager.h"
|
||||
#include "embed.h"
|
||||
#include "engine.h"
|
||||
@@ -97,6 +98,9 @@ inline void loadTranslation( const QString & _tname,
|
||||
|
||||
int main( int argc, char * * argv )
|
||||
{
|
||||
// initialize memory manager
|
||||
MemoryManager::init();
|
||||
|
||||
// intialize RNG
|
||||
srand( getpid() + time( 0 ) );
|
||||
|
||||
@@ -529,6 +533,10 @@ int main( int argc, char * * argv )
|
||||
|
||||
const int ret = app->exec();
|
||||
delete app;
|
||||
|
||||
// cleanup memory manager
|
||||
MemoryManager::cleanup();
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user