sample formats, threshold for saving as s16, slightly more "correct" playback output
parent
cbce51744c
commit
0a14aec9e5
10
notes
10
notes
|
@ -35,14 +35,14 @@ TODO {
|
|||
about-license info
|
||||
}
|
||||
|
||||
fix overrun-by-1 on sample preview
|
||||
|
||||
templatize svfilter and have mono version for synth use
|
||||
|
||||
revert-to-saved menu action
|
||||
|
||||
- splice-between behavior when trying to hook up a command input to something with both a command input and output while already connected
|
||||
|
||||
distortion effect
|
||||
|
||||
uh... maybe save/load samples as s16 instead of f32
|
||||
|
||||
automation node {
|
||||
listens for one specific param
|
||||
supports tweening
|
||||
|
@ -58,6 +58,8 @@ TODO {
|
|||
editing song info should probably be an UndoStack action
|
||||
editing song *tempo* ABSOLUTELY should
|
||||
|
||||
maybe retool rendering to feed f32 (or even f64) to ffmpeg
|
||||
|
||||
figure out what to actually do with directory config
|
||||
|
||||
buffer helper akin to what quicklevel does {
|
||||
|
|
|
@ -406,8 +406,8 @@ qint64 AudioEngine::readData(char *data, qint64 maxlen) {
|
|||
// convert non-interleaved floating point into interleaved int16
|
||||
int16_t* l = reinterpret_cast<int16_t*>(data);
|
||||
int16_t* r = reinterpret_cast<int16_t*>(data+smp);
|
||||
*l = static_cast<int16_t>(std::clamp(buffer[0][bufPos], -1.0f, 1.0f) * 32767);
|
||||
*r = static_cast<int16_t>(std::clamp(buffer[1][bufPos], -1.0f, 1.0f) * 32767);
|
||||
*l = static_cast<int16_t>(std::clamp(buffer[0][bufPos] * 32768.0f, -32767.0f, 32767.0f));
|
||||
*r = static_cast<int16_t>(std::clamp(buffer[1][bufPos] * 32768.0f, -32767.0f, 32767.0f));
|
||||
|
||||
bufPos++;
|
||||
data += stride;
|
||||
|
|
|
@ -48,17 +48,35 @@ std::array<float, 2> Sample::plotBetween(size_t ch, size_t start, size_t end) co
|
|||
return {mn, mx};
|
||||
}
|
||||
|
||||
// threshold in MiB-stored-as-float for saving long samples as s16 instead
|
||||
const constexpr double PCM_MiB_THRESHOLD = 5;
|
||||
const constexpr int PCM_THRESHOLD = static_cast<int>(PCM_MiB_THRESHOLD * (1024*1024) / sizeof(float));
|
||||
QCborMap Sample::toCbor() const {
|
||||
QCborMap m;
|
||||
|
||||
m[qs("name")] = name;
|
||||
m[qs("rate")] = sampleRate;
|
||||
|
||||
QString fmt = qs("f32");
|
||||
if (numChannels() * length() > PCM_THRESHOLD) fmt = qs("s16");
|
||||
m[qs("fmt")] = fmt;
|
||||
|
||||
{
|
||||
QCborArray ch;
|
||||
|
||||
auto n = static_cast<size_t>(numChannels());
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
ch[static_cast<qsizetype>(i)] = QByteArray(reinterpret_cast<const char*>(data[i].data()), static_cast<int>(data[i].size() * sizeof(data[i][0])));
|
||||
if (fmt == qs("f32")) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
ch[static_cast<qsizetype>(i)] = QByteArray(reinterpret_cast<const char*>(data[i].data()), static_cast<int>(data[i].size() * sizeof(data[i][0])));
|
||||
}
|
||||
} else if (fmt == qs("s16")) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
auto sz = data[i].size();
|
||||
QByteArray dat(static_cast<int>(sz * 2), static_cast<char>(0));
|
||||
|
||||
for (size_t j = 0; j < sz; j++) *reinterpret_cast<int16_t*>(dat.data() + j*2) = static_cast<int16_t>(std::clamp(static_cast<double>(data[i][j]) * 32768.0, -32767.0, 32767.0));
|
||||
ch[static_cast<qsizetype>(i)] = dat;
|
||||
}
|
||||
}
|
||||
|
||||
m[qs("channels")] = ch;
|
||||
|
@ -82,14 +100,29 @@ std::shared_ptr<Sample> Sample::fromCbor(const QCborMap& m, QUuid uuid) {
|
|||
|
||||
smp->sampleRate = static_cast<int>(m.value("rate").toInteger(48000));
|
||||
|
||||
auto fmt = m.value("fmt").toString(qs("f32"));
|
||||
|
||||
auto ch = m.value("channels").toArray();
|
||||
auto s = static_cast<size_t>(ch.size());
|
||||
|
||||
for (size_t i = 0; i < s; i++) {
|
||||
auto c = ch[static_cast<qint64>(i)].toByteArray();
|
||||
auto bs = static_cast<size_t>(c.size());
|
||||
smp->data[i].resize(bs / sizeof(*smp->data[i].begin()));
|
||||
memcpy(smp->data[i].data(), c.constData(), bs);
|
||||
if (fmt == qs("f32")) {
|
||||
for (size_t i = 0; i < s; i++) {
|
||||
auto c = ch[static_cast<qint64>(i)].toByteArray();
|
||||
auto bs = static_cast<size_t>(c.size());
|
||||
smp->data[i].resize(bs / sizeof(*smp->data[i].begin()));
|
||||
memcpy(smp->data[i].data(), c.constData(), bs);
|
||||
}
|
||||
} else if (fmt == qs("s16")) {
|
||||
for (size_t i = 0; i < s; i++) {
|
||||
auto c = ch[static_cast<qint64>(i)].toByteArray();
|
||||
auto bs = static_cast<size_t>(c.size());
|
||||
auto sz = bs / 2;
|
||||
smp->data[i].resize(sz);
|
||||
for (size_t j = 0; j < sz; j++) {
|
||||
smp->data[i][j] = static_cast<float>(static_cast<double>(*reinterpret_cast<int16_t*>(c.data()+j*2))/32768.0);
|
||||
}
|
||||
//memcpy(smp->data[i].data(), c.constData(), bs);
|
||||
}
|
||||
}
|
||||
|
||||
smp->loopStart = static_cast<int>(m.value("loopStart").toInteger(-1));
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace {
|
|||
+ (static_cast<uint32_t>(minor)<<16)
|
||||
+ (static_cast<uint32_t>(major)<<24);
|
||||
}
|
||||
constexpr const uint32_t XYBRID_VERSION = packedVersion(0,0,0,1);
|
||||
constexpr const uint32_t XYBRID_VERSION = packedVersion(0,0,0,2);
|
||||
|
||||
constexpr const QSize dlgSize(700, 500);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue