diff --git a/include/SampleBuffer.h b/include/SampleBuffer.h index 89a3add3b..680ec60c4 100644 --- a/include/SampleBuffer.h +++ b/include/SampleBuffer.h @@ -117,10 +117,10 @@ public: const float _freq, const LoopMode _loopmode = LoopOff ); - void visualize( QPainter & _p, const QRect & _dr, const QRect & _clip, f_cnt_t _from_frame = 0, f_cnt_t _to_frame = 0 ); - inline void visualize( QPainter & _p, const QRect & _dr, f_cnt_t _from_frame = 0, f_cnt_t _to_frame = 0 ) + void visualize(QPainter & p, const QRect & dr, const QRect & clip, f_cnt_t from_frame = 0, f_cnt_t to_frame = 0); + inline void visualize(QPainter & p, const QRect & dr, f_cnt_t from_frame = 0, f_cnt_t to_frame = 0) { - visualize( _p, _dr, _dr, _from_frame, _to_frame ); + visualize(p, dr, dr, from_frame, to_frame); } inline const QString & audioFile() const @@ -266,8 +266,8 @@ private: void update( bool _keep_settings = false ); - void convertIntToFloat ( int_sample_t * & _ibuf, f_cnt_t _frames, int _channels); - void directFloatWrite ( sample_t * & _fbuf, f_cnt_t _frames, int _channels); + void convertIntToFloat(int_sample_t * & ibuf, f_cnt_t frames, int channels); + void directFloatWrite(sample_t * & fbuf, f_cnt_t frames, int channels); f_cnt_t decodeSampleSF( QString _f, sample_t * & _buf, ch_cnt_t & _channels, diff --git a/include/SampleTrack.h b/include/SampleTrack.h index eda1299a5..110b16576 100644 --- a/include/SampleTrack.h +++ b/include/SampleTrack.h @@ -94,6 +94,7 @@ private: signals: void sampleChanged(); + void wasReversed(); } ; @@ -109,6 +110,7 @@ public: public slots: void updateSample(); + void reverseSample(); diff --git a/src/core/SampleBuffer.cpp b/src/core/SampleBuffer.cpp index ffe631ca4..649494568 100644 --- a/src/core/SampleBuffer.cpp +++ b/src/core/SampleBuffer.cpp @@ -296,75 +296,49 @@ 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; } @@ -935,39 +909,45 @@ f_cnt_t SampleBuffer::getPingPongIndex( f_cnt_t _index, f_cnt_t _startf, f_cnt_t } -void SampleBuffer::visualize( QPainter & _p, const QRect & _dr, - const QRect & _clip, f_cnt_t _from_frame, f_cnt_t _to_frame ) +void SampleBuffer::visualize( + QPainter & p, + const QRect & dr, + const QRect & clip, + f_cnt_t from_frame, + f_cnt_t to_frame) { - if( m_frames == 0 ) return; + if (m_frames == 0) { return; } - const bool focus_on_range = _to_frame <= m_frames - && 0 <= _from_frame && _from_frame < _to_frame; - //_p.setClipRect( _clip ); - const int w = _dr.width(); - const int h = _dr.height(); + const bool focus_on_range = to_frame <= m_frames && 0 <= from_frame && from_frame < to_frame; + //p.setClipRect( clip ); + const int w = dr.width(); + const int h = dr.height(); - const int yb = h / 2 + _dr.y(); + const int yb = h / 2 + dr.y(); const float y_space = h*0.5f; - const int nb_frames = focus_on_range ? _to_frame - _from_frame : m_frames; + const int nb_frames = focus_on_range ? to_frame - from_frame : m_frames; - const int fpp = qBound( 1, nb_frames / w, 20 ); + const int fpp = qBound(1, nb_frames / w, 20); QPointF * l = new QPointF[nb_frames / fpp + 1]; QPointF * r = new QPointF[nb_frames / fpp + 1]; int n = 0; - 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 ) + const int xb = dr.x(); + const int first = focus_on_range ? from_frame : 0; + const int last = focus_on_range ? to_frame - 1 : m_frames - 1; + + 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 ) ) ); + auto x = xb + ((frame - first) * double(w) / nb_frames); + // Partial Y calculation + auto py = y_space * m_amplification; + l[n] = QPointF(x, (yb - (m_data[frame][0] * py))); + r[n] = QPointF(x, (yb - (m_data[frame][1] * py))); ++n; } - _p.setRenderHint( QPainter::Antialiasing ); - _p.drawPolyline( l, nb_frames / fpp ); - _p.drawPolyline( r, nb_frames / fpp ); + + p.setRenderHint(QPainter::Antialiasing); + p.drawPolyline(l, nb_frames / fpp); + p.drawPolyline(r, nb_frames / fpp); delete[] l; delete[] r; } diff --git a/src/tracks/SampleTrack.cpp b/src/tracks/SampleTrack.cpp index 398fbd28a..197e3fcf1 100644 --- a/src/tracks/SampleTrack.cpp +++ b/src/tracks/SampleTrack.cpp @@ -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 } @@ -310,6 +314,12 @@ 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 + } } @@ -332,8 +342,9 @@ SampleTCOView::SampleTCOView( SampleTCO * _tco, TrackView * _tv ) : updateSample(); // track future changes of SampleTCO - connect( m_tco, SIGNAL( sampleChanged() ), - this, SLOT( updateSample() ) ); + connect(m_tco, SIGNAL(sampleChanged()), this, SLOT(updateSample())); + + connect(m_tco, SIGNAL(wasReversed()), this, SLOT(update())); setStyle( QApplication::style() ); } @@ -408,6 +419,13 @@ 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" ), @@ -625,6 +643,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) :