attempt to speed up pattern switching

portability/macos
zetaPRIME 2019-07-22 03:26:39 -04:00
parent 43f6374fc2
commit b1449ebcf6
3 changed files with 48 additions and 44 deletions

8
notes
View File

@ -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 {

View File

@ -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() {

View File

@ -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() {