added resampling with Sinc-interpolation in case LMMS processes with higher sample-rate than 96 KHz

git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@920 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
Tobias Doerffel
2008-04-14 21:01:45 +00:00
parent 5fc7ffe42d
commit 4b8cf35c40
3 changed files with 78 additions and 10 deletions

View File

@@ -1,3 +1,10 @@
2008-04-14 Tobias Doerffel <tobydox/at/users/dot/sourceforge/dot/net>
* plugins/sf2_player/sf2_player.cpp:
* plugins/sf2_player/sf2_player.h:
added resampling with Sinc-interpolation in case LMMS processes with
higher sample-rate than 96 KHz
2008-04-14 Paul Giblock <drfaygo/at/gmail/dot/com>
* plugins/sf2_player/sf2_player.cpp:

View File

@@ -76,6 +76,7 @@ int (* sf2Instrument::s_origFree)( fluid_sfont_t * );
sf2Instrument::sf2Instrument( instrumentTrack * _instrument_track ) :
instrument( _instrument_track, &sf2player_plugin_descriptor ),
m_srcState( NULL ),
m_fontId( 0 ),
m_filename( "" ),
m_bankNum( -1, -1, 999, 1, this ),
@@ -126,6 +127,10 @@ sf2Instrument::~sf2Instrument()
engine::getMixer()->removePlayHandles( getInstrumentTrack() );
delete_fluid_synth( m_synth );
delete_fluid_settings( m_settings );
if( m_srcState != NULL )
{
src_delete( m_srcState );
}
}
@@ -225,22 +230,44 @@ void sf2Instrument::updateSampleRate( void )
fluid_settings_getnum( m_settings, "synth.sample-rate", &tempRate );
m_internalSampleRate = static_cast<int>( tempRate );
if( m_filename != "" ) {
// New synth
fluid_synth_t * synth = new_fluid_synth( m_settings );
// Load sfont, should be in memory and increment refCount
m_fontId = fluid_synth_sfload( synth, qPrintable( m_filename ), TRUE );
if( m_filename != "" )
{
// Now, delete the old one and replace
m_synthMutex.lock();
delete_fluid_synth( m_synth );
m_synth = synth;
// New synth
m_synth = new_fluid_synth( m_settings );
// Load sfont, should be in memory and increment refCount
char * sf2Ascii = qstrdup( qPrintable( m_filename ) );
m_fontId = fluid_synth_sfload( m_synth, sf2Ascii, TRUE );
delete[] sf2Ascii;
// openFile( m_filename );
m_synthMutex.unlock();
// synth program change (set bank and patch)
updatePatch();
}
if( m_internalSampleRate < engine::getMixer()->sampleRate() )
{
m_synthMutex.lock();
if( m_srcState != NULL )
{
src_delete( m_srcState );
}
int error;
m_srcState = src_new( SRC_SINC_MEDIUM_QUALITY,
DEFAULT_CHANNELS, &error );
if( m_srcState == NULL || error )
{
printf( "error while creating SRC-data-"
"structure in sf2Instrument::"
"updateSampleRate()\n" );
}
m_synthMutex.unlock();
}
}
@@ -292,8 +319,39 @@ void sf2Instrument::play( bool _try_parallelizing,
// to account properly for accumulated error (i.e: using frames*internalRate/mixerRate
// will not work unless the value is whole. Probably only a big deal for small period-sizes?
fluid_synth_write_float( m_synth, frames, _working_buffer, 0, 2,
if( m_internalSampleRate < engine::getMixer()->sampleRate() &&
m_srcState != NULL )
{
const fpp_t f = frames * m_internalSampleRate /
engine::getMixer()->sampleRate();
sampleFrame * tmp = new sampleFrame[f];
fluid_synth_write_float( m_synth, f, tmp, 0, 2, tmp, 1, 2 );
SRC_DATA src_data;
src_data.data_in = tmp[0];
src_data.data_out = _working_buffer[0];
src_data.input_frames = f;
src_data.output_frames = frames;
src_data.src_ratio = (float) frames / f;
src_data.end_of_input = 0;
int error = src_process( m_srcState, &src_data );
delete[] tmp;
if( error )
{
printf( "sf2Instrument: error while resampling: %s\n",
src_strerror( error ) );
}
if( src_data.output_frames_gen > frames )
{
printf( "sf2Instrument: not enough frames: %ld / %d\n",
src_data.output_frames_gen, frames );
}
}
else
{
fluid_synth_write_float( m_synth, frames, _working_buffer, 0, 2,
_working_buffer, 1, 2 );
}
m_synthMutex.unlock();
getInstrumentTrack()->processAudioBuffer( _working_buffer, frames,

View File

@@ -34,6 +34,7 @@
#include "knob.h"
#include "lcd_spinbox.h"
#include "fluidsynth.h"
#include "sample_buffer.h"
class sf2InstrumentView;
class sf2Font;
@@ -88,7 +89,9 @@ public slots:
private:
static QMap<QString, sf2Font*> s_fonts;
static int (* s_origFree)( fluid_sfont_t * );
static int (* s_origFree)( fluid_sfont_t * );
SRC_STATE * m_srcState;
fluid_settings_t* m_settings;
fluid_synth_t* m_synth;