1 /* -----------------------------------------------------------------------------
2  *
3  * Giada - Your Hardcore Loopmachine
4  *
5  * -----------------------------------------------------------------------------
6  *
7  * Copyright (C) 2010-2020 Giovanni A. Zuliani | Monocasual
8  *
9  * This file is part of Giada - Your Hardcore Loopmachine.
10  *
11  * Giada - Your Hardcore Loopmachine is free software: you can
12  * redistribute it and/or modify it under the terms of the GNU General
13  * Public License as published by the Free Software Foundation, either
14  * version 3 of the License, or (at your option) any later version.
15  *
16  * Giada - Your Hardcore Loopmachine is distributed in the hope that it
17  * will be useful, but WITHOUT ANY WARRANTY; without even the implied
18  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19  * See the GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with Giada - Your Hardcore Loopmachine. If not, see
23  * <http://www.gnu.org/licenses/>.
24  *
25  * -------------------------------------------------------------------------- */
26 
27 
28 #ifndef G_MIXER_H
29 #define G_MIXER_H
30 
31 
32 #include <atomic>
33 #include <functional>
34 #include <vector>
35 #include "deps/rtaudio/RtAudio.h"
36 #include "core/ringBuffer.h"
37 #include "core/recorder.h"
38 #include "core/types.h"
39 #include "core/queue.h"
40 #include "core/midiEvent.h"
41 
42 
43 namespace giada {
44 namespace m
45 {
46 struct Action;
47 class Channel;
48 class AudioBuffer;
49 
50 namespace mixer
51 {
52 enum class EventType
53 {
54 	KEY_PRESS,
55 	KEY_RELEASE,
56 	KEY_KILL,
57 	SEQUENCER_FIRST_BEAT, // 3
58 	SEQUENCER_BAR,        // 4
59 	SEQUENCER_START,      // 5
60 	SEQUENCER_STOP,       // 6
61 	SEQUENCER_REWIND,     // 7
62 	SEQUENCER_REWIND_REQ, // 8
63 	MIDI,
64 	ACTION,
65 	CHANNEL_TOGGLE_READ_ACTIONS,
66 	CHANNEL_KILL_READ_ACTIONS,
67 	CHANNEL_TOGGLE_ARM,
68 	CHANNEL_MUTE,
69 	CHANNEL_SOLO,
70 	CHANNEL_VOLUME,
71 	CHANNEL_PITCH,
72 	CHANNEL_PAN
73 };
74 
75 struct Event
76 {
77 	EventType type;
78 	Frame     delta;
79 	Action    action;
80 };
81 
82 /* EventBuffer
83 Alias for a RingBuffer containing events to be sent to engine. The double size
84 is due to the presence of two distinct Queues for collecting events coming from
85 other threads. See below. */
86 
87 using EventBuffer = RingBuffer<Event, G_MAX_QUEUE_EVENTS * 2>;
88 
89 constexpr int MASTER_OUT_CHANNEL_ID = 1;
90 constexpr int MASTER_IN_CHANNEL_ID  = 2;
91 constexpr int PREVIEW_CHANNEL_ID    = 3;
92 
93 extern std::atomic<float> peakOut; // TODO - move to model::
94 extern std::atomic<float> peakIn;  // TODO - move to model::
95 
96 /* Channel Event queues
97 Collect events coming from the UI or MIDI devices to be sent to channels. Our
98 poor's man Queue is a single-producer/single-consumer one, so we need two queues
99 for two writers. TODO - let's add a multi-producer queue sooner or later! */
100 
101 extern Queue<Event, G_MAX_QUEUE_EVENTS> UIevents;
102 extern Queue<Event, G_MAX_QUEUE_EVENTS> MidiEvents;
103 
104 void init(Frame framesInSeq, Frame framesInBuffer);
105 
106 /* enable, disable
107 Toggles master callback processing. Useful when loading a new patch. Mixer
108 will flush itself to wait for a processing cycle to finish when disable() is
109 called. */
110 
111 void enable();
112 void disable();
113 
114 /* allocRecBuffer
115 Allocates new memory for the virtual input channel. Call this whenever you
116 shrink or resize the sequencer. */
117 
118 void allocRecBuffer(Frame frames);
119 
120 /* clearRecBuffer
121 Clears internal virtual channel. */
122 
123 void clearRecBuffer();
124 
125 /* getRecBuffer
126 Returns a read-only reference to the internal virtual channel. Use this to
127 merge data into channel after an input recording session. */
128 
129 const AudioBuffer& getRecBuffer();
130 
131 void close();
132 
133 /* masterPlay
134 Core method (callback) */
135 
136 int masterPlay(void* outBuf, void* inBuf, unsigned bufferSize, double streamTime,
137 	RtAudioStreamStatus status, void* userData);
138 
139 /* startInputRec, stopInputRec
140 Starts/stops input recording on frame clock::getCurrentFrame(). */
141 
142 void startInputRec();
143 void stopInputRec();
144 
145 void setSignalCallback(std::function<void()> f);
146 
147 /* pumpEvent
148 Pumps a new mixer::Event into the event vector. Use this function when you want
149 to inject a new event for the **current** block. Push the event in the two
150 queues UIevents and MIDIevents above if the event can be processed in the next
151 block instead. */
152 
153 void pumpEvent(Event e);
154 }}} // giada::m::mixer::;
155 
156 
157 #endif
158