2 #ifndef AL_SYNTHSEQUENCER_HPP
3 #define AL_SYNTHSEQUENCER_HPP
57 #include "al/graphics/al_Graphics.hpp"
58 #include "al/io/al_AudioIOData.hpp"
59 #include "al/io/al_File.hpp"
60 #include "al/scene/al_PolySynth.hpp"
61 #include "al/ui/al_Parameter.hpp"
75 typedef enum { EVENT_VOICE, EVENT_PFIELDS, EVENT_TEMPO } EventType;
81 EventType type{EVENT_VOICE};
85 std::vector<ParameterField> pFields;
94 enum SynthEventType { TRIGGER_ON, TRIGGER_OFF, PARAMETER_CHANGE };
97 std::string synthName;
100 double duration = -1;
101 std::vector<ParameterField> pFields;
178 SynthSequencer(TimeMasterMode masterMode = TimeMasterMode::TIME_MASTER_CPU) {
179 mMasterMode = masterMode;
180 mInternalSynth = std::make_unique<PolySynth>(masterMode);
181 registerSynth(*mInternalSynth.get());
199 void update(
double dt);
218 template <
class TSynthVoice>
219 TSynthVoice &
add(
double startTime,
double duration = -1);
224 template <
class TSynthVoice>
225 void addVoice(TSynthVoice *voice,
double startTime,
double duration = -1);
231 template <
class TSynthVoice>
233 double duration = -1);
249 bool playing() {
return mPlaying; }
251 bool verbose() {
return mVerbose; }
252 void verbose(
bool verbose) { mVerbose = verbose; }
254 void setTempo(
float tempo) { mNormalizedTempo = tempo / 60.; }
256 bool playSequence(std::string sequenceName =
"",
float startTime = 0.0f);
259 void setTime(
float newTime);
261 void setDirectory(std::string directory);
263 std::string buildFullPath(std::string sequenceName);
265 std::list<SynthSequencerEvent> loadSequence(std::string sequenceName,
266 double timeOffset = 0,
267 double timeScale = 1.0);
273 double timeOffset = 0.1);
275 std::vector<std::string> getSequenceList();
277 double getSequenceDuration(std::string sequenceName);
279 PolySynth &synth() {
return *mPolySynth; }
282 void registerTimeChangeCallback(std::function<
void(
float)> func,
283 float minTimeDeltaSec = 0);
285 void registerSequenceBeginCallback(std::function<
void(std::string)> func);
300 void operator<<(
PolySynth &synth) {
return registerSynth(synth); }
304 std::unique_ptr<PolySynth> mInternalSynth;
306 std::string mDirectory{
"."};
307 bool mVerbose{
false};
308 std::string mLastSequencePlayed;
312 unsigned int mNextEvent{0};
313 std::list<SynthSequencerEvent>
315 std::mutex mEventLock;
316 std::mutex mLoadingLock;
317 bool mPlaying{
false};
319 TimeMasterMode mMasterMode{TimeMasterMode::TIME_MASTER_AUDIO};
320 double mMasterTime{0.0};
321 double mPlaybackStartTime{0.0};
323 double mNormalizedTempo{1.0};
327 std::vector<std::pair<std::function<void(
float)>,
float>>
328 mTimeChangeCallbacks;
330 std::vector<double> mTimeAccumCallbackNs;
333 std::vector<std::function<void(std::string sequenceName)>>
334 mSequenceBeginCallbacks;
335 std::vector<std::function<void(std::string sequenceName)>>
336 mSequenceEndCallbacks;
339 std::shared_ptr<std::thread> mCpuThread;
341 void processEvents(
double blockStartTime,
double fps);
346 template <
class TSynthVoice>
348 TSynthVoice *newVoice = mPolySynth->
getVoice<TSynthVoice>();
350 addVoice<TSynthVoice>(newVoice, startTime, duration);
355 template <
class TSynthVoice>
358 std::list<SynthSequencerEvent>::iterator insertedEvent;
359 std::unique_lock<std::mutex> lk(mEventLock);
361 auto position = mEvents.begin();
362 while (position != mEvents.end() && position->startTime < startTime) {
366 insertedEvent->startTime = startTime;
367 insertedEvent->duration = duration;
368 insertedEvent->voice = voice;
371 template <
class TSynthVoice>
374 float triggerOffset = 0.05;
375 addVoice(voice, mMasterTime + startTime + triggerOffset, duration);
void * user() const
Get pointer to user data.
Interface for loading fonts and rendering text.
A PolySynth manages polyphony and rendering of SynthVoice instances.
TSynthVoice * getVoice(bool forceAlloc=false)
Get a reference to a voice.
SynthSequencerEvent class.
Event Sequencer triggering audio visual "notes".
void setGraphicsFrameRate(float fps)
void addVoice(TSynthVoice *voice, double startTime, double duration=-1)
void playEvents(std::list< SynthSequencerEvent > events, double timeOffset=0.1)
play the event list provided all other events in list are discarded
void render(AudioIOData &io)
Insert this function within the audio callback.
void render(Graphics &g)
Insert this function within the graphics callback.
void registerSequenceEndCallback(std::function< void(std::string)> func)
registerSequenceEndCallback
TSynthVoice & add(double startTime, double duration=-1)
insert an event in the sequencer
static void audioCB(AudioIOData &io)
Basic audio callback for quick prototyping.
void addVoiceFromNow(TSynthVoice *voice, double startTime, double duration=-1)
void print()
print current sequence