LMMS
Loading...
Searching...
No Matches
SFZSynth.cpp
Go to the documentation of this file.
1/*************************************************************************************
2 * Original code copyright (C) 2012 Steve Folta
3 * Converted to Juce module (C) 2016 Leo Olivers
4 * Forked from https://github.com/stevefolta/SFZero
5 * For license info please see the LICENSE file distributed with this source code
6 *************************************************************************************/
7
8#include "SFZSynth.h"
9#include "SFZSound.h"
10#include "SFZVoice.h"
11
12namespace sfzero
13{
14
16{
17 carla_zeroStructs(noteVelocities_, 128);
18}
19
20void Synth::noteOn(int midiChannel, int midiNoteNumber, float velocity)
21{
22 int i;
23
24 int midiVelocity = static_cast<int>(velocity * 127);
25
26 // First, stop any currently-playing sounds in the group.
27 //*** Currently, this only pays attention to the first matching region.
28 int group = 0;
29 Sound *sound = dynamic_cast<Sound *>(getSound(0));
30
31 if (sound)
32 {
33 Region *region = sound->getRegionFor(midiNoteNumber, midiVelocity);
34 if (region)
35 {
36 group = region->group;
37 }
38 }
39 if (group != 0)
40 {
41 for (i = voices.size(); --i >= 0;)
42 {
43 Voice *voice = dynamic_cast<Voice *>(voices.getUnchecked(i));
44 if (voice == nullptr)
45 {
46 continue;
47 }
48 if (voice->getGroup() == group)
49 {
50 voice->stopNoteForGroup();
51 }
52 }
53 }
54
55 // Are any notes playing? (Needed for first/legato trigger handling.)
56 // Also stop any voices still playing this note.
57 bool anyNotesPlaying = false;
58 for (i = voices.size(); --i >= 0;)
59 {
60 Voice *voice = dynamic_cast<Voice *>(voices.getUnchecked(i));
61 if (voice == nullptr)
62 {
63 continue;
64 }
65 if (voice->isPlayingChannel(midiChannel))
66 {
67 if (voice->isPlayingNoteDown())
68 {
69 if (voice->getCurrentlyPlayingNote() == midiNoteNumber)
70 {
71 if (!voice->isPlayingOneShot())
72 {
73 voice->stopNoteQuick();
74 }
75 }
76 else
77 {
78 anyNotesPlaying = true;
79 }
80 }
81 }
82 }
83
84 // Play *all* matching regions.
85 Region::Trigger trigger = (anyNotesPlaying ? Region::legato : Region::first);
86 if (sound)
87 {
88 int numRegions = sound->getNumRegions();
89 for (i = 0; i < numRegions; ++i)
90 {
91 Region *region = sound->regionAt(i);
92 if (region->matches(midiNoteNumber, midiVelocity, trigger))
93 {
94 Voice *voice =
95 dynamic_cast<Voice *>(findFreeVoice(sound, midiNoteNumber, midiChannel, isNoteStealingEnabled()));
96 if (voice)
97 {
98 voice->setRegion(region);
99 startVoice(voice, sound, midiChannel, midiNoteNumber, velocity);
100 }
101 }
102 }
103 }
104
105 noteVelocities_[midiNoteNumber] = midiVelocity;
106}
107
108void Synth::noteOff(int midiChannel, int midiNoteNumber, float velocity, bool allowTailOff)
109{
110 Synthesiser::noteOff(midiChannel, midiNoteNumber, velocity, allowTailOff);
111
112 // Start release region.
113 Sound *sound = dynamic_cast<Sound *>(getSound(0));
114 if (sound)
115 {
116 Region *region = sound->getRegionFor(midiNoteNumber, noteVelocities_[midiNoteNumber], Region::release);
117 if (region)
118 {
119 Voice *voice = dynamic_cast<Voice *>(findFreeVoice(sound, midiNoteNumber, midiChannel, false));
120 if (voice)
121 {
122 // Synthesiser is too locked-down (ivars are private rt protected), so
123 // we have to use a "setRegion()" mechanism.
124 voice->setRegion(region);
125 startVoice(voice, sound, midiChannel, midiNoteNumber, noteVelocities_[midiNoteNumber] / 127.0f);
126 }
127 }
128 }
129}
130
132{
133 int numUsed = 0;
134
135 for (int i = voices.size(); --i >= 0;)
136 {
137 if (voices.getUnchecked(i)->getCurrentlyPlayingNote() >= 0)
138 {
139 numUsed += 1;
140 }
141 }
142
143 return numUsed;
144}
145
147{
148 enum
149 {
150 maxShownVoices = 20,
151 };
152
153 water::StringArray lines;
154 int numUsed = 0, numShown = 0;
155
156 for (int i = voices.size(); --i >= 0;)
157 {
158 Voice *voice = dynamic_cast<Voice *>(voices.getUnchecked(i));
159 if (voice->getCurrentlyPlayingNote() < 0)
160 {
161 continue;
162 }
163 numUsed += 1;
164 if (numShown >= maxShownVoices)
165 {
166 continue;
167 }
168 lines.add(voice->infoString());
169 }
170
171 lines.insert(0, "voices used: " + water::String(numUsed));
172 return lines.joinIntoString("\n");
173}
174
175}
Definition SFZSound.h:22
Region * regionAt(int index)
Definition SFZSound.cpp:121
int getNumRegions()
Definition SFZSound.cpp:119
Region * getRegionFor(int note, int velocity, Region::Trigger trigger=Region::attack)
Definition SFZSound.cpp:103
water::String voiceInfoString()
Definition SFZSynth.cpp:146
void noteOn(int midiChannel, int midiNoteNumber, float velocity) override
Definition SFZSynth.cpp:20
void noteOff(int midiChannel, int midiNoteNumber, float velocity, bool allowTailOff) override
Definition SFZSynth.cpp:108
int numVoicesUsed()
Definition SFZSynth.cpp:131
int noteVelocities_[128]
Definition SFZSynth.h:31
Synth()
Definition SFZSynth.cpp:15
Definition SFZVoice.h:21
bool isPlayingNoteDown()
Definition SFZVoice.cpp:271
bool isPlayingOneShot()
Definition SFZVoice.cpp:273
void setRegion(Region *nextRegion)
Definition SFZVoice.cpp:279
water::String infoString()
Definition SFZVoice.cpp:281
void stopNoteForGroup()
Definition SFZVoice.cpp:141
void stopNoteQuick()
Definition SFZVoice.cpp:153
int getGroup()
Definition SFZVoice.cpp:275
Definition StringArray.h:41
bool add(const String &stringToAdd)
Definition StringArray.cpp:108
bool insert(int index, const String &stringToAdd)
Definition StringArray.cpp:113
String joinIntoString(StringRef separatorString, int startIndex=0, int numberOfElements=-1) const
Definition StringArray.cpp:270
Definition String.h:48
bool isNoteStealingEnabled() const noexcept
Definition Synthesiser.h:364
SynthesiserSound * getSound(int index) const noexcept
Definition Synthesiser.h:340
Synthesiser()
Definition Synthesiser.cpp:86
virtual SynthesiserVoice * findFreeVoice(SynthesiserSound *soundToPlay, int midiChannel, int midiNoteNumber, bool stealIfNoneAvailable) const
Definition Synthesiser.cpp:504
void startVoice(SynthesiserVoice *voice, SynthesiserSound *sound, int midiChannel, int midiNoteNumber, float velocity)
Definition Synthesiser.cpp:300
OwnedArray< SynthesiserVoice > voices
Definition Synthesiser.h:558
int getCurrentlyPlayingNote() const noexcept
Definition Synthesiser.h:109
virtual bool isPlayingChannel(int midiChannel) const
Definition Synthesiser.cpp:54
register unsigned i
Definition inflate.c:1575
Definition SFZDebug.cpp:11
Definition SFZRegion.h:30
int group
Definition SFZRegion.h:68
bool matches(int note, int velocity, Trigger trig)
Definition SFZRegion.h:58
Trigger
Definition SFZRegion.h:32
@ legato
Definition SFZRegion.h:36
@ release
Definition SFZRegion.h:34
@ first
Definition SFZRegion.h:35