attempt to speed up pattern switching
parent
43f6374fc2
commit
b1449ebcf6
8
notes
8
notes
|
@ -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 {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue