AFP: Add interpolation selector, fix segfault-causing bug with reverse mode

This commit is contained in:
Vesa
2014-04-23 12:18:35 +03:00
parent ddf54fe5a0
commit fa67d0b436
4 changed files with 65 additions and 17 deletions

View File

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

View File

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

View File

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

View File

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