attempt to speed up pattern switching
parent
43f6374fc2
commit
b1449ebcf6
8
notes
8
notes
|
@ -32,17 +32,13 @@ parameters {
|
||||||
|
|
||||||
TODO {
|
TODO {
|
||||||
immediate frontburner {
|
immediate frontburner {
|
||||||
- reimplement sample import to IPC from standalone ffmpeg since QAudioDecoder is partially broken on arch and completely broken on macOS
|
|
||||||
# ffprobe -v quiet -show_streams -select_streams a -of json testOut.mp3
|
|
||||||
# ffmpeg -i input.flv -f f32le -acodec pcm_f32le -
|
|
||||||
|
|
||||||
distortion effect
|
distortion effect
|
||||||
single-selection sampler
|
single-selection sampler
|
||||||
|
|
||||||
global (default) pan (PXX) for InstrumentCore
|
global (default) pan (PXX) for InstrumentCore
|
||||||
|
|
||||||
- node function to release unneeded old data when stopping playback
|
add ,XX support to global tempo
|
||||||
...
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- actual config file loading/saving
|
- actual config file loading/saving
|
||||||
|
@ -55,6 +51,8 @@ TODO {
|
||||||
bugs to fix {
|
bugs to fix {
|
||||||
playback after stopping immediately after a note in the first pattern played sometimes skips that note
|
playback after stopping immediately after a note in the first pattern played sometimes skips that note
|
||||||
things can apparently be hooked up cyclically, which completely breaks the queue
|
things can apparently be hooked up cyclically, which completely breaks the queue
|
||||||
|
|
||||||
|
pattern switching is slow when changing (especially increasing) number of rows; set fixed page size to avoid reallocation?
|
||||||
}
|
}
|
||||||
|
|
||||||
misc features needed before proper release {
|
misc features needed before proper release {
|
||||||
|
|
|
@ -5,6 +5,8 @@ using Xybrid::Data::Pattern;
|
||||||
#include "ui/patterneditorview.h"
|
#include "ui/patterneditorview.h"
|
||||||
using Xybrid::UI::PatternEditorView;
|
using Xybrid::UI::PatternEditorView;
|
||||||
|
|
||||||
|
#include "util/strings.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QFontMetrics>
|
#include <QFontMetrics>
|
||||||
|
@ -16,6 +18,7 @@ namespace { // helper functions
|
||||||
int cellWidthParam;
|
int cellWidthParam;
|
||||||
int cellWidthParamTab;
|
int cellWidthParamTab;
|
||||||
int headerHeight;
|
int headerHeight;
|
||||||
|
QSize hsz, hhsz;
|
||||||
|
|
||||||
constexpr char hexmap[] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
constexpr char hexmap[] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||||||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
|
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
|
||||||
|
@ -23,21 +26,21 @@ namespace { // helper functions
|
||||||
|
|
||||||
constexpr char notemap[] = "C-C#D-D#E-F-F#G-G#A-A#B-";
|
constexpr char notemap[] = "C-C#D-D#E-F-F#G-G#A-A#B-";
|
||||||
|
|
||||||
std::string hexStr(unsigned char *data, uint len) {
|
QString hexStr(unsigned char *data, int len) {
|
||||||
std::string s(len * 2, ' ');
|
QString s(len * 2, ' ');
|
||||||
for (uint i = 0; i < len; ++i) {
|
for (int i = 0; i < len; ++i) {
|
||||||
s[2 * i] = hexmap[(data[i] & 0xF0) >> 4];
|
s[2 * i] = hexmap[(data[i] & 0xF0) >> 4];
|
||||||
s[2 * i + 1] = hexmap[data[i] & 0x0F];
|
s[2 * i + 1] = hexmap[data[i] & 0x0F];
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
std::string byteStr(int t) {
|
QString byteStr(int t) {
|
||||||
unsigned char c = static_cast<unsigned char>(t & 255);
|
unsigned char c = static_cast<unsigned char>(t & 255);
|
||||||
return hexStr(&c, 1);
|
return hexStr(&c, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string noteStr(int n) {
|
QString noteStr(int n) {
|
||||||
std::string s(3, ' ');
|
QString s(3, ' ');
|
||||||
int nn = n % 12;
|
int nn = n % 12;
|
||||||
int oc = (n - nn) / 12;
|
int oc = (n - nn) / 12;
|
||||||
s[2] = '0' + static_cast<char>(oc);
|
s[2] = '0' + static_cast<char>(oc);
|
||||||
|
@ -95,29 +98,27 @@ QVariant PatternEditorModel::data(const QModelIndex &index, int role) const {
|
||||||
int ch = (index.column() - cc) / colsPerChannel;
|
int ch = (index.column() - cc) / colsPerChannel;
|
||||||
auto& row = pattern->rowAt(ch, index.row()-1);
|
auto& row = pattern->rowAt(ch, index.row()-1);
|
||||||
if (cc == 0) { // port
|
if (cc == 0) { // port
|
||||||
if (row.port >= 0 && row.port < 256) return QString::fromStdString(byteStr(row.port));
|
if (row.port >= 0 && row.port < 256) return byteStr(row.port);
|
||||||
if (row.port == -2) return QString("(G)");
|
if (row.port == -2) return qs("(G)");
|
||||||
if (row.port == -3) return QString("L");
|
if (row.port == -3) return qs("L");
|
||||||
return QString(" - ");
|
return qs(" - ");
|
||||||
} else if (cc == 1) { // note
|
} else if (cc == 1) { // note
|
||||||
if (row.note >= 0) return QString::fromStdString(noteStr(row.note));
|
if (row.note >= 0) return noteStr(row.note);
|
||||||
if (row.note == -2) return QString(" ^ "); // note off
|
if (row.note == -2) return qs(" ^ "); // note off
|
||||||
if (row.note == -3) return QString(" x "); // hard cut
|
if (row.note == -3) return qs(" x "); // hard cut
|
||||||
return QString(" - ");
|
return qs(" - ");
|
||||||
} else {
|
} else {
|
||||||
size_t cp = static_cast<size_t>(((cc - 2) - (cc % 2)) / 2);
|
size_t cp = static_cast<size_t>(((cc - 2) - (cc % 2)) / 2);
|
||||||
//return QString::number((cp));
|
|
||||||
if (cc % 2 == 0) {
|
if (cc % 2 == 0) {
|
||||||
if (row.numParams() > cp) return QString::fromStdString(std::string(1,static_cast<char>(row.params->at(cp)[0])));
|
if (row.numParams() > cp) return QString(1,static_cast<char>(row.params->at(cp)[0]));
|
||||||
if (row.numParams() == cp) return QString("» ");
|
if (row.numParams() == cp) return qs("» ");
|
||||||
return QString("");
|
return qs("");
|
||||||
}
|
}
|
||||||
if (row.numParams() > cp) {
|
if (row.numParams() > cp) {
|
||||||
if (row.params->at(cp)[0] == ' ') return QString("- ");
|
if (row.params->at(cp)[0] == ' ') return qs("- ");
|
||||||
return QString::fromStdString(byteStr(row.params->at(cp)[1]));
|
return byteStr(row.params->at(cp)[1]);
|
||||||
}
|
}
|
||||||
return QString("");
|
return qs("");
|
||||||
//return QString("--");
|
|
||||||
}
|
}
|
||||||
} else if (role == Qt::SizeHintRole) {
|
} else if (role == Qt::SizeHintRole) {
|
||||||
if (index.row() >= pattern->rows) return QSize(-1, -1);
|
if (index.row() >= pattern->rows) return QSize(-1, -1);
|
||||||
|
@ -131,12 +132,15 @@ QVariant PatternEditorModel::headerData(int section, Qt::Orientation orientation
|
||||||
if (section == 0 || section > pattern->rows) return QVariant(); // blank end section
|
if (section == 0 || section > pattern->rows) return QVariant(); // blank end section
|
||||||
return QString::number(section-1);
|
return QString::number(section-1);
|
||||||
} else if (role == Qt::SizeHintRole) {
|
} else if (role == Qt::SizeHintRole) {
|
||||||
|
if (orientation == Qt::Orientation::Vertical) if (section == 0 || section > pattern->rows) return QSize(-1, endHeight); // fill ends to center
|
||||||
|
if (hsz.isEmpty()) {
|
||||||
auto fm = QFontMetrics(QFont(/*"Iosevka Term Light", 9*/));
|
auto fm = QFontMetrics(QFont(/*"Iosevka Term Light", 9*/));
|
||||||
if (orientation == Qt::Orientation::Vertical) {
|
hsz = fm.boundingRect("255").size() + QSize(8, 4); // this should fit 0-999
|
||||||
if (section == 0 || section > pattern->rows) return QSize(-1, endHeight); // fill ends to center
|
hhsz = QSize(0, hsz.height());
|
||||||
return fm.boundingRect("255").size() + QSize(8, 4); // this should fit 0-999
|
|
||||||
}
|
}
|
||||||
return QSize(0, fm.height() + 4);
|
return orientation == Qt::Vertical ? hsz : hhsz;
|
||||||
|
|
||||||
|
//return QSize(0, fm.height() + 4);
|
||||||
} else if (role == Qt::TextAlignmentRole) return Qt::AlignCenter;
|
} else if (role == Qt::TextAlignmentRole) return Qt::AlignCenter;
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
@ -179,12 +183,10 @@ void PatternEditorModel::setPattern(const std::shared_ptr<Pattern>& pattern) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PatternEditorModel::updateColumnDisplay() {
|
void PatternEditorModel::updateColumnDisplay() {
|
||||||
/*static int qi = 0;
|
|
||||||
qDebug() << QString("column display request #%1").arg(qi++);//*/
|
|
||||||
if (pattern == nullptr) return;
|
if (pattern == nullptr) return;
|
||||||
auto view = static_cast<PatternEditorView*>(parent());
|
auto view = static_cast<PatternEditorView*>(parent());
|
||||||
view->setUpdatesEnabled(false);
|
//view->setUpdatesEnabled(false);
|
||||||
auto fm = QFontMetrics(QFont("Iosevka Term Light", 9));
|
//auto fm = QFontMetrics(QFont("Iosevka Term Light", 9));
|
||||||
for (size_t ch = 0; ch < pattern->channels.size(); ch++) {
|
for (size_t ch = 0; ch < pattern->channels.size(); ch++) {
|
||||||
auto& c = pattern->channels.at(ch);
|
auto& c = pattern->channels.at(ch);
|
||||||
size_t maxParams = 0;
|
size_t maxParams = 0;
|
||||||
|
@ -217,13 +219,13 @@ void PatternEditorModel::updateColumnDisplay() {
|
||||||
int lsw = view->columnWidth(lastShown);
|
int lsw = view->columnWidth(lastShown);
|
||||||
view->setColumnWidth(lastShown, std::max(lsw + 3, minWidth - (chWidth - lsw)));
|
view->setColumnWidth(lastShown, std::max(lsw + 3, minWidth - (chWidth - lsw)));
|
||||||
}
|
}
|
||||||
view->setUpdatesEnabled(true);
|
//view->setUpdatesEnabled(true);
|
||||||
view->updateHeader(true);
|
view->updateHeader(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PatternEditorModel::updateFold() {
|
void PatternEditorModel::updateFold() {
|
||||||
auto view = static_cast<PatternEditorView*>(parent());
|
auto view = static_cast<PatternEditorView*>(parent());
|
||||||
view->setUpdatesEnabled(false);
|
//view->setUpdatesEnabled(false);
|
||||||
int ifold = 1;
|
int ifold = 1;
|
||||||
if (folded && pattern->fold > 1) ifold = pattern->fold;
|
if (folded && pattern->fold > 1) ifold = pattern->fold;
|
||||||
int rows = this->rowCount()-2;
|
int rows = this->rowCount()-2;
|
||||||
|
@ -231,9 +233,9 @@ void PatternEditorModel::updateFold() {
|
||||||
view->setRowHidden(rows+1, false);
|
view->setRowHidden(rows+1, false);
|
||||||
for (int i = 0; i < rows; i++) {
|
for (int i = 0; i < rows; i++) {
|
||||||
view->setRowHidden(i+1, false); // dispel any "phantoms" we might end up having
|
view->setRowHidden(i+1, false); // dispel any "phantoms" we might end up having
|
||||||
view->setRowHidden(i+1, (i < pattern->rows && i % ifold != 0));
|
if (i < pattern->rows && i % ifold != 0) view->setRowHidden(i+1, true);
|
||||||
}
|
}
|
||||||
view->setUpdatesEnabled(true);
|
//view->setUpdatesEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PatternEditorModel::toggleFold() {
|
void PatternEditorModel::toggleFold() {
|
||||||
|
|
|
@ -158,6 +158,7 @@ PatternEditorView::PatternEditorView(QWidget *parent) : QTableView(parent) {
|
||||||
|
|
||||||
// fold
|
// fold
|
||||||
connect(new QShortcut(QKeySequence("Ctrl+Space"), this), &QShortcut::activated, this, [this] {
|
connect(new QShortcut(QKeySequence("Ctrl+Space"), this), &QShortcut::activated, this, [this] {
|
||||||
|
setUpdatesEnabled(false);
|
||||||
mdl->toggleFold();
|
mdl->toggleFold();
|
||||||
auto p = mdl->getPattern();
|
auto p = mdl->getPattern();
|
||||||
auto ind = currentIndex();
|
auto ind = currentIndex();
|
||||||
|
@ -167,7 +168,9 @@ PatternEditorView::PatternEditorView(QWidget *parent) : QTableView(parent) {
|
||||||
setCurrentIndex(ind);
|
setCurrentIndex(ind);
|
||||||
if (selectedIndexes().count() <= 1) selectionModel()->select(ind, QItemSelectionModel::SelectionFlag::ClearAndSelect);
|
if (selectedIndexes().count() <= 1) selectionModel()->select(ind, QItemSelectionModel::SelectionFlag::ClearAndSelect);
|
||||||
}
|
}
|
||||||
QTimer::singleShot(1, [this, ind]{ scrollTo(ind, ScrollHint::PositionAtCenter); });
|
scrollTo(ind, ScrollHint::PositionAtCenter);
|
||||||
|
setUpdatesEnabled(true);
|
||||||
|
//QTimer::singleShot(1, [this, ind]{ scrollTo(ind, ScrollHint::PositionAtCenter); });
|
||||||
});
|
});
|
||||||
|
|
||||||
// cut/copy/paste
|
// cut/copy/paste
|
||||||
|
@ -321,10 +324,10 @@ void PatternEditorView::stopPreview(int key) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PatternEditorView::setPattern(const std::shared_ptr<Pattern>& pattern) {
|
void PatternEditorView::setPattern(const std::shared_ptr<Pattern>& pattern) {
|
||||||
|
setUpdatesEnabled(false);
|
||||||
mdl->setPattern(pattern);
|
mdl->setPattern(pattern);
|
||||||
//horizontalHeader()->isSectionHidden()
|
|
||||||
//columnCountChanged(0, mdl->columnCount());
|
//rowCountChanged(0, mdl->rowCount());
|
||||||
rowCountChanged(0, mdl->rowCount());
|
|
||||||
|
|
||||||
auto cur = currentIndex();
|
auto cur = currentIndex();
|
||||||
auto ind = model()->index(std::clamp(cur.row(), 1, pattern->rows), std::clamp(cur.column(), 0, std::max(0, mdl->columnCount() - 2)));
|
auto ind = model()->index(std::clamp(cur.row(), 1, pattern->rows), std::clamp(cur.column(), 0, std::max(0, mdl->columnCount() - 2)));
|
||||||
|
@ -333,6 +336,7 @@ void PatternEditorView::setPattern(const std::shared_ptr<Pattern>& pattern) {
|
||||||
setCurrentIndex(ind);
|
setCurrentIndex(ind);
|
||||||
selectionModel()->select(ind, QItemSelectionModel::ClearAndSelect);
|
selectionModel()->select(ind, QItemSelectionModel::ClearAndSelect);
|
||||||
scrollTo(ind, ScrollHint::PositionAtCenter);
|
scrollTo(ind, ScrollHint::PositionAtCenter);
|
||||||
|
setUpdatesEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PatternEditorView::updateGeometries() {
|
void PatternEditorView::updateGeometries() {
|
||||||
|
|
Loading…
Reference in New Issue