mirror of
https://github.com/LMMS/lmms.git
synced 2026-03-13 11:38:24 -04:00
* extremly basic slicer, note playback and gui works * very simple peak detection working * basic phase vocoder implementation, no effects yet * phase vocoder slight rewrite * pitch shifting works more or less * basic timeshift working * PV timeshift working (no pitch shift) * basic functions work (UI, editing, playback) * slice editor Ui working * fundamental functionality done * Everything basic works fully * cleanup and code guidelines * more file cleanup * Tried fixing multi slice playback (still broken) * remove includes, add license * code factoring issues * more code factoring * fixed multinote playback and bpm check * UI performance improvments + code style * initial UI changes + more code style * threadsafe(maybe) + UI finished * preparing for dinamic timeshifting * dynamic timeshifting start * realtime time scaling (no stereo) * stereo added, very slow * playback performance improvments * Roxas new UI start * fixed cmake * Waveform UI finished * Roxas UI knobs + layout * Spectral flux onset detection * build + PV fixes * clang-format formatting * slice snap + better defaults * windows build fixes * windows build fixes part 2 * Fixed slice bug + Waveform code cleanup * UI button text + reorder + file cleanup * Added knob colors * comments + code cleanup * var names fit convention * PV better windowing * waveform zoom * Minor style fixes. * Initial artistic rebalancing of the plugin artwork. * PV phase ghosting fix * Use base note as keyboard slice start * Good draft of Artwork, renamed bg to artwork * Removed soft glow. * Fixed load crashes + findSlices cleanup * Added sync button * added pitch shifting, sometimes crashes * pitch fixes * MacOs build fixes * use linear interpolation * copyright + div by 0 fixes * Fixed rare crash + name changes + license * review: memcpy, no array, LMMS header, name change * static constexpr added * static vars to public + LMMS guards * remove references in classes * remove constexpr and parent pointer in waveform * std::array for fft * fixed wrong name in style * remove c style casts * use src_process * use note vector for return * Moved PhaseVocoder into core * removed PV from plugin * remove pointers in waveform * clang-format again * Use std:: + review suggestions Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> Co-authored-by: saker <sakertooth@gmail.com> * More review changes * new signal slot + more review * Fixed pitch shifting * Fixed buffer overflow in PV * Fixed mouse bug + better empty screen * Small editor refactor + improvments * Editor playback visual + small fixes * Roxas UI improvments * initial timeshift removing * Remove timeshift + slice refactor * Removed unused files * Fix export bug * Fix zoom bug * Review changes SakerTooth#2 * Remove most comments * Performance + click to load * update PlaybackState + zerocross snapping * Fix windows build issue * Review + version * Fixed fade out bug * Use cosine interpolation * Apply suggestions from code review Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> * More review changes * Renamed files * Full sample only at base note * Fix memory leak Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> * Style fixes --------- Co-authored-by: Katherine Pratt <consolegrl@gmail.com> Co-authored-by: Dalton Messmer <33463986+messmerd@users.noreply.github.com> Co-authored-by: saker <sakertooth@gmail.com>
194 lines
6.1 KiB
C++
194 lines
6.1 KiB
C++
/*
|
|
* SlicerTView.cpp - controls the UI for slicerT
|
|
*
|
|
* Copyright (c) 2023 Daniel Kauss Serna <daniel.kauss.serna@gmail.com>
|
|
*
|
|
* This file is part of LMMS - https://lmms.io
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public
|
|
* License along with this program (see COPYING); if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301 USA.
|
|
*
|
|
*/
|
|
|
|
#include "SlicerTView.h"
|
|
|
|
#include <QDropEvent>
|
|
#include <QFileInfo>
|
|
|
|
#include "Clipboard.h"
|
|
#include "DataFile.h"
|
|
#include "Engine.h"
|
|
#include "InstrumentTrack.h"
|
|
#include "SlicerT.h"
|
|
#include "Song.h"
|
|
#include "StringPairDrag.h"
|
|
#include "Track.h"
|
|
#include "embed.h"
|
|
|
|
namespace lmms {
|
|
|
|
namespace gui {
|
|
|
|
SlicerTView::SlicerTView(SlicerT* instrument, QWidget* parent)
|
|
: InstrumentViewFixedSize(instrument, parent)
|
|
, m_slicerTParent(instrument)
|
|
{
|
|
// window settings
|
|
setAcceptDrops(true);
|
|
setAutoFillBackground(true);
|
|
|
|
// render background
|
|
QPalette pal;
|
|
pal.setBrush(backgroundRole(), PLUGIN_NAME::getIconPixmap("artwork"));
|
|
setPalette(pal);
|
|
|
|
m_wf = new SlicerTWaveform(248, 128, instrument, this);
|
|
m_wf->move(2, 6);
|
|
|
|
m_snapSetting = new ComboBox(this, tr("Slice snap"));
|
|
m_snapSetting->setGeometry(185, 200, 55, ComboBox::DEFAULT_HEIGHT);
|
|
m_snapSetting->setToolTip(tr("Set slice snapping for detection"));
|
|
m_snapSetting->setModel(&m_slicerTParent->m_sliceSnap);
|
|
|
|
m_syncToggle = new LedCheckBox("Sync", this, tr("SyncToggle"), LedCheckBox::LedColor::Green);
|
|
m_syncToggle->move(135, 187);
|
|
m_syncToggle->setToolTip(tr("Enable BPM sync"));
|
|
m_syncToggle->setModel(&m_slicerTParent->m_enableSync);
|
|
|
|
m_bpmBox = new LcdSpinBox(3, "19purple", this);
|
|
m_bpmBox->move(130, 201);
|
|
m_bpmBox->setToolTip(tr("Original sample BPM"));
|
|
m_bpmBox->setModel(&m_slicerTParent->m_originalBPM);
|
|
|
|
m_noteThresholdKnob = createStyledKnob();
|
|
m_noteThresholdKnob->move(10, 197);
|
|
m_noteThresholdKnob->setToolTip(tr("Threshold used for slicing"));
|
|
m_noteThresholdKnob->setModel(&m_slicerTParent->m_noteThreshold);
|
|
|
|
m_fadeOutKnob = createStyledKnob();
|
|
m_fadeOutKnob->move(64, 197);
|
|
m_fadeOutKnob->setToolTip(tr("Fade Out per note in milliseconds"));
|
|
m_fadeOutKnob->setModel(&m_slicerTParent->m_fadeOutFrames);
|
|
|
|
m_midiExportButton = new QPushButton(this);
|
|
m_midiExportButton->move(199, 150);
|
|
m_midiExportButton->setIcon(PLUGIN_NAME::getIconPixmap("copy_midi"));
|
|
m_midiExportButton->setToolTip(tr("Copy midi pattern to clipboard"));
|
|
connect(m_midiExportButton, &PixmapButton::clicked, this, &SlicerTView::exportMidi);
|
|
|
|
m_resetButton = new QPushButton(this);
|
|
m_resetButton->move(18, 150);
|
|
m_resetButton->setIcon(PLUGIN_NAME::getIconPixmap("reset_slices"));
|
|
m_resetButton->setToolTip(tr("Reset Slices"));
|
|
connect(m_resetButton, &PixmapButton::clicked, m_slicerTParent, &SlicerT::updateSlices);
|
|
}
|
|
|
|
Knob* SlicerTView::createStyledKnob()
|
|
{
|
|
Knob* newKnob = new Knob(KnobType::Styled, this);
|
|
newKnob->setFixedSize(50, 40);
|
|
newKnob->setCenterPointX(24.0);
|
|
newKnob->setCenterPointY(15.0);
|
|
return newKnob;
|
|
}
|
|
|
|
// copied from piano roll
|
|
void SlicerTView::exportMidi()
|
|
{
|
|
using namespace Clipboard;
|
|
if (m_slicerTParent->m_originalSample.frames() <= 1) { return; }
|
|
|
|
DataFile dataFile(DataFile::Type::ClipboardData);
|
|
QDomElement noteList = dataFile.createElement("note-list");
|
|
dataFile.content().appendChild(noteList);
|
|
|
|
auto notes = m_slicerTParent->getMidi();
|
|
if (notes.empty()) { return; }
|
|
|
|
TimePos startPos(notes.front().pos().getBar(), 0);
|
|
for (Note& note : notes)
|
|
{
|
|
note.setPos(note.pos(startPos));
|
|
note.saveState(dataFile, noteList);
|
|
}
|
|
|
|
copyString(dataFile.toString(), MimeType::Default);
|
|
}
|
|
|
|
void SlicerTView::openFiles()
|
|
{
|
|
QString audioFile = m_slicerTParent->m_originalSample.openAudioFile();
|
|
if (audioFile.isEmpty()) { return; }
|
|
m_slicerTParent->updateFile(audioFile);
|
|
}
|
|
|
|
// all the drag stuff is copied from AudioFileProcessor
|
|
void SlicerTView::dragEnterEvent(QDragEnterEvent* dee)
|
|
{
|
|
// For mimeType() and MimeType enum class
|
|
using namespace Clipboard;
|
|
|
|
if (dee->mimeData()->hasFormat(mimeType(MimeType::StringPair)))
|
|
{
|
|
QString txt = dee->mimeData()->data(mimeType(MimeType::StringPair));
|
|
if (txt.section(':', 0, 0) == QString("clip_%1").arg(static_cast<int>(Track::Type::Sample)))
|
|
{
|
|
dee->acceptProposedAction();
|
|
}
|
|
else if (txt.section(':', 0, 0) == "samplefile") { dee->acceptProposedAction(); }
|
|
else { dee->ignore(); }
|
|
}
|
|
else { dee->ignore(); }
|
|
}
|
|
|
|
void SlicerTView::dropEvent(QDropEvent* de)
|
|
{
|
|
QString type = StringPairDrag::decodeKey(de);
|
|
QString value = StringPairDrag::decodeValue(de);
|
|
if (type == "samplefile")
|
|
{
|
|
// set m_wf wave file
|
|
m_slicerTParent->updateFile(value);
|
|
return;
|
|
}
|
|
else if (type == QString("clip_%1").arg(static_cast<int>(Track::Type::Sample)))
|
|
{
|
|
DataFile dataFile(value.toUtf8());
|
|
m_slicerTParent->updateFile(dataFile.content().firstChild().toElement().attribute("src"));
|
|
de->accept();
|
|
return;
|
|
}
|
|
|
|
de->ignore();
|
|
}
|
|
|
|
void SlicerTView::paintEvent(QPaintEvent* pe)
|
|
{
|
|
QPainter brush(this);
|
|
brush.setPen(QColor(255, 255, 255));
|
|
brush.setFont(QFont(brush.font().family(), 7, -1, false));
|
|
|
|
brush.drawText(8, s_topTextY, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Reset"));
|
|
brush.drawText(188, s_topTextY, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Midi"));
|
|
|
|
brush.drawText(8, s_bottomTextY, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Threshold"));
|
|
brush.drawText(63, s_bottomTextY, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Fade Out"));
|
|
brush.drawText(127, s_bottomTextY, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("BPM"));
|
|
brush.drawText(188, s_bottomTextY, s_textBoxWidth, s_textBoxHeight, Qt::AlignCenter, tr("Snap"));
|
|
}
|
|
|
|
} // namespace gui
|
|
} // namespace lmms
|