# AgsAudio a container of AgsChannel

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:

1. AgsAudio
2. AgsChannel
3. AgsRecycling
4. AgsAudioSignal

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).

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 ...

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 ...

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.

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.

You may resize the count of pads or audio channels with `void ags_audio_set_pads(AgsAudio*, GType, guint, guint)` and `void ags_audio_set_audio_channels(AgsAudio*, guint, guint)`. Like in the following example the channels are adjusted and notation is added.

## Using AgsAudio

## AgsNotation and AgsNote

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.

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

- `void ags_notation_find_near_timestamp(GList*, guint, AgsTimestamp*)`

The notation object stores your notes as a GList. You can add or remove a note by calling appropriate function:

- `void ags_notation_add_note(AgsNotation*, AgsNote*, gboolean)`
- `gboolean ags_notation_remove_note_at_position(AgsNotation, guint, guint)`

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:

- `AgsNote* ags_notation_find_point(AgsNotation*, guint, guint, gboolean)`
- `GList* ags_notation_find_region(AgsNotation*, guint, guint, guint, guint, gboolean)`

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

### Using AgsNotation Clipboard

## AgsAutomation and AgsAcceleration

The automation objects stores your accelerations as a GList. There are analogous to notation functions to add or remove accelerations.

- `void ags_automation_add_acceleration(AgsAutomation*, AgsAcceleration*, gboolean)`
- `gboolean ags_automation_remove_acceleration_at_position(AgsAutomation*, guint, gdouble)`

The automation object provides functions to lookup a specific point or region, too.

- `AgsAcceleration* ags_automation_find_point(AgsAutomation*, guint, gdouble, gboolean)`
- `GList* ags_automation_find_region(AgsAutomation*, guint, gdouble, guint, gdouble, gboolean)`

## AgsWave and AgsBuffer

The wave objects stores your buffers as a GList. There are analogous to notation functions to add or remove buffers.

- `void ags_wave_add_buffer(AgsWave*, AgsBuffer*, gboolean)`
- `gboolean ags_wave_remove_buffer(AgsWave*, AgsBuffer*, gboolean)`

AgsAudio holds a sorted list of AgsWave objects, `gint ags_wave_sort_func(gconstpointer, gconstpointer)` does the actual sorting. You can use it with `GList* g_list_insert_sorted(GList*, gpointer, GCompareFunc)`.

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

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

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

1. ags-fx-playback does feed AgsWave to AgsAudioSignal of AgsInput.
2. ags-fx-buffer does buffer AgsAudioSignal from AgsInput to AgsOutput.
3. Another AgsAudio containing ags-fx-playback, then it plays it on your soundcard. Assumed you prior linked the the audio tree.

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.

### Concat AgsWave

## AgsRecallID and AgsRecyclingContext

As mentioned previously in this chapter AgsAudio organizes your recall ids and recycling contices. The following functions are here to add and remove them.

- `void ags_audio_add_recall_id(AgsAudio*, GObject*)`
- `void ags_audio_remove_recall_id(AgsAudio*, GObject*)`
- `void ags_audio_add_recycling_context(AgsAudio*, GObject*)`
- `void ags_audio_remove_recycling_context(AgsAudio*, GObject*)`

## Dealing with recalls

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 `void ags_audio_add_recall(AgsAudio*, GObject*, gboolean)` and `void ags_audio_remove_recall(AgsAudio*, GObject*, gboolean)`.

All audio processing is performed by one single function. Wheter you want to initialize, run or cancel playback. This is all done by `void ags_channel_recursive_run_stage(AgsChannel*, gint, guint)`.

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

### Get port of recall

Ports are accessed as `GList*` from recall by accessing AgsRecall:port property.

Below an example shows howto instantiate an application context implementation, obtain it by its generic function `ags_application_context_get_instance()` and create an audio object with ags-fx recalls.

The recalls port "./volume[0]" is modified by `ags_port_safe_write(AgsPort*, GValue*)`.

#### Modify recall port

## Open audio files

There is a handy function called `void ags_audio_open_files(AgsAudio*, GSList*, gboolean, gboolean)` 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.

### Audio container

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.

There are convenient functions to obtain a GObject subtype implementing AgsSoundResource:

- GList* ags_sound_container_get_resource_all()
- GList* ags_sound_container_get_resource_by_name()
- GList* ags_sound_container_get_resource_by_index()
- GList* ags_sound_container_get_resource_current()

### Audio file

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.

- void ags_sound_resource_info()
- void ags_sound_resource_set_presets()
- void ags_sound_resource_get_presets()
- guint ags_sound_resource_read()
- void ags_sound_resource_write()
- void ags_sound_resource_flush()
- void ags_sound_resource_seek()