Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow SampleTCOs/Sample Clips to be reversed #5765

Merged
merged 13 commits into from
Nov 21, 2020
2 changes: 2 additions & 0 deletions include/SampleTrack.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public slots:

signals:
void sampleChanged();
void wasReversed();

} ;

Expand All @@ -109,6 +110,7 @@ class SampleTCOView : public TrackContentObjectView

public slots:
void updateSample();
void reverseSample();



Expand Down
96 changes: 35 additions & 61 deletions src/core/SampleBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,75 +296,43 @@ void SampleBuffer::update( bool _keep_settings )
}


void SampleBuffer::convertIntToFloat ( int_sample_t * & _ibuf, f_cnt_t _frames, int _channels)
void SampleBuffer::convertIntToFloat (int_sample_t * & ibuf, f_cnt_t frames, int channels)
{
// following code transforms int-samples into
// float-samples and does amplifying & reversing
// following code transforms int-samples into float-samples and does amplifying & reversing
const float fac = 1 / OUTPUT_SAMPLE_MULTIPLIER;
m_data = MM_ALLOC( sampleFrame, _frames );
const int ch = ( _channels > 1 ) ? 1 : 0;
m_data = MM_ALLOC(sampleFrame, frames);
const int ch = (channels > 1) ? 1 : 0;

// if reversing is on, we also reverse when
// scaling
if( m_reversed )
// if reversing is on, we also reverse when scaling
bool isReversed = m_reversed;
int idx = isReversed ? (frames - 1) * channels : 0;
for (f_cnt_t frame = 0; frame < frames; ++frame)
{
int idx = ( _frames - 1 ) * _channels;
for( f_cnt_t frame = 0; frame < _frames;
++frame )
{
m_data[frame][0] = _ibuf[idx+0] * fac;
m_data[frame][1] = _ibuf[idx+ch] * fac;
idx -= _channels;
}
}
else
{
int idx = 0;
for( f_cnt_t frame = 0; frame < _frames;
++frame )
{
m_data[frame][0] = _ibuf[idx+0] * fac;
m_data[frame][1] = _ibuf[idx+ch] * fac;
idx += _channels;
}
m_data[frame][0] = ibuf[idx+0] * fac;
m_data[frame][1] = ibuf[idx+ch] * fac;
idx += isReversed ? -channels : channels;
}

delete[] _ibuf;
delete[] ibuf;
}

void SampleBuffer::directFloatWrite ( sample_t * & _fbuf, f_cnt_t _frames, int _channels)

void SampleBuffer::directFloatWrite (sample_t * & fbuf, f_cnt_t frames, int channels)
{

m_data = MM_ALLOC( sampleFrame, _frames );
const int ch = ( _channels > 1 ) ? 1 : 0;
m_data = MM_ALLOC(sampleFrame, frames);
const int ch = (channels > 1) ? 1 : 0;

// if reversing is on, we also reverse when
// scaling
if( m_reversed )
// if reversing is on, we also reverse when scaling
bool isReversed = m_reversed;
int idx = isReversed ? (frames - 1) * channels : 0;
for (f_cnt_t frame = 0; frame < frames; ++frame)
{
int idx = ( _frames - 1 ) * _channels;
for( f_cnt_t frame = 0; frame < _frames;
++frame )
{
m_data[frame][0] = _fbuf[idx+0];
m_data[frame][1] = _fbuf[idx+ch];
idx -= _channels;
}
}
else
{
int idx = 0;
for( f_cnt_t frame = 0; frame < _frames;
++frame )
{
m_data[frame][0] = _fbuf[idx+0];
m_data[frame][1] = _fbuf[idx+ch];
idx += _channels;
}
m_data[frame][0] = fbuf[idx+0];
m_data[frame][1] = fbuf[idx+ch];
idx += isReversed ? -channels : channels;
}

delete[] _fbuf;
delete[] fbuf;
}


Expand Down Expand Up @@ -957,12 +925,18 @@ void SampleBuffer::visualize( QPainter & _p, const QRect & _dr,
const int xb = _dr.x();
const int first = focus_on_range ? _from_frame : 0;
const int last = focus_on_range ? _to_frame : m_frames;
for( int frame = first; frame < last; frame += fpp )
{
l[n] = QPointF( xb + ( (frame - first) * double( w ) / nb_frames ),
( yb - ( m_data[frame][0] * y_space * m_amplification ) ) );
r[n] = QPointF( xb + ( (frame - first) * double( w ) / nb_frames ),
( yb - ( m_data[frame][1] * y_space * m_amplification ) ) );

const bool isReversed = m_reversed;

auto startFrame = isReversed ? last : first;
auto count = (last - first) / fpp + 1;
auto step = isReversed ? -fpp : fpp;
for (int frame = startFrame, i = 0; i < count; frame += step, i++)
{
l[n] = QPointF (xb + ((frame - first) * double(w) / nb_frames),
(yb - (m_data[frame][0] * y_space * m_amplification)));
r[n] = QPointF (xb + ((frame - first) * double(w) / nb_frames),
(yb - (m_data[frame][1] * y_space * m_amplification)));
++n;
}
_p.setRenderHint( QPainter::Antialiasing );
Expand Down
27 changes: 27 additions & 0 deletions src/tracks/SampleTrack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,10 @@ void SampleTCO::saveSettings( QDomDocument & _doc, QDomElement & _this )
{
_this.setAttribute( "color", color().name() );
}
if(m_sampleBuffer->reversed())
{
_this.setAttribute("reversed", "true");
}
// TODO: start- and end-frame
}

Expand Down Expand Up @@ -310,11 +314,18 @@ void SampleTCO::loadSettings( const QDomElement & _this )
useCustomClipColor( true );
setColor( _this.attribute( "color" ) );
}

if(_this.hasAttribute("reversed"))
{
m_sampleBuffer->setReversed(true);
emit wasReversed(); // tell SampleTCOView to update the view
}
}





TrackContentObjectView * SampleTCO::createView( TrackView * _tv )
{
return new SampleTCOView( this, _tv );
Expand All @@ -335,6 +346,9 @@ SampleTCOView::SampleTCOView( SampleTCO * _tco, TrackView * _tv ) :
connect( m_tco, SIGNAL( sampleChanged() ),
this, SLOT( updateSample() ) );

connect(m_tco, SIGNAL(wasReversed()),
this, SLOT(update()));

setStyle( QApplication::style() );
}

Expand Down Expand Up @@ -408,6 +422,9 @@ void SampleTCOView::contextMenuEvent( QContextMenuEvent * _cme )
tr( "Set/clear record" ),
m_tco, SLOT( toggleRecord() ) );*/

contextMenu.addAction(embed::getIconPixmap("flip_x"),
tr("Reverse sample"), this, SLOT(reverseSample()));

contextMenu.addSeparator();

contextMenu.addAction( embed::getIconPixmap( "colorize" ),
Expand Down Expand Up @@ -625,6 +642,16 @@ void SampleTCOView::paintEvent( QPaintEvent * pe )



void SampleTCOView::reverseSample()
{
m_tco->sampleBuffer()->setReversed(!m_tco->sampleBuffer()->reversed());
Engine::getSong()->setModified();
update();
}






SampleTrack::SampleTrack(TrackContainer* tc) :
Expand Down