Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions include/Clip.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,30 @@ class LMMS_EXPORT Clip : public Model, public JournallingObject
TimePos startTimeOffset() const;
void setStartTimeOffset( const TimePos &startTimeOffset );

TimePos startCrossfadeLength() const { return m_startCrossfadeLength; }
void setStartCrossfadeLength(const TimePos& startCrossfadeLength)
{
m_startCrossfadeLength = std::max(TimePos{0}, startCrossfadeLength);
}
TimePos endCrossfadeLength() const { return m_endCrossfadeLength; }
void setEndCrossfadeLength(const TimePos &endCrossfadeLength)
{
m_endCrossfadeLength = std::max(TimePos{0}, endCrossfadeLength);
}

float startCrossfadeTension() const { return m_startCrossfadeTension; }
void setStartCrossfadeTension(float startCrossfadeTension)
{
m_startCrossfadeTension = std::clamp(startCrossfadeTension, 0.0f, 1.0f);
}
float endCrossfadeTension() const { return m_endCrossfadeTension; }
void setEndCrossfadeTension(float endCrossfadeTension)
{
m_endCrossfadeTension = std::clamp(endCrossfadeTension, 0.0f, 1.0f);
}

virtual bool isCrossfadeable() const { return false; }

// Will copy the state of a clip to another clip
static void copyStateTo( Clip *src, Clip *dst );

Expand Down Expand Up @@ -181,6 +205,11 @@ public slots:
TimePos m_length;
TimePos m_startTimeOffset;

TimePos m_startCrossfadeLength;
TimePos m_endCrossfadeLength;
float m_startCrossfadeTension;
float m_endCrossfadeTension;

BoolModel m_mutedModel;
BoolModel m_soloModel;
bool m_resizable = true;
Expand Down
11 changes: 11 additions & 0 deletions include/ClipView.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ public slots:
void mousePressEvent( QMouseEvent * me ) override;
void mouseMoveEvent( QMouseEvent * me ) override;
void mouseReleaseEvent( QMouseEvent * me ) override;
void leaveEvent(QEvent * e) override;
void resizeEvent( QResizeEvent * re ) override
{
m_needsUpdate = true;
Expand All @@ -184,6 +185,7 @@ public slots:
DataFile createClipDataFiles(const QVector<ClipView *> & clips) const;

virtual void paintTextLabel(QString const & text, QPainter & painter);
virtual void drawCrossfade(QPainter& painter, QRect rect);

auto hasCustomColor() const -> bool;

Expand All @@ -200,6 +202,10 @@ protected slots:
MoveSelection,
Resize,
ResizeLeft,
EditStartCrossfade,
EditEndCrossfade,
EditStartCrossfadeTension,
EditEndCrossfadeTension,
Split,
CopySelection,
ToggleSelected
Expand Down Expand Up @@ -231,6 +237,11 @@ protected slots:
QCursor m_cursorKnife;
bool m_cursorSetYet;

bool m_mouseOverStartCrossfadeHandle;
bool m_mouseOverStartCrossfadeTensionHandle;
bool m_mouseOverEndCrossfadeHandle;
bool m_mouseOverEndCrossfadeTensionHandle;

bool m_needsUpdate;
inline void setInitialPos( QPoint pos )
{
Expand Down
4 changes: 3 additions & 1 deletion include/SampleClip.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,16 @@ class SampleClip : public Clip
void setIsPlaying(bool isPlaying);
void setSampleBuffer(std::shared_ptr<const SampleBuffer> sb);

bool isCrossfadeable() const override { return true; }

SampleClip* clone() override
{
return new SampleClip(*this);
}

public slots:
void setSampleFile(const QString& sf);
void updateLength();
void updateLength() override;
void toggleRecord();
void playbackPositionChanged();
void updateTrackClips();
Expand Down
1 change: 1 addition & 0 deletions include/SamplePlayHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ class LMMS_EXPORT SamplePlayHandle : public PlayHandle
FloatModel m_defaultVolumeModel;
FloatModel * m_volumeModel;
Track * m_track;
SampleClip * m_clip;

PatternTrack* m_patternTrack;

Expand Down
10 changes: 10 additions & 0 deletions src/core/Clip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ Clip::Clip( Track * track ) :
m_track( track ),
m_startPosition(),
m_length(),
m_startCrossfadeLength(0),
m_endCrossfadeLength(0),
m_startCrossfadeTension(1.0f - std::sqrt(2) / 2),
m_endCrossfadeTension(1.0f - std::sqrt(2) / 2),
m_mutedModel( false, this, tr( "Mute" ) ),
m_selectViewOnCreate{false}
{
Expand Down Expand Up @@ -74,6 +78,10 @@ Clip::Clip(const Clip& other):
m_startPosition(other.m_startPosition),
m_length(other.m_length),
m_startTimeOffset(other.m_startTimeOffset),
m_startCrossfadeLength(other.m_startCrossfadeLength),
m_endCrossfadeLength(other.m_endCrossfadeLength),
m_startCrossfadeTension(other.m_startCrossfadeTension),
m_endCrossfadeTension(other.m_endCrossfadeTension),
m_mutedModel(other.m_mutedModel.value(), this, tr( "Mute" )),
m_resizable(other.m_resizable),
m_autoResize(other.m_autoResize),
Expand Down Expand Up @@ -137,6 +145,8 @@ void Clip::movePosition( const TimePos & pos )
void Clip::changeLength( const TimePos & length )
{
m_length = length;
setStartCrossfadeLength(std::min(m_startCrossfadeLength, m_length));
setEndCrossfadeLength(std::min(m_endCrossfadeLength, m_length));
Engine::getSong()->updateLength();
emit lengthChanged();
}
Expand Down
9 changes: 9 additions & 0 deletions src/core/SampleClip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include <QDomElement>
#include <QFileInfo>
#include <numbers>

#include "PathUtil.h"
#include "SampleBuffer.h"
Expand Down Expand Up @@ -308,6 +309,10 @@ void SampleClip::saveSettings( QDomDocument & _doc, QDomElement & _this )
_this.setAttribute( "src", sampleFile() );
_this.setAttribute( "off", startTimeOffset() );
_this.setAttribute("autoresize", QString::number(getAutoResize()));
_this.setAttribute("startfadelength", QString::number(startCrossfadeLength()));
_this.setAttribute("endfadelength", QString::number(endCrossfadeLength()));
_this.setAttribute("startfadetension", QString::number(startCrossfadeTension()));
_this.setAttribute("endfadetension", QString::number(endCrossfadeTension()));
if( sampleFile() == "" )
{
QString s;
Expand Down Expand Up @@ -357,6 +362,10 @@ void SampleClip::loadSettings( const QDomElement & _this )
setMuted( _this.attribute( "muted" ).toInt() );
setStartTimeOffset( _this.attribute( "off" ).toInt() );
setAutoResize(_this.attribute("autoresize", "1").toInt());
setStartCrossfadeLength(_this.attribute("startfadelength").toInt());
setEndCrossfadeLength(_this.attribute("endfadelength").toInt());
setStartCrossfadeTension(_this.attribute("startfadetension", QString::number(1.0f - std::numbers::sqrt2 / 2)).toFloat());
setEndCrossfadeTension(_this.attribute("endfadetension", QString::number(1.0f - std::numbers::sqrt2 / 2)).toFloat());

if (_this.hasAttribute("color"))
{
Expand Down
41 changes: 41 additions & 0 deletions src/core/SamplePlayHandle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#include "AudioEngine.h"
#include "AudioBusHandle.h"
#include "Engine.h"
#include "lmms_math.h"
#include "MixHelpers.h"
#include "Note.h"
#include "PatternTrack.h"
#include "SampleClip.h"
Expand All @@ -44,6 +46,7 @@
m_defaultVolumeModel(DefaultVolume, MinVolume, MaxVolume, 1),
m_volumeModel(&m_defaultVolumeModel),
m_track(nullptr),
m_clip(nullptr),
m_patternTrack(nullptr)
{
if (ownAudioBusHandle)
Expand All @@ -66,6 +69,7 @@
SamplePlayHandle::SamplePlayHandle( SampleClip* clip ) :
SamplePlayHandle(&clip->sample(), false)
{
m_clip = clip;
m_track = clip->getTrack();
setAudioBusHandle(((SampleTrack *)clip->getTrack())->audioBusHandle());
}
Expand All @@ -84,43 +88,80 @@




void SamplePlayHandle::play( SampleFrame* buffer )
{
const fpp_t fpp = Engine::audioEngine()->framesPerPeriod();
//play( 0, _try_parallelizing );
if( framesDone() >= totalFrames() )
{
zeroSampleFrames(buffer, fpp);
return;
}

SampleFrame* workingBuffer = buffer;
f_cnt_t frames = fpp;

// apply offset for the first period
if( framesDone() == 0 )
{
zeroSampleFrames(buffer, offset());
workingBuffer += offset();
frames -= offset();
}

const f_cnt_t initialFrameIndex = m_state.frameIndex();

if( !( m_track && m_track->isMuted() )
&& !(m_patternTrack && m_patternTrack->isMuted()))
{
/* StereoVolumeVector v =
{ { m_volumeModel->value() / DefaultVolume,
m_volumeModel->value() / DefaultVolume } };*/
// SamplePlayHandle always plays the sample at its original pitch;
// it is used only for previews, SampleTracks and the metronome.
if (!m_sample->play(workingBuffer, &m_state, frames, DefaultBaseFreq))
{
zeroSampleFrames(workingBuffer, frames);
}

// Apply crossfade if this play handle is for a clip
if (m_clip && (m_clip->startCrossfadeLength() != 0 || m_clip->endCrossfadeLength() != 0))
{
const int framesPerTick = Engine::framesPerTick(Engine::audioEngine()->outputSampleRate());
const int startCrossfadeFrames = m_clip->startCrossfadeLength() * framesPerTick;
const int endCrossfadeFrames = m_clip->endCrossfadeLength() * framesPerTick;
const int startOffsetFrames = m_clip->startTimeOffset() * framesPerTick;
const int lengthFrames = m_clip->length() * framesPerTick;
const float startPower = std::log(1.0f - m_clip->startCrossfadeTension()) / -std::numbers::ln2;
const float endPower = std::log(1.0f - m_clip->endCrossfadeTension()) / -std::numbers::ln2;

for (f_cnt_t f = 0; f < frames; ++f)
{
const f_cnt_t frameIndex = initialFrameIndex + f;
const int framesRelativeToClipStart = frameIndex + startOffsetFrames;
const int framesRelativeToClipEnd = lengthFrames - framesRelativeToClipStart;
if (framesRelativeToClipStart < 0 || framesRelativeToClipEnd < 0) { workingBuffer[f] = SampleFrame(); continue; }

if (framesRelativeToClipStart < startCrossfadeFrames && framesRelativeToClipEnd < endCrossfadeFrames)
{
workingBuffer[f] *=
fastPow(static_cast<float>(framesRelativeToClipStart) / static_cast<float>(startCrossfadeFrames), startPower)
* fastPow(static_cast<float>(framesRelativeToClipEnd) / static_cast<float>(endCrossfadeFrames), endPower);
}
else if (framesRelativeToClipStart < startCrossfadeFrames)
{
workingBuffer[f] *= fastPow(static_cast<float>(framesRelativeToClipStart) / static_cast<float>(startCrossfadeFrames), startPower);
}
else if (framesRelativeToClipEnd < endCrossfadeFrames)
{
workingBuffer[f] *= fastPow(static_cast<float>(framesRelativeToClipEnd) / static_cast<float>(endCrossfadeFrames), endPower);
}
}
}
}

m_frame += frames;

Check notice on line 164 in src/core/SamplePlayHandle.cpp

View check run for this annotation

codefactor.io / CodeFactor

src/core/SamplePlayHandle.cpp#L91-L164

Complex Method
}


Expand Down
Loading
Loading