sample formats, threshold for saving as s16, slightly more "correct" playback output

master
zetaPRIME 2022-03-22 22:18:57 -04:00
parent cbce51744c
commit 0a14aec9e5
4 changed files with 49 additions and 14 deletions

10
notes
View File

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

View File

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

View File

@ -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));

View File

@ -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);
}