MCPcopy Create free account
hub / github.com/SFML/SFML / Echo

Method Echo

examples/sound_effects/SoundEffects.cpp:860–913  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

858struct Echo : Processing
859{
860 Echo() : Processing("Echo")
861 {
862 auto& music = getMusic();
863
864 static constexpr auto delay = 0.2f;
865 static constexpr auto decay = 0.75f;
866 static constexpr auto wet = 0.8f;
867 static constexpr auto dry = 1.f;
868
869 const auto sampleRate = sf::PlaybackDevice::getDeviceSampleRate().value_or(44100);
870 const auto delayInFrames = static_cast<unsigned int>(static_cast<float>(sampleRate) * delay);
871
872 // We use a mutable lambda to tie the lifetime of the state to the lambda itself
873 // This is necessary since the Echo object will be destroyed before the Music object
874 // While the Music object exists, it is possible that the audio engine will try to call
875 // this lambda hence we need to always have a usable state until the Music and the
876 // associated lambda are destroyed
877 music.setEffectProcessor(
878 [delayInFrames,
879 enabled = getEnabled(),
880 buffer = std::vector<float>(),
881 cursor = 0u](const float* inputFrames,
882 unsigned int& inputFrameCount,
883 float* outputFrames,
884 unsigned int& outputFrameCount,
885 unsigned int frameChannelCount) mutable
886 {
887 // IMPORTANT: The channel count of the audio engine currently sourcing data from this sound
888 // will always be provided in frameChannelCount, this can be different from the channel count
889 // of the audio source so make sure to size your buffers according to the engine and not the source
890 // Ensure we have enough space to store the delayed frames for all of the audio engine's channels
891 if (buffer.size() < delayInFrames * frameChannelCount)
892 buffer.resize(delayInFrames * frameChannelCount - buffer.size(), 0.f);
893
894 for (auto frame = 0u; frame < outputFrameCount; ++frame)
895 {
896 for (auto channel = 0u; channel < frameChannelCount; ++channel)
897 {
898 const auto input = inputFrames ? inputFrames[channel] : 0.f; // Read silence if no input data available
899 const auto bufferIndex = (cursor * frameChannelCount) + channel;
900 buffer[bufferIndex] = (buffer[bufferIndex] * decay) + (input * dry);
901 outputFrames[channel] = *enabled ? buffer[bufferIndex] * wet : input;
902 }
903
904 cursor = (cursor + 1) % delayInFrames;
905
906 inputFrames += (inputFrames ? frameChannelCount : 0u);
907 outputFrames += frameChannelCount;
908 }
909
910 // We processed data 1:1
911 inputFrameCount = outputFrameCount;
912 });
913 }
914};
915
916

Callers

nothing calls this directly

Calls 3

getDeviceSampleRateFunction · 0.85
setEffectProcessorMethod · 0.45
resizeMethod · 0.45

Tested by

no test coverage detected