Allow SampleTCOs/Sample Clips to be reversed (#5765)

Enable the reverse option from `SampleBuffer.cpp`, and partially change the style and make more readable `SampleBuffer.cpp`.
This commit is contained in:
Kumar
2020-11-21 09:56:06 +05:30
committed by GitHub
parent 83e51ffc45
commit 53b003bc8f
4 changed files with 94 additions and 84 deletions

View File

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

View File

@@ -94,6 +94,7 @@ private:
signals:
void sampleChanged();
void wasReversed();
} ;
@@ -109,6 +110,7 @@ public:
public slots:
void updateSample();
void reverseSample();

View File

@@ -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<int>( 1, nb_frames / w, 20 );
const int fpp = qBound<int>(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;
}

View File

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