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 {
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
single-selection sampler
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
@ -55,6 +51,8 @@ TODO {
bugs to fix {
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
pattern switching is slow when changing (especially increasing) number of rows; set fixed page size to avoid reallocation?
}
misc features needed before proper release {

View File

@ -5,6 +5,8 @@ using Xybrid::Data::Pattern;
#include "ui/patterneditorview.h"
using Xybrid::UI::PatternEditorView;
#include "util/strings.h"
#include <QDebug>
#include <QString>
#include <QFontMetrics>
@ -16,6 +18,7 @@ namespace { // helper functions
int cellWidthParam;
int cellWidthParamTab;
int headerHeight;
QSize hsz, hhsz;
constexpr char hexmap[] = {'0', '1', '2', '3', '4', '5', '6', '7',
'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-";
std::string hexStr(unsigned char *data, uint len) {
std::string s(len * 2, ' ');
for (uint i = 0; i < len; ++i) {
QString hexStr(unsigned char *data, int len) {
QString s(len * 2, ' ');
for (int i = 0; i < len; ++i) {
s[2 * i] = hexmap[(data[i] & 0xF0) >> 4];
s[2 * i + 1] = hexmap[data[i] & 0x0F];
}
return s;
}
std::string byteStr(int t) {
QString byteStr(int t) {
unsigned char c = static_cast<unsigned char>(t & 255);
return hexStr(&c, 1);
}
std::string noteStr(int n) {
std::string s(3, ' ');
QString noteStr(int n) {
QString s(3, ' ');
int nn = n % 12;
int oc = (n - nn) / 12;
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;
auto& row = pattern->rowAt(ch, index.row()-1);
if (cc == 0) { // port
if (row.port >= 0 && row.port < 256) return QString::fromStdString(byteStr(row.port));
if (row.port == -2) return QString("(G)");
if (row.port == -3) return QString("L");
return QString(" - ");
if (row.port >= 0 && row.port < 256) return byteStr(row.port);
if (row.port == -2) return qs("(G)");
if (row.port == -3) return qs("L");
return qs(" - ");
} else if (cc == 1) { // note
if (row.note >= 0) return QString::fromStdString(noteStr(row.note));
if (row.note == -2) return QString(" ^ "); // note off
if (row.note == -3) return QString(" x "); // hard cut
return QString(" - ");
if (row.note >= 0) return noteStr(row.note);
if (row.note == -2) return qs(" ^ "); // note off
if (row.note == -3) return qs(" x "); // hard cut
return qs(" - ");
} else {
size_t cp = static_cast<size_t>(((cc - 2) - (cc % 2)) / 2);
//return QString::number((cp));
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("» ");
return QString("");
if (row.numParams() > cp) return QString(1,static_cast<char>(row.params->at(cp)[0]));
if (row.numParams() == cp) return qs("» ");
return qs("");
}
if (row.numParams() > cp) {
if (row.params->at(cp)[0] == ' ') return QString("- ");
return QString::fromStdString(byteStr(row.params->at(cp)[1]));
if (row.params->at(cp)[0] == ' ') return qs("- ");
return byteStr(row.params->at(cp)[1]);
}
return QString("");
//return QString("--");
return qs("");
}
} else if (role == Qt::SizeHintRole) {
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
return QString::number(section-1);
} else if (role == Qt::SizeHintRole) {
auto fm = QFontMetrics(QFont(/*"Iosevka Term Light", 9*/));
if (orientation == Qt::Orientation::Vertical) {
if (section == 0 || section > pattern->rows) return QSize(-1, endHeight); // fill ends to center
return fm.boundingRect("255").size() + QSize(8, 4); // this should fit 0-999
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*/));
hsz = fm.boundingRect("255").size() + QSize(8, 4); // this should fit 0-999
hhsz = QSize(0, hsz.height());
}
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;
return QVariant();
}
@ -179,12 +183,10 @@ void PatternEditorModel::setPattern(const std::shared_ptr<Pattern>& pattern) {
}
void PatternEditorModel::updateColumnDisplay() {
/*static int qi = 0;
qDebug() << QString("column display request #%1").arg(qi++);//*/
if (pattern == nullptr) return;
auto view = static_cast<PatternEditorView*>(parent());
view->setUpdatesEnabled(false);
auto fm = QFontMetrics(QFont("Iosevka Term Light", 9));
//view->setUpdatesEnabled(false);
//auto fm = QFontMetrics(QFont("Iosevka Term Light", 9));
for (size_t ch = 0; ch < pattern->channels.size(); ch++) {
auto& c = pattern->channels.at(ch);
size_t maxParams = 0;
@ -217,13 +219,13 @@ void PatternEditorModel::updateColumnDisplay() {
int lsw = view->columnWidth(lastShown);
view->setColumnWidth(lastShown, std::max(lsw + 3, minWidth - (chWidth - lsw)));
}
view->setUpdatesEnabled(true);
//view->setUpdatesEnabled(true);
view->updateHeader(true);
}
void PatternEditorModel::updateFold() {
auto view = static_cast<PatternEditorView*>(parent());
view->setUpdatesEnabled(false);
//view->setUpdatesEnabled(false);
int ifold = 1;
if (folded && pattern->fold > 1) ifold = pattern->fold;
int rows = this->rowCount()-2;
@ -231,9 +233,9 @@ void PatternEditorModel::updateFold() {
view->setRowHidden(rows+1, false);
for (int i = 0; i < rows; i++) {
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() {

View File

@ -158,6 +158,7 @@ PatternEditorView::PatternEditorView(QWidget *parent) : QTableView(parent) {
// fold
connect(new QShortcut(QKeySequence("Ctrl+Space"), this), &QShortcut::activated, this, [this] {
setUpdatesEnabled(false);
mdl->toggleFold();
auto p = mdl->getPattern();
auto ind = currentIndex();
@ -167,7 +168,9 @@ PatternEditorView::PatternEditorView(QWidget *parent) : QTableView(parent) {
setCurrentIndex(ind);
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
@ -321,10 +324,10 @@ void PatternEditorView::stopPreview(int key) {
}
void PatternEditorView::setPattern(const std::shared_ptr<Pattern>& pattern) {
setUpdatesEnabled(false);
mdl->setPattern(pattern);
//horizontalHeader()->isSectionHidden()
//columnCountChanged(0, mdl->columnCount());
rowCountChanged(0, mdl->rowCount());
//rowCountChanged(0, mdl->rowCount());
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)));
@ -333,6 +336,7 @@ void PatternEditorView::setPattern(const std::shared_ptr<Pattern>& pattern) {
setCurrentIndex(ind);
selectionModel()->select(ind, QItemSelectionModel::ClearAndSelect);
scrollTo(ind, ScrollHint::PositionAtCenter);
setUpdatesEnabled(true);
}
void PatternEditorView::updateGeometries() {