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:
Tobias Doerffel
2006-01-30 10:50:02 +00:00
parent 422e4364e6
commit 66d18659a4
9 changed files with 98 additions and 46 deletions

View File

@@ -16,4 +16,4 @@ gabriel
Andreas Brandmaier
<andy/at/brandmaier.de>
BitInvader plugin
BitInvader plugin

View File

@@ -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
View File

@@ -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

View File

@@ -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)

View File

@@ -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>

View File

@@ -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 ) ) );
}

View File

@@ -83,6 +83,7 @@ void graph::setSamplePointer( float * _pointer, int _length )
{
samplePointer = _pointer;
sampleLength = _length;
update();
}
void graph::mouseMoveEvent ( QMouseEvent * _me )

View File

@@ -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;
}

View File

@@ -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();