Ping-pong loop implementation: done, starting on AFP changes...
@@ -76,7 +76,7 @@ audioFileProcessor::audioFileProcessor( InstrumentTrack * _instrument_track ) :
|
||||
m_endPointModel( 1, 0, 1, 0.0000001f, this, tr( "End of sample" ) ),
|
||||
m_loopPointModel( 0, 0, 1, 0.0000001f, this, tr( "Loopback point" ) ),
|
||||
m_reverseModel( false, this, tr( "Reverse sample" ) ),
|
||||
m_loopModel( false, this, tr( "Loop enabled" ) ),
|
||||
m_loopModel( 0, 0, 2, this, tr( "Loop mode" ) ),
|
||||
m_stutterModel( false, this, tr( "Stutter" ) ),
|
||||
m_nextPlayStartPoint( 0 )
|
||||
{
|
||||
@@ -383,7 +383,7 @@ AudioFileProcessorView::AudioFileProcessorView( Instrument * _instrument,
|
||||
|
||||
m_reverseButton = new pixmapButton( this );
|
||||
m_reverseButton->setCheckable( TRUE );
|
||||
m_reverseButton->move( 174, 124 );
|
||||
m_reverseButton->move( 200, 124 );
|
||||
m_reverseButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"reverse_on" ) );
|
||||
m_reverseButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
@@ -394,17 +394,50 @@ AudioFileProcessorView::AudioFileProcessorView( Instrument * _instrument,
|
||||
"This is useful for cool effects, e.g. a reversed "
|
||||
"crash." ) );
|
||||
|
||||
m_loopButton = new pixmapButton( this );
|
||||
m_loopButton->setCheckable( TRUE );
|
||||
m_loopButton->move( 200, 124 );
|
||||
m_loopButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"loop_on" ) );
|
||||
m_loopButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"loop_off" ) );
|
||||
toolTip::add( m_loopButton, tr( "Enable loop" ) );
|
||||
m_loopButton->setWhatsThis(
|
||||
tr( "This button enables looping. "
|
||||
// loop button group
|
||||
|
||||
pixmapbutton * m_loopOffButton = new pixmapButton( this );
|
||||
m_loopOffButton->setCheckable( TRUE );
|
||||
m_loopOffButton->move( 174, 144 );
|
||||
m_loopOffButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"loop_off_on" ) );
|
||||
m_loopOffButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"loop_off_off" ) );
|
||||
toolTip::add( m_loopOffButton, tr( "Disable loop" ) );
|
||||
m_loopOffButton->setWhatsThis(
|
||||
tr( "This button disables looping. "
|
||||
"The sample plays only once from start to end. " ) );
|
||||
|
||||
|
||||
pixmapbutton * m_loopOnButton = new pixmapButton( this );
|
||||
m_loopOnButton->setCheckable( TRUE );
|
||||
m_loopOnButton->move( 200, 144 );
|
||||
m_loopOnButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"loop_on_on" ) );
|
||||
m_loopOnButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"loop_on_off" ) );
|
||||
toolTip::add( m_loopOnButton, tr( "Enable loop" ) );
|
||||
m_loopOnButton->setWhatsThis(
|
||||
tr( "This button enables forwards-looping. "
|
||||
"The sample loops between the end point and the loop point." ) );
|
||||
|
||||
pixmapbutton * m_loopPingPongButton = new pixmapButton( this );
|
||||
m_loopPingPongButton->setCheckable( TRUE );
|
||||
m_loopPingPongButton->move( 226, 144 );
|
||||
m_loopPingPongButton->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"loop_pingpong_on" ) );
|
||||
m_loopPingPongButton->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"loop_pingpong_off" ) );
|
||||
toolTip::add( m_loopPingPongButton, tr( "Enable loop" ) );
|
||||
m_loopPingPongButton->setWhatsThis(
|
||||
tr( "This button enables ping-pong-looping. "
|
||||
"The sample loops backwards and forwards between the end point "
|
||||
"and the loop point." ) );
|
||||
|
||||
m_loopGroup = new automatableButtonGroup( this );
|
||||
m_loopGroup->addButton( m_loopOffButton );
|
||||
m_loopGroup->addButton( m_loopOnButton );
|
||||
m_loopGroup->addButton( m_loopPingPongButton );
|
||||
|
||||
m_stutterButton = new pixmapButton( this );
|
||||
m_stutterButton->setCheckable( true );
|
||||
@@ -604,7 +637,7 @@ void AudioFileProcessorView::modelChanged( void )
|
||||
m_endKnob->setModel( &a->m_endPointModel );
|
||||
m_loopKnob->setModel( &a->m_loopPointModel );
|
||||
m_reverseButton->setModel( &a->m_reverseModel );
|
||||
m_loopButton->setModel( &a->m_loopModel );
|
||||
m_loopGroup->setModel( &a->m_loopModel );
|
||||
m_stutterButton->setModel( &a->m_stutterModel );
|
||||
sampleUpdated();
|
||||
}
|
||||
@@ -684,7 +717,7 @@ void AudioFileProcessorWaveView::mousePressEvent( QMouseEvent * _me )
|
||||
if( start_dist < loop_dist ) { dt = sample_start; md = start_dist; }
|
||||
if( end_dist < start_dist ) { dt = sample_end; md = end_dist; }
|
||||
|
||||
if( md < 3 )
|
||||
if( md < 4 )
|
||||
{
|
||||
m_draggingType = dt;
|
||||
}
|
||||
@@ -780,7 +813,6 @@ void AudioFileProcessorWaveView::paintEvent( QPaintEvent * _pe )
|
||||
|
||||
p.drawPixmap( s_padding, s_padding, m_graph );
|
||||
|
||||
p.setPen( QColor( 0xFF, 0xFF, 0xFF ) ); //TODO: put into a qproperty
|
||||
const QRect graph_rect( s_padding, s_padding, width() - 2 * s_padding, height() - 2 * s_padding );
|
||||
const f_cnt_t frames = m_to - m_from;
|
||||
m_startFrameX = graph_rect.x() + ( m_sampleBuffer.startFrame() - m_from ) *
|
||||
@@ -792,6 +824,14 @@ void AudioFileProcessorWaveView::paintEvent( QPaintEvent * _pe )
|
||||
const int played_width_px = ( m_framesPlayed - m_from ) *
|
||||
double( graph_rect.width() ) / frames;
|
||||
|
||||
// loop point line
|
||||
p.setPen( QColor( 0x7F, 0xFF, 0xFF ) ); //TODO: put into a qproperty
|
||||
p.drawLine( m_loopFrameX, graph_rect.y(),
|
||||
m_loopFrameX,
|
||||
graph_rect.height() + graph_rect.y() );
|
||||
|
||||
// start/end lines
|
||||
p.setPen( QColor( 0xFF, 0xFF, 0xFF ) ); //TODO: put into a qproperty
|
||||
p.drawLine( m_startFrameX, graph_rect.y(),
|
||||
m_startFrameX,
|
||||
graph_rect.height() + graph_rect.y() );
|
||||
@@ -799,10 +839,6 @@ void AudioFileProcessorWaveView::paintEvent( QPaintEvent * _pe )
|
||||
m_endFrameX,
|
||||
graph_rect.height() + graph_rect.y() );
|
||||
|
||||
p.setPen( QColor( 0x7F, 0xFF, 0xFF ) ); //TODO: put into a qproperty
|
||||
p.drawLine( m_loopFrameX, graph_rect.y(),
|
||||
m_loopFrameX,
|
||||
graph_rect.height() + graph_rect.y() );
|
||||
|
||||
if( m_endFrameX - m_startFrameX > 2 )
|
||||
{
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "SampleBuffer.h"
|
||||
#include "knob.h"
|
||||
#include "pixmap_button.h"
|
||||
#include "automatable_button.h"
|
||||
|
||||
|
||||
|
||||
@@ -91,7 +92,7 @@ private:
|
||||
FloatModel m_endPointModel;
|
||||
FloatModel m_loopPointModel;
|
||||
BoolModel m_reverseModel;
|
||||
BoolModel m_loopModel;
|
||||
IntModel m_loopModel;
|
||||
BoolModel m_stutterModel;
|
||||
|
||||
f_cnt_t m_nextPlayStartPoint;
|
||||
@@ -137,7 +138,7 @@ private:
|
||||
|
||||
pixmapButton * m_openAudioFileButton;
|
||||
pixmapButton * m_reverseButton;
|
||||
pixmapButton * m_loopButton;
|
||||
automatableButtonGroup * m_loopGroup;
|
||||
pixmapButton * m_stutterButton;
|
||||
|
||||
} ;
|
||||
@@ -270,7 +271,7 @@ private:
|
||||
|
||||
static bool isCloseTo( int _a, int _b )
|
||||
{
|
||||
return qAbs( _a - _b ) < 3;
|
||||
return qAbs( _a - _b ) < 4;
|
||||
}
|
||||
|
||||
} ;
|
||||
|
||||
BIN
plugins/audio_file_processor/loop_off_off.png
Normal file
|
After Width: | Height: | Size: 534 B |
BIN
plugins/audio_file_processor/loop_off_on.png
Normal file
|
After Width: | Height: | Size: 463 B |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
plugins/audio_file_processor/loop_pingpong_off.png
Normal file
|
After Width: | Height: | Size: 655 B |
BIN
plugins/audio_file_processor/loop_pingpong_on.png
Normal file
|
After Width: | Height: | Size: 611 B |
@@ -620,10 +620,10 @@ bool SampleBuffer::play( sampleFrame * _ab, handleState * _state,
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// variable for determining if we should currently be playing backwards in a ping-pong loop
|
||||
bool is_backwards = _state->isBackwards();
|
||||
|
||||
|
||||
const double freq_factor = (double) _freq / (double) m_frequency *
|
||||
m_sampleRate / engine::mixer()->processingSampleRate();
|
||||
|
||||
@@ -639,6 +639,7 @@ bool SampleBuffer::play( sampleFrame * _ab, handleState * _state,
|
||||
|
||||
// this holds the number of the first frame to play
|
||||
f_cnt_t play_frame = _state->m_frameIndex;
|
||||
|
||||
if( play_frame < m_startFrame )
|
||||
{
|
||||
play_frame = m_startFrame;
|
||||
@@ -656,9 +657,9 @@ bool SampleBuffer::play( sampleFrame * _ab, handleState * _state,
|
||||
else if( _loopmode == LoopPingPong )
|
||||
{
|
||||
play_frame = getPingPongIndex( play_frame );
|
||||
if( is_backwards )
|
||||
if( is_backwards )
|
||||
frames_for_loop = static_cast<f_cnt_t>( ( play_frame - m_loopStartFrame ) / freq_factor );
|
||||
else
|
||||
else
|
||||
frames_for_loop = static_cast<f_cnt_t>( ( m_loopEndFrame - play_frame ) / freq_factor );
|
||||
}
|
||||
else
|
||||
@@ -730,7 +731,7 @@ bool SampleBuffer::play( sampleFrame * _ab, handleState * _state,
|
||||
}
|
||||
play_frame += left;
|
||||
play_frame = getPingPongIndex( play_frame );
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -768,7 +769,7 @@ bool SampleBuffer::play( sampleFrame * _ab, handleState * _state,
|
||||
}
|
||||
play_frame += left;
|
||||
play_frame = getPingPongIndex( play_frame );
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -804,8 +805,9 @@ sampleFrame * SampleBuffer::getSampleFragment( f_cnt_t _start,
|
||||
}
|
||||
/* else
|
||||
{
|
||||
if( ! *_backwards && _start + _frames < m_loopEndFrame )
|
||||
return m_data + _start;
|
||||
if( ! *_backwards && pos + _frames < m_loopEndFrame )
|
||||
*_index = pos + _frames;
|
||||
return m_data + pos;
|
||||
}*/
|
||||
|
||||
*_tmp = new sampleFrame[_frames];
|
||||
@@ -815,20 +817,19 @@ sampleFrame * SampleBuffer::getSampleFragment( f_cnt_t _start,
|
||||
f_cnt_t copied = qMin( _frames, m_loopEndFrame - _start );
|
||||
memcpy( *_tmp, m_data + _start, copied * BYTES_PER_FRAME );
|
||||
f_cnt_t loop_frames = m_loopEndFrame - m_loopStartFrame;
|
||||
while( _frames - copied > 0 )
|
||||
while( copied < _frames )
|
||||
{
|
||||
f_cnt_t todo = qMin( _frames - copied, loop_frames );
|
||||
memcpy( *_tmp + copied, m_data + m_loopStartFrame,
|
||||
todo * BYTES_PER_FRAME );
|
||||
memcpy( *_tmp + copied, m_data + m_loopStartFrame, todo * BYTES_PER_FRAME );
|
||||
copied += todo;
|
||||
}
|
||||
}
|
||||
else if( _loopmode == LoopPingPong )
|
||||
{
|
||||
f_cnt_t copied = 0;
|
||||
bool backwards = *_backwards;
|
||||
f_cnt_t pos = _start;
|
||||
|
||||
bool backwards = *_backwards;
|
||||
f_cnt_t copied = 0;
|
||||
|
||||
if( backwards )
|
||||
{
|
||||
copied = qMin( _frames, pos - m_loopStartFrame );
|
||||
@@ -866,7 +867,7 @@ sampleFrame * SampleBuffer::getSampleFragment( f_cnt_t _start,
|
||||
(*_tmp)[ copied + i ][1] = m_data[ pos - i ][1];
|
||||
}
|
||||
pos -= todo;
|
||||
copied += todo;
|
||||
copied += todo;
|
||||
if( pos == m_loopStartFrame ) backwards = false;
|
||||
}
|
||||
else
|
||||
@@ -874,6 +875,7 @@ sampleFrame * SampleBuffer::getSampleFragment( f_cnt_t _start,
|
||||
f_cnt_t todo = qMin( _frames - copied, m_loopEndFrame - pos );
|
||||
memcpy( *_tmp + copied, m_data + pos, todo * BYTES_PER_FRAME );
|
||||
pos += todo;
|
||||
copied += todo;
|
||||
if( pos == m_loopEndFrame ) backwards = true;
|
||||
}
|
||||
}
|
||||
|
||||