Skip to content
Merged
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
2 changes: 1 addition & 1 deletion include/Sample.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class LMMS_EXPORT Sample
auto sampleDuration() const -> std::chrono::milliseconds;
auto sampleFile() const -> const QString& { return m_buffer->audioFile(); }
auto sampleRate() const -> int { return m_buffer->sampleRate(); }
auto sampleSize() const -> int { return m_buffer->size(); }
auto sampleSize() const -> size_t { return m_buffer->size(); }

auto toBase64() const -> QString { return m_buffer->toBase64(); }

Expand Down
10 changes: 9 additions & 1 deletion include/SampleWaveform.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,15 @@ namespace lmms::gui {
class LMMS_EXPORT SampleWaveform
{
public:
static void visualize(const Sample& sample, QPainter& p, const QRect& dr, int fromFrame = 0, int toFrame = 0);
struct Parameters
{
const sampleFrame* buffer;
size_t size;
float amplification;
bool reversed;
};

static void visualize(Parameters parameters, QPainter& painter, const QRect& rect);
};
} // namespace lmms::gui

Expand Down
12 changes: 8 additions & 4 deletions plugins/AudioFileProcessor/AudioFileProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,7 @@ void AudioFileProcessorWaveView::updateSampleRange()
{
const f_cnt_t marging = (m_sample->endFrame() - m_sample->startFrame()) * 0.1;
m_from = qMax(0, m_sample->startFrame() - marging);
m_to = qMin(m_sample->endFrame() + marging, m_sample->sampleSize());
m_to = qMin<size_t>(m_sample->endFrame() + marging, m_sample->sampleSize());
}
}

Expand Down Expand Up @@ -1014,7 +1014,11 @@ void AudioFileProcessorWaveView::updateGraph()
m_graph.fill( Qt::transparent );
QPainter p( &m_graph );
p.setPen( QColor( 255, 255, 255 ) );
SampleWaveform::visualize(*m_sample, p, QRect(0, 0, m_graph.width(), m_graph.height()), m_from, m_to);

const auto rect = QRect{0, 0, m_graph.width(), m_graph.height()};
const auto waveform = SampleWaveform::Parameters{
m_sample->data() + m_from, static_cast<size_t>(m_to - m_from), m_sample->amplification(), m_sample->reversed()};
SampleWaveform::visualize(waveform, p, rect);
}


Expand Down Expand Up @@ -1076,8 +1080,8 @@ void AudioFileProcessorWaveView::slide( int _px )
step = -step;
}

f_cnt_t step_from = qBound(0, m_from + step, m_sample->sampleSize()) - m_from;
f_cnt_t step_to = qBound(m_from + 1, m_to + step, m_sample->sampleSize()) - m_to;
f_cnt_t step_from = qBound<size_t>(0, m_from + step, m_sample->sampleSize()) - m_from;
f_cnt_t step_to = qBound<size_t>(m_from + 1, m_to + step, m_sample->sampleSize()) - m_to;

step = qAbs( step_from ) < qAbs( step_to ) ? step_from : step_to;

Expand Down
17 changes: 10 additions & 7 deletions plugins/SlicerT/SlicerTWaveform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,10 @@ void SlicerTWaveform::drawSeekerWaveform()
QPainter brush(&m_seekerWaveform);
brush.setPen(s_waveformColor);

SampleWaveform::visualize(m_slicerTParent->m_originalSample, brush,
QRect(0, 0, m_seekerWaveform.width(), m_seekerWaveform.height()), 0,
m_slicerTParent->m_originalSample.sampleSize());
const auto& sample = m_slicerTParent->m_originalSample;
const auto waveform = SampleWaveform::Parameters{sample.data(), sample.sampleSize(), sample.amplification(), sample.reversed()};
const auto rect = QRect(0, 0, m_seekerWaveform.width(), m_seekerWaveform.height());
SampleWaveform::visualize(waveform, brush, rect);

// increase brightness in inner color
QBitmap innerMask = m_seekerWaveform.createMaskFromColor(s_waveformMaskColor, Qt::MaskMode::MaskOutColor);
Expand Down Expand Up @@ -139,14 +140,16 @@ void SlicerTWaveform::drawEditorWaveform()
if (m_slicerTParent->m_originalSample.sampleSize() <= 1) { return; }

QPainter brush(&m_editorWaveform);
float startFrame = m_seekerStart * m_slicerTParent->m_originalSample.sampleSize();
float endFrame = m_seekerEnd * m_slicerTParent->m_originalSample.sampleSize();
size_t startFrame = m_seekerStart * m_slicerTParent->m_originalSample.sampleSize();
size_t endFrame = m_seekerEnd * m_slicerTParent->m_originalSample.sampleSize();

brush.setPen(s_waveformColor);
float zoomOffset = (m_editorHeight - m_zoomLevel * m_editorHeight) / 2;

SampleWaveform::visualize(m_slicerTParent->m_originalSample, brush,
QRect(0, zoomOffset, m_editorWidth, m_zoomLevel * m_editorHeight), startFrame, endFrame);
const auto& sample = m_slicerTParent->m_originalSample;
const auto waveform = SampleWaveform::Parameters{sample.data() + startFrame, endFrame - startFrame, sample.amplification(), sample.reversed()};
const auto rect = QRect(0, zoomOffset, m_editorWidth, m_zoomLevel * m_editorHeight);
SampleWaveform::visualize(waveform, brush, rect);

// increase brightness in inner color
QBitmap innerMask = m_editorWaveform.createMaskFromColor(s_waveformMaskColor, Qt::MaskMode::MaskOutColor);
Expand Down
55 changes: 24 additions & 31 deletions src/gui/SampleWaveform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,31 +26,25 @@

namespace lmms::gui {

void SampleWaveform::visualize(const Sample& sample, QPainter& p, const QRect& dr, int fromFrame, int toFrame)
void SampleWaveform::visualize(Parameters parameters, QPainter& painter, const QRect& rect)
{
if (sample.sampleSize() == 0) { return; }

const auto x = dr.x();
const auto height = dr.height();
const auto width = dr.width();
const auto centerY = dr.center().y();
const auto x = rect.x();
const auto height = rect.height();
const auto width = rect.width();
const auto centerY = rect.center().y();

const auto halfHeight = height / 2;
const auto buffer = sample.data() + fromFrame;

const auto color = p.pen().color();
const auto color = painter.pen().color();
const auto rmsColor = color.lighter(123);

auto numFrames = toFrame - fromFrame;
if (numFrames == 0) { numFrames = sample.sampleSize(); }

const auto framesPerPixel = std::max(1, numFrames / width);
const auto framesPerPixel = std::max<size_t>(1, parameters.size / width);

constexpr auto maxFramesPerPixel = 512;
const auto resolution = std::max(1, framesPerPixel / maxFramesPerPixel);
const auto resolution = std::max<size_t>(1, framesPerPixel / maxFramesPerPixel);
const auto framesPerResolution = framesPerPixel / resolution;

const auto numPixels = std::min(numFrames, width);
const auto numPixels = std::min<size_t>(parameters.size, width);
auto min = std::vector<float>(numPixels, 1);
auto max = std::vector<float>(numPixels, -1);
auto squared = std::vector<float>(numPixels);
Expand All @@ -59,35 +53,34 @@ void SampleWaveform::visualize(const Sample& sample, QPainter& p, const QRect& d
for (int i = 0; i < maxFrames; i += resolution)
{
const auto pixelIndex = i / framesPerPixel;
const auto value = std::accumulate(buffer[i].begin(), buffer[i].end(), 0.0f) / buffer[i].size();
const auto frameIndex = !parameters.reversed ? i : maxFrames - i;

const auto& frame = parameters.buffer[frameIndex];
const auto value = std::accumulate(frame.begin(), frame.end(), 0.0f) / frame.size();

if (value > max[pixelIndex]) { max[pixelIndex] = value; }
if (value < min[pixelIndex]) { min[pixelIndex] = value; }

squared[pixelIndex] += value * value;
}

const auto amplification = sample.amplification();
const auto reversed = sample.reversed();

for (int i = 0; i < numPixels; i++)
{
const auto lineY1 = centerY - max[i] * halfHeight * amplification;
const auto lineY2 = centerY - min[i] * halfHeight * amplification;

auto lineX = i + x;
if (reversed) { lineX = width - lineX; }

p.drawLine(lineX, lineY1, lineX, lineY2);
const auto lineY1 = centerY - max[i] * halfHeight * parameters.amplification;
const auto lineY2 = centerY - min[i] * halfHeight * parameters.amplification;
const auto lineX = i + x;
painter.drawLine(lineX, lineY1, lineX, lineY2);

const auto rms = std::sqrt(squared[i] / framesPerResolution);
const auto maxRMS = std::clamp(rms, min[i], max[i]);
const auto minRMS = std::clamp(-rms, min[i], max[i]);

const auto rmsLineY1 = centerY - maxRMS * halfHeight * amplification;
const auto rmsLineY2 = centerY - minRMS * halfHeight * amplification;
const auto rmsLineY1 = centerY - maxRMS * halfHeight * parameters.amplification;
const auto rmsLineY2 = centerY - minRMS * halfHeight * parameters.amplification;

p.setPen(rmsColor);
p.drawLine(lineX, rmsLineY1, lineX, rmsLineY2);
p.setPen(color);
painter.setPen(rmsColor);
painter.drawLine(lineX, rmsLineY1, lineX, rmsLineY2);
painter.setPen(color);
}
}

Expand Down
5 changes: 4 additions & 1 deletion src/gui/clips/SampleClipView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,10 @@ void SampleClipView::paintEvent( QPaintEvent * pe )
float offset = m_clip->startTimeOffset() / ticksPerBar * pixelsPerBar();
QRect r = QRect( offset, spacing,
qMax( static_cast<int>( m_clip->sampleLength() * ppb / ticksPerBar ), 1 ), rect().bottom() - 2 * spacing );
SampleWaveform::visualize(m_clip->m_sample, p, r);

const auto& sample = m_clip->m_sample;
const auto waveform = SampleWaveform::Parameters{sample.data(), sample.sampleSize(), sample.amplification(), sample.reversed()};
SampleWaveform::visualize(waveform, p, r);

QString name = PathUtil::cleanName(m_clip->m_sample.sampleFile());
paintTextLabel(name, p);
Expand Down
7 changes: 6 additions & 1 deletion src/gui/editors/AutomationEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1248,7 +1248,12 @@ void AutomationEditor::paintEvent(QPaintEvent * pe )
int yOffset = (editorHeight - sampleHeight) / 2.0f + TOP_MARGIN;

p.setPen(m_ghostSampleColor);
SampleWaveform::visualize(m_ghostSample->sample(), p, QRect(startPos, yOffset, sampleWidth, sampleHeight), 0, sampleFrames);

const auto& sample = m_ghostSample->sample();
const auto waveform = SampleWaveform::Parameters{
sample.data(), sample.sampleSize(), sample.amplification(), sample.reversed()};
const auto rect = QRect(startPos, yOffset, sampleWidth, sampleHeight);
SampleWaveform::visualize(waveform, p, rect);
}

// draw ghost notes
Expand Down