sample base note support
parent
14af2ffeb7
commit
d4aa622fa6
13
notes
13
notes
|
@ -32,22 +32,11 @@ parameters {
|
|||
|
||||
TODO {
|
||||
immediate frontburner {
|
||||
... resampling matches modplug-xmms with kaiser window, not modplug's polyphase
|
||||
|
||||
fiddling with things, figured out much better sounding cases {
|
||||
rate<1.0, omit window
|
||||
rate>1.0, omit window AND USE HALF RATIO SINC???
|
||||
rate near 1.0, windowed is probably best
|
||||
|
||||
triple-lut this?? fade to windowed near 1.0, pick one of the other two for main
|
||||
maybe only double, windowed with a=5.5 sounds good for rate<1.0
|
||||
}
|
||||
???
|
||||
|
||||
distortion effect
|
||||
single-selection sampler
|
||||
|
||||
- global (default) pan (PXX) for InstrumentCore
|
||||
|
||||
add ,XX support to global tempo
|
||||
}
|
||||
|
||||
|
|
|
@ -69,6 +69,9 @@ QCborMap Sample::toCbor() const {
|
|||
m[qs("loopEnd")] = loopEnd;
|
||||
}
|
||||
|
||||
m[qs("note")] = baseNote;
|
||||
m[qs("subNote")] = subNote;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
@ -92,6 +95,9 @@ std::shared_ptr<Sample> Sample::fromCbor(const QCborMap& m, QUuid uuid) {
|
|||
smp->loopStart = static_cast<int>(m.value("loopStart").toInteger(-1));
|
||||
smp->loopEnd = static_cast<int>(m.value("loopEnd").toInteger(-1));
|
||||
|
||||
smp->baseNote = static_cast<int>(m.value("note").toInteger(60));
|
||||
smp->subNote = m.value("subNote").toDouble(0.0);
|
||||
|
||||
return smp;
|
||||
}
|
||||
std::shared_ptr<Sample> Sample::fromCbor(const QCborValue& m, QUuid uuid) { return fromCbor(m.toMap(), uuid); }
|
||||
|
|
|
@ -29,6 +29,9 @@ namespace Xybrid::Data {
|
|||
int loopStart = -1;
|
||||
int loopEnd = -1;
|
||||
|
||||
int baseNote = 60;
|
||||
double subNote = 0.0;
|
||||
|
||||
inline AudioFrame operator[] (size_t at) const {
|
||||
if (data[1].empty()) return {data[0][at]};
|
||||
return {data[0][at], data[1][at]};
|
||||
|
@ -43,6 +46,8 @@ namespace Xybrid::Data {
|
|||
inline int length() const { return static_cast<int>(data[0].size()); }
|
||||
std::array<float, 2> plotBetween(size_t ch, size_t start, size_t end) const;
|
||||
|
||||
inline double getNote() const { return static_cast<double>(baseNote) + subNote; }
|
||||
|
||||
QCborMap toCbor() const;
|
||||
static std::shared_ptr<Sample> fromCbor(const QCborMap&, QUuid);
|
||||
static std::shared_ptr<Sample> fromCbor(const QCborValue&, QUuid);
|
||||
|
|
|
@ -397,6 +397,21 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
ui->waveformPreview->update();
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->spinSampleNote, qOverload<int>(&QSpinBox::valueChanged), this, [this](int v) {
|
||||
auto sp = ui->spinSampleNote;
|
||||
sp->setSuffix(")");
|
||||
sp->setPrefix(qs("%1 (").arg(Util::noteName(static_cast<int16_t>(v))));
|
||||
|
||||
if (editingSample) editingSample->baseNote = v;
|
||||
});
|
||||
connect(ui->spinSampleNoteSub, qOverload<double>(&QDoubleSpinBox::valueChanged), this, [this](double v) {
|
||||
auto sp = ui->spinSampleNoteSub;
|
||||
sp->setPrefix(v >= 0.0 ? qs("+") : QString());
|
||||
|
||||
if (editingSample) editingSample->subNote = v;
|
||||
});
|
||||
emit ui->spinSampleNoteSub->valueChanged(0.0); // force refresh
|
||||
}
|
||||
|
||||
// Set up signaling from project to UI
|
||||
|
@ -659,6 +674,9 @@ void MainWindow::selectSampleForEditing(std::shared_ptr<Xybrid::Data::Sample> sm
|
|||
ui->groupSampleLoop->setChecked(false);
|
||||
ui->spinSampleLoopStart->setValue(0);
|
||||
ui->spinSampleLoopEnd->setValue(0);
|
||||
|
||||
ui->spinSampleNote->setValue(60);
|
||||
ui->spinSampleNoteSub->setValue(0.0);
|
||||
} else {
|
||||
editingSample = nullptr;
|
||||
ui->sampleViewPane->setEnabled(true);
|
||||
|
@ -685,6 +703,9 @@ void MainWindow::selectSampleForEditing(std::shared_ptr<Xybrid::Data::Sample> sm
|
|||
ui->spinSampleLoopEnd->setValue(smp->loopEnd);
|
||||
}
|
||||
|
||||
ui->spinSampleNote->setValue(smp->baseNote);
|
||||
ui->spinSampleNoteSub->setValue(smp->subNote);
|
||||
|
||||
editingSample = smp;
|
||||
}
|
||||
|
||||
|
|
|
@ -688,7 +688,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="sampleLoopRow" native="true">
|
||||
<widget class="QWidget" name="sampleEditRow" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
|
@ -826,6 +826,93 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupSampleNote">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Base Note</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_3" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_11">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinSampleNote">
|
||||
<property name="maximum">
|
||||
<number>119</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="spinSampleNoteSub">
|
||||
<property name="minimum">
|
||||
<double>-1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
|
|
|
@ -81,13 +81,14 @@ void Capaxitor::init() {
|
|||
if (!smp) return core.deleteNote(note);
|
||||
|
||||
double rate = static_cast<double>(smp->sampleRate) / static_cast<double>(audioEngine->curSampleRate());
|
||||
double baseNote = smp->getNote();
|
||||
|
||||
size_t ts = p->size;
|
||||
for (size_t i = 0; i < ts; i++) {
|
||||
core.advanceNote(note);
|
||||
|
||||
double n = note.effectiveNote();
|
||||
double fr = std::pow(SEMI, n - 12*5);
|
||||
double fr = std::pow(SEMI, n - baseNote);
|
||||
|
||||
// actual sample pos
|
||||
double sp = data.sampleTime * rate;
|
||||
|
|
Loading…
Reference in New Issue