AFP: Add interpolation selector, fix segfault-causing bug with reverse mode
This commit is contained in:
@@ -37,12 +37,16 @@
|
||||
#include "lmms_basics.h"
|
||||
#include "lmms_math.h"
|
||||
#include "shared_object.h"
|
||||
#include "Mixer.h"
|
||||
|
||||
|
||||
class QPainter;
|
||||
|
||||
|
||||
const f_cnt_t MARGIN = 4;
|
||||
// values for buffer margins, used for various libsamplerate interpolation modes
|
||||
// the array positions correspond to the converter_type parameter values in libsamplerate
|
||||
// if there appears problems with playback on some interpolation mode, then the value for that mode
|
||||
// may need to be higher - conversely, to optimize, some may work with lower values
|
||||
const f_cnt_t MARGIN[] = { 64, 64, 64, 4, 4 };
|
||||
|
||||
class EXPORT SampleBuffer : public QObject, public sharedObject
|
||||
{
|
||||
@@ -56,7 +60,7 @@ public:
|
||||
class EXPORT handleState
|
||||
{
|
||||
public:
|
||||
handleState( bool _varying_pitch = false );
|
||||
handleState( bool _varying_pitch = false, int interp_mode = SRC_LINEAR );
|
||||
virtual ~handleState();
|
||||
|
||||
inline const f_cnt_t frameIndex() const
|
||||
@@ -78,6 +82,11 @@ public:
|
||||
{
|
||||
m_isBackwards = _backwards;
|
||||
}
|
||||
|
||||
inline int interpMode() const
|
||||
{
|
||||
return m_interpMode;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
@@ -85,6 +94,7 @@ public:
|
||||
const bool m_varyingPitch;
|
||||
bool m_isBackwards;
|
||||
SRC_STATE * m_resamplingData;
|
||||
int m_interpMode;
|
||||
|
||||
friend class SampleBuffer;
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtGui/QDropEvent>
|
||||
|
||||
#include <samplerate.h>
|
||||
|
||||
#include "audio_file_processor.h"
|
||||
#include "engine.h"
|
||||
@@ -78,6 +79,7 @@ audioFileProcessor::audioFileProcessor( InstrumentTrack * _instrument_track ) :
|
||||
m_reverseModel( false, this, tr( "Reverse sample" ) ),
|
||||
m_loopModel( 0, 0, 2, this, tr( "Loop mode" ) ),
|
||||
m_stutterModel( false, this, tr( "Stutter" ) ),
|
||||
m_interpModel( this, tr( "Interpolation mode" ) ),
|
||||
m_nextPlayStartPoint( 0 ),
|
||||
m_nextPlayBackwards( false )
|
||||
{
|
||||
@@ -93,6 +95,13 @@ audioFileProcessor::audioFileProcessor( InstrumentTrack * _instrument_track ) :
|
||||
this, SLOT( loopPointChanged() ) );
|
||||
connect( &m_stutterModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( stutterModelChanged() ) );
|
||||
|
||||
//interpolation modes
|
||||
m_interpModel.addItem( tr( "None" ) );
|
||||
m_interpModel.addItem( tr( "Linear" ) );
|
||||
m_interpModel.addItem( tr( "Sinc" ) );
|
||||
m_interpModel.setValue( 1 );
|
||||
|
||||
loopPointChanged();
|
||||
}
|
||||
|
||||
@@ -130,7 +139,21 @@ void audioFileProcessor::playNote( NotePlayHandle * _n,
|
||||
m_nextPlayStartPoint = m_sampleBuffer.startFrame();
|
||||
m_nextPlayBackwards = false;
|
||||
}
|
||||
_n->m_pluginData = new handleState( _n->hasDetuningInfo() );
|
||||
// set interpolation mode for libsamplerate
|
||||
int srcmode = SRC_LINEAR;
|
||||
switch( m_interpModel.value() )
|
||||
{
|
||||
case 0:
|
||||
srcmode = SRC_ZERO_ORDER_HOLD;
|
||||
break;
|
||||
case 1:
|
||||
srcmode = SRC_LINEAR;
|
||||
break;
|
||||
case 2:
|
||||
srcmode = SRC_SINC_MEDIUM_QUALITY;
|
||||
break;
|
||||
}
|
||||
_n->m_pluginData = new handleState( _n->hasDetuningInfo(), srcmode );
|
||||
((handleState *)_n->m_pluginData)->setFrameIndex( m_nextPlayStartPoint );
|
||||
((handleState *)_n->m_pluginData)->setBackwards( m_nextPlayBackwards );
|
||||
|
||||
@@ -197,6 +220,7 @@ void audioFileProcessor::saveSettings( QDomDocument & _doc,
|
||||
m_endPointModel.saveSettings( _doc, _this, "eframe" );
|
||||
m_loopPointModel.saveSettings( _doc, _this, "lframe" );
|
||||
m_stutterModel.saveSettings( _doc, _this, "stutter" );
|
||||
m_interpModel.saveSettings( _doc, _this, "interp" );
|
||||
|
||||
}
|
||||
|
||||
@@ -214,7 +238,6 @@ void audioFileProcessor::loadSettings( const QDomElement & _this )
|
||||
m_sampleBuffer.loadFromBase64( _this.attribute( "srcdata" ) );
|
||||
}
|
||||
|
||||
m_reverseModel.loadSettings( _this, "reversed" );
|
||||
m_loopModel.loadSettings( _this, "looped" );
|
||||
m_ampModel.loadSettings( _this, "amp" );
|
||||
m_endPointModel.loadSettings( _this, "eframe" );
|
||||
@@ -231,7 +254,17 @@ void audioFileProcessor::loadSettings( const QDomElement & _this )
|
||||
m_startPointModel.setValue( m_loopPointModel.value() );
|
||||
}
|
||||
|
||||
m_reverseModel.loadSettings( _this, "reversed" );
|
||||
|
||||
m_stutterModel.loadSettings( _this, "stutter" );
|
||||
if( _this.hasAttribute( "interp" ) )
|
||||
{
|
||||
m_interpModel.loadSettings( _this, "interp" );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_interpModel.setValue( 1 ); //linear by default
|
||||
}
|
||||
|
||||
loopPointChanged();
|
||||
}
|
||||
@@ -299,6 +332,8 @@ void audioFileProcessor::setAudioFile( const QString & _audio_file,
|
||||
void audioFileProcessor::reverseModelChanged( void )
|
||||
{
|
||||
m_sampleBuffer.setReversed( m_reverseModel.value() );
|
||||
m_nextPlayStartPoint = m_sampleBuffer.startFrame();
|
||||
m_nextPlayBackwards = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -501,7 +536,12 @@ AudioFileProcessorView::AudioFileProcessorView( Instrument * _instrument,
|
||||
tr( "With this knob you can set the point where "
|
||||
"the loop starts. " ) );
|
||||
|
||||
// interpolation selector
|
||||
m_interpBox = new comboBox( this );
|
||||
m_interpBox->setGeometry( 142, 62, 82, 22 );
|
||||
m_interpBox->setFont( pointSize<8>( m_interpBox->font() ) );
|
||||
|
||||
// wavegraph
|
||||
m_waveView = new AudioFileProcessorWaveView( this, 245, 75, castModel<audioFileProcessor>()->m_sampleBuffer );
|
||||
m_waveView->move( 2, 172 );
|
||||
m_waveView->setKnobs(
|
||||
@@ -652,6 +692,7 @@ void AudioFileProcessorView::modelChanged( void )
|
||||
m_reverseButton->setModel( &a->m_reverseModel );
|
||||
m_loopGroup->setModel( &a->m_loopModel );
|
||||
m_stutterButton->setModel( &a->m_stutterModel );
|
||||
m_interpBox->setModel( &a->m_interpModel );
|
||||
sampleUpdated();
|
||||
}
|
||||
|
||||
@@ -668,6 +709,7 @@ AudioFileProcessorWaveView::AudioFileProcessorWaveView( QWidget * _parent, int _
|
||||
m_last_to( 0 ),
|
||||
m_startKnob( 0 ),
|
||||
m_endKnob( 0 ),
|
||||
m_loopKnob( 0 ),
|
||||
m_isDragging( false ),
|
||||
m_reversed( false ),
|
||||
m_framesPlayed( 0 ),
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#include "knob.h"
|
||||
#include "pixmap_button.h"
|
||||
#include "automatable_button.h"
|
||||
|
||||
#include "combobox.h"
|
||||
|
||||
|
||||
class audioFileProcessor : public Instrument
|
||||
@@ -94,6 +94,7 @@ private:
|
||||
BoolModel m_reverseModel;
|
||||
IntModel m_loopModel;
|
||||
BoolModel m_stutterModel;
|
||||
ComboBoxModel m_interpModel;
|
||||
|
||||
f_cnt_t m_nextPlayStartPoint;
|
||||
bool m_nextPlayBackwards;
|
||||
@@ -141,6 +142,7 @@ private:
|
||||
pixmapButton * m_reverseButton;
|
||||
automatableButtonGroup * m_loopGroup;
|
||||
pixmapButton * m_stutterButton;
|
||||
comboBox * m_interpBox;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
|
||||
#include "SampleBuffer.h"
|
||||
#include "Mixer.h"
|
||||
|
||||
|
||||
#include <QtCore/QBuffer>
|
||||
@@ -664,7 +663,7 @@ bool SampleBuffer::play( sampleFrame * _ab, handleState * _state,
|
||||
{
|
||||
SRC_DATA src_data;
|
||||
// Generate output
|
||||
f_cnt_t fragment_size = (f_cnt_t)( _frames * freq_factor ) + MARGIN;
|
||||
f_cnt_t fragment_size = (f_cnt_t)( _frames * freq_factor ) + MARGIN[ _state->interpMode() ];
|
||||
src_data.data_in =
|
||||
getSampleFragment( play_frame, fragment_size, _loopmode, &tmp, &is_backwards,
|
||||
loopStartFrame, loopEndFrame, endFrame )[0];
|
||||
@@ -1439,22 +1438,17 @@ QString SampleBuffer::tryToMakeAbsolute( const QString & _file )
|
||||
|
||||
|
||||
|
||||
SampleBuffer::handleState::handleState( bool _varying_pitch ) :
|
||||
SampleBuffer::handleState::handleState( bool _varying_pitch, int interp_mode ) :
|
||||
m_frameIndex( 0 ),
|
||||
m_varyingPitch( _varying_pitch ),
|
||||
m_isBackwards( false )
|
||||
{
|
||||
int error;
|
||||
m_interpMode = interp_mode;
|
||||
|
||||
if( ( m_resamplingData = src_new(/*
|
||||
( engine::mixer()->highQuality() == true ) ?
|
||||
SRC_SINC_FASTEST :*/
|
||||
engine::mixer()->currentQualitySettings().
|
||||
libsrcInterpolation(),
|
||||
/*SRC_LINEAR,*/
|
||||
DEFAULT_CHANNELS, &error ) ) == NULL )
|
||||
if( ( m_resamplingData = src_new( interp_mode, DEFAULT_CHANNELS, &error ) ) == NULL )
|
||||
{
|
||||
printf( "Error: src_new() failed in sample_buffer.cpp!\n" );
|
||||
qDebug( "Error: src_new() failed in sample_buffer.cpp!\n" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user