Skip to content

Commit

Permalink
Restructure SF2 to not over-load
Browse files Browse the repository at this point in the history
The SF2 indexes samples by the preset/instrument/region
but that resolves to a sample index. Since I was using P/I/R
as SampleID that meant identical samples had different IDs
and thus loaded multiple times. Defacto this made a 3MB SF2
with lots of instruments load as 90MB and stuff. Ugh.

So fix this in two ways

1. Make loadeFromSF2 (p,i,r) remap the sample to index if needed
2. Change the sample->load to be index based

and voila
  • Loading branch information
baconpaul committed Sep 29, 2024
1 parent 114ea16 commit 8542984
Show file tree
Hide file tree
Showing 9 changed files with 55 additions and 33 deletions.
2 changes: 1 addition & 1 deletion libs/sst/libgig-modified
Submodule libgig-modified updated 1 files
+5 −0 src/SF.cpp
1 change: 0 additions & 1 deletion src-ui/app/SCXTEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,6 @@ struct SCXTEditor : sst::jucegui::components::WindowPanel, juce::DragAndDropCont
selection::SelectionManager::selectedZones_t allGroupSelections;
int16_t selectedPart{0};

// TODO: Do we allow part multi-select? I think we don't
std::set<int> groupsWithSelectedZones;
bool isAnyZoneFromGroupSelected(int groupIdx)
{
Expand Down
1 change: 0 additions & 1 deletion src/engine/engine_voice_responder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ int32_t Engine::VoiceManagerResponder::beginVoiceCreationTransaction(uint16_t po
SCLOG_IF(voiceResponder, "begin voice transaction " << SCD(port) << SCD(channel) << SCD(key)
<< SCD(noteId) << SCD(velocity));
assert(!transactionValid);
// TODO: We can optimize this so we don't have to find twice in the future
auto useKey = engine.midikeyRetuner.remapKeyTo(channel, key);
auto nts = engine.findZone(channel, useKey, noteId, std::clamp((int)(velocity * 128), 0, 127),
findZoneWorkingBuffer);
Expand Down
3 changes: 0 additions & 3 deletions src/json/engine_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ SC_STREAMDEF(scxt::engine::Engine, SC_FROM({

engine::Engine::UnstreamGuard sg(sv);

// TODO: engine gets a SV? Guess maybe
// Order matters here. Samples need to be there before the patch and patch
// before selection

Expand Down Expand Up @@ -175,7 +174,6 @@ SC_STREAMDEF(scxt::engine::Part::ZoneMappingItem,

SC_STREAMDEF(
scxt::engine::Part, SC_FROM({
// TODO: Do a non-empty part stream with the If variant
v = {{"config", from.configuration}, {"groups", from.getGroups()}, {"macros", from.macros}};
if (SC_STREAMING_FOR_PART)
{
Expand Down Expand Up @@ -273,7 +271,6 @@ SC_STREAMDEF(scxt::engine::Group, SC_FROM({
if (group.parentPart && group.parentPart->parentPatch &&
group.parentPart->parentPatch->parentEngine)
{
// TODO: MOve this somewhere more intelligent
group.getZone(idx)->setupOnUnstream(
*(group.parentPart->parentPatch->parentEngine));
}
Expand Down
26 changes: 6 additions & 20 deletions src/sample/sample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,31 +127,18 @@ bool Sample::load(const fs::path &path)
return false;
}

bool Sample::loadFromSF2(const fs::path &p, sf2::File *f, int presetNum, int inst, int reg)
bool Sample::loadFromSF2(const fs::path &p, sf2::File *f, int sampleIndex)
{
mFileName = p;
preset = presetNum;
instrument = inst;
region = reg;
preset = -1;
instrument = -1;
region = sampleIndex;
type = SF2_FILE;

auto *preset = f->GetPreset(presetNum);

auto *presetRegion = preset->GetRegion(inst);
sf2::Instrument *instr = presetRegion->pInstrument;

if (instr->pGlobalRegion)
{
// TODO: Global Region
}

auto sfsample = instr->GetRegion(region)->GetSample();
auto sfsample = f->GetSample(sampleIndex);
if (!sfsample)
return false;

SCLOG("Loading individual sf2 sample '" << sfsample->Name << "' " << SCD(presetNum)
<< SCD(instrument) << SCD(region) << SCD(p.u8string()));

auto frameSize = sfsample->GetFrameSize();
channels = sfsample->GetChannelCount();
sample_length = sfsample->GetTotalFrameCount();
Expand All @@ -160,8 +147,7 @@ bool Sample::loadFromSF2(const fs::path &p, sf2::File *f, int presetNum, int ins
auto s = sfsample;

auto fnp = fs::path{f->GetRiffFile()->GetFileName()};
displayName = fmt::format("{} - {} ({} @ {}.{})", f->GetInstrument(inst)->GetName(), s->Name,
fnp.filename().u8string(), inst, region);
displayName = fmt::format("{} - ({} @ {})", s->Name, fnp.filename().u8string(), sampleIndex);

if (frameSize == 2 && channels == 1 && sfsample->SampleType == sf2::Sample::MONO_SAMPLE)
{
Expand Down
2 changes: 1 addition & 1 deletion src/sample/sample.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ struct alignas(16) Sample : MoveableOnly<Sample>
std::string displayName{};
std::string getDisplayName() const { return displayName; }
bool load(const fs::path &path);
bool loadFromSF2(const fs::path &path, sf2::File *f, int preset, int inst, int region);
bool loadFromSF2(const fs::path &path, sf2::File *f, int sampleIndex);

const fs::path &getPath() const { return mFileName; }
std::string md5Sum{};
Expand Down
51 changes: 46 additions & 5 deletions src/sample/sample_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ std::optional<SampleID> SampleManager::loadSampleFromSF2(const fs::path &p, sf2:
{
try
{
SCLOG("Opening file " << p.u8string());
SCLOG("Opening SF2 : " << p.u8string());

auto riff = std::make_unique<RIFF::File>(p.u8string());
auto sf = std::make_unique<sf2::File>(riff.get());
Expand All @@ -136,34 +136,75 @@ std::optional<SampleID> SampleManager::loadSampleFromSF2(const fs::path &p, sf2:
sf2MD5ByPath[p.u8string()] = infrastructure::createMD5SumFromFile(p);

assert(f);

auto sidx = -1;
if (preset >= 0 && instrument >= 0)
{
sidx = findSF2SampleIndexFor(f, preset, instrument, region);
}
else
{
sidx = region;
}

if (sidx < 0 && sidx >= f->GetSampleCount())
{
return std::nullopt;
}
for (const auto &[id, sm] : samples)
{
if (sm->type == Sample::SF2_FILE)
{
const auto &[type, path, md5sum, pre, inst, reg] = sm->getSampleFileAddress();
if (path == p && pre == preset && instrument == inst && region == reg)
if (sm->getPath() == p && sm->getCompoundRegion() == sidx)
return id;
}
}

auto sp = std::make_shared<Sample>();

if (!sp->loadFromSF2(p, f, preset, instrument, region))
if (!sp->loadFromSF2(p, f, sidx))
return {};

sp->md5Sum = sf2MD5ByPath[p.u8string()];
assert(!sp->md5Sum.empty());
sp->id.setAsMD5WithAddress(sp->md5Sum, preset, instrument, region);
sp->id.setAsMD5WithAddress(sp->md5Sum, -1, -1, sidx);
sp->id.setPathHash(p);

SCLOG("Loading : " << p.u8string());
SCLOG(" : " << sp->displayName);
SCLOG(" : " << sp->id.to_string());

samples[sp->id] = sp;
updateSampleMemory();
return sp->id;
}

int SampleManager::findSF2SampleIndexFor(sf2::File *f, int presetNum, int instrument, int region)
{
auto *preset = f->GetPreset(presetNum);

auto *presetRegion = preset->GetRegion(instrument);
sf2::Instrument *instr = presetRegion->pInstrument;

if (instr->pGlobalRegion)
{
// TODO: Global Region
}

auto sfsample = instr->GetRegion(region)->GetSample();
if (!sfsample)
return false;

for (int i = 0; i < f->GetSampleCount(); ++i)
{
if (f->GetSample(i) == sfsample)
{
return i;
}
}
return -1;
}

std::optional<SampleID> SampleManager::setupSampleFromMultifile(const fs::path &p,
const std::string &md5, int idx,
void *data, size_t dataSize)
Expand Down
1 change: 1 addition & 0 deletions src/sample/sample_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ struct SampleManager : MoveableOnly<SampleManager>
std::optional<SampleID> loadSampleFromSF2(const fs::path &,
sf2::File *f, // if this is null I will re-open it
int preset, int instrument, int region);
int findSF2SampleIndexFor(sf2::File *, int preset, int instrument, int region);

std::optional<SampleID> setupSampleFromMultifile(const fs::path &, const std::string &md5,
int idx, void *data, size_t dataSize);
Expand Down
1 change: 0 additions & 1 deletion src/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,6 @@ struct SampleRateSupport

struct ThreadingChecker
{
// TODO: Remove this workaround once I have startup working
std::atomic<bool> bypassThreadChecks{false};

std::thread::id clientThreadId{}, serialThreadId{}, audioThreadId{};
Expand Down

0 comments on commit 8542984

Please sign in to comment.