-
Notifications
You must be signed in to change notification settings - Fork 0
/
FmVoice.h
157 lines (148 loc) · 4.52 KB
/
FmVoice.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
==============================================================================
FmVoice.h
Created: 6 Oct 2020 3:28:58pm
Author: Hayden Setlik
==============================================================================
*/
#pragma once
#include <JuceHeader.h>
#include "OperatorProcessor.h"
class FmSound : public juce::SynthesiserSound
{
public:
bool appliesToNote(int /*midiNoteNumber*/) //just plays this sound for any midi note
{
return true;
}
bool appliesToChannel(int /*midiChannel*/) //plays the sound on both channels
{
return true;
}
};
class FmVoice : public juce::SynthesiserVoice
{
public:
juce::AudioProcessorValueTreeState* tree;
FmVoice(int numOperators, int index, juce::AudioProcessorValueTreeState* t);
~FmVoice()
{
//printf("Voice #: %d -- %d total jumps\n", voiceIndex, numJumps);
}
bool canPlaySound(juce::SynthesiserSound* sound) override
{
return dynamic_cast<FmSound*>(sound) != nullptr;
}
void startNote (int midiNoteNumber,
float velocity,
juce::SynthesiserSound *sound,
int currentPitchWheelPosition) override
{
fundamental = convert::mtof(midiNoteNumber);
for(Operator* i : operators)
{
i->envelope.triggerOn();
}
}
void stopNote (float velocity, bool allowTailOff) override
{
for(Operator* i : operators)
{
i->envelope.triggerOff();
}
allowTailOff = true;
if(velocity == 0 || !isActive())
clearCurrentNote();
}
void applyLfo(int index);
void setRoutingFromGrid(juce::AudioProcessorValueTreeState* pTree, std::vector<std::vector<juce::String>> grid);
void setSampleRate(double newRate)
{
for(Operator* i : operators)
{
i->updateSampleRate(newRate);
}
}
void pitchWheelMoved(int newPitchWheelVal) override {}
//=============================================
void controllerMoved(int controllerNumber, int controllerValue) override{}
//===============================================
void aftertouchChanged (int newAftertouchValue) override{}
//==============================================
void channelPressureChanged (int newChannelPressureValue) override{}
//===============================================
void renderNextBlock (juce::AudioBuffer<float> &outputBuffer, int startSample, int numSamples) override;
//==============================================
void setCurrentPlaybackSampleRate (double newRate) override
{
setSampleRate(newRate);
}
float getValue(juce::String str)
{
return *tree->getRawParameterValue(str);
}
bool isActive()
{
for(auto op : operators)
{
if(op->envelope.isActive())
return true;
}
return false;
}
void updateParams();
int voiceIndex;
int numJumps;
int operatorCount;
float fundamental;
juce::OwnedArray<LfoProcessor> lfoBank;
juce::OwnedArray<Operator> operators;
float opSample;
float opSum;
float lastOpSample;
int lfoTarget;
float sumL;
float sumR;
float lfoValue;
float lfoMax;
float lfoMin;
private:
int op1Index, op2Index;
juce::String opRoutingIds[TOTAL_OPERATORS][TOTAL_OPERATORS];
juce::String opAudibleIds[TOTAL_OPERATORS];
int opRouting[TOTAL_OPERATORS][TOTAL_OPERATORS];
int opAudible[TOTAL_OPERATORS];
};
class FmSynth : public juce::Synthesiser
{
public:
juce::AudioProcessorValueTreeState* tree;
FmSynth(int operators, int lfos, int nVoices, juce::AudioProcessorValueTreeState* t) : juce::Synthesiser(), tree(t), numOperators(operators), numLfos(lfos), numVoices(nVoices)
{
for(int i = 0; i < numVoices; ++i)
{
addVoice(new FmVoice(numOperators, i, tree));
}
addSound(new FmSound());
}
FmVoice* getFmVoice(int& i)
{
return dynamic_cast<FmVoice*>(voices.getUnchecked(i));
}
juce::OwnedArray<juce::SynthesiserVoice>* voiceArray()
{
return &voices;
}
void updateParams()
{
for(idx = 0; idx < numVoices; ++idx)
{
getFmVoice(idx)->updateParams();
}
}
private:
int idx;
int numOperators;
int numLfos;
int numVoices;
};