Skip to content

Commit 2592273

Browse files
committed
sampler trigger note
1 parent 428e8cd commit 2592273

2 files changed

Lines changed: 81 additions & 25 deletions

File tree

‎Source/Node/nodes/sampler/SamplerNode.cpp‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ SamplerNode::SamplerNode(var params) :
3939

4040
oneShotFadeTimeMS = playCC.addIntParameter("One Shot Fade MS", "Fade applied to the end of a hit/one shot sample (ms)", 10, 0, 1000);
4141

42+
playNoteNumber = playCC.addIntParameter("Play Note", "Choose note to trigger", 60, 0, 127);
43+
playNoteTimeMS = playCC.addIntParameter("Play Note Time", "Duration (ms) before it sends a note off automatically. 0 means infinite until manually stopped.", 500, 0, 10000);
44+
playNoteTrigger = playCC.addTrigger("Trigger Note", "Trigger the chosen note");
45+
4246

4347
addChildControllableContainer(&playCC, false, 0);
4448

@@ -488,6 +492,33 @@ void SamplerNode::onControllableFeedbackUpdateInternal(ControllableContainer* cc
488492
{
489493
computeAutoKeys();
490494
}
495+
else if (c == playNoteTrigger)
496+
{
497+
int note = playNoteNumber->intValue();
498+
handleNoteOn(&keyboardState, 1, note, 1.0f);
499+
500+
int durationMS = playNoteTimeMS->intValue();
501+
if (durationMS > 0)
502+
{
503+
GenericScopedLock<SpinLock> lock(scheduledNoteOffsLock);
504+
int samples = durationMS * processor->getSampleRate() / 1000;
505+
// check if already scheduling this note off
506+
bool found = false;
507+
for (auto& sn : scheduledNoteOffs)
508+
{
509+
if (sn.first == note)
510+
{
511+
sn.second = samples; // update duration
512+
found = true;
513+
break;
514+
}
515+
}
516+
if (!found)
517+
{
518+
scheduledNoteOffs.add({note, samples});
519+
}
520+
}
521+
}
491522
}
492523

493524
void SamplerNode::controllableStateChanged(Controllable* c)
@@ -830,6 +861,23 @@ void SamplerNode::processBlockInternal(AudioBuffer<float>& buffer, MidiBuffer& m
830861

831862
int blockSize = buffer.getNumSamples();
832863

864+
{
865+
GenericScopedTryLock<SpinLock> lock(scheduledNoteOffsLock);
866+
if (lock.isLocked() && scheduledNoteOffs.size() > 0)
867+
{
868+
for (int i = scheduledNoteOffs.size() - 1; i >= 0; i--)
869+
{
870+
scheduledNoteOffs.getReference(i).second -= blockSize;
871+
if (scheduledNoteOffs.getReference(i).second <= 0)
872+
{
873+
int note = scheduledNoteOffs.getReference(i).first;
874+
handleNoteOff(&keyboardState, 1, note, 1.0f);
875+
scheduledNoteOffs.remove(i);
876+
}
877+
}
878+
}
879+
}
880+
833881
if (isRecording->boolValue())
834882
{
835883
GenericScopedTryLock<SpinLock> lock(recLock);

‎Source/Node/nodes/sampler/SamplerNode.h‎

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,28 @@ class SamplerNode :
3939
BoolParameter* autoKeyLoopFade;
4040
EnumParameter* autoKeyMode;
4141

42+
// --- Trigger Action ---
43+
IntParameter* playNoteNumber;
44+
Trigger* playNoteTrigger;
45+
IntParameter* playNoteTimeMS;
46+
47+
Array<std::pair<int, int>> scheduledNoteOffs; // Note number, remaining samples
48+
SpinLock scheduledNoteOffsLock;
49+
4250
// --- New RubberBand Parameters ---
4351
BoolParameter* rbPreserveFormants;
4452
EnumParameter* rbPitchMode;
4553
EnumParameter* rbTransients;
4654
EnumParameter* rbWindowSize;
4755

4856
ControllableContainer controlsCC;
49-
BoolParameter* clearMode;
50-
enum ClearMode { LAST_PLAYED, LAST_RECORDED };
51-
EnumParameter* clearLastMode;
52-
Trigger* clearLastRecordedTrigger;
53-
Trigger* clearAllNotesTrigger;
54-
EnumParameter* revertLastMode;
55-
Trigger* revertLastRecordedTrigger;
57+
BoolParameter* clearMode;
58+
enum ClearMode { LAST_PLAYED, LAST_RECORDED };
59+
EnumParameter* clearLastMode;
60+
Trigger* clearLastRecordedTrigger;
61+
Trigger* clearAllNotesTrigger;
62+
EnumParameter* revertLastMode;
63+
Trigger* revertLastRecordedTrigger;
5664
IntParameter* startAutoKey;
5765
IntParameter* endAutoKey;
5866
Trigger* computeAutoKeysTrigger;
@@ -130,10 +138,10 @@ class SamplerNode :
130138
float oldFadeStartGain = 0.0f;
131139

132140

133-
AudioSampleBuffer buffer;
134-
135-
//offline pitching
136-
double shifting = 0;
141+
AudioSampleBuffer buffer;
142+
143+
//offline pitching
144+
double shifting = 0;
137145
int fadeNumSamples = 0;
138146
int autoKeyAlgorithm = 0;
139147
bool loopFadeEnabled = false;
@@ -155,20 +163,20 @@ class SamplerNode :
155163
void setAutoKey(SamplerNote* remoteNote, double shift = 0);
156164
void computeAutoKey(SamplerNote* remoteNote, double shift, int fadeSamples, int algorithm, bool formants, int transients, int pitchMode, int windowSize, bool shouldLoopFade);
157165

158-
void run();
159-
160-
void reset();
161-
162-
bool hasContent() const { return buffer.getNumSamples() > 0; }
163-
bool isProxyNote() const { return autoKeyFromNote != nullptr; }
164-
};
165-
166-
OwnedArray<SamplerNote> samplerNotes;
167-
168-
void revertNote(int note);
169-
void clearNote(int note);
170-
void clearAllNotes();
171-
void resetAllNotes();
166+
void run();
167+
168+
void reset();
169+
170+
bool hasContent() const { return buffer.getNumSamples() > 0; }
171+
bool isProxyNote() const { return autoKeyFromNote != nullptr; }
172+
};
173+
174+
OwnedArray<SamplerNote> samplerNotes;
175+
176+
void clearNote(int note);
177+
void revertNote(int note);
178+
void clearAllNotes();
179+
void resetAllNotes();
172180

173181
void computeAutoKeys();
174182

0 commit comments

Comments
 (0)