File: chap5.xml

package info (click to toggle)
gsequencer 7.7.5-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 71,040 kB
  • sloc: ansic: 1,145,949; xml: 31,016; cpp: 9,487; sh: 5,798; makefile: 3,845; perl: 155; sed: 16; python: 11
file content (374 lines) | stat: -rw-r--r-- 13,894 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE chapter>

<!-- Copyright (C) 2005-2018 Jo\u00EBl Kr\u00E4hemann -->
<!-- Permission is granted to copy, distribute and/or modify this document -->
<!-- under the terms of the GNU Free Documentation License, Version 1.3 -->
<!-- or any later version published by the Free Software Foundation; -->
<!-- with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. -->
<!-- A copy of the license is included in the section entitled "GNU -->
<!-- Free Documentation License". -->

<chapter xmlns="http://docbook.org/ns/docbook"
	 xmlns:xi="http://www.w3.org/2001/XInclude" version="5.0">
  <title>AgsAudio a container of AgsChannel</title>
  <para>
    AgsAudio contains a pointer to your notation and automation data. It has its
    own recall context, AgsRecallAudio. It organizes your recycling contices and
    thus having an associated AgsRecallID for running contices. Further AgsAudio
    is your topmost nesting level of AgsAudioSignal. You might traverse the layers
    in following order:
  </para>

  <orderedlist numeration="lowerroman">
    <listitem>
      AgsAudio
    </listitem>
    <listitem>
      AgsChannel
    </listitem>
    <listitem>
      AgsRecycling
    </listitem>
    <listitem>
      AgsAudioSignal
    </listitem>
  </orderedlist>

  <para>
    In order the audio processing threads are capable to iterate the audio tree, you
    need to set either (AGS_AUDIO_SYNC) or (AGS_AUDIO_SYNC | AGS_AUDIO_ASYNC)
    flags. Further if your AgsAudio is a source of AgsAudioSignal you need to set
    both flags (AGS_AUDIO_OUTPUT_HAS_RECYCLING | AGS_AUDIO_INPUT_HAS_RECYCLING).
  </para>

  <para>
    If you set AGS_AUDIO_SYNC flag, this causes the output and input channels to be aligned
    straight. Eg. input line 0 goes to output line 0, input line 1 goes to output line 1 ...
  </para>

  <para>
    If you set both flags AGS_AUDIO_SYNC and AGS_AUDIO_ASYNC, output and input is
    not aligned straight. Eg. you have 2 audio channels, 1 output pad and 8 input pads, then
    input line 0 goes to output line 0, input line 1 goes to output line 1, input line 3 goes to
    output line 0 ...
  </para>

  <para>
    It is only possible to have mulitple output pads if you have AgsRecycling assigned to
    AgsOutput of AgsAudio. This is usually done by sources like instruments.
  </para>
  
  <para>
    AgsAudioSignal keeps your audio data as a GList of buffers. AgsRecycling is your
    nested tree to AgsChannel, giving you the opportunity to emit ::add_audio_signal
    or ::remove_audio_signal by producer and to have many consumers. AgsChannel is your
    opposite to an audio channel representing a single line. AgsAudio keeps track of
    all of them. You might want to add your audio object to an AgsSoundcard.
  </para>

  <para>
    You may resize the count of pads or audio channels with <code language="C">void ags_audio_set_pads(AgsAudio*, GType, guint, guint)</code>
    and <code language="C">void ags_audio_set_audio_channels(AgsAudio*, guint, guint)</code>. Like in the following example the channels are
    adjusted and notation is added.
  </para>

  <example>
    <title>Using AgsAudio</title>
    <programlisting language="C">
<xi:include href="../listings/audio.c" parse="text" />
    </programlisting>
  </example>

  <sect1>
    <title>AgsNotation and AgsNote</title>
    <para>
      AgsAudio provides many AgsNotation objects for one single audio channel. They all have a different :timestamp property. Usually a new
      AgsNotation object is introduced as AGS_NOTATION_DEFAULT_OFFSET is exceeded. So AgsNotation can hold at most 1024 x-positions of AgsNote.
    </para>

    <para>
      You might want to query a GList of AgsNotation by the matching AgsTimestamp using AGS_TIMESTAMP_OFFSET.
    </para>

    <itemizedlist mark="bullet">
      <listitem>
	<code language="C">void ags_notation_find_near_timestamp(GList*, guint, AgsTimestamp*)</code>
      </listitem>
    </itemizedlist>
        
    <para>
      The notation object stores your notes as a GList. You can add or remove a note
      by calling appropriate function:
    </para>

    <itemizedlist mark="bullet">
      <listitem>
	<code language="C">void ags_notation_add_note(AgsNotation*, AgsNote*, gboolean)</code>
      </listitem>
      <listitem>
	<code language="C">gboolean ags_notation_remove_note_at_position(AgsNotation, guint, guint)</code>
      </listitem>
    </itemizedlist>
    
    <para>
      The notation object supports selection of notes. There are functions available
      to select a single point or a region of the notation. You may find specific
      notes by calling:
    </para>

    <itemizedlist mark="bullet">
      <listitem>
	<code language="C">AgsNote* ags_notation_find_point(AgsNotation*, guint, guint, gboolean)</code>
      </listitem>
      <listitem>
	<code language="C">GList* ags_notation_find_region(AgsNotation*, guint, guint, guint, guint, gboolean)</code>
      </listitem>
    </itemizedlist>

    <para>
      To copy &amp; paste notes you might want to select a region first. Then copy the selection and insert it using new x_offset later.
    </para>

  <example>
    <title>Using AgsNotation Clipboard</title>
    <programlisting language="C">
<xi:include href="../listings/notation_clipboard.c" parse="text" />
    </programlisting>
  </example>
    
  </sect1>

  <sect1>
    <title>AgsAutomation and AgsAcceleration</title>
    <para>
      The automation objects stores your accelerations as a GList. There are analogous
      to notation functions to add or remove accelerations.
    </para>
    
    <itemizedlist mark="bullet">
      <listitem>
	<code language="C">void ags_automation_add_acceleration(AgsAutomation*, AgsAcceleration*, gboolean)</code>
      </listitem>
      <listitem>
	<code language="C">gboolean ags_automation_remove_acceleration_at_position(AgsAutomation*, guint, gdouble)</code>
      </listitem>
    </itemizedlist>

    <para>
      The automation object provides functions to lookup a specific point or region, too.
    </para>

    <itemizedlist mark="bullet">
      <listitem>
	<code language="C">AgsAcceleration* ags_automation_find_point(AgsAutomation*, guint, gdouble, gboolean)</code>
      </listitem>
      <listitem>
	<code language="C">GList* ags_automation_find_region(AgsAutomation*, guint, gdouble, guint, gdouble, gboolean)</code>
      </listitem>
    </itemizedlist>
  </sect1>

  <sect1>
    <title>AgsWave and AgsBuffer</title>
    <para>
      The wave objects stores your buffers as a GList. There are analogous
      to notation functions to add or remove buffers.
    </para>
    
    <itemizedlist mark="bullet">
      <listitem>
	<code language="C">void ags_wave_add_buffer(AgsWave*, AgsBuffer*, gboolean)</code>
      </listitem>
      <listitem>
	<code language="C">gboolean ags_wave_remove_buffer(AgsWave*, AgsBuffer*, gboolean)</code>
      </listitem>
    </itemizedlist>

    <para>
      AgsAudio holds a sorted list of AgsWave objects, <code language="C">gint ags_wave_sort_func(gconstpointer, gconstpointer)</code>
      does the actual sorting. You can use it with <code language="C">GList* g_list_insert_sorted(GList*, gpointer, GCompareFunc)</code>.
    </para>

    <para>
      AgsWave holds a sorted list of AgsBuffer objects, <code language="C">gint ags_buffer_sort_func (gconstpointer, gconstpointer)</code>
      does the actual sorting. You can use it with <code language="C">GList* g_list_insert_sorted(GList*, gpointer, GCompareFunc)</code>.
      AgsWave:timestamp uses sample position with matching samplerate. As using
      <code language="C">void ags_timestamp_set_ags_offset (AgsTimestamp*, guint64)</code> ags_offset equals 0
      is your very first sample. You have to introduce after <code language="C">AGS_WAVE_DEFAULT_BUFFER_LENGTH * samplerate</code> samples
      a new AgsWave object. The actual playback recall does bisect AgsWave and AgsBuffer in order to get current playing audio data.
    </para>

    <para>
      AgsBuffer:data contains your actual audio data of AgsBuffer:format type. AgsBuffer:x is the actual
      sample position with matching samplerate.
    </para>

    <para>
      Note audio effects are not applied to AgsWave but to AgsAudioSignal. The program flow is as following:
    </para>

    <orderedlist numeration="arabic">
      <listitem>
	ags-fx-playback does feed AgsWave to AgsAudioSignal of AgsInput.
      </listitem>
      <listitem>
	ags-fx-buffer does buffer AgsAudioSignal from AgsInput to AgsOutput.
      </listitem>
      <listitem>
	Another AgsAudio containing ags-fx-playback, then it plays it on your soundcard. Assumed you prior linked
	the the audio tree.
      </listitem>
    </orderedlist>

    <para>
      In this example, we first read audio data from 2 different files and concat the returned AgsWave objects. Note
      if you want to read multi-channel data, you have to modify the example with a for loop or such, to copy overlapping
      AgsBuffer. AgsBuffer:x shall be unique for specific audio channel.
    </para>

    <example>
    <title>Concat AgsWave</title>
    <programlisting language="C">
<xi:include href="../listings/wave_concat.c" parse="text" />
    </programlisting>
  </example>
    
  </sect1>
  
  <sect1>
    <title>AgsRecallID and AgsRecyclingContext</title>
    <para>
      As mentioned previously in this chapter AgsAudio organizes your recall ids and
      recycling contices. The following functions are here to add and remove them.
    </para>
    
    <itemizedlist mark="bullet">
      <listitem>
	<code language="C">void ags_audio_add_recall_id(AgsAudio*, GObject*)</code>
      </listitem>
      <listitem>
	<code language="C">void ags_audio_remove_recall_id(AgsAudio*, GObject*)</code>
      </listitem>
      <listitem>
	<code language="C">void ags_audio_add_recycling_context(AgsAudio*, GObject*)</code>
      </listitem>
      <listitem>
	<code language="C">void ags_audio_remove_recycling_context(AgsAudio*, GObject*)</code>
      </listitem>
    </itemizedlist>
  </sect1>

  <sect1>
    <title>Dealing with recalls</title>
    <para>
      Since AgsAudio is your entry point to do sound processing there are some useful
      functions to set it up, but later on them. Instances of AgsRecallAudio base object
      may be added or removed with <code language="C">void ags_audio_add_recall(AgsAudio*, GObject*, gboolean)</code>
      and <code language="C">void ags_audio_remove_recall(AgsAudio*, GObject*, gboolean)</code>.
    </para>
    
    <para>
      All audio processing is performed by one single function. Wheter you want to initialize, run or cancel playback.
      This is all done by <code language="C">void ags_channel_recursive_run_stage(AgsChannel*, gint, guint)</code>.
    </para>

    <para>
      The following signals are triggered during playback ::play, ::tact and ::done - 
      ::cancel and ::remove during termination.
    </para>

    <sect2>
      <title>Get port of recall</title>
      <para>
	Ports are accessed as <code language="C">GList*</code> from recall by accessing AgsRecall:port property.
      </para>

      <para>
	Below an example shows howto instantiate an application context implementation, obtain it by its generic function
	<code language="C">ags_application_context_get_instance()</code> and create an audio object with ags-fx recalls.
      </para>

      <para>
	The recalls port &quot;./volume[0]&quot; is modified by <code language="C">ags_port_safe_write(AgsPort*, GValue*)</code>.
      </para>

      <example>
	<title>Modify recall port</title>
	<programlisting language="C">
<xi:include href="../listings/find_port.c" parse="text" />
	</programlisting>
      </example>
    </sect2>
  </sect1>

  <sect1>
    <title>Open audio files</title>
    <para>
      There is a handy function called <code language="C">void ags_audio_open_files(AgsAudio*, GSList*, gboolean, gboolean)</code>
      taking as parameter filenames as GSList, overwrite_channels and create_channels as boolean. Filenames is a single
      linked list of strings, overwrite_channels means use pre-allocated channels and
      create_channels to allow instantiate new channels. The boolean parameters can be combined
      as you want.
    </para>
    
    <sect2>
      <title>Audio container</title>
      <para>
	The AgsAudioContainer object can open Soundfont2, Gig and DLS2 files by using libinstpatch. The AgsAudioContainer:sound-container
	field implements AgsSoundContainer and provides you many functions to dealing with container formats.
      </para>

      <para>
	There are convenient functions to obtain a GObject subtype implementing AgsSoundResource:
      </para>

      <itemizedlist>
	<listitem>
	  GList* ags_sound_container_get_resource_all()
	</listitem>
	<listitem>
	  GList* ags_sound_container_get_resource_by_name()
	</listitem>
	<listitem>
	  GList* ags_sound_container_get_resource_by_index()
	</listitem>
	<listitem>
	  GList* ags_sound_container_get_resource_current()
	</listitem>
      </itemizedlist>
    </sect2>

    <sect2>
      <title>Audio file</title>
      <para>
	The AgsAudioFile object can open FLAC, WAV, AIFF and OGG using libsndfile. The AgsAudioFile:sound-resource
	field implements AgsSoundResource and provides you many functions to dealing with audio file formats.
      </para>

      <itemizedlist>
	<listitem>
	  void ags_sound_resource_info()
	</listitem>
	<listitem>
	  void ags_sound_resource_set_presets()
	</listitem>
	<listitem>
	  void ags_sound_resource_get_presets()
	</listitem>
	<listitem>
	  guint ags_sound_resource_read()
	</listitem>
	<listitem>
	  void ags_sound_resource_write()
	</listitem>
	<listitem>
	  void ags_sound_resource_flush()
	</listitem>
	<listitem>
	  void ags_sound_resource_seek()
	</listitem>
      </itemizedlist>
    </sect2>
  </sect1>
</chapter>