From 9c25be1bde33247a8fb0c435950864e1d8345e51 Mon Sep 17 00:00:00 2001 From: Vesa Date: Fri, 22 Aug 2014 20:52:30 +0300 Subject: [PATCH] LMMS Memory Manager --- include/AudioPort.h | 6 +- include/ConfigManager.h | 3 +- include/DetuningHelper.h | 7 +- include/Effect.h | 2 +- include/MemoryManager.h | 130 ++++++++++++++++++ include/MidiEvent.h | 2 + include/MidiEventProcessor.h | 3 +- include/NotePlayHandle.h | 3 +- include/Plugin.h | 3 + include/SampleBuffer.h | 2 + include/basic_filters.h | 2 + include/engine.h | 5 +- plugins/bit_invader/bit_invader.h | 6 +- plugins/kicker/KickerOsc.h | 2 + plugins/monstro/Monstro.h | 1 + plugins/nes/Nes.h | 2 + plugins/papu/Basic_Gb_Apu.h | 2 + plugins/patman/patman.h | 7 +- plugins/sf2_player/sf2_player.h | 2 + plugins/sfxr/sfxr.h | 2 + plugins/vibed/string_container.h | 3 +- plugins/watsyn/Watsyn.h | 2 + src/core/MemoryManager.cpp | 210 ++++++++++++++++++++++++++++++ src/core/SampleBuffer.cpp | 33 ++--- src/core/main.cpp | 8 ++ 25 files changed, 415 insertions(+), 33 deletions(-) create mode 100644 include/MemoryManager.h create mode 100644 src/core/MemoryManager.cpp diff --git a/include/AudioPort.h b/include/AudioPort.h index 63a9e90eef7..8d70f83067f 100644 --- a/include/AudioPort.h +++ b/include/AudioPort.h @@ -22,19 +22,21 @@ * */ -#ifndef _AUDIO_PORT_H -#define _AUDIO_PORT_H +#ifndef AUDIO_PORT_H +#define AUDIO_PORT_H #include #include #include #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(); diff --git a/include/ConfigManager.h b/include/ConfigManager.h index 716c1dc9d3a..567dbd1d9d6 100644 --- a/include/ConfigManager.h +++ b/include/ConfigManager.h @@ -34,7 +34,7 @@ #include #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() { diff --git a/include/DetuningHelper.h b/include/DetuningHelper.h index 7aa1d39d482..7f702ac4a71 100644 --- a/include/DetuningHelper.h +++ b/include/DetuningHelper.h @@ -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() diff --git a/include/Effect.h b/include/Effect.h index 8f261d4e42c..44aabbacb51 100644 --- a/include/Effect.h +++ b/include/Effect.h @@ -31,7 +31,7 @@ #include "Mixer.h" #include "AutomatableModel.h" #include "TempoSyncKnobModel.h" - +#include "MemoryManager.h" class EffectChain; class EffectControls; diff --git a/include/MemoryManager.h b/include/MemoryManager.h new file mode 100644 index 00000000000..ddc5596e7e3 --- /dev/null +++ b/include/MemoryManager.h @@ -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 + * + * 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 +#include +#include +#include +#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 MemoryPoolVector; +typedef QMap 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 diff --git a/include/MidiEvent.h b/include/MidiEvent.h index 1ead0d56ff3..82eef85cc57 100644 --- a/include/MidiEvent.h +++ b/include/MidiEvent.h @@ -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, diff --git a/include/MidiEventProcessor.h b/include/MidiEventProcessor.h index 9da114577be..46eacea0bc4 100644 --- a/include/MidiEventProcessor.h +++ b/include/MidiEventProcessor.h @@ -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() { diff --git a/include/NotePlayHandle.h b/include/NotePlayHandle.h index 6585efc1116..b1cee41903a 100644 --- a/include/NotePlayHandle.h +++ b/include/NotePlayHandle.h @@ -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 ConstNotePlayHandleList; class EXPORT NotePlayHandle : public PlayHandle, public note { + MM_OPERATORS public: void * m_pluginData; basicFilters<> * m_filter; diff --git a/include/Plugin.h b/include/Plugin.h index 4887ef0fbdc..a6c344b4483 100644 --- a/include/Plugin.h +++ b/include/Plugin.h @@ -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 { diff --git a/include/SampleBuffer.h b/include/SampleBuffer.h index 1cb5864ca8a..b1b8e5fd31e 100644 --- a/include/SampleBuffer.h +++ b/include/SampleBuffer.h @@ -38,6 +38,7 @@ #include "lmms_math.h" #include "shared_object.h" #include "Mixer.h" +#include "MemoryManager.h" class QPainter; @@ -59,6 +60,7 @@ class EXPORT SampleBuffer : public QObject, public sharedObject }; class EXPORT handleState { + MM_OPERATORS public: handleState( bool _varying_pitch = false, int interpolation_mode = SRC_LINEAR ); virtual ~handleState(); diff --git a/include/basic_filters.h b/include/basic_filters.h index 76b782f6d84..0a8553a4754 100644 --- a/include/basic_filters.h +++ b/include/basic_filters.h @@ -43,6 +43,7 @@ #include "templates.h" #include "lmms_constants.h" #include "interpolation.h" +#include "MemoryManager.h" //#include //#include @@ -50,6 +51,7 @@ template class basicFilters { + MM_OPERATORS public: enum FilterTypes { diff --git a/include/engine.h b/include/engine.h index 0b21fe74ad6..7ca7e78f22c 100644 --- a/include/engine.h +++ b/include/engine.h @@ -23,10 +23,11 @@ */ -#ifndef _ENGINE_H -#define _ENGINE_H +#ifndef ENGINE_H +#define ENGINE_H #include "lmmsconfig.h" +#include "MemoryManager.h" #include diff --git a/plugins/bit_invader/bit_invader.h b/plugins/bit_invader/bit_invader.h index e7fff611fb8..d4eae0352bf 100644 --- a/plugins/bit_invader/bit_invader.h +++ b/plugins/bit_invader/bit_invader.h @@ -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, diff --git a/plugins/kicker/KickerOsc.h b/plugins/kicker/KickerOsc.h index a2b20aee834..bbe0dd584c2 100644 --- a/plugins/kicker/KickerOsc.h +++ b/plugins/kicker/KickerOsc.h @@ -31,11 +31,13 @@ #include "lmms_math.h" #include "interpolation.h" +#include "MemoryManager.h" template 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 ) : diff --git a/plugins/monstro/Monstro.h b/plugins/monstro/Monstro.h index fe9a1508c2c..8bbdcb83ecb 100644 --- a/plugins/monstro/Monstro.h +++ b/plugins/monstro/Monstro.h @@ -189,6 +189,7 @@ class MonstroView; class MonstroSynth { + MM_OPERATORS public: MonstroSynth( MonstroInstrument * _i, NotePlayHandle * _nph ); virtual ~MonstroSynth(); diff --git a/plugins/nes/Nes.h b/plugins/nes/Nes.h index da321642a1c..337d31c6956 100644 --- a/plugins/nes/Nes.h +++ b/plugins/nes/Nes.h @@ -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(); diff --git a/plugins/papu/Basic_Gb_Apu.h b/plugins/papu/Basic_Gb_Apu.h index ee01ed5788a..24b9dc7749d 100644 --- a/plugins/papu/Basic_Gb_Apu.h +++ b/plugins/papu/Basic_Gb_Apu.h @@ -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(); diff --git a/plugins/patman/patman.h b/plugins/patman/patman.h index 3568663d20c..9bf61db8eb1 100644 --- a/plugins/patman/patman.h +++ b/plugins/patman/patman.h @@ -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; diff --git a/plugins/sf2_player/sf2_player.h b/plugins/sf2_player/sf2_player.h index 574bd81ed61..a7b9262b615 100644 --- a/plugins/sf2_player/sf2_player.h +++ b/plugins/sf2_player/sf2_player.h @@ -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 @@ public slots: // A soundfont in our font-map class sf2Font { + MM_OPERATORS public: sf2Font( fluid_sfont_t * f ) : fluidFont( f ), diff --git a/plugins/sfxr/sfxr.h b/plugins/sfxr/sfxr.h index c2da90caafc..d83c982838b 100644 --- a/plugins/sfxr/sfxr.h +++ b/plugins/sfxr/sfxr.h @@ -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(); diff --git a/plugins/vibed/string_container.h b/plugins/vibed/string_container.h index 1e1864a0d4f..7d15e3dfe1e 100644 --- a/plugins/vibed/string_container.h +++ b/plugins/vibed/string_container.h @@ -27,11 +27,12 @@ #include #include "vibrating_string.h" - +#include "MemoryManager.h" class stringContainer { + MM_OPERATORS public: stringContainer(const float _pitch, const sample_rate_t _sample_rate, diff --git a/plugins/watsyn/Watsyn.h b/plugins/watsyn/Watsyn.h index c4fb63a5523..7b2a09bb43d 100644 --- a/plugins/watsyn/Watsyn.h +++ b/plugins/watsyn/Watsyn.h @@ -35,6 +35,7 @@ #include "NotePlayHandle.h" #include "pixmap_button.h" #include +#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, diff --git a/src/core/MemoryManager.cpp b/src/core/MemoryManager.cpp new file mode 100644 index 00000000000..09a3215c3fa --- /dev/null +++ b/src/core/MemoryManager.cpp @@ -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 + * + * 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 + + +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(); +} diff --git a/src/core/SampleBuffer.cpp b/src/core/SampleBuffer.cpp index 2f69eb7ac9d..957e638ae44 100644 --- a/src/core/SampleBuffer.cpp +++ b/src/core/SampleBuffer.cpp @@ -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 diff --git a/src/core/main.cpp b/src/core/main.cpp index d33bf118ce0..8626c20f978 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -64,6 +64,7 @@ #include #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 ); }