1
Midi, Audio and Synchronization:
2
================================
6
3. Midi synchronization
7
4. Audio timestamping and synchronization
14
Since aRts-1.0 (as shipped with KDE3.0), aRts provides a lot more
15
infrastructure to deal with midi, audio, and their synchronization. The main
16
goal is to provide a unified interface between sequencers (or other programs
17
that require notes or audio tracks to be played at certain given time stamps)
18
and underlying software/hardware that can play notes/audio tracks.
20
Currently, there exist five distinct destinations that aRts supports, which
21
can all be used at the same time or individually, that is:
23
* aRts synthetic midi instruments
27
* other aRts modules (including but not limited to the playback/recording
33
The midi manager is the basic component that connects between applications
34
that supply/record midi data, and devices that process midi data. Devices
35
might be both, virtual (as in software synthesis) or real (as in hardware
38
From the view of the midi manager, all event streams correspond to one midi
39
client. So, a midi client might be an application (such as a sequencer) that
40
provides events, or an ALSA hardware device that consumes events. If there
41
are multiple event streams, they correspond to multiple clients. That is,
42
if an application wishes to play three different midi tracks, one over ALSA,
43
and two over two different synthetic instruments, it needs to register itself
44
three times, with three different clients.
46
The midi managers job is to connect midi clients (as in event streams). It
47
maintains a list of connections that the user can modify with an application
48
like artscontrol. Applications could also, if they wish so, modify this
51
As a use case, we'll consider the following: you want to write a sequencer
52
application that plays back two different tracks to two different devices.
53
You want the user to be able to select these devices in a drop down box for
56
1) getting a list of choices:
58
First, you will want to obtain a list of choices which the user could possibly
59
connect your tracks to. You do so by reading the
61
interface MidiManager { // SINGLETON: Arts_MidiManager
65
readonly attribute sequence<MidiClientInfo> clients;
70
attribute. The three fields of each client that are interesting for you are
72
struct MidiClientInfo {
77
MidiClientDirection direction;
82
You would list those devices in the dropdown box that are of the appropriate
83
direction, which is mcdRecord, as you would want a client that receives midi
84
events (this might be confusing, but you look from the view of the client).
86
Then, there is the type field, which tells you whether the client is a device-
87
like thing (like a synthetic instrument), or another application (like another
88
application currently recording a track). While it might not be an impossible
89
setup that you send events between two applications, usually users will choose
90
such clients that have mctDestination as type.
92
Finally, you can list the titles in a drop down box, and keep the ID for making
95
2) registering clients:
97
You will need to register one client for each track. Use
102
* this creates a new MidiManagerClient
104
MidiClient addClient(MidiClientDirection direction, MidiClientType type,
105
string title, string autoRestoreID);
111
As you probably don't want your sequencer user to use artscontrol to setup
112
connections between your tracks and the devices, you will need to connect
113
your clients to the hardware devices for playing something.
115
You can connect clients to their appropriate destinations using
118
* connect two clients
120
void connect(long clientID, long destinationID);
125
* disconnect two clients
127
void disconnect(long clientID, long destinationID);
129
Keep in mind that a client might be connected to more than one destination
130
at the same time, so that you will need to disconnect the old destination
131
before connecting the new one.
135
You can now play events to the tracks, using each client's
137
MidiPort addOutputPort();
139
function for getting a port where you can send events to. However, you will
140
also need to ensure that the events will get synchronized as soon as you are
141
playing back events to different devices. Read the next section for details
144
3. Midi synchronization
145
-----------------------
147
As soon as you are writing a real sequencer, you might want to output to more
148
than one midi device at a time. For instance, you might want to let some of
149
your midi events be played by aRts synthesis, while others should be sent
150
over the external midi port.
152
To support this setup, a new interface called MidiSyncGroup has been added. To
153
output midi events synchronized over more than one port, you proceed as follows:
155
a) you obtain a reference to the midi manager object
157
MidiManager midiManager = DynamicCast(Reference("global:Arts_MidiManager"));
158
if(midiManager.isNull()) arts_fatal("midimanager is null");
160
b) you create a midi synchronization group which will ensure that the
161
timestamps of your midi events will be synchronized
163
MidiSyncGroup syncGroup = midiManager.addSyncGroup();
165
c) you add a client to the midi manager for each port you want to output
168
MidiClient client = midiManager.addClient(mcdPlay, mctApplication, "midisynctest", "midisynctest");
169
MidiClient client2 = midiManager.addClient(mcdPlay, mctApplication, "midisynctest2", "midisynctest2");
171
d) you insert the clients in the synchronization group
173
syncGroup.addClient(client);
174
syncGroup.addClient(client2);
176
e) you create ports for each client as usual
178
MidiPort port = client.addOutputPort();
179
MidiPort port2 = client2.addOutputPort();
181
f) at this point, you will need to ensure that the midi clients you created
182
are connected, you can either leave the user with artscontrol for doing
183
this, or use the clients and connect methods of the midiManager object
184
yourself (see use case discussed in previous section)
186
g) you output events over the ports as usual
188
/* where t is a suitable TimeStamp */
189
MidiEvent e = MidiEvent(t,MidiCommand(mcsNoteOn|0, notes[np], 100));
190
port.processEvent(e);
191
port2.processEvent(e);
193
4. Audio timestamping and synchronization
194
-----------------------------------------
196
Audio in aRts is usually handled as structures consisting of small modules
197
that do something. While this model allows you to describe anything you want
198
to, from playing a sample to playing a synthetic sequence of notes with a
199
synthetic instruments, it doesn't give you any notion of time. More so, if
200
you build a large graph of objects, you might need quite some time for this,
201
and you will want to have them all started at the same time.
203
To solve this issue, an AudioSync interface has been introduced, that allows
204
you to start() and stop() either synchronized at a specific point in time.
206
Suppose you have two synthesis modules which together play back a sample.
207
What can you do to start them at the same time?
209
Synth_PLAY_WAV wav = //... create on server
210
Synth_AMAN_PLAY sap //... create on server
211
AudioSync audioSync = //... create on server
213
wav.filename("/opt/kde3/share/sounds/pop.wav");
214
sap.title("midisynctest2");
215
sap.autoRestoreID("midisynctest2");
218
// this queues back start() to be called atomically later
219
audioSync.queueStart(wav);
220
audioSync.queueStart(sap);
222
// this line is a synchronized version of
227
You could also play them back at a specific time in the future and query the
228
current time using the time and executeAt methods:
230
interface AudioSync {
234
readonly attribute TimeStamp time;
239
* atomically executes all queued modifications to the flow system
242
void executeAt(TimeStamp timeStamp);
245
Finally, to get synchronized midi and audio, you can insert the AudioSync
246
object into a midi synchronization group, then their timestamps will be
247
synchronized to those of the midi channels.
252
An example that illustrates most things discussed in this document is
253
midisynctest.cc, which plays back two synchronized midi streams and samples.
254
Note that you might want to change the source code, as it hardcodes the
255
location of the .wav file.
258
Questions and comments are welcome.