Skip to content

Commit

Permalink
added base class for double buffered effects
Browse files Browse the repository at this point in the history
  • Loading branch information
ozguronsoy committed Nov 2, 2024
1 parent 569eda7 commit 7c34ee9
Show file tree
Hide file tree
Showing 14 changed files with 120 additions and 38 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25)

set(HEPHAUDIO_VERSION_MAJOR 3)
set(HEPHAUDIO_VERSION_MINOR 0)
set(HEPHAUDIO_VERSION_PATCH 4)
set(HEPHAUDIO_VERSION_PATCH 5)
set(HEPHAUDIO_VERSION ${HEPHAUDIO_VERSION_MAJOR}.${HEPHAUDIO_VERSION_MINOR}.${HEPHAUDIO_VERSION_PATCH})

option(ENABLE_STATIC "ENABLE_STATIC" Off)
Expand Down
12 changes: 12 additions & 0 deletions HephAudio/HeaderFiles/AudioEffects/AudioEffect.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ namespace HephAudio
*/
virtual size_t CalculateRequiredFrameCount(size_t outputFrameCount, const AudioFormatInfo& formatInfo) const;

/**
* calculates the number of frames the buffer will contain after applying the effect.
*
* @param buffer contains the audio data which will be processed.
*
*/
virtual size_t CalculateOutputFrameCount(const AudioBuffer& buffer) const;

/**
* Applies the effect.
* @param buffer contains the audio data which will be processed.
Expand All @@ -71,6 +79,7 @@ namespace HephAudio

/**
* Applies the effect.
*
* @param buffer contains the audio data which will be processed.
* @param startIndex index of the first audio frame to process.
*
Expand All @@ -79,6 +88,7 @@ namespace HephAudio

/**
* Applies the effect.
*
* @param buffer contains the audio data which will be processed.
* @param startIndex index of the first audio frame to process.
* @param frameCount number of frames to process.
Expand All @@ -89,6 +99,7 @@ namespace HephAudio
protected:
/**
* applies the effect using single thread.
*
* @param inputBuffer contains the dry data.
* @param outputBuffer contains the wet data.
* @param startIndex index of the first sample to process.
Expand All @@ -99,6 +110,7 @@ namespace HephAudio

/**
* applies the effect using multiple threads.
*
* @param inputBuffer contains the dry data.
* @param outputBuffer contains the wet data.
*
Expand Down
30 changes: 30 additions & 0 deletions HephAudio/HeaderFiles/AudioEffects/DoubleBufferedAudioEffect.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once
#include "HephAudioShared.h"
#include "AudioEffect.h"

/** @file */

namespace HephAudio
{
/**
* @brief base class for audio effects that use a temporary buffer while processing.
*/
class DoubleBufferedAudioEffect : public AudioEffect
{
public:
using AudioEffect::Process;

protected:
/** @copydoc default_constructor */
DoubleBufferedAudioEffect();

/** @copydoc AudioEffect(size_t) */
explicit DoubleBufferedAudioEffect(size_t threadCount);

public:
/** @copydoc destructor */
virtual ~DoubleBufferedAudioEffect() = default;

virtual void Process(AudioBuffer& buffer, size_t startIndex, size_t frameCount) override;
};
}
9 changes: 6 additions & 3 deletions HephAudio/HeaderFiles/AudioEffects/ModulationEffect.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once
#include "HephAudioShared.h"
#include "AudioEffect.h"
#include "DoubleBufferedAudioEffect.h"
#include "Buffers/DoubleBuffer.h"
#include "Oscillators/Oscillator.h"

Expand All @@ -11,10 +11,10 @@ namespace HephAudio
/**
* @brief base class for effects that use LFOs.
*/
class ModulationEffect : public AudioEffect
class ModulationEffect : public DoubleBufferedAudioEffect
{
public:
using AudioEffect::Process;
using DoubleBufferedAudioEffect::Process;

protected:
/**
Expand All @@ -40,6 +40,7 @@ namespace HephAudio

/**
* @copydoc constructor
*
* @param depth @copydetails depth
* @param lfo low-frequency oscillator.
*
Expand All @@ -54,6 +55,7 @@ namespace HephAudio

/**
* sets the lfo.
*
* @param lfo low-frequency oscillator.
*/
virtual void SetOscillator(Oscillator& lfo);
Expand All @@ -66,6 +68,7 @@ namespace HephAudio

/**
* sets the depth.
*
* @param depth @copydetails depth
*/
virtual void SetDepth(double depth);
Expand Down
5 changes: 5 additions & 0 deletions HephAudio/HeaderFiles/AudioEffects/TremoloEffect.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ namespace HephAudio
*/
class TremoloEffect final : public ModulationEffect
{
public:
using ModulationEffect::Process;

public:
/** @copydoc default_constructor */
TremoloEffect();
Expand All @@ -19,6 +22,8 @@ namespace HephAudio

std::string Name() const override;

void Process(AudioBuffer& buffer, size_t startIndex, size_t frameCount) override;

private:
void ProcessST(const AudioBuffer& inputBuffer, AudioBuffer& outputBuffer, size_t startIndex, size_t endIndex) override;
};
Expand Down
1 change: 1 addition & 0 deletions HephAudio/HeaderFiles/AudioEffects/VibratoEffect.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ namespace HephAudio

/**
* @copydoc ModulationEffect(double, Oscillator&)
*
* @param extent @copydetails extent
*/
VibratoEffect(double depth, double extent, Oscillator& lfo);
Expand Down
2 changes: 1 addition & 1 deletion HephAudio/HeaderFiles/HephAudioShared.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
* patch part of the version.
*
*/
#define HEPHAUDIO_VERSION_PATCH 4
#define HEPHAUDIO_VERSION_PATCH 5

/**
* full version as string litteral.
Expand Down
2 changes: 2 additions & 0 deletions HephAudio/HephAudio.vcxitems
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<ProjectCapability Include="SourceItemsFromImports" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(MSBuildThisFileDirectory)HeaderFiles\AudioEffects\DoubleBufferedAudioEffect.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)HeaderFiles\AudioEffects\AudioEffect.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)HeaderFiles\EncodedAudioBuffer.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)HeaderFiles\FFmpeg\FFmpegEncodedAudioBuffer.h" />
Expand Down Expand Up @@ -90,6 +91,7 @@
<ClInclude Include="$(MSBuildThisFileDirectory)HeaderFiles\AudioEffects\VibratoEffect.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)SourceFiles\AudioEffects\DoubleBufferedAudioEffect.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SourceFiles\AudioEffects\ModulationEffect.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SourceFiles\AudioEffects\SineLawPanningEffect.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SourceFiles\AudioEffects\LinearPanningEffect.cpp" />
Expand Down
2 changes: 2 additions & 0 deletions HephAudio/HephAudio.vcxitems.filters
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@
<ClInclude Include="$(MSBuildThisFileDirectory)HeaderFiles\AudioEffects\ModulationEffect.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)HeaderFiles\AudioEffects\TremoloEffect.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)HeaderFiles\AudioEffects\VibratoEffect.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)HeaderFiles\AudioEffects\DoubleBufferedAudioEffect.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)SourceFiles\AudioProcessor.cpp">
Expand Down Expand Up @@ -400,5 +401,6 @@
<ClCompile Include="$(MSBuildThisFileDirectory)SourceFiles\AudioEffects\ModulationEffect.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SourceFiles\AudioEffects\TremoloEffect.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SourceFiles\AudioEffects\VibratoEffect.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SourceFiles\AudioEffects\DoubleBufferedAudioEffect.cpp" />
</ItemGroup>
</Project>
5 changes: 5 additions & 0 deletions HephAudio/SourceFiles/AudioEffects/AudioEffect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ namespace HephAudio
return outputFrameCount;
}

size_t AudioEffect::CalculateOutputFrameCount(const AudioBuffer& buffer) const
{
return buffer.FrameCount();
}

void AudioEffect::Process(AudioBuffer& buffer)
{
this->Process(buffer, 0, buffer.FrameCount());
Expand Down
45 changes: 45 additions & 0 deletions HephAudio/SourceFiles/AudioEffects/DoubleBufferedAudioEffect.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include "AudioEffects/DoubleBufferedAudioEffect.h"
#include "Exceptions/InvalidArgumentException.h"

using namespace Heph;

namespace HephAudio
{
DoubleBufferedAudioEffect::DoubleBufferedAudioEffect() : AudioEffect() {}

DoubleBufferedAudioEffect::DoubleBufferedAudioEffect(size_t threadCount) : AudioEffect(threadCount) {}

void DoubleBufferedAudioEffect::Process(AudioBuffer& buffer, size_t startIndex, size_t frameCount)
{
if (startIndex > buffer.FrameCount())
{
HEPH_RAISE_AND_THROW_EXCEPTION(this, InvalidArgumentException(HEPH_FUNC, "startIndex out of bounds."));
}

const size_t endIndex = startIndex + frameCount;
if (endIndex > buffer.FrameCount())
{
HEPH_RAISE_AND_THROW_EXCEPTION(this, InvalidArgumentException(HEPH_FUNC, "(startIndex + frameCount) exceeds the buffer's frame count."));
}

const AudioFormatInfo& formatInfo = buffer.FormatInfo();
AudioBuffer resultBuffer(this->CalculateOutputFrameCount(buffer), formatInfo.channelLayout, formatInfo.sampleRate, BufferFlags::AllocUninitialized);

if (startIndex > 0)
{
(void)memcpy(resultBuffer.begin(), buffer.begin(), startIndex * formatInfo.FrameSize());
}

if (endIndex < buffer.FrameCount())
{
(void)memcpy(resultBuffer.begin() + endIndex, buffer.begin() + endIndex, (buffer.FrameCount() - endIndex) * formatInfo.FrameSize());
}

if (this->threadCount == 1)
this->ProcessST(buffer, resultBuffer, startIndex, frameCount);
else
this->ProcessMT(buffer, resultBuffer, startIndex, frameCount);

buffer = std::move(resultBuffer);
}
}
33 changes: 2 additions & 31 deletions HephAudio/SourceFiles/AudioEffects/ModulationEffect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ using namespace Heph;

namespace HephAudio
{
ModulationEffect::ModulationEffect() : AudioEffect(), lfoIndex(0), depth(1.0) {}
ModulationEffect::ModulationEffect() : DoubleBufferedAudioEffect(), lfoIndex(0), depth(1.0) {}

ModulationEffect::ModulationEffect(double depth, Oscillator& lfo) : ModulationEffect()
{
Expand All @@ -15,36 +15,7 @@ namespace HephAudio

void ModulationEffect::Process(AudioBuffer& buffer, size_t startIndex, size_t frameCount)
{
if (startIndex > buffer.FrameCount())
{
HEPH_RAISE_AND_THROW_EXCEPTION(this, InvalidArgumentException(HEPH_FUNC, "startIndex out of bounds."));
}

const size_t endIndex = startIndex + frameCount;
if (endIndex > buffer.FrameCount())
{
HEPH_RAISE_AND_THROW_EXCEPTION(this, InvalidArgumentException(HEPH_FUNC, "(startIndex + frameCount) exceeds the buffer's frame count."));
}

const AudioFormatInfo& formatInfo = buffer.FormatInfo();
AudioBuffer resultBuffer(buffer.FrameCount(), formatInfo.channelLayout, formatInfo.sampleRate, BufferFlags::AllocUninitialized);

if (startIndex > 0)
{
(void)memcpy(resultBuffer.begin(), buffer.begin(), startIndex * formatInfo.FrameSize());
}

if (endIndex < buffer.FrameCount())
{
(void)memcpy(resultBuffer.begin() + endIndex, buffer.begin() + endIndex, (buffer.FrameCount() - endIndex) * formatInfo.FrameSize());
}

if (this->threadCount == 1)
this->ProcessST(buffer, resultBuffer, startIndex, frameCount);
else
this->ProcessMT(buffer, resultBuffer, startIndex, frameCount);

buffer = std::move(resultBuffer);
DoubleBufferedAudioEffect::Process(buffer, startIndex, frameCount);
this->lfoIndex += frameCount;
}

Expand Down
8 changes: 7 additions & 1 deletion HephAudio/SourceFiles/AudioEffects/TremoloEffect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ namespace HephAudio
return "Tremolo";
}

void TremoloEffect::Process(AudioBuffer& buffer, size_t startIndex, size_t frameCount)
{
AudioEffect::Process(buffer, startIndex, frameCount);
this->lfoIndex += frameCount;
}

void TremoloEffect::ProcessST(const AudioBuffer& inputBuffer, AudioBuffer& outputBuffer, size_t startIndex, size_t frameCount)
{
const size_t endIndex = startIndex + frameCount;
Expand All @@ -20,7 +26,7 @@ namespace HephAudio
const double lfoSample = this->lfoBuffer[(i + this->lfoIndex) % this->lfoBuffer.Size()];
for (size_t j = 0; j < channelCount; ++j)
{
outputBuffer[i][j] = inputBuffer[i][j] * this->depth * lfoSample + inputBuffer[i][j] * (1.0 - this->depth);
outputBuffer[i][j] *= this->depth * lfoSample + (1.0 - this->depth);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion docs/Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ PROJECT_NAME = "HephAudio"
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER = "v3.0.4"
PROJECT_NUMBER = "v3.0.5"

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
Expand Down

0 comments on commit 7c34ee9

Please sign in to comment.