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:
@@ -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,
|
||||
|
||||
@@ -94,6 +94,7 @@ private:
|
||||
|
||||
signals:
|
||||
void sampleChanged();
|
||||
void wasReversed();
|
||||
|
||||
} ;
|
||||
|
||||
@@ -109,6 +110,7 @@ public:
|
||||
|
||||
public slots:
|
||||
void updateSample();
|
||||
void reverseSample();
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) :
|
||||
|
||||
Reference in New Issue
Block a user