diff --git a/sources/FilePool.cpp b/sources/FilePool.cpp index 5ba1b218..2f2f2623 100644 --- a/sources/FilePool.cpp +++ b/sources/FilePool.cpp @@ -32,6 +32,7 @@ std::optional sfz::FilePool::getFileInformation( } FileInformation returnedValue; + returnedValue.numChannels = sndFile.channels(); returnedValue.end = static_cast(sndFile.frames()); returnedValue.sampleRate = static_cast(sndFile.samplerate()); diff --git a/sources/FilePool.h b/sources/FilePool.h index 4e3e1e29..d832276d 100644 --- a/sources/FilePool.h +++ b/sources/FilePool.h @@ -27,6 +27,7 @@ public: size_t getNumPreloadedSamples() const noexcept { return preloadedData.size(); } struct FileInformation { + int numChannels { 1 }; uint32_t end { Default::sampleEndRange.getEnd() }; uint32_t loopBegin { Default::loopRange.getStart() }; uint32_t loopEnd { Default::loopRange.getEnd() }; diff --git a/sources/Region.cpp b/sources/Region.cpp index efdedf1d..161135d4 100644 --- a/sources/Region.cpp +++ b/sources/Region.cpp @@ -408,7 +408,7 @@ bool sfz::Region::isSwitchedOn() const noexcept return keySwitched && previousKeySwitched && sequenceSwitched && pitchSwitched && bpmSwitched && aftertouchSwitched && allCCSwitched; } -bool sfz::Region::registerNoteOn(int channel, int noteNumber, uint8_t velocity, float randValue) noexcept +bool sfz::Region::registerNoteOn(int channel, int noteNumber, uint8_t velocity, float randValue) noexcept { const bool chanOk = channelRange.containsWithEnd(channel); if (!chanOk) @@ -586,4 +586,9 @@ bool sfz::Region::canUsePreloadedData() const noexcept return false; return trueSampleEnd() < static_cast(preloadedData->getNumFrames()); +} + +bool sfz::Region::isStereo() const noexcept +{ + return this->numChannels == 2; } \ No newline at end of file diff --git a/sources/Synth.cpp b/sources/Synth.cpp index 74977931..7b98aa76 100644 --- a/sources/Synth.cpp +++ b/sources/Synth.cpp @@ -87,8 +87,11 @@ void sfz::Synth::clear() void sfz::Synth::handleGlobalOpcodes(const std::vector& members) { for (auto& member : members) { - if (member.opcode == "sw_default") + switch (hash(member.opcode)) { + case hash("sw_default"): setValueFromOpcode(member, defaultSwitch, Default::keyRange); + break; + } } } @@ -132,24 +135,22 @@ bool sfz::Synth::loadSfzFile(const std::filesystem::path& filename) while (currentRegion <= lastRegion) { auto region = currentRegion->get(); - if (region->isGenerator()) { - currentRegion++; - continue; - } + if (!region->isGenerator()) { + auto fileInformation = filePool.getFileInformation(region->sample); + if (!fileInformation) { + DBG("Removing the region with sample " << region->sample); + std::iter_swap(currentRegion, lastRegion); + lastRegion--; + continue; + } - auto fileInformation = filePool.getFileInformation(region->sample); - if (!fileInformation) { - DBG("Removing the region with sample " << region->sample); - std::iter_swap(currentRegion, lastRegion); - lastRegion--; - continue; + region->numChannels = fileInformation->numChannels; + region->sampleEnd = std::min(region->sampleEnd, fileInformation->end); + region->loopRange.shrinkIfSmaller(fileInformation->loopBegin, fileInformation->loopEnd); + region->preloadedData = fileInformation->preloadedData; + region->sampleRate = fileInformation->sampleRate; } - region->sampleEnd = std::min(region->sampleEnd, fileInformation->end); - region->loopRange.shrinkIfSmaller(fileInformation->loopBegin, fileInformation->loopEnd); - region->preloadedData = fileInformation->preloadedData; - region->sampleRate = fileInformation->sampleRate; - for (auto note = region->keyRange.getStart(); note <= region->keyRange.getEnd(); note++) noteActivationLists[note].push_back(region); diff --git a/tests/FilesT.cpp b/tests/FilesT.cpp index 06e7c5b6..f4b21348 100644 --- a/tests/FilesT.cpp +++ b/tests/FilesT.cpp @@ -11,6 +11,7 @@ TEST_CASE("[Files] Single region (regions_one.sfz)") REQUIRE(synth.getRegionView(0)->sample == "dummy.wav"); } + TEST_CASE("[Files] Multiple regions (regions_many.sfz)") { sfz::Synth synth; @@ -227,48 +228,55 @@ TEST_CASE("[Files] Pizz basic") REQUIRE(synth.getRegionView(3)->sample == R"(../Samples/pizz/a0_vl4_rr4.wav)"); } -// TEST_CASE("[Files] sw_default") -// { -// const double sampleRate { 48000 }; -// const int blockSize { 256 }; -// sfz::Synth synth; -// synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/sw_default.sfz"); -// REQUIRE( synth.getNumRegions() == 4 ); -// REQUIRE( !synth.getRegionView(0)->isSwitchedOn() ); -// REQUIRE( synth.getRegionView(1)->isSwitchedOn() ); -// REQUIRE( !synth.getRegionView(2)->isSwitchedOn() ); -// REQUIRE( synth.getRegionView(3)->isSwitchedOn() ); -// } +TEST_CASE("[Files] Channels (channels.sfz)") +{ + sfz::Synth synth; + synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/channels.sfz"); + REQUIRE(synth.getNumRegions() == 2); + REQUIRE(synth.getRegionView(0)->sample == "mono_sample.wav"); + REQUIRE(synth.getRegionView(0)->numChannels == 1); + REQUIRE(!synth.getRegionView(0)->isStereo()); + REQUIRE(synth.getRegionView(1)->sample == "stereo_sample.wav"); + REQUIRE(synth.getRegionView(1)->numChannels == 2); + REQUIRE(synth.getRegionView(1)->isStereo()); +} -// TEST_CASE("[Files] sw_default and playing with switches") -// { -// const double sampleRate { 48000 }; -// const int blockSize { 256 }; -// sfz::Synth synth; -// synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/sw_default.sfz"); -// REQUIRE( synth.getNumRegions() == 4 ); -// REQUIRE( !synth.getRegionView(0)->isSwitchedOn() ); -// REQUIRE( synth.getRegionView(1)->isSwitchedOn() ); -// REQUIRE( !synth.getRegionView(2)->isSwitchedOn() ); -// REQUIRE( synth.getRegionView(3)->isSwitchedOn() ); -// AudioBuffer buffer { 2, blockSize }; -// synth.prepareToPlay(sampleRate, blockSize); -// buffer.clear(); -// synth.registerNoteOn(1, 41, 64, 0); -// REQUIRE( synth.getRegionView(0)->isSwitchedOn() ); -// REQUIRE( !synth.getRegionView(1)->isSwitchedOn() ); -// REQUIRE( synth.getRegionView(2)->isSwitchedOn() ); -// REQUIRE( !synth.getRegionView(3)->isSwitchedOn() ); -// synth.registerNoteOff(1, 41, 0, 0); -// synth.registerNoteOn(1, 42, 64, 0); -// REQUIRE( !synth.getRegionView(0)->isSwitchedOn() ); -// REQUIRE( !synth.getRegionView(1)->isSwitchedOn() ); -// REQUIRE( !synth.getRegionView(2)->isSwitchedOn() ); -// REQUIRE( !synth.getRegionView(3)->isSwitchedOn() ); -// synth.registerNoteOff(1, 42, 0, 0); -// synth.registerNoteOn(1, 40, 64, 0); -// REQUIRE( !synth.getRegionView(0)->isSwitchedOn() ); -// REQUIRE( synth.getRegionView(1)->isSwitchedOn() ); -// REQUIRE( !synth.getRegionView(2)->isSwitchedOn() ); -// REQUIRE( synth.getRegionView(3)->isSwitchedOn() ); -// } \ No newline at end of file +TEST_CASE("[Files] sw_default") +{ + sfz::Synth synth; + synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/sw_default.sfz"); + REQUIRE( synth.getNumRegions() == 4 ); + REQUIRE( !synth.getRegionView(0)->isSwitchedOn() ); + REQUIRE( synth.getRegionView(1)->isSwitchedOn() ); + REQUIRE( !synth.getRegionView(2)->isSwitchedOn() ); + REQUIRE( synth.getRegionView(3)->isSwitchedOn() ); +} + +TEST_CASE("[Files] sw_default and playing with switches") +{ + sfz::Synth synth; + synth.loadSfzFile(std::filesystem::current_path() / "tests/TestFiles/sw_default.sfz"); + REQUIRE( synth.getNumRegions() == 4 ); + REQUIRE( !synth.getRegionView(0)->isSwitchedOn() ); + REQUIRE( synth.getRegionView(1)->isSwitchedOn() ); + REQUIRE( !synth.getRegionView(2)->isSwitchedOn() ); + REQUIRE( synth.getRegionView(3)->isSwitchedOn() ); + synth.noteOn(0, 1, 41, 64); + synth.noteOff(0, 1, 41, 0); + REQUIRE( synth.getRegionView(0)->isSwitchedOn() ); + REQUIRE( !synth.getRegionView(1)->isSwitchedOn() ); + REQUIRE( synth.getRegionView(2)->isSwitchedOn() ); + REQUIRE( !synth.getRegionView(3)->isSwitchedOn() ); + synth.noteOn(0, 1, 42, 64); + synth.noteOff(0, 1, 42, 0); + REQUIRE( !synth.getRegionView(0)->isSwitchedOn() ); + REQUIRE( !synth.getRegionView(1)->isSwitchedOn() ); + REQUIRE( !synth.getRegionView(2)->isSwitchedOn() ); + REQUIRE( !synth.getRegionView(3)->isSwitchedOn() ); + synth.noteOn(0, 1, 40, 64); + synth.noteOff(0, 1, 40, 64); + REQUIRE( !synth.getRegionView(0)->isSwitchedOn() ); + REQUIRE( synth.getRegionView(1)->isSwitchedOn() ); + REQUIRE( !synth.getRegionView(2)->isSwitchedOn() ); + REQUIRE( synth.getRegionView(3)->isSwitchedOn() ); +} \ No newline at end of file diff --git a/tests/TestFiles/channels.sfz b/tests/TestFiles/channels.sfz new file mode 100644 index 00000000..bed3c070 --- /dev/null +++ b/tests/TestFiles/channels.sfz @@ -0,0 +1,2 @@ + key=60 sample=mono_sample.wav + key=61 sample=stereo_sample.wav diff --git a/tests/TestFiles/mono_sample.wav b/tests/TestFiles/mono_sample.wav new file mode 100755 index 00000000..d31835e5 Binary files /dev/null and b/tests/TestFiles/mono_sample.wav differ diff --git a/tests/TestFiles/stereo_sample.wav b/tests/TestFiles/stereo_sample.wav new file mode 100755 index 00000000..027a41d4 Binary files /dev/null and b/tests/TestFiles/stereo_sample.wav differ