Audacity 3.2.0
ToneGenBase.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 Split from ToneGen.cpp
6
7 Steve Jolly
8 James Crook (Adapted for 'Chirps')
9
10 This class implements a tone generator effect.
11
12*******************************************************************//*******************************************************************/
20#include "ToneGenBase.h"
21#include "Project.h"
22#include "ProjectRate.h"
23#include "ShuttleAutomation.h"
24#include <math.h>
25
26const EnumValueSymbol ToneGenBase::kInterStrings[nInterpolations] = {
27 // These are acceptable dual purpose internal/visible names
28 { XO("Linear") },
29 { XO("Logarithmic") }
30};
31
33 { XO("Sine") },
34 { XO("Square") },
35 { XO("Sawtooth") },
36 { XO("Square, no alias") },
37 { XC("Triangle", "waveform") }
38};
39
41{
42 static const auto postSet = [](ToneGenBase&, EffectSettings&, ToneGenBase& e,
43 bool updating) {
44 if (updating)
45 e.PostSet();
46 return true;
47 };
48 static CapturedParameters<
50 chirpParameters { postSet };
51 static CapturedParameters<
53 toneParameters { postSet };
54 if (mChirp)
55 return chirpParameters;
56 else
57 return toneParameters;
58}
59
61 : mChirp { isChirp }
62{
63 Parameters().Reset(*this);
64
65 wxASSERT(nWaveforms == WXSIZEOF(kWaveStrings));
66 wxASSERT(nInterpolations == WXSIZEOF(kInterStrings));
67
68 // Chirp varies over time so must use selected duration.
69 // TODO: When previewing, calculate only the first 'preview length'.
70 if (isChirp)
72 else
74}
75
77{
78}
79
80// EffectDefinitionInterface implementation
81
83{
84 return EffectTypeGenerate;
85}
86
88{
89 return 1;
90}
91
93 EffectSettings&, double sampleRate, ChannelNames chanMap)
94{
97 mSample = 0;
98 return true;
99}
100
102 EffectSettings&, const float* const*, float* const* outBlock,
103 size_t blockLen)
104{
105 float* buffer = outBlock[0];
106 double throwaway = 0; // passed to modf but never used
107 double f = 0.0;
108 double a, b;
109 int k;
110
111 double frequencyQuantum;
112 double BlendedFrequency;
113 double BlendedAmplitude;
114 double BlendedLogFrequency = 0.0;
115
116 // calculate delta, and reposition from where we left
117 auto doubleSampleCount = mSampleCnt.as_double();
118 auto doubleSample = mSample.as_double();
119 double amplitudeQuantum = (mAmplitude1 - mAmplitude0) / doubleSampleCount;
120 BlendedAmplitude = mAmplitude0 + amplitudeQuantum * doubleSample;
121
122 // precalculations:
123 double pre2PI = 2.0 * M_PI;
124 double pre4divPI = 4.0 / M_PI;
125
126 // initial setup should calculate deltas
128 {
129 // this for log interpolation
130 mLogFrequency[0] = log10(mFrequency0);
131 mLogFrequency[1] = log10(mFrequency1);
132 // calculate delta, and reposition from where we left
133 frequencyQuantum =
134 (mLogFrequency[1] - mLogFrequency[0]) / doubleSampleCount;
135 BlendedLogFrequency = mLogFrequency[0] + frequencyQuantum * doubleSample;
136 BlendedFrequency = pow(10.0, BlendedLogFrequency);
137 }
138 else
139 {
140 // this for regular case, linear interpolation
141 frequencyQuantum = (mFrequency1 - mFrequency0) / doubleSampleCount;
142 BlendedFrequency = mFrequency0 + frequencyQuantum * doubleSample;
143 }
144
145 // synth loop
146 for (decltype(blockLen) i = 0; i < blockLen; i++)
147 {
148 switch (mWaveform)
149 {
150 case kSine:
151 f = sin(pre2PI * mPositionInCycles / mSampleRate);
152 break;
153 case kSquare:
154 f = (modf(mPositionInCycles / mSampleRate, &throwaway) < 0.5) ? 1.0 :
155 -1.0;
156 break;
157 case kSawtooth:
158 f = (2.0 * modf(mPositionInCycles / mSampleRate + 0.5, &throwaway)) -
159 1.0;
160 break;
161 case kTriangle:
162 f = modf(mPositionInCycles / mSampleRate, &throwaway);
163 if (f < 0.25)
164 {
165 f *= 4.0;
166 }
167 else if (f > 0.75)
168 {
169 f = (f - 1.0) * 4.0;
170 }
171 else
172 { /* f >= 0.25 || f <= 0.75 */
173 f = (0.5 - f) * 4.0;
174 }
175 break;
176 case kSquareNoAlias: // Good down to 110Hz @ 44100Hz sampling.
177 // do fundamental (k=1) outside loop
178 b = (1.0 + cos((pre2PI * BlendedFrequency) / mSampleRate)) /
179 pre4divPI; // scaling
180 f = pre4divPI * sin(pre2PI * mPositionInCycles / mSampleRate);
181 for (k = 3; (k < 200) && (k * BlendedFrequency < mSampleRate / 2.0);
182 k += 2)
183 {
184 // Hann Window in freq domain
185 a = 1.0 + cos((pre2PI * k * BlendedFrequency) / mSampleRate);
186 // calc harmonic, apply window, scale to amplitude of fundamental
187 f +=
188 a * sin(pre2PI * mPositionInCycles / mSampleRate * k) / (b * k);
189 }
190 }
191 // insert value in buffer
192 buffer[i] = (float)(BlendedAmplitude * f);
193 // update freq,amplitude
194 mPositionInCycles += BlendedFrequency;
195 BlendedAmplitude += amplitudeQuantum;
197 {
198 BlendedLogFrequency += frequencyQuantum;
199 BlendedFrequency = pow(10.0, BlendedLogFrequency);
200 }
201 else
202 {
203 BlendedFrequency += frequencyQuantum;
204 }
205 }
206
207 // update external placeholder
208 mSample += blockLen;
209
210 return blockLen;
211}
212
214{
215 if (!mChirp)
216 {
219 }
220 // double freqMax =
221 // (FindProject()
222 // ? ProjectRate::Get( *FindProject() ).GetRate()
223 // : 44100.0)
224 // / 2.0;
225 // mFrequency1 = std::clamp<double>(mFrequency1, EndFreq.min, freqMax);
226}
#define M_PI
Definition: Distortion.cpp:30
EffectType
@ EffectTypeGenerate
ChannelName
XO("Cut/Copy/Paste")
#define XC(s, c)
Definition: Internat.h:37
an object holding per-project preferred sample rate
Generates EffectParameterMethods overrides from variadic template arguments.
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
void SetLinearEffectFlag(bool linearEffectFlag)
Definition: EffectBase.cpp:210
Interface for manipulations of an Effect's settings.
virtual void Reset(Effect &effect) const =0
sampleCount mSampleCnt
An Effect that can generate a sine, square or sawtooth wave. An extended mode of ToneGenBase supports...
Definition: ToneGenBase.h:22
double mAmplitude1
Definition: ToneGenBase.h:61
size_t ProcessBlock(EffectSettings &settings, const float *const *inBlock, float *const *outBlock, size_t blockLen) override
Called for destructive effect computation.
static const EnumValueSymbol kInterStrings[nInterpolations]
Definition: ToneGenBase.h:90
static constexpr EffectParameter StartAmp
Definition: ToneGenBase.h:99
const bool mChirp
Definition: ToneGenBase.h:45
double mLogFrequency[2]
Definition: ToneGenBase.h:64
sampleCount mSample
Definition: ToneGenBase.h:50
static constexpr EffectParameter StartFreq
Definition: ToneGenBase.h:93
unsigned GetAudioOutCount() const override
How many output buffers to allocate at once.
Definition: ToneGenBase.cpp:87
double mFrequency0
Definition: ToneGenBase.h:58
double mFrequency1
Definition: ToneGenBase.h:59
static constexpr EffectParameter Frequency
Definition: ToneGenBase.h:105
static constexpr EnumParameter Interp
Definition: ToneGenBase.h:119
static constexpr EffectParameter EndAmp
Definition: ToneGenBase.h:102
double mSampleRate
Definition: ToneGenBase.h:44
int mInterpolation
Definition: ToneGenBase.h:57
static constexpr EnumParameter Waveform
Definition: ToneGenBase.h:111
bool ProcessInitialize(EffectSettings &settings, double sampleRate, ChannelNames chanMap) override
Definition: ToneGenBase.cpp:92
double mAmplitude0
Definition: ToneGenBase.h:60
const EffectParameterMethods & Parameters() const override
Definition: ToneGenBase.cpp:40
static constexpr EffectParameter Amplitude
Definition: ToneGenBase.h:108
virtual ~ToneGenBase()
Definition: ToneGenBase.cpp:76
EffectType GetType() const override
Type determines how it behaves.
Definition: ToneGenBase.cpp:82
ToneGenBase(bool isChirp)
Definition: ToneGenBase.cpp:60
static const EnumValueSymbol kWaveStrings[nWaveforms]
Definition: ToneGenBase.h:81
void PostSet()
static constexpr EffectParameter EndFreq
Definition: ToneGenBase.h:96
double mPositionInCycles
Definition: ToneGenBase.h:51
double as_double() const
Definition: SampleCount.h:46
Externalized state of a plug-in.