Improved buffer-allocator
git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@71 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
2
AUTHORS
2
AUTHORS
@@ -16,4 +16,4 @@ gabriel
|
||||
|
||||
Andreas Brandmaier
|
||||
<andy/at/brandmaier.de>
|
||||
BitInvader plugin
|
||||
BitInvader plugin
|
||||
|
||||
29
ChangeLog
29
ChangeLog
@@ -1,13 +1,34 @@
|
||||
2006-01-29 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
|
||||
* plugins/bit_invader/bit_invader.cpp:
|
||||
- call graph::setSamplePointer() after loading settings
|
||||
- memcpy() samples in bitInvader::smoothClicked() instead of copying
|
||||
them in a loop
|
||||
|
||||
* plugins/bit_invader/graph.cpp:
|
||||
- update after settings new sample
|
||||
|
||||
* src/tracks/pattern.cpp:
|
||||
- disable auto-cleanup during pattern-freeze
|
||||
- initialize member m_progress in patternFreezeStatusDialig-dtor - fixes
|
||||
bug which sometimes closed the window before actual freezing was
|
||||
started
|
||||
|
||||
* include/buffer_allocator.h:
|
||||
* src/lib/buffer_allocator.cpp:
|
||||
- added possibility to disable auto-cleanup at certain times e.g. when
|
||||
freezing a pattern
|
||||
- cleanup only every 10th free()-call for decreasing overhead
|
||||
- only start searching for free bufs if there're enough remaining
|
||||
|
||||
2006-01-24 Andreas Brandmaier <andy/at/brandmaier.de>
|
||||
|
||||
* plugins/bit_invader/bit_invader.cpp:
|
||||
* plugins/bit_invader/bit_invader.h:
|
||||
* presets/BitInvader:
|
||||
- changed sample buffer encoding in presets
|
||||
- to base64
|
||||
- changed sample buffer encoding in presets to base64
|
||||
- added BitInvader various presets
|
||||
|
||||
|
||||
2006-01-23 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
|
||||
* include/sample_buffer.h:
|
||||
@@ -1712,7 +1733,7 @@
|
||||
|
||||
* include/song_editor.h:
|
||||
* src/core/song_editor.cpp:
|
||||
added combo-box for selecting zooming-factor
|
||||
added combo-box for selectinf zooming-factor
|
||||
|
||||
* include/piano_roll.h:
|
||||
* src/core/piano_roll.cpp:
|
||||
|
||||
3
TODO
3
TODO
@@ -1,6 +1,5 @@
|
||||
to be done as soon as possible:
|
||||
|
||||
- disable auto-cleanup of bufferAllocator during memory-expensive operations (pattern-freezing etc.)
|
||||
- autosave every 30s (configurable!) and offer recovery at startup after crash
|
||||
- make piano-roll use rubberband instead of implementing a simple one on it's own
|
||||
- level-meters in output-graph and channel-track
|
||||
@@ -16,7 +15,7 @@ to be done as soon as possible:
|
||||
- speed up painting of sampleTCO
|
||||
- save window-positions, -states and -sizes in files
|
||||
- solve problems with different keyboard-layouts when playing channel-track with pc-keyboard -> use tr()
|
||||
- balance env+lfo
|
||||
- panning env+lfo
|
||||
- plucked-string-synth: knob for metallic -> use noise as wave-shape
|
||||
- finish qt4-port and make LMMS usable when compiling with Qt4
|
||||
- rewrite export-project-dialog using layout-mechanism
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.50)
|
||||
AC_INIT(lmms, 0.1.2-cvs20060123, tobydox/at/users/dot/sourceforge/dot/net)
|
||||
AM_INIT_AUTOMAKE(lmms, 0.1.2-cvs20060123)
|
||||
AC_INIT(lmms, 0.1.2-cvs20060129, tobydox/at/users/dot/sourceforge/dot/net)
|
||||
AM_INIT_AUTOMAKE(lmms, 0.1.2-cvs20060129)
|
||||
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* buffer_allocator.h - namespace bufferAllocator providing routines for own
|
||||
* optimized memory-management for audio-buffers
|
||||
*
|
||||
* Copyright (c) 2005 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2005-2006 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -46,10 +46,15 @@ namespace bufferAllocator
|
||||
return( (T *) allocBytes( sizeof( T ) * _n ) );
|
||||
}
|
||||
|
||||
// free given buffer
|
||||
void FASTCALL free( void * _buf );
|
||||
|
||||
// try to cleanup _level unused buffers
|
||||
void FASTCALL cleanUp( Uint16 _level );
|
||||
|
||||
// disable autocleanup-mechanisms
|
||||
void FASTCALL disableAutoCleanup( bool _disabled );
|
||||
|
||||
|
||||
// simple class for automatically freeing buffer in complex functions
|
||||
template<class T = void>
|
||||
|
||||
@@ -613,11 +613,7 @@ void bitInvader::loadSettings( const QDomElement & _this )
|
||||
base64::decode( sampleString, &dst, &size );
|
||||
memcpy( sample_shape, dst, size );
|
||||
|
||||
cout << sampleString.ascii() << endl;
|
||||
for (int i=0; i < sample_length; i++)
|
||||
{
|
||||
cout << sample_shape[i] << endl;
|
||||
}
|
||||
m_graph->setSamplePointer( sample_shape, sample_length );
|
||||
|
||||
// Load LED normalize
|
||||
m_interpolationToggle->setChecked( _this.attribute(
|
||||
@@ -657,11 +653,7 @@ void bitInvader::smoothClicked( void )
|
||||
{
|
||||
// store values in temporary array
|
||||
float* temp = new float[sample_length];
|
||||
for (int i=0; i < sample_length; i++)
|
||||
{
|
||||
temp[i] = sample_shape[i];
|
||||
}
|
||||
|
||||
memcpy( temp, sample_shape, sizeof( float ) * sample_length );
|
||||
|
||||
// Smoothing
|
||||
sample_shape[0] = ( temp[0]+temp[sample_length-1] ) * 0.5f;
|
||||
@@ -777,8 +769,7 @@ void bitInvader::sampleSizeChanged( float _new_sample_length )
|
||||
|
||||
// update sample graph
|
||||
m_graph->setSamplePointer( sample_shape, sample_length );
|
||||
m_graph->update();
|
||||
|
||||
|
||||
// set Song modified
|
||||
songEditor::inst()->setModified();
|
||||
|
||||
@@ -791,7 +782,7 @@ void bitInvader::sampleChanged()
|
||||
float max = 0;
|
||||
for (int i=0; i < sample_length; i++)
|
||||
{
|
||||
if (fabs(sample_shape[i]) > max) { max = fabs(sample_shape[i]); }
|
||||
if (fabsf(sample_shape[i]) > max) { max = fabs(sample_shape[i]); }
|
||||
}
|
||||
normalizeFactor = 1.0 / max;
|
||||
|
||||
@@ -813,8 +804,7 @@ extern "C"
|
||||
// neccessary for getting instance out of shared lib
|
||||
plugin * lmms_plugin_main( void * _data )
|
||||
{
|
||||
return( new bitInvader(
|
||||
static_cast<channelTrack *>( _data ) ) );
|
||||
return( new bitInvader( static_cast<channelTrack *>( _data ) ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@ void graph::setSamplePointer( float * _pointer, int _length )
|
||||
{
|
||||
samplePointer = _pointer;
|
||||
sampleLength = _length;
|
||||
update();
|
||||
}
|
||||
|
||||
void graph::mouseMoveEvent ( QMouseEvent * _me )
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* buffer_allocator.cpp - namespace bufferAllocator providing routines for own
|
||||
* optimized memory-management for audio-buffers
|
||||
*
|
||||
* Copyright (c) 2005 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2005-2006 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -66,7 +66,7 @@ inline bool operator<( const bufDesc & _bd1, const bufDesc & _bd2 )
|
||||
return( _bd1.timesUsed < _bd2.timesUsed );
|
||||
}
|
||||
|
||||
#ifdef QT4
|
||||
#ifndef QT3
|
||||
|
||||
inline bool operator==( const bufDesc & _bd1, const bufDesc & _bd2 )
|
||||
{
|
||||
@@ -86,7 +86,9 @@ inline bool operator!=( const bufDesc & _bd1, const bufDesc & _bd2 )
|
||||
static vlist<bufDesc> s_buffers;
|
||||
typedef vlist<bufDesc>::iterator bufIt;
|
||||
|
||||
QMutex s_buffersMutex;
|
||||
static int s_freeBufs = 0;
|
||||
static bool s_autoCleanupDisabled = FALSE;
|
||||
static QMutex s_buffersMutex;
|
||||
|
||||
|
||||
const int BUFFER_ALIGN = 16;
|
||||
@@ -112,13 +114,16 @@ void bufferAllocator::cleanUp( Uint16 _level )
|
||||
|
||||
const Sint16 todo = tMin<Sint16>( s_buffers.size() - _level,
|
||||
bufsToRemove.size() );
|
||||
|
||||
// now cleanup the first n elements of sorted array
|
||||
for( Sint16 i = 0; i < todo; ++i )
|
||||
{
|
||||
delete[] bufsToRemove[i].origPtr;
|
||||
s_buffers.erase( qFind( s_buffers.begin(), s_buffers.end(),
|
||||
bufsToRemove[i] ) );
|
||||
--s_freeBufs;
|
||||
}
|
||||
|
||||
#ifdef LMMS_DEBUG
|
||||
//printf( "cleaned up %d buffers\n", todo );
|
||||
#endif
|
||||
@@ -138,17 +143,23 @@ void bufferAllocator::free( void * _buf )
|
||||
{
|
||||
++( *it ).timesUsed;
|
||||
( *it ).free = TRUE;
|
||||
++s_freeBufs;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// do clean-up if neccessary
|
||||
static Uint16 CLEANUP_LEVEL = static_cast<Uint16>( 512 / ( logf(
|
||||
static const Uint32 CLEANUP_LEVEL = static_cast<Uint32>( 768 / ( logf(
|
||||
mixer::inst()->framesPerAudioBuffer() ) /
|
||||
logf( 2 ) ) );
|
||||
if( s_buffers.size() > CLEANUP_LEVEL )
|
||||
static int count = 0;
|
||||
// only cleanup every 10th time, because otherwise there's a lot of
|
||||
// overhead e.g. when freeing a lot of single buffers
|
||||
if( s_autoCleanupDisabled == FALSE &&
|
||||
s_buffers.size() > CLEANUP_LEVEL && ++count > 10 )
|
||||
{
|
||||
cleanUp( CLEANUP_LEVEL );
|
||||
count = 0;
|
||||
}
|
||||
|
||||
s_buffersMutex.unlock();
|
||||
@@ -161,26 +172,37 @@ void * bufferAllocator::allocBytes( Uint32 _bytes )
|
||||
{
|
||||
QMutexLocker ml( &s_buffersMutex );
|
||||
|
||||
bufIt free_buf = s_buffers.end();
|
||||
|
||||
// look whether there's a buffer matching to the one wanted and
|
||||
// find out the most used one (higher chances for being in CPU-cache)
|
||||
for( bufIt it = s_buffers.begin(); it != s_buffers.end(); ++it )
|
||||
// there's a low probability that we find a matching buffer, if there're
|
||||
// less than 2 bufs available, so do not search - this speeds up
|
||||
// processes like pattern-freezing because this way we do not have to
|
||||
// search for a free buffer in an array, containing several
|
||||
// 10.000 buffers
|
||||
if( s_freeBufs > s_buffers.size() / 10 )
|
||||
{
|
||||
if( ( *it ).free && ( *it ).bytes == _bytes )
|
||||
bufIt free_buf = s_buffers.end();
|
||||
|
||||
// look whether there's a buffer matching to the one wanted and
|
||||
// find out the most used one (higher chances for being in CPU-
|
||||
// cache)
|
||||
for( bufIt it = s_buffers.begin(); it != s_buffers.end(); ++it )
|
||||
{
|
||||
if( free_buf == s_buffers.end() ||
|
||||
( *it ).timesUsed > ( *free_buf ).timesUsed )
|
||||
if( ( *it ).free && ( *it ).bytes == _bytes )
|
||||
{
|
||||
free_buf = it;
|
||||
if( free_buf == s_buffers.end() ||
|
||||
( *it ).timesUsed >
|
||||
( *free_buf ).timesUsed )
|
||||
{
|
||||
free_buf = it;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( free_buf != s_buffers.end() )
|
||||
{
|
||||
( *free_buf ).free = FALSE;
|
||||
return( ( *free_buf ).buf );
|
||||
if( free_buf != s_buffers.end() )
|
||||
{
|
||||
--s_freeBufs;
|
||||
( *free_buf ).free = FALSE;
|
||||
return( ( *free_buf ).buf );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -195,3 +217,9 @@ void * bufferAllocator::allocBytes( Uint32 _bytes )
|
||||
|
||||
|
||||
|
||||
|
||||
void bufferAllocator::disableAutoCleanup( bool _disabled )
|
||||
{
|
||||
s_autoCleanupDisabled = _disabled;
|
||||
}
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
#include "tooltip.h"
|
||||
#include "bb_editor.h"
|
||||
#include "string_pair_drag.h"
|
||||
#include "buffer_allocator.h"
|
||||
|
||||
|
||||
QPixmap * pattern::s_stepBtnOn = NULL;
|
||||
@@ -1145,7 +1146,8 @@ void pattern::updateBBTrack( void )
|
||||
|
||||
patternFreezeStatusDialog::patternFreezeStatusDialog( QThread * _thread ) :
|
||||
QDialog(),
|
||||
m_freezeThread( _thread )
|
||||
m_freezeThread( _thread ),
|
||||
m_progress( 0 )
|
||||
{
|
||||
setWindowTitle( tr( "Freezing pattern..." ) );
|
||||
#if QT_VERSION >= 0x030200
|
||||
@@ -1249,6 +1251,7 @@ patternFreezeThread::patternFreezeThread( pattern * _pattern ) :
|
||||
QThread(),
|
||||
m_pattern( _pattern )
|
||||
{
|
||||
// create status-dialog
|
||||
m_statusDlg = new patternFreezeStatusDialog( this );
|
||||
QObject::connect( m_statusDlg, SIGNAL( aborted() ),
|
||||
m_pattern, SLOT( abortFreeze() ) );
|
||||
@@ -1269,6 +1272,8 @@ patternFreezeThread::~patternFreezeThread()
|
||||
|
||||
void patternFreezeThread::run( void )
|
||||
{
|
||||
bufferAllocator::disableAutoCleanup( TRUE );
|
||||
|
||||
// create and install audio-sample-recorder
|
||||
bool b;
|
||||
// we cannot create local copy, because at a later stage
|
||||
@@ -1288,10 +1293,10 @@ void patternFreezeThread::run( void )
|
||||
ppp.setCurrentFrame( 0 );
|
||||
ppp.m_timeLineUpdate = FALSE;
|
||||
|
||||
// create status-dialog
|
||||
m_pattern->m_freezeAborted = FALSE;
|
||||
m_pattern->m_freezing = TRUE;
|
||||
|
||||
|
||||
// now render everything
|
||||
while( ppp < m_pattern->length() &&
|
||||
m_pattern->m_freezeAborted == FALSE )
|
||||
@@ -1300,6 +1305,7 @@ void patternFreezeThread::run( void )
|
||||
m_statusDlg->setProgress( ppp * 100 / m_pattern->length() );
|
||||
}
|
||||
|
||||
|
||||
m_pattern->m_freezing = FALSE;
|
||||
|
||||
// reset song-editor settings
|
||||
@@ -1315,6 +1321,8 @@ void patternFreezeThread::run( void )
|
||||
m_pattern->m_frozenPatternMutex.unlock();
|
||||
}
|
||||
|
||||
bufferAllocator::disableAutoCleanup( FALSE );
|
||||
|
||||
// restore original audio-device
|
||||
mixer::inst()->restoreAudioDevice();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user