1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

DSP module: Added a Phase class

This commit is contained in:
jules 2017-12-12 12:52:25 +00:00
parent 2215001d0c
commit fdebb67071
3 changed files with 86 additions and 26 deletions

View file

@ -241,6 +241,7 @@ namespace juce
#include "maths/juce_SpecialFunctions.h"
#include "maths/juce_Matrix.h"
#include "maths/juce_Phase.h"
#include "maths/juce_Polynomial.h"
#include "maths/juce_FastMathApproximations.h"
#include "maths/juce_LookupTable.h"

View file

@ -0,0 +1,66 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
namespace dsp
{
/**
Represents an increasing phase value between 0 and 2*pi.
This represents a value which can be incremented, and which wraps back to 0 when it
goes past 2 * pi.
*/
template <typename Type>
struct Phase
{
/** Resets the phase to 0. */
void reset() noexcept { phase = 0; }
/** Returns the current value, and increments the phase by the given increment.
The increment must be a positive value, it can't go backwards!
The new value of the phase after calling this function will be (phase + increment) % (2 * pi).
*/
Type advance (Type increment) noexcept
{
jassert (increment >= 0); // cannot run this value backwards!
auto last = phase;
auto next = last + increment;
while (next >= MathConstants<Type>::twoPi)
next -= MathConstants<Type>::twoPi;
phase = next;
return last;
}
Type phase = 0;
};
} // namespace dsp
} // namespace juce

View file

@ -50,7 +50,8 @@ public:
If lookup table is not zero, then the function will be approximated
with a lookup table.
*/
Oscillator (const std::function<NumericType (NumericType)>& function, size_t lookupTableNumPoints = 0)
Oscillator (const std::function<NumericType (NumericType)>& function,
size_t lookupTableNumPoints = 0)
{
initialise (function, lookupTableNumPoints);
}
@ -59,13 +60,14 @@ public:
bool isInitialised() const noexcept { return static_cast<bool> (generator); }
/** Initialises the oscillator with a waveform. */
void initialise (const std::function<NumericType (NumericType)>& function, size_t lookupTableNumPoints = 0)
void initialise (const std::function<NumericType (NumericType)>& function,
size_t lookupTableNumPoints = 0)
{
if (lookupTableNumPoints != 0)
{
auto* table = new LookupTableTransform<NumericType> (function,
static_cast<NumericType> (-1.0 * MathConstants<double>::pi),
static_cast<NumericType> (MathConstants<double>::pi),
-MathConstants<NumericType>::pi,
MathConstants<NumericType>::pi,
lookupTableNumPoints);
lookupTable = table;
@ -97,7 +99,7 @@ public:
/** Resets the internal state of the oscillator */
void reset() noexcept
{
pos = 0.0;
phase.reset();
if (sampleRate > 0)
frequency.reset (sampleRate, 0.05);
@ -108,11 +110,8 @@ public:
SampleType JUCE_VECTOR_CALLTYPE processSample (SampleType) noexcept
{
jassert (isInitialised());
auto increment = static_cast<NumericType> (MathConstants<double>::twoPi) * frequency.getNextValue() / sampleRate;
auto value = generator (pos - static_cast<NumericType> (MathConstants<double>::pi));
pos = std::fmod (pos + increment, static_cast<NumericType> (MathConstants<double>::twoPi));
return value;
auto increment = MathConstants<NumericType>::twoPi * frequency.getNextValue() / sampleRate;
return generator (phase.advance (increment) - MathConstants<NumericType>::pi);
}
/** Processes the input and output buffers supplied in the processing context. */
@ -128,19 +127,15 @@ public:
auto len = outBlock.getNumSamples();
auto numChannels = outBlock.getNumChannels();
auto baseIncrement = static_cast<NumericType> (MathConstants<double>::twoPi) / sampleRate;
auto baseIncrement = MathConstants<NumericType>::twoPi / sampleRate;
if (frequency.isSmoothing())
{
auto* buffer = rampBuffer.getRawDataPointer();
for (size_t i = 0; i < len; ++i)
{
buffer[i] = pos - static_cast<NumericType> (MathConstants<double>::pi);
pos = std::fmod (pos + (baseIncrement * frequency.getNextValue()),
static_cast<NumericType> (MathConstants<double>::twoPi));
}
buffer[i] = phase.advance (baseIncrement * frequency.getNextValue())
- MathConstants<NumericType>::pi;
for (size_t ch = 0; ch < numChannels; ++ch)
{
@ -153,21 +148,18 @@ public:
else
{
auto freq = baseIncrement * frequency.getNextValue();
auto p = phase;
for (size_t ch = 0; ch < numChannels; ++ch)
{
auto p = pos;
p = phase;
auto* dst = outBlock.getChannelPointer (ch);
for (size_t i = 0; i < len; ++i)
{
dst[i] = generator (p - static_cast<NumericType> (MathConstants<double>::pi));
p = std::fmod (p + freq, static_cast<NumericType> (MathConstants<double>::twoPi));
}
dst[i] = generator (p.advance (freq) - MathConstants<NumericType>::pi);
}
pos = std::fmod (pos + freq * static_cast<NumericType> (len),
static_cast<NumericType> (MathConstants<double>::twoPi));
phase = p;
}
}
@ -176,8 +168,9 @@ private:
std::function<NumericType (NumericType)> generator;
ScopedPointer<LookupTableTransform<NumericType>> lookupTable;
Array<NumericType> rampBuffer;
LinearSmoothedValue<NumericType> frequency {static_cast<NumericType> (440.0)};
NumericType sampleRate = 48000.0, pos = 0.0;
LinearSmoothedValue<NumericType> frequency { static_cast<NumericType> (440.0) };
NumericType sampleRate = 48000.0;
Phase<NumericType> phase;
};
} // namespace dsp