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:
parent
2215001d0c
commit
fdebb67071
3 changed files with 86 additions and 26 deletions
|
|
@ -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"
|
||||
|
|
|
|||
66
modules/juce_dsp/maths/juce_Phase.h
Normal file
66
modules/juce_dsp/maths/juce_Phase.h
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue