This shows you the differences between two versions of the page.
Both sides previous revision Previous revision | |||
enum_class_rather_than_typedef_enum [2017/09/01 13:16] shane [Applying enum class in VanillaJuce: case 2] |
enum_class_rather_than_typedef_enum [2017/09/01 14:01] (current) shane [Conclusion and analysis] |
||
---|---|---|---|
Line 147: | Line 147: | ||
(The above code was automatically generated by the Projucer.) | (The above code was automatically generated by the Projucer.) | ||
Clearly, I needed to re-think the whole notion of waveform selection. | Clearly, I needed to re-think the whole notion of waveform selection. | ||
+ | |||
+ | ===== Re-thinking waveform selection in VanillaJuce ===== | ||
+ | The notion of // | ||
+ | * The set of waveforms might not always be finite. What if, down the road, I were to add some facility for users to define their own? | ||
+ | * For humans, waveforms are identified by //string constants//, | ||
+ | * For program code, a more compact, unambiguous representation is needed, e.g. for my // | ||
+ | |||
+ | The set of available waveforms in a synthesizer is essentially an //ordered collection// | ||
+ | |||
+ | I decided to create a new class // | ||
+ | <code cpp> | ||
+ | class SynthWaveform | ||
+ | { | ||
+ | private: | ||
+ | enum WaveformTypeIndex { | ||
+ | kSine, kTriangle, kSquare, kSawtooth, | ||
+ | kNumberOfWaveformTypes | ||
+ | } index; | ||
+ | | ||
+ | friend class SynthOscillator; | ||
+ | |||
+ | public: | ||
+ | // default constructor | ||
+ | SynthWaveform() : index(kSine) {} | ||
+ | |||
+ | // set to default state after construction | ||
+ | void setToDefault() { index = kSine; } | ||
+ | |||
+ | // serialize: get human-readable name of this waveform | ||
+ | String name(); | ||
+ | |||
+ | // deserialize: | ||
+ | void setFromName(String wfName); | ||
+ | |||
+ | // convenience funtions to allow selecting SynthWaveform from a juce:: | ||
+ | static void setupComboBox(ComboBox& | ||
+ | void fromComboBox(ComboBox& | ||
+ | void toComboBox(ComboBox& | ||
+ | |||
+ | |||
+ | private: | ||
+ | // waveform names: ordered list of string literals | ||
+ | static const char* const wfNames[]; | ||
+ | }; | ||
+ | |||
+ | const char* const SynthWaveform:: | ||
+ | " | ||
+ | }; | ||
+ | |||
+ | void SynthWaveform:: | ||
+ | { | ||
+ | for (int i = 0; i < kNumberOfWaveformTypes; | ||
+ | { | ||
+ | if (wfName == wfNames[i]) | ||
+ | { | ||
+ | index = (WaveformTypeIndex)i; | ||
+ | return; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // Were we given an invalid waveform name? | ||
+ | jassertfalse; | ||
+ | } | ||
+ | |||
+ | String SynthWaveform:: | ||
+ | { | ||
+ | return wfNames[index]; | ||
+ | } | ||
+ | |||
+ | void SynthWaveform:: | ||
+ | { | ||
+ | for (int i = 0; i < kNumberOfWaveformTypes; | ||
+ | cb.addItem(wfNames[i], | ||
+ | } | ||
+ | |||
+ | void SynthWaveform:: | ||
+ | { | ||
+ | index = (WaveformTypeIndex)(cb.getSelectedItemIndex()); | ||
+ | } | ||
+ | |||
+ | void SynthWaveform:: | ||
+ | { | ||
+ | cb.setSelectedItemIndex((int)index); | ||
+ | } | ||
+ | </ | ||
+ | I have used a traditional C++ '' | ||
+ | |||
+ | <code cpp> | ||
+ | float SynthOscillator:: | ||
+ | { | ||
+ | float sample = 0.0f; | ||
+ | switch (waveform.index) | ||
+ | { | ||
+ | case SynthWaveform:: | ||
+ | sample = (float)(std:: | ||
+ | break; | ||
+ | case SynthWaveform:: | ||
+ | sample = (phase <= 0.5) ? 1.0f : -1.0f; | ||
+ | break; | ||
+ | case SynthWaveform:: | ||
+ | sample = (float)(2.0 * (0.5 - std:: | ||
+ | break; | ||
+ | case SynthWaveform:: | ||
+ | sample = (float)(2.0 * phase - 1.0); | ||
+ | break; | ||
+ | } | ||
+ | |||
+ | phase += phaseDelta; | ||
+ | while (phase > 1.0) phase -= 1.0; | ||
+ | |||
+ | return sample; | ||
+ | } | ||
+ | </ | ||
===== Conclusion and analysis ===== | ===== Conclusion and analysis ===== | ||
- | After eliminating a few old-fashioned '' | + | A C++11 "enum class" is an excellent, type-safe replacement for " |
+ | For waveform selection in **VanillaJuce**, | ||