diff --git a/src/sfizz/Config.h b/src/sfizz/Config.h index 22a18327..32778125 100644 --- a/src/sfizz/Config.h +++ b/src/sfizz/Config.h @@ -56,6 +56,7 @@ namespace config { constexpr int filtersInPool { maxVoices * 2 }; constexpr int filtersPerVoice { 2 }; constexpr int eqsPerVoice { 3 }; + constexpr float noiseVariance { 0.1f }; /** Minimum interval in frames between recomputations of coefficients of the modulated filter. The lower, the more CPU resources are consumed. diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp index e39faf7a..df7430c8 100644 --- a/src/sfizz/Voice.cpp +++ b/src/sfizz/Voice.cpp @@ -478,35 +478,41 @@ void sfz::Voice::fillWithData(AudioSpan buffer) noexcept void sfz::Voice::fillWithGenerator(AudioSpan buffer) noexcept { - if (region->sample != "*sine") - return; + const auto leftSpan = buffer.getSpan(0); + const auto rightSpan = buffer.getSpan(1); + if (region->sample == "*noise") { + absl::c_generate(leftSpan, [&](){ return noiseDist(Random::randomGenerator); }); + absl::c_generate(rightSpan, [&](){ return noiseDist(Random::randomGenerator); }); + } + else if (region->sample == "*sine") { + // TODO: wavetables for sine and other generators + if (buffer.getNumFrames() == 0) + return; - if (buffer.getNumFrames() == 0) - return; + auto jumps = tempSpan1.first(buffer.getNumFrames()); + auto bends = tempSpan2.first(buffer.getNumFrames()); + auto phases = tempSpan2.first(buffer.getNumFrames()); - auto jumps = tempSpan1.first(buffer.getNumFrames()); - auto bends = tempSpan2.first(buffer.getNumFrames()); - auto phases = tempSpan2.first(buffer.getNumFrames()); + const float step = baseFrequency * twoPi / sampleRate; + fill(jumps, step); - const float step = baseFrequency * twoPi / sampleRate; - fill(jumps, step); + if (region->bendStep > 1) + pitchBendEnvelope.getQuantizedBlock(bends, bendStepFactor); + else + pitchBendEnvelope.getBlock(bends); - if (region->bendStep > 1) - pitchBendEnvelope.getQuantizedBlock(bends, bendStepFactor); - else - pitchBendEnvelope.getBlock(bends); + applyGain(bends, jumps); + jumps[0] += phase; + cumsum(jumps, phases); + phase = phases.back(); - applyGain(bends, jumps); - jumps[0] += phase; - cumsum(jumps, phases); - phase = phases.back(); + sin(phases, leftSpan); + copy(leftSpan, rightSpan); - sin(phases, buffer.getSpan(0)); - copy(buffer.getSpan(0), buffer.getSpan(1)); - - // Wrap the phase so we don't loose too much precision on longer notes - const auto numTwoPiWraps = static_cast(phase / twoPi); - phase -= twoPi * static_cast(numTwoPiWraps); + // Wrap the phase so we don't loose too much precision on longer notes + const auto numTwoPiWraps = static_cast(phase / twoPi); + phase -= twoPi * static_cast(numTwoPiWraps); + } } bool sfz::Voice::checkOffGroup(int delay, uint32_t group) noexcept diff --git a/src/sfizz/Voice.h b/src/sfizz/Voice.h index caaaee72..adf18930 100644 --- a/src/sfizz/Voice.h +++ b/src/sfizz/Voice.h @@ -18,6 +18,7 @@ #include #include #include +#include namespace sfz { /** @@ -308,6 +309,8 @@ private: MultiplicativeEnvelope volumeEnvelope; float bendStepFactor { centsFactor(1) }; + std::normal_distribution noiseDist { 0, config::noiseVariance }; + HistoricalBuffer powerHistory { config::powerHistoryLength }; LEAK_DETECTOR(Voice); };