## Introduction

Libaudioverse is a system for the development of realtime audio effects and synthesis. Its capabilities include filters, 3D simulation, oscillators, and a variety of other useful tools needed to construct engaging audio experiences. The readme provides a detailed overview from the perspective of why you might wish to use Libaudioverse, whereas this manual is focused on how it works. If you found this manual first, the readme is a much better place to start.

The rest of this manual discusses Libaudioverse from a technical point of view. You probably want to read in order, though advanced readers may prefer to skip to the technical overview. When demonstrating concepts, the programming language of choice for this manual is Python, but a discussion of the C API can be found here.

Libaudioverse is programming language agnostic. Where possible, language bindings will contain specific documentation in the format most common to your language of choice, but it is impractical for this manual to cover all languages. In order to find out if documentation is available for your language, see the readme.

## Overview

This section tries to get you started with Libaudioverse quickly. A high-level technical overview can be found further along in this manual, but this section is probably what you actually want when you’re starting. Reading in order is recommended.

Each subsection starts with some Python code and follows it with an explanation. The translation to the C API should be fairly straightforward. In the cases where it is not, this manual will make an effort to tell you what you need to use.

Note that the following examples are written against Python 3, but the needed changes for Python 2 are minimal.

### Playing a Sine Wave

Output a sine wave for 5 seconds:

```import libaudioverse
import time

libaudioverse.initialize()

#Create a server using the defaults.
server = libaudioverse.Server()

#A sine node synthesizes a sine wave:
sine = libaudioverse.SineNode(server)

#In order to output, we connect to the server.
#See below for notes on the C API.
sine.connect(0, server)
#or sine.connect(0, sine.server)

#The  server will play once it has been told to use a specific output device.
server.set_output_device("default")

time.sleep(5.0)
libaudioverse.shutdown()```

This program synthesizes a sine wave for 5 seconds using a sine node. The default frequency for a sine node is 440 HZ.

The first and last lines are simple initialization, and every program needs them. Failure to initialize Libaudioverse will lead to errors, as will attempting to access Libaudioverse objects after shutdown. For exploration in a REPL, it is generally safe not to call `shutdown`. Failure to call `shutdown` will crash rarely, but it is still very important to have it in production code as this can and will happen.

Nodes are referred to by their class names (`SineNode`), their C enumerations (`Lav_OBJTYPE_SINE_NODE`) or an English description derived from their name, depending on the context in this manual. For the most part, nodes either synthesize, process, or analyze audio.

Almost all nodes have inputs and outputs, numbered starting at 0. Each output carries 1 or more channels of audio and each input accepts one or more channels of audio. The node referencedocuments the meanings of each input and output, as well as how many channels they have. With a few rare exceptions, nodes have at most one of each.

When we call the connect function (Lav_nodeConnect in the C API), we are telling Libaudioverse where to send the output. Though not shown here, it is possible to connect an output to multiple inputs at the same time.

When you connect outputs to destinations with different channel counts, Libaudioverse will automatically do the necessary conversions to make everything work. There is a detailed description of this algorithm elsewhere in this manual, but for the most part you need only know that Libaudioverse understands and automatically converts between mono, stereo, 4.0, 5.1, and 7.1 without input on your part.

Libaudioverse identifies output devices with strings. The special string "default" specifies the system’s default audio device. If it can, Libaudioverse will attempt to follow changes in the default audio device, as is expected on platforms like Windows.

Servers hold global state such as the current output device. There are other ways to get audio from a server, but the one shown here is `server.set_output_device`. This call (Lav_serverSetOutputDevice in C)sets the output device. If you want to change it later, you can simply call it again.

This example demonstrates one of the two special types of connection. The line `sine.connect(0, server)` connects output 0 of the sine node to the server. Libaudioverse overloads the connect function in any language which supports function overloading. because C doesn’t, the C bindings expose this functionality as Lav_nodeConnectServer.

Finally, it is worth discussing when nodes advance a block. Libaudioverse processes audio in blocks. The size of these blocks is set when you create the server. With the default settings, the duration of each block is about 23 milliseconds. The rules are simple, and mostly do what you want:

• The server advances if it’s connected to an audio device or if you ask it for a block of audio.

• A node never advances if its state is set to paused. This will be discussed later in this overview and is used to pause playing files, for example.

• A node always advances if its state is set to always playing. This is not discussed much in this overview because it is something that you almost never need to do.

• A node advances if it has an output connected directly to the server.

• A node advances if it has an output connected to any node which is advancing.

• In all other cases save one exception (see the section on 3D audio), a node never advances.

While this looks complicated, you can for the most part ignore it. If you build a chain of effects and the last effect is connected to the server, then it works exactly as you expect it will.

### Automating Properties

```import libaudioverse
import time

libaudioverse.initialize()

s=libaudioverse.Server()
n = libaudioverse.SineNode(s)
n.frequency = 0
n.connect(0, n.server)
s.set_output_device(-1)

#Recall that Python omits the last value.
for i in range(0, 1010, 10):
n.mul.value = i/1000.0
n.frequency.value = i
time.sleep(0.02)```

This example has audible artifacts. The reasoning for this and how to fix it will be explained in a later section.

In addition to inputs, all nodes have properties. Every node has at least `mul` and `add`. `Mul` represents volume and ranges from -INFINITY to INFINITY. If you set `mul` to a negative value, the node’s output will be negated. `Add`, not shown here, is the second of 3 standard properties, and adds a specific amount of DC offset.

Oscillators such as the sine node also have a number of other properties. Every oscillator has `frequency`, `phase`, and `frequency_multiplier`. `Frequency` is always in hertz, and `phase` is on the range 0 to 1. `Frequency_multiplier` is an additional multiplier applied to the frequency of the oscillator, and is useful when building instruments; moving up and down by an octave on the musical scale is a doubling or halving of the frequency.

In the C API, properties are specified by numeric identifiers and set with functions like Lav_nodeSetIntProperty or Lav_nodeSetFloatProperty. The identifiers for the properties used in the above example are `Lav_NODE_MUL`, `Lav_NODE_ADD`, and `Lav_SINE_FREQUENCY`. Other properties follow a similar nomenclature.

### Buffers and Playing Files

The following loops a file. It understands three commands: play, pause, and quit.

```import libaudioverse

libaudioverse.initialize()

server = libaudioverse.Server()

print("Enter a path to a sound file.")
path = input()

buffer=libaudioverse.Buffer(server)

buffer_player=libaudioverse.BufferNode(server)
buffer_player.buffer = buffer
buffer_player.looping = True
buffer_player.connect(0, server)

server.set_output_device("default")

while True:
print("Play, pause, or quit?")
command = input()
if command == "play":
buffer_player.state = libaudioverse.NodeStates.playing
elif command == "pause":
buffer_player.state = libaudioverse.NodeStates.paused
elif command == "quit":
break

libaudioverse.shutdown()```

A buffer represents a chunk of decoded, resampled audio. They can be loaded from a number of sources, but by far the most common is from a file.

Buffer nodes play the specified buffer, and have some properties of interest:

• `buffer` is the buffer itself.

• `position` is the position of the audio, in seconds.

• `rate` is the playback rate of the buffer. 1.0 is identity. 2.0 is twice as fast and 0.5 is half as fast.

• `looping` causes the buffer to loop, if true.

• `ended_count` increments every time the buffer ends. You can reset it by writing to it.

As mentioned above, buffers store uncompressed, decoded audio data as float32, resampled to match the sampling rate of their server. This means they are quite large. Caching buffers is therefore very highly recommended, as 1 second of mono audio will take 176KB and a minute of stereo audio will take about 21 MB. You cannot share buffers between servers, but you can easily share them between buffer nodes.

Finally, this section introduces the above-mentioned node state. A node’s state is set through the `state` property, identified in C as `Lav_NODE_STATE`. Nodes have 3 states:

1. Playing or `Lav_NODESTATE_PLAYING` in C: this node advances if it is directly or indirectly connected to the server. The default.

2. Paused or `Lav_NODESTATE_PAUSED`: this node never advances no matter what, and any nodes that would have advanced because of a connection to it won’t either.

3. Always playing or `Lav_NODESTATE_ALWAYS_PLAYING`: This node always advances and any nodes connected to it always advance as well. You will probably never use this one, but it’s there for some advanced apps.

### Panning

This sets up a panner that you can play with in the Python REPL. Use `python -i test.py` or similar to run it.

```import libaudioverse
import time

libaudioverse.initialize()
s=libaudioverse.Server()

buffer_player  = libaudioverse.BufferNode(s)
buffer = libaudioverse.Buffer(s)
buffer_player.buffer = buffer
buffer_player.looping = True

panner=libaudioverse.MultipannerNode(s, "default")
buffer_player.connect(output = 0, node = panner, input = 0)
panner.connect(0, s)
s.set_output_device(-1)```

Multipanners are the most commonly used panner, as they support switching between HRTf, stereo, 4.0, 5.1, and 7.1 at runtime and without recreating objects.

The second parameter to the multipanner constructor is the path to an HRTF file. As a special case, Libaudioverse recognizes the string "default" in all contexts in which an HRTF path is required. This is an instruction to use the dataset embedded in the Libaudioverse assemlby, and will be what most applications want.

At this time, the default HRTF only works well if you use the default sample rate of the server: 44100 HZ. making Libaudioverse resample HRTF datasets is on the to-do list however, so you can expect this to improve.

The multipanner is an example of a node with an input. Inputs are also numbered starting at 0, and accept a specific number of audio channels. In this case, the multipanner has only one mono input.

The three properties of interest on a multipanner are `azimuth`, `elevation`, and `strategy`. All panners have the first two, but `strategy` is unique to the multipanner.

`Azimuth` is an angle in degrees, such that 0 is straight in front, 90 is straight to the right, 180 is behind, and 270 is to the left. Angles greater than 359 will wrap and negative values are allowed.

`Elevation` is an elevation from the horizontal plane, ranging from -90 to 90. Unlike `azimuth`, elevation does not wrap, and is only audible when using the HRTf strategy.

Finally, `strategy` controls the panning strategy to use. You may see the allowed values by inspecting the Lav_PANNING_STRATEGIES enumeration, bound in Python as `libaudioverse.PanningStrategies.hrtf`, `libaudioverse.PanningStrategies.stereo`, etc.

### Higher-level 3D components

This example sets up a source and an environment with HRTF enabled. As with the above example, copy it to a file and run with `python -i`.

```import libaudioverse
libaudioverse.initialize()

s=libaudioverse.Server()

b=libaudioverse.Buffer(s)

n=libaudioverse.BufferNode(s)
n.buffer = b

e = libaudioverse.EnvironmentNode(s, "default")
e.panning_strategy = libaudioverse.PanningStrategies.hrtf
e.output_channels = 2
e.connect(0, s)

o=libaudioverse.SourceNode(s, e)
n.connect(0, o, 0)

s.set_output_device("default")```

The 3D components of Libaudioverse primarily involve two objects: an environment and a source node.

Environments represent the listener, provide defaults for new sources, aggregate source output, and allow for the creation of effect sends (see the next section).

Sources act as simple speakers. A source takes the environment from which it is to be created as the second parameter to its constructor. All audio sent through sources is panned, aggregated, and sent through output 0 of the source’s environment.

It is important to note that unlike other nodes, sources are always connected to the environment with which they were created. This is the exception mentioned in the advancement rules above.

Unlike other nodes, this connection is implicit and weak. In the usual case, keeping a node alive will recursively keep all nodes connected to its inputs alive as well. Sources break this rule. As a consequence, you need to be sure to keep sources alive for as long as they are needed. If you do not hold a strong reference to them, they will be garbage collected. This is usually what you want. You can find more information on object lifetimes in the technical overview.

Environments and sources are the only nodes to make use of `float3` and `float6` properties, vectors of 3 and 6 floats respectively. In Python, these are represented as 3-tuples and 6-tuples; changing only one component at a time is not allowed because vector updates need to always be atomic.

An environment has two properties of note, `position` and `orientation`.

`Position` is the position of the listener, and `orientation` the listener’s orientation. `Position` is represented as a float3, that is a vector of x, y, and z.

Without changing the orientation, the default coordinate system is as follows: positive x is right, positive y is up, and negative z is forward. This was chosen to match OpenGL and OpenAL.

Orientation is represented as a `float6`. The first three values of this are the at vector, a unit vector pointing in the direction that the listener is facing. The second three are the up vector, a unit vector pointing in the direction of the top of the listener. These vectors must always be perpendicular. If they are not, undefined behavior results.

There are two useful values for the `orientation` property.

The first, `(0, 1, 0, 0, 0, 1)` orients the coordinate system such that positive x is right, positive y is forward, and positive z is up. This is useful for side-scrollers or other applications that do not involve turning.

The second is provided as a reference for those who do not know trigonometry, you can import math and use `(math.sin(theta), math.cos(theta), 0, 0, 0, 1)` to represent orientations as radians clockwise from north. In this coordinate system, positive X is right and positive Y is north. If you need to use degrees, note that `theta = degrees*math.pi/180.0`.

There are two immediately interesting properties on sources. The first is `position`, the same as the environment’s position but for sources. The coordinate system of a source depends greatly on how you calculate the orientation of the listener, but using either or both of the above-suggested values will allow you to make east positive x and north positive y.

The other is `occlusion`, a value from 0 to 1. This property controls an occlusion model, such that 0 is unoccluded and 1 is fully occluded. Libaudioverse is unfortunately incapable of calculating occlusion for you, as this depends greatly on how you represent your level maps. If you periodically update the `occlusion` property on all sources, however, Libaudioverse is more than happy to synthesize it.

There are many other properties on sources controlling the distance model and panning technique, but this section is quite long enough as-is. You will want to be sure to read the Environment Node documentation and the Source Node documentation.

Finally, we must discuss `output_channels` and `panning_strategy`.

For technical reasons beyond the control of Libaudioverse, it is not possible to properly detect the type of audio device the user is using. For this reason, the environment defaults to normal, stereo panning. This is safe on basically every setup imaginable.

Every source has a `panning_strategy` property which can be used to change it for that source. By default, however, this is set to `PanningStrategies.delegate` (`Lav_PANNING_STRATEGY_DELEGATE`). This special value behaves as stereo panning in any case save the 3D components. In the context of a source, it tells the source to get its panning strategy from the environment by looking at the environment’s `panning_strategy` property. By default, all sources delegate. this means that you can change the panning strategy of all sources by reconfiguring the environment.

Unfortunately, it is possible for sources to have different panning strategies from one another. This is somewhat intensional, as you might choose to use stereo on less-important sources and HRTF on more-important ones in order to save CPU processing power.

But it leads to a difficult-to-resolve ambiguity. If you set some of your sources to panning strategies with different channel counts, the environment is then unable to determine how many output channels it needs to have. You might have meant the one with the lower channel count, but you might also have meant the one with the higher channel count.

In order to make it explicit and deterministic, environments require you to also specify the `output_channels` property. Use 2 for stereo and HRTF, 4 for quad, 6 for 5.1, and 8 for 7.1.

### Using Reverb

This snippet begins where the last example ended, and adds an environmental reverb. As with the proceeding examples, run it with `python -i`.

```reverb = libaudioverse.FdnReverbNode(s)
send = e.add_effect_send(channels = 4, is_reverb = True, connect_by_default = True)
e.connect(send, reverb, 0)
reverb.connect(0, s)```

This example sets up an effect send, an additional output on the environment which is intended to be routed through effects. Sources also pan a copy of their audio through the effect sends, using any strategy but HRTF as determined implicitly by the channel count of the send To be more specific: 1 channel is mono, 2 is stereo, 4 is 4.0, 6 is 5.1, and 8 is 7.1. All other values are disallowed.

In this example we specify that all sources created and any created in future should be connected to the effect send, that it is for reverb, and that it has 4 channels. Any attempt to create an effect send for reverb without using 4 channels will error. Unlike non-reverb sends, effect sends for reverb pan their audio differently, such that the reverb fades in with distance.

`create_effect_send` returns the index of the newly created output, which we then feed through an FDN reverb and then to the server. In C, this function is [function-Lav_environmentNodeCreateEffectSend].

FDN reverbs are very simple reverberators. The two most important properties are `density` and `t60`. `Density` ranges from 0 to 1, specifying how close together the reflections are. `T60` is the time it will take for the reverb to decay by 60 decibals, assuming that you play and then stop some input. You can think of `t60` as roughly analogous to the reverb’s duration.

FDN reverbs also contain configurable lowpass filters, and the ability to modulate the delay lines. See the documentation for more.

 Note While FDN reverbs support delay line modulation, this does not currently work well and will be fixed post-0.9.

You have as many effect sends as you want, limited only by computation capacity. Sources have functions to connect and disconnect themselves from effect sends in a fully configurable manner, and you can feel free to make your own custom effects, as well as the ones demonstrated here.

### Using Automators

 Note The following API needs to either be extended or thrown out. It is not yet clear which will occur. This is not an immediate concern, and the following API will exist in its current form until something better is in place and sufficient notice of any compatibility issues is given in accordance with Libaudioverse’s compatibility policy.

This sets up a siren-like effect and then turns off the sine node.

```import time
import libaudioverse
libaudioverse.initialize()

s=libaudioverse.Server()
n=libaudioverse.SineNode(s)

n.frequency = 300
n.frequency.linear_ramp_to_value(1.0, 600)
n.frequency.linear_ramp_to_value(2.0, 300)
n.frequency.linear_ramp_to_value(3.0, 600)
n.frequency.linear_ramp_to_value(4.0, 300)
n.frequency.linear_ramp_to_value(5.0, 600)

n.mul.set(5.1, 1.0)
n.mul.linear_ramp_to_value(5.2, 0.0)

n.connect(0, s)
s.set_output_device("default")
time.sleep(8.0)

libaudioverse.shutdown()```

The above example demonstrates automators. Libaudioverse processes audio in blocks, submitting each block to the sound card before beginning the next. During the processing of a block, no API call can have effect. The problem with this setup is that there is no way to allow user code to be called more rapidly than once per block. Worse yet, being called exactly once per block requires extra work and degrades performance. Automators exist to allow smoothe property modifications despite this limitation.

The linear ramp is an automator which begins moving the value of the property to the specified value. The first argument is the time at which the property must reach the target value erelative to the current time, and the second the value which must be reached. Set is a similar function, but instead moves the value instantaneously at the specified time. Note that all times are specified relative to now, and that it is not possible to schedule automators in the past.

What we do in the above example, therefore, is schedule a triangular sweep of the frequency between 300 HZ and 600 HZ. Then we schedule a fade-out using the set and linear ramp.

There are three notable points about automators worth specifically pointing out, though the first may or may not be obvious.

First, the linear ramp and many other automators use the "previous" value of the property. To that end, it is necessary to set the property to the starting point before automating it. If you don’t, then it will start from wherever it was last set; this may or not be a problem, depending on application structure.

Second, setting a property cancels all pending automators. This is to avoid strange conditions and make validation of inputs possible.

Finally, the setup with mul is a bit strange. Since linear ramps start immediately, it is often necessary to schedule another automator before them. Since we don’t want mul to start ramping until a bit after 5 seconds, we use the set automator. This makes the linear ramp’s previous value the endpoint of the set automator, such that it only takes effect afterwords. If that line is commented out, the sine node will get progressively quieter for the entire example rather than rapidly fading out at the end.

Properties come in two variations, a-rate and k-rate. Most properties are k-rate properties, and their value is computed once per block. Some are processed as much as every sample, such as the sine node’s frequency and the mul propperty on all nodes. These are referred to as the a-rate properties.

The biggest advantage of automators is that they are computed per-sample on a-rate properties. Since both `mul` and `frequency` are a-rate, the above example will not become choppy, even should the block size be set absurdly high.

### Connecting Nodes to Properties

 Note the above notice about the automation API needing a redesign does not apply to this section. The following functionality will always be available.

This example sets up ring modulation. As with other examples, you will want to run it interactively; this one is worth experimenting with.

```import libaudioverse
import time

libaudioverse.initialize()

s = libaudioverse.Server()
n1, n2 = libaudioverse.SineNode(s), libaudioverse.SineNode(s)

n2.mul = 0.0

n1.frequency = 100
n2.frequency=400

n1.connect(0, n2.mul)
n2.connect(0, s)
s.set_output_device("default")

time.sleep(10.0)```

The above example shows how to connect the output of a node to a property, the third type of connection supported by Libaudioverse. In C, this is mapped to Lav_nodeConnectProperty. This works only with float and double properties. Attempting to do it to any other property type will produce an error.

As with automators, this type of control can be sample-perfect on a-rate properties. Unlike automators, connected nodes act as offsets to whatever the property would be without the node. It is common, therefore, to first set the target property to 0.

You can connect multiple outputs to the property. They function identically to 1-channel inputs, including downmixing logic.

While Libaudioverse already has a ringmod node which is admittedly much more efficient, this is the simplest example to demonstrate it with. A similar technique can be used to set up FM synthesis or continuous filter sweeping, as well as a wide variety of other interesting effects.

## Technical Description Of Libaudioverse

This section of the manual describes Libaudioverse from a high-level perspective and provides technical details required to optimize and troubleshoot your application. For a gentler and much more hands-on introduction, see the overview.

### Introduction

Libaudioverse is composed primarily of three object types: the server, buffers, and nodes.

The server is the main entry point, and is required for creating any other Libaudioverse object. All objects save for servers are themselves associated with servers. Attempts to combine objects from different servers are always errors.

Buffers represent chunks of decoded audio data, and can be loaded from a variety of sources. Buffers commonly hold data from files and are usually combined with a buffer node for playback.

Finally, nodes represent audio production, analysis, and transformation. They are by far the most complex and interesting object type in Libaudioverse.

### Initialization

Before using Libaudioverse, call Lav_initialize. Failure to do so will result in crashes. When done using the library, call Lav_shutdown. Failure to do so may lead to crashes, depending on what is or is not created. It is not safe to assume that Libaudioverse will properly clean itself up at process exit without a call to Lav_shutdown, though failing to do so is common in exploratory situations for languages which provide a REPL.

You may initialize the library more than once: subsequent initializations do nothing. You must deinitialize the library exactly as many times as it has been initialized, no more.

### Pointer Ownership and Object Lifetime

#### A Note for Users of Languages with Automatic Memory Management

The following sections are very complicated, but languages whichcan be integrated with Libaudioverse’s freeing logic handle all of it for you. Unless you are in C or another language where you must manually manage memory, all you need to know is that the following are strong references:

• Given some node `a` and some other node `b`, the call `a.connect(some_output, b, some_input)` creates a strong reference from `b` to `a`. The connection remains alive until `b` is collected or you explicitly kill it.

• Connecting to properties creates a strong reference in the same manner as above. So does connecting to the server.

• The server is alive as long as something created from it is alive.

Finally, deinitialization of the library kills all the objects on the library’s side. You should never use anything after deinitializing the library.

Everything related to pointer ownership and keeping pointers alive is handled deep inside the bindings to such languages. You need not concern yourself with it. Any language with concerns along these lines will clearly mention them in the documentation for that language.

#### Pointer Ownership

When Libaudioverse returns a buffer of memory, it almost always allocates a copy. Exceptions to this rule will be clearly documented.

The calling application is responsible for freeing this buffer, always through Lav_free. Use of `free` from the standard library on these pointers will cause memory leaks at best.

When Lav_shutdown is called, all pointers that libaudioverse allocated are immediately freed. Calling this function after the library is deinitialized does nothing.

Libaudioverse objects ar publicly exposed through reference-counted handles. There are three functions dealing with handle management: Lav_handleIncRef, Lav_handleDecRef, and Lav_handleGetAndClearFirstAccess. As above, calling these functions after library shutdown does nothing.

In order to be as fast as possible and to block as little as possible, Libaudioverse defers deletions to the end of the current block. This means that any pending callbacks for a deleted handle may still fire, depending on when and how they were called. Even if you think a handle should no longer exist, you should be prepared to see it again.

In order to be sane and avoid crashes, Libaudioverse creates strong references internally. Examples include connections (from the input of the target to the output of the source) and setting buffer properties. The rest of this section explains how this logic works.

A handle is either external or internal. Handles are external if and only if their reference count is greater than or equal to 1. The most common method of getting an external handle is to create an object. When a handle first transitions from the internal to external state, its reference count is always set to one. The function Lav_handleGetAndClearFirstAccess indicates whether a handle has just transitioned from the internal to external states, clearing an internal flag. This function exists primarily to assist bindings in knowing when they need to increment the handle’s reference count. When a handle’s reference count goes to 0, it is not immediately deleted but instead becomes internal once more.

Relationships between Libaudioverse objects will also keep handles alive by forming invisible and internal strong references. The following are the common cases in which this occurs:

• A server is alive so long as any object created using the server is still alive.

• A node is alive so long as it has an output connected to another node that is also still alive.

• Buffers are alive as long as they are assigned to a buffer property, or otherwise in use.

In order to detect the death of a handle, Libaudioverse provides the Lav_setHandleDestroyedCallback function. Handle values are not reused unless the application manages to overflow a 32-bit signed integer. Most bindings therefore use the proxy pattern: the objects that user code deals with are thin proxies containing the handle and a pointer to global state. When the handle destroyed callback is called, the global state is then destroyed. This allows for keeping callback objects and other such resources alive in languages with garbage collectors, as not to invalidate pointers held by Libaudioverse. The handle destroyed callback must do its best to not block whenever possible, as it may be called from any thread.

### The Server

The server is the main entry point to Libaudioverse.

The two most crutial pieces of information needed for the server are the block size and sample rate. The latter is self-explanatory. The block size is the number of samples to process at once, and must be a multiple of 4. Servers are created with Lav_createServer. The strongly suggested defaults for these parameters are 1024 and 44100 respectively. These are sufficient and performant for most applications.

By default, Libaudioverse will use one thread per core on the current system for audio mixing. This may be changed via Lav_serverSetThreads.

Servers handle audio output and hold state, provided via dependency injection to created objects. All Libaudioverse objects are associated with exactly one server in a permanent manner. Any attempt to use a pair of objjects from different servers together will error.

#### Audio Output

Servers are the final destination for audio, and output may be retrieved in 3 ways. In all cases, Libaudioverse applies the audio upmixing and downmixing algorithms as specified here to reach the required channel count. None of the following three methods of receiving audio should be mixed; doing so results in undefined behavior.

Lav_serverGetBlock fills a buffer allocated by the calling application with a block of audio data.

Lav_serverWriteFile drives the server for the specified duration, synthesizing as fast as possible and writing to the specified file. The file format is determined from the extension of the provided path. The supported file formats are not currently documented as this is in flux, but you are guaranteed to have at least .wav and .ogg.

The final option is to call Lav_serverSetOutputDevice. This links the server to a specific audio device.

Libaudioverse represents specific audio devices with string identifiers. These strings should be considered opaque. They should never be stored. In future, Libaudioverse will make a best effort to allow you to put them in configuration files, but this functionality is not currently implemented. The format of these strings is subject to change.

The default audio device is the string "default". Where it can, Libaudioverse will attempt to follow any changes in the default audio device.

Multiple calls to Lav_serverSetOutputDevice are allowed, though playback may not be gapless.

 Important Audio stacks are limited. There is no reliable way to properly detect channel counts for all setups. For this reason, your application should assume that it is running on a set of stereo speakers (2 channels, don’t apply HRTFs) until the user specifies otherwise. If you use the wrong channel count, Libaudioverse will apply the remixing algorithms but the experience will be sub-par. Always trust the user; if it is important for your application to know if it is running on surround sound, ask or direct users to an options menu before choosing on their behalf.

#### Atomicity and Batching Calls

Libaudioverse outputs audio in blocks. When outputting to an audio device, any operation which may be completed with one function call will either be completely audible or not audible on the next block. If the operation in question can be done in one function call, hearing partial results is not possible.

There are three ways to ensure that operations which take more than one function call are only audible when finished:

• Perform the operations on a set of disconnected nodes before connecting them.

• use Lav_serverLock and Lav_serverUnlock. Note that, as these function names imply, servers function as mutexes; lock inversion and other concerns can apply in multithreaded scenarios.

• Set a per-block callback which Libaudioverse will call just before mixing every block. This can be done with Lav_serverSetBlockCallback.

Most applications will want to use Lav_serverLock before beginning their per-frame audio update, and Lav_serverUnlock afterwords. Failure to call Lav_serverUnlock in a timely manner will cause audio glitching; failure to call it at all will cause silence and freeze Libaudioverse’s background threads.

The per-block callback is for advanced synthesis applications which need a stronger guarantee: not only is the operation happening completely before the next block, it is running every block. Using the per-block callback for a game’s frame updates will lead to massively degraded performance. You should only use it when controlling nodes exactly every block is important.

### Buffers

Buffers store un-encoded float32 audio data at the sampling rate of the server. They can be loaded from files or arrays, and will resample the data exactly once when loaded. Buffers are most commonly used with buffer nodes.

Save for the contained audio data, buffers are stateless; using them requires coupling them with a node. Since buffers are quite large, using a cache is recommended. Buffers may safely be used in more than one place at a time. Modifying a buffer’s audio data while it is in use will result in an error.

### Nodes

Nodes represent audio transformation, genneration, and analysis. This section discusses nodes generally, including the audio conversion algorithms, properties, and connection logic,. To see what kinds of specific nodes are on offer, see the Nodes reference.

#### Connections and Automatic Audio Channel Count Conversion

Nodes have 0 or more inputs and 0 or more outputs. Outputs are connected to inputs in a many-to-many relationship, such that each input acts as a mixer. Libaudioverse makes the opinionated decision that connections are made from outputs to inputs and broken in the same manner.

The two functions relevant to node-to-node connections are Lav_nodeConnect and Lav_nodeDisconnect. Connecting nodes to the server is accomplished with Lav_nodeConnectServer. Lav_nodeConnectProperty will be discussed later. In languages with function overloading or sufficient flexibility to fake it, these three functions are often combined into one. Any connection that would cause a cycle (i.e. `a.connect(0, b, 0)` and `b.connect(0, a, 0)` in Python) will error.

All inputs and outputs have a documented channel count. Libaudioverse has intrinsic understanding of the following channel counts, and can freely and automatically convert between them:

 Count Name Order 1 Mono Mono 2 Stereo Left, Right 4 4.0 Surround (quad) front left, front right, back left, back right 6 5.1 surround front left, front right, center, lfe, back left, back right 8 7.1 Surround front left, front right, center, lfe, back left, back right, side left, side right

Where applicable, libaudioverse prefers to copy WebAudio’s conversion algorithms. This is used for everything save conversions involving 7.1. Regretfully, the WebAudio specification does not specify what to do in this case. To that end, Libaudioverse uses a custom algorithm that is subject to change.

If an input or an output has a channel count not found in the above table, then one of three things happens:

• If the output is mono, then the mono output fills all channels of the input.

• If the output has less channels than the input, additional channels are filled with zero.

• If the output has more channels than the input, additional channels are dropped.

Conceptually, nodes have a time that is specific to each node. This time does not actually exist and cannot be queried, but makes a good metaphorical mechanism for understanding how nodes advance. You can observe it somewhat directly by looking at the position property on a buffer node.

If the node’s state is paused, time does not advance for it under any circumstance, and it simply always outputs zero. Time advances for a node if one of the following two conditions is true:

• You can grab one or more of the node’s outputs and somehow follow them via any path whatsoever through nodes which are playing or always playing to the server.

• The node’s state is always playing.

If some node `a` has a connection to some node `b` from an output of `a` to an input of `b` then `a` will always execute before `b`. In addition, any callbacks that happen in the audio thread on `a` will happen before any such on `b`.

#### Properties

Properties control aspects of nodes in the manner that their name suggests. They are managed through a variety of functions depending on the property type, i.e. Lav_nodeSetIntProperty.

The full list of property management functions is too long to be listed here, but they all follow a similar naming pattern. `Lav_nodeSetTypeProperty` and `Lav_nodeGetTypeProperty`, where `Type` is the property’s type, are the most important.

Properties are always of one of the following types: int (32-bit signed integer), float, double, float3, float6, string, array of int, array of float, or buffer.

Boolean properties are int properties with the range 0 to 1, and are used as int properties in the C bindings. They exist for bindings generation and documentation clarity.

Some int properties must take their values from an enum. When this is the case, which enum is documented with the property.

Float3 and float6 properties are packed vectors primarily used for the 3D components. The purpose of float3 and float6 properties are to provide a fast path for orientations and positions, and to reduce need for Lav_serverLock and Lav_serverUnlock with the 3D components of this library.

There are three standard properties on all nodes. They are as follows, with more complete documentation here:

• `State`. An int. This property takes its value from the Lav_NODE_STATES enumeration. Nodes which are playing are used as-needed. Nodes which are paused act as though they are always outputting zeros. Nodes which are always playing always process, even if no one needs their output. The default is playing.

• `Mul`. A float. This is a multiplier (naively volume) which is applied to the node’s outputs before `add`.

• `Add`. A float. This is an additional additive factor (DC offset) applied to the outputs of the node after the application of `mul`.

#### Automation and Property Connections

While all other types of properties are exactly the value they are currently set to, float and double properties have two additional features which allow for fine-grained control. The value of a float or double property is actually a sum of all of the following:

• The set value, if no automators are currently effecting the property.

• The automation value, computed by looking at the automation timeline.

• The value of the property’s input.

These will be discussed here.

First is the set value. This is fairly self-explanatory: call `Lav_nodeSetFloatProperty`.

Second is the automation timeline. Automators include such things as Lav_automationLinearRampToValue and Lav_automationEnvelope. When in use, the automation timeline takes the place of the set value; note that setting the property explicitly will cancel all automators.

Only one automator can be in effect at any given time. They have both a duration and a starting point. Automators such as the envelope have a non-zero duration, and will move the value of the property appropriately as described by the provided array. Other automators such as linear ramps have a duration of zero and affect the property starting when the previous automator ends.

Attempting to schedule an automator during the duration of another automator (or such that they start at the same exact time for those automators which have a duration of zero) is an error.

Finally, every float and double property can be treated as a mono input via the function Lav_nodeConnectProperty. The value of all connected nodes is converted and summed, and then acts as an additional additive factor.

Proper use of these features includes understanding k-rate versus a-rate properties, terms borrowed from csound. A k-rate property has it’s value read at the beginning of every block, while an a-rate property has it’s value read more often. Usually a-rate properties are read every sample, but this is not a guarantee; if an a-rate property is read less often, this will be documented in the description.

#### Callbacks

Some nodes have callbacks, which work exactly as the name suggests.

What needs to be mentioned about callbacks that makes them deserve a section is this: they can be called in two places, and which place will always be documented.

Any callback which does not explicitly specify that it is called outside the audio thread is allowed to run in the audio thread. These callbacks should consequently not have the Libaudioverse API used from it. If the Libaudioverse API can be used from such a callback, then the specific parts of the API that should be used will be outlined. Using the Libaudioverse API in an incorrect manner from a callback which is called inside the audio thread will lead to undefined behavior. Said undefined behavior will be well down the road to outright crashing.

The other place that callbacks can be called is on a background thread owned by the server. This will be clearly documented. This thread is created even if you opt to use `Lav_serverGetBlock`. In this case, using the Libaudioverse API is safe.

Blocking in a callback is usually a bad idea. If the callback is running in the audio threads, blocking will decrease performance and cause Libaudioverse to begin adjusting the latency upward. In extreme cases, blocking in the audio threads will cause glitching. Blocking inside callbacks which are not in the audio threads will stop further callbacks from executing, but will otherwise not degrade performance immediately. It should be noted that Libaudioverse sometimes uses the thread on which these callbacks run internally, and that blocking the callback queue may cause resources to build up over time.

No guarantee is made that only one callback will execute at a time. All callbacks should be fully threadsafe.

## The Libaudioverse C API

This section of the Libaudioverse documentation documents the low-level C API.

### Functions By Category

The following is a complete listing of non-node-specific Libaudioverse functions. If you do not see a function here, it is documented with its node.

Each function lists a description, the full C prototype, and information on all involved typedefs. The `LavError` and `LavHandle` typedefs are intensionally omitted: both typedef to int.

All functions return error codes which should be checked. Error conditions are not documented at this time; see the enum section of this documentation for specific information on possible error return values. Most error conditions are indicative of programmer error.

#### Core Functions

The following functions are the most important functions of Libaudioverse. Writing an app without them is impossible.

##### Lav_errorGetFile

Prototype: `LavError Lav_errorGetFile(const char** destination)`

Get the Libaudioverse cpp file where the most recent error on this thread occured. The pointer returned is valid until another error occurs on this thread. This function is mainly for debugging and bindings.

 Type Name Description `const char**` destination Holds the result of a call to this function.
##### Lav_errorGetLine

Prototype: `LavError Lav_errorGetLine(int* destination)`

Return the source line for the last error that occured on this thread. This function is mainly for debugging and bindings.

 Type Name Description `int*` destination Holds the result of a call to this function.
##### Lav_errorGetMessage

Prototype: `LavError Lav_errorGetMessage(const char** destination)`

Get the message corresponding to the last error that happened on this thread. The returned pointer is valid until another error occurs. The main purpose of this function is debugging and bindings.

 Type Name Description `const char**` destination Holds the result of a call to this function.
##### Lav_free

Prototype: `LavError Lav_free(void* ptr)`

Frees pointers that Libaudioverse gives you. In order to free pointers from Libaudioverse, be sure to use this function rather than the normal system free.

This function is no-op after shutdown, but should not be used before initialization. This behavior simplifies writing garbage-collected bindings to Libaudioverse, and should not be relied on in C code.

 Type Name Description `void*` ptr The pointer to free.
##### Lav_getLoggingCallback

Prototype: `LavError Lav_getLoggingCallback(LavLoggingCallback* destination)`

Get the logging callback.

 Type Name Description `LavLoggingCallback*` destination The pointer to the logging callback if set, otherwise NULL.
 Name Actual Type LavLoggingCallback `void (*)(int level, const char* message)`
##### Lav_getLoggingLevel

Prototype: `LavError Lav_getLoggingLevel(int* destination)`

Get the current logging level

 Type Name Description `int*` destination Holds the result of a call to this function.
##### Lav_handleDecRef

Prototype: `LavError Lav_handleDecRef(LavHandle handle)`

Decrement the reference count of a Libaudioverse handle. This function is the equivalent to Lav_free for objects. Note that this is only a decrement. If you call it in the middle of a block or in a variety of other situations, you may see the same handle again via a callback.

This function is no-op after shutdown, but should not be used before initialization. This behavior simplifies writing garbage-collected bindings to Libaudioverse, and should not be relied on directly by C programs.

 Type Name Description `LavHandle` handle The handle whose reference count we are decrementing.
##### Lav_handleGetAndClearFirstAccess

Prototype: `LavError Lav_handleGetAndClearFirstAccess(LavHandle handle, int* destination)`

Checks the handle’s first access flag and clears it. This is an atomic operation, used by bindings to automatically increment and decrement handle reference counts appropriately.

 Type Name Description `LavHandle` handle The handle to check. `int*` destination 1 if the first access flag is set, otherwise 0.
##### Lav_handleGetRefCount

Prototype: `LavError Lav_handleGetRefCount(LavHandle handle, int* destination)`

For debugging. Allows obtaining the current reference count of the handle. This function is not guaranteed to be reliable; do not assume that it is correct or change application behavior based off it.

 Type Name Description `LavHandle` handle The handle to obtain the reference count of `int*` destination After a call to this function, contains the reference count of the handle.
##### Lav_handleGetType

Prototype: `LavError Lav_handleGetType(LavHandle handle, int* destination)`

Returns the type of the handle.

 Type Name Description `LavHandle` handle The handle to obtain the type of. `int*` destination A `Lav_OBJTYPES` constant corresponding to the handle’s type.
##### Lav_handleIncRef

Prototype: `LavError Lav_handleIncRef(LavHandle handle)`

Newly allocated Libaudioverse handles have a reference count of 1. This function allows incrementing this reference count. If you are working in C, this function is not very helpful. It is used primarily by the various programming language bindings in order to make the garbage collector play nice.

 Type Name Description `LavHandle` handle The handle whose reference count is to be incremented.
##### Lav_initialize

Prototype: `LavError Lav_initialize()`

This function initializes Libaudioverse. You must call it before calling any other functions.

##### Lav_isInitialized

Prototype: `LavError Lav_isInitialized(int* destination)`

Indicates whether Libaudioverse is initialized.

 Type Name Description `int*` destination Holds the result of a call to this function.
##### Lav_setHandleDestroyedCallback

Prototype: `LavError Lav_setHandleDestroyedCallback(LavHandleDestroyedCallback cb)`

Set the callback to be called when a Libaudioverse handle is permanently destroyed. Libaudioverse guarantees that handle values will not be recycled. When this callback is called, it is the last time your program can see the specific handle in question, and further use of that handle will cause crashes.

 Type Name Description `LavHandleDestroyedCallback` cb The callback to be called when handles are destroyed.
 Name Actual Type LavHandleDestroyedCallback `void (*)(LavHandle which)`
##### Lav_setLoggingCallback

Prototype: `LavError Lav_setLoggingCallback(LavLoggingCallback cb)`

Configure a callback to receive logging messages. Note that this function can be called before Libaudioverse initialization.

The callback will receive 3 parameters: level, message, and is_final. Level is the logging level. Message is the message to log. is_final is always 0, save when the message is the last message the logging callback will receive, ever. Use is_final to determine when to deinitialize your Libaudioverse logging.

 Type Name Description `LavLoggingCallback` cb The callback to use for logging.
 Name Actual Type LavLoggingCallback `void (*)(int level, const char* message)`
##### Lav_setLoggingLevel

Prototype: `LavError Lav_setLoggingLevel(int level)`

Set the logging level. You will receive messages via the logging callback for all levels greater than the logging level.

 Type Name Description `int` level The new logging level.
##### Lav_shutdown

Prototype: `LavError Lav_shutdown()`

Shuts down Libaudioverse. You must call this function at the end of your application. Failure to do so may cause crashes. Once this function has been called, all pointers and handles from Libaudioverse are invalid. Libaudioverse cannot be safely reinitialized.

#### Server Functions

The following functions relate to and control the server.

##### Lav_createServer

Prototype: `LavError Lav_createServer(unsigned int sr, unsigned int blockSize, LavHandle* destination)`

Creates a server. The new server has no associated audio device. To make it output, use `Lav_serverSetOutputDevice`.

 Type Name Description `unsigned int` sr The sampling rate of the new server. `unsigned int` blockSize The block size of the new server. `LavHandle*` destination Holds the result of a call to this function.
##### Lav_serverCallIn

Prototype: `LavError Lav_serverCallIn(LavHandle serverHandle, double when, int inAudioThread, LavTimeCallback cb, void* userdata)`

Schedule a function to run in the future.

This function is either called inside the audio thread or outside the audio thread. If called inside the audio thread, it must exit quickly and not call the Libaudioverse API. If called outside the audio thread, it can call the Libaudioverse API and will not block audio. This is the same as node callbacks.

Time advances for servers if and only if they are processing audio for some purpose; this callback is called in audio time, as it were. The precision of the callback is limited by the block size. Smaller block sizes will call callbacks more precisely.

 Type Name Description `LavHandle` serverHandle The simulation to manipulate. `double` when The number of seconds from the current time to call the callback. `int` inAudioThread If nonzero, call the callback in the audio thread. `LavTimeCallback` cb The callback to call. `void*` userdata An extra parameter that will be passed to the callback.
 Name Actual Type LavTimeCallback `void (*)(LavHandle handle, double time, void* userdata)`
##### Lav_serverClearOutputDevice

Prototype: `LavError Lav_serverClearOutputDevice(LavHandle serverHandle)`

Clear a server’s output device.

This is no-op if no output device has been set.

After a call to this function, it is again safe to use `Lav_serverGetBlock`.

 Type Name Description `LavHandle` serverHandle The simulation to manipulate.
##### Lav_serverGetBlock

Prototype: `LavError Lav_serverGetBlock(LavHandle serverHandle, unsigned int channels, int mayApplyMixingMatrix, float* buffer)`

Gets a block of audio from the server and advances its time. You must allocate enough space to hold exactly one block of audio: the server’s block size times the number of channels requested floating point values. Note that mixing this function with other output methods invokes undefined behavior.

 Type Name Description `LavHandle` serverHandle The handle of the server to read a block from. `unsigned int` channels The number of channels we want. The servers' output will be upmixed or downmixed as appropriate. `int` mayApplyMixingMatrix If 0, drop any additional channels in the server’s output and set any missing channels in the server’s output to 0. Otherwise, if we can, apply a mixing matrix. `float*` buffer The memory to which to write the result.
##### Lav_serverGetBlockSize

Prototype: `LavError Lav_serverGetBlockSize(LavHandle serverHandle, int* destination)`

Query the block size of the specified server.

 Type Name Description `LavHandle` serverHandle The simulation to manipulate. `int*` destination Holds the result of a call to this function.
##### Lav_serverGetSr

Prototype: `LavError Lav_serverGetSr(LavHandle serverHandle, int* destination)`

Query the server’s sampling rate.

 Type Name Description `LavHandle` serverHandle The simulation to manipulate. `int*` destination Holds the result of a call to this function.

Prototype: `LavError Lav_serverGetThreads(LavHandle serverHandle, int* destination)`

Get the number of threads that the server is currently using.

 Type Name Description `LavHandle` serverHandle The simulation to manipulate. `int*` destination Holds the result of a call to this function.
##### Lav_serverLock

Prototype: `LavError Lav_serverLock(LavHandle serverHandle)`

All operations between a call to this function and a call to Lav_serverUnlock will happen together, with no blocks mixed between them. This is equivalent to assuming that the server is a lock, with all of the required caution that implies. No other thread will be able to access this server or objects created from it until Lav_serverUnlock is called. If you do not call Lav_serverUnlock in a timely manner, then audio will stop until you do.

Pairs of Lav_serverLock and Lav_serverUnlock nest safely.

 Type Name Description `LavHandle` serverHandle The simulation to manipulate.
##### Lav_serverSetBlockCallback

Prototype: `LavError Lav_serverSetBlockCallback(LavHandle serverHandle, LavTimeCallback callback, void* userdata)`

Set a callback to be called just before every block and in the audio thread. This callback can and should access the Libaudioverse API: the point of it is that you can use it to perform tasks where missing even one block would be problematic, i.e. very precise scheduling of events.

This callback can even block, though this will slow down audio mixing and may cause glitchy audio. The one thing you should never do in this callback is access anything belonging to another server, as this can cause deadlock.

The callback receives two parameters: the server to which it is associated and the time in server time that corresponds to the beginning of the block about to be mixed.

 Type Name Description `LavHandle` serverHandle The simulation to manipulate. `LavTimeCallback` callback The callback to use. `void*` userdata An extra parameter that will be passed to the callback.
 Name Actual Type LavTimeCallback `void (*)(LavHandle handle, double time, void* userdata)`
##### Lav_serverSetOutputDevice

Prototype: `LavError Lav_serverSetOutputDevice(LavHandle serverHandle, const char* device, int channels, int mixahead)`

Set the output device of the server. Use the literal string "default" for the default audio device.

Note that it is possible to change the output device of a server even after it has been set.

After the output device has been set, calls to `Lav_serverGetBlock` will error.

 Type Name Description `LavHandle` serverHandle The simulation to manipulate. `const char*` device The output device the server is to play on. `int` channels The number of channels we wish to output. `int` mixahead The number of audio blocks to prepare ahead of the audio device. Must be at least 1.

Prototype: `LavError Lav_serverSetThreads(LavHandle serverHandle, int threads)`

Set the number of threads that the server is allowed to use.

The value of the threads parameter may be from 1 to infinity. When set to 1, processing happens in the thread who calls Lav_serverGetBlock. All other values sleep the thread calling Lav_serverGetBlock and perform processing in background threads.

 Type Name Description `LavHandle` serverHandle The simulation to manipulate. `int` threads The number of threads to use for processing. Must be at least 1. Typical values include 1 and 1 less than the available cores.
##### Lav_serverUnlock

Prototype: `LavError Lav_serverUnlock(LavHandle serverHandle)`

Release the internal lock of a server, allowing normal operation to resume. This is to be used after a call to Lav_serverLock and on the same thread as that call; calling it in any other circumstance or on any other thread invokes undefined behavior.

Pairs of Lav_serverLock and Lav_serverUnlock nest safely.

 Type Name Description `LavHandle` serverHandle The simulation to manipulate.
##### Lav_serverWriteFile

Prototype: `LavError Lav_serverWriteFile(LavHandle serverHandle, const char* path, int channels, double duration, int mayApplyMixingMatrix)`

Write the server’s output to the specified file.

This function advances the server as though Lav_serverGetBlock were called multiple times, the number of times determined by duration. As a consequence, it is not possible to use this function while the server is outputting.

The file format is determined from the path. Recognized extensions include ".wav" and ".ogg", which are guaranteed to work on all systems. In all cases, reasonable defaults are used for those settings which are specific to the encoder.

 Type Name Description `LavHandle` serverHandle The simulation to manipulate. `const char*` path The path to the audio file to be written. `int` channels The number of channels in the resulting file. `double` duration Duration of the resulting file, in seconds. `int` mayApplyMixingMatrix 1 if applying a mixing matrix should be attempted, 0 if extra channels should be treated as 0 or dropped. This is the same behavior as with Lav_serverGetBlock.

#### Device Enumeration

The following functions are for queryng informationa bout audio devices.

Note that channel counts are not reliable, and that you should probably use stereo unless the user explicitly says otherwise.

##### Lav_deviceGetChannels

Prototype: `LavError Lav_deviceGetChannels(unsigned int index, unsigned int* destination)`

Query the maximum number of channels for this device before downmixing occurs. You should query the user as to the type of audio they want rather than relying on this function. Some operating systems and backends will perform their own downmixing and happily claim 8-channel audio on stereo headphones. Furthermore, some hardware and device drivers will do the same. It is not possible for Libaudioverse to detect this case.

 Type Name Description `unsigned int` index The index of the audio device. `unsigned int*` destination Holds the result of a call to this function.
##### Lav_deviceGetCount

Prototype: `LavError Lav_deviceGetCount(unsigned int* destination)`

Get the number of audio devices on the system.

 Type Name Description `unsigned int*` destination Holds the result of a call to this function.
##### Lav_deviceGetName

Prototype: `LavError Lav_deviceGetName(unsigned int index, char** destination)`

Returns a human-readable name for the specified audio device.

The string that this function outputs is encoded in UTF8.

 Type Name Description `unsigned int` index The index of the audio device. `char**` destination Contains a pointer to a string allocated by Libaudioverse containing the name. Use Lav_free on this string when done with it.

#### Node Functions

The following functions work on all Libaudioverse nodes.

##### Lav_nodeConnect

Prototype: `LavError Lav_nodeConnect(LavHandle nodeHandle, int output, LavHandle destHandle, int input)`

Connect the specified output of the specified node to the specified input of the specified node.

it is an error if this would cause a cycle in the graph of nodes.

 Type Name Description `LavHandle` nodeHandle The node whose output we are going to connect. `int` output The index of the output to connect. `LavHandle` destHandle The node to whose input we are connecting. `int` input The input to which to connect.
##### Lav_nodeConnectProperty

Prototype: `LavError Lav_nodeConnectProperty(LavHandle nodeHandle, int output, LavHandle otherHandle, int slot)`

Connect a node’s output to an automatable property.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` output The output to connect. `LavHandle` otherHandle The node to which we are connecting. `int` slot The index of the property to which to connect.
##### Lav_nodeConnectServer

Prototype: `LavError Lav_nodeConnectServer(LavHandle nodeHandle, int output)`

Connect the specified output of the specified node to the server’s input.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` output The index of the output to connect.
##### Lav_nodeDisconnect

Prototype: `LavError Lav_nodeDisconnect(LavHandle nodeHandle, int output, LavHandle otherHandle, int input)`

Disconnect the output of the specified node.

If otherHandle is 0, disconnect from all inputs.

If otherHandle is nonzero, disconnect from the specific node and input combination.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` output The output to disconnect. `LavHandle` otherHandle The node from which to disconnect. `int` input The input of the other node from which to disconnect.
##### Lav_nodeGetArrayPropertyLengthRange

Prototype: `LavError Lav_nodeGetArrayPropertyLengthRange(LavHandle nodeHandle, int propertyIndex, unsigned int* destinationMin, unsigned int* destinationMax)`

Get the allowed range for the length of an array in an array property. This works on both int and float properties.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `unsigned int*` destinationMin After a call to this function, contains the minimum allowed length. `unsigned int*` destinationMax After a call to this function, contains the maximum allowed length.
##### Lav_nodeGetBufferProperty

Prototype: `LavError Lav_nodeGetBufferProperty(LavHandle nodeHandle, int propertyIndex, LavHandle* destination)`

Gets the value of a specified buffer property.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `LavHandle*` destination Holds the result of a call to this function.
##### Lav_nodeGetDoubleProperty

Prototype: `LavError Lav_nodeGetDoubleProperty(LavHandle nodeHandle, int propertyIndex, double* destination)`

Get the specified double property.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `double*` destination Holds the result of a call to this function.
##### Lav_nodeGetDoublePropertyRange

Prototype: `LavError Lav_nodeGetDoublePropertyRange(LavHandle nodeHandle, int propertyIndex, double* destinationMin, double* destinationMax)`

Query the range of a double property. Note that ranges are meaningless for read-only properties.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `double*` destinationMin After a call to this function, holds the range’s minimum. `double*` destinationMax After a call to this function, holds the range’s maximum.
##### Lav_nodeGetFloatArrayPropertyLength

Prototype: `LavError Lav_nodeGetFloatArrayPropertyLength(LavHandle nodeHandle, int propertyIndex, unsigned int* destination)`

Get the length of the specified float array property.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `unsigned int*` destination Holds the result of a call to this function.
##### Lav_nodeGetFloatProperty

Prototype: `LavError Lav_nodeGetFloatProperty(LavHandle nodeHandle, int propertyIndex, float* destination)`

Get the specified float property’s value.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `float*` destination Holds the result of a call to this function.
##### Lav_nodeGetFloatPropertyRange

Prototype: `LavError Lav_nodeGetFloatPropertyRange(LavHandle nodeHandle, int propertyIndex, float* destinationMin, float* destinationMax)`

Get the range of a float property. Note that ranges are meaningless for read-only properties.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `float*` destinationMin After a call to this function, holds the range’s minimum. `float*` destinationMax After a call to this function, holds the range’s maximum.
##### Lav_nodeGetInputConnectionCount

Prototype: `LavError Lav_nodeGetInputConnectionCount(LavHandle nodeHandle, unsigned int* destination)`

Get the number of inputs this node has.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `unsigned int*` destination Holds the result of a call to this function.
##### Lav_nodeGetIntArrayPropertyLength

Prototype: `LavError Lav_nodeGetIntArrayPropertyLength(LavHandle nodeHandle, int propertyIndex, int* destination)`

Get the length of the specified int array property.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `int*` destination Holds the result of a call to this function.
##### Lav_nodeGetIntProperty

Prototype: `LavError Lav_nodeGetIntProperty(LavHandle nodeHandle, int propertyIndex, int* destination)`

Get the value of the specified int property.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `int*` destination Holds the result of a call to this function.
##### Lav_nodeGetIntPropertyRange

Prototype: `LavError Lav_nodeGetIntPropertyRange(LavHandle nodeHandle, int propertyIndex, int* destinationMin, int* destinationMax)`

Get the range of an int property. Note that ranges are meaningless for read-only properties.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `int*` destinationMin After a call to this function, holds the range’s minimum. `int*` destinationMax After a call to this function, holds the range’s maximum.
##### Lav_nodeGetOutputConnectionCount

Prototype: `LavError Lav_nodeGetOutputConnectionCount(LavHandle nodeHandle, unsigned int* destination)`

Get the number of outputs this node has.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `unsigned int*` destination Holds the result of a call to this function.
##### Lav_nodeGetPropertyHasDynamicRange

Prototype: `LavError Lav_nodeGetPropertyHasDynamicRange(LavHandle nodeHandle, int propertyIndex, int* destination)`

Find out whether or not a property has a dynamic range. Properties with dynamic ranges change their ranges at specified times, as documented by the documentation for the property of interest.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `int*` destination After a call to this function, contains 1 if the property has a dynamic range, otherwise 0.
##### Lav_nodeGetPropertyName

Prototype: `LavError Lav_nodeGetPropertyName(LavHandle nodeHandle, int propertyIndex, char** destination)`

Get the name of a property.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `char**` destination After a call to this function, contains a newly allocated string that should be freed with Lav_free. The string is the name of this property.
##### Lav_nodeGetPropertyType

Prototype: `LavError Lav_nodeGetPropertyType(LavHandle nodeHandle, int propertyIndex, int* destination)`

Get the type of a property.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `int*` destination Holds the result of a call to this function.
##### Lav_nodeGetServer

Prototype: `LavError Lav_nodeGetServer(LavHandle nodeHandle, LavHandle* destination)`

Get the server that a node belongs to.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `LavHandle*` destination Holds the result of a call to this function.
##### Lav_nodeGetStringProperty

Prototype: `LavError Lav_nodeGetStringProperty(LavHandle nodeHandle, int propertyIndex, const char** destination)`

Get the specified string property.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `const char**` destination After a call to this function, contains a pointer to a newly allocated string that is a copy of the value of the property. Free this string with Lav_free.
##### Lav_nodeIsolate

Prototype: `LavError Lav_nodeIsolate(LavHandle nodeHandle)`

Equivalent to disconnecting all of the outputs of this node. After a call to isolate, this node will no longer be affecting audio in any way.

 Type Name Description `LavHandle` nodeHandle The node to manipulate.

Prototype: `LavError Lav_nodeReadFloatArrayProperty(LavHandle nodeHandle, int propertyIndex, unsigned int index, float* destination)`

Read the float array property at a specified index.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `unsigned int` index The index at which to read. `float*` destination Holds the result of a call to this function.

Prototype: `LavError Lav_nodeReadIntArrayProperty(LavHandle nodeHandle, int propertyIndex, unsigned int index, int* destination)`

Read the int array property at a specified index.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `unsigned int` index The index at which to read. `int*` destination Holds the result of a call to this function.
##### Lav_nodeReplaceFloatArrayProperty

Prototype: `LavError Lav_nodeReplaceFloatArrayProperty(LavHandle nodeHandle, int propertyIndex, unsigned int length, float* values)`

Replace the array contained by a float array property with a new array. Note that, as usual, memory is copied, not shared.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `unsigned int` length The length of the new array. `float*` values The array itself.
##### Lav_nodeReplaceIntArrayProperty

Prototype: `LavError Lav_nodeReplaceIntArrayProperty(LavHandle nodeHandle, int propertyIndex, unsigned int length, int* values)`

Replace the array contained by an int array property with a new array. Note that, as usual, memory is copied, not shared.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `unsigned int` length The length of the new array. `int*` values The array itself.
##### Lav_nodeReset

Prototype: `LavError Lav_nodeReset(LavHandle nodeHandle)`

Reset a node. What this means depends on the node in question. Properties are not touched by node resetting.

 Type Name Description `LavHandle` nodeHandle The node to manipulate.
##### Lav_nodeResetProperty

Prototype: `LavError Lav_nodeResetProperty(LavHandle nodeHandle, int propertyIndex)`

Reset a property to its default.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate.
##### Lav_nodeSetBufferProperty

Prototype: `LavError Lav_nodeSetBufferProperty(LavHandle nodeHandle, int propertyIndex, LavHandle value)`

Set a buffer property.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `LavHandle` value The buffer to set the property to. 0 means none.
##### Lav_nodeSetDoubleProperty

Prototype: `LavError Lav_nodeSetDoubleProperty(LavHandle nodeHandle, int propertyIndex, double value)`

Set the specified double property.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `double` value the new value of the property.
##### Lav_nodeSetFloat3Property

Prototype: `LavError Lav_nodeSetFloat3Property(LavHandle nodeHandle, int propertyIndex, float v1, float v2, float v3)`

Set the specified float3 property.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `float` v1 The first component of the float3. `float` v2 The second component of the float3. `float` v3 The third component of the float3.
##### Lav_nodeSetFloat6Property

Prototype: `LavError Lav_nodeSetFloat6Property(LavHandle nodeHandle, int propertyIndex, float v1, float v2, float v3, float v4, float v5, float v6)`

Set the specified float6 property.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `float` v1 The first component of the float6. `float` v2 The second component of the float6. `float` v3 The third component of the float6. `float` v4 The fourth component of the float6. `float` v5 The fifth component of the float6. `float` v6 The 6th component of the float6.
##### Lav_nodeSetFloatProperty

Prototype: `LavError Lav_nodeSetFloatProperty(LavHandle nodeHandle, int propertyIndex, float value)`

Set the specified float property.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `float` value the new value of the property.
##### Lav_nodeSetIntProperty

Prototype: `LavError Lav_nodeSetIntProperty(LavHandle nodeHandle, int propertyIndex, int value)`

Set an int property. Note that this function also applies to boolean properties, as these are actually int properties with the range [0, 1].

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `int` value The new value of the property.
##### Lav_nodeSetStringProperty

Prototype: `LavError Lav_nodeSetStringProperty(LavHandle nodeHandle, int propertyIndex, char* value)`

Set the specified string property.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `char*` value the new value of the property. Note that the specified string is copied and the memory may be freed.
##### Lav_nodeWriteFloatArrayProperty

Prototype: `LavError Lav_nodeWriteFloatArrayProperty(LavHandle nodeHandle, int propertyIndex, unsigned int start, unsigned int stop, float* values)`

Write a range of values into the specified float array property, without changing its length.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `unsigned int` start The starting index of the range to replace. Must be less than the length of the property. `unsigned int` stop One past the end of the region to be replaced. Must be no more than the length of the property. `float*` values the data with which to replace the range. Must have length stop-start.
##### Lav_nodeWriteIntArrayProperty

Prototype: `LavError Lav_nodeWriteIntArrayProperty(LavHandle nodeHandle, int propertyIndex, unsigned int start, unsigned int stop, int* values)`

Write a range of values into the specified int array property, without changing its length.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `unsigned int` start The starting index of the range to replace. Must be less than the length of the property. `unsigned int` stop One past the end of the region to be replaced. Must be no more than the length of the property. `int*` values the data with which to replace the range. Must have length stop-start.

#### Automator Functions

The following functions manipulate automatable properties.

##### Lav_automationCancelAutomators

Prototype: `LavError Lav_automationCancelAutomators(LavHandle nodeHandle, int propertyIndex, double time)`

Cancel all automators that are scheduled to begin running after the specified time.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` propertyIndex The property to manipulate. `double` time The time after which to cancel automation. This is relative to the node.
##### Lav_automationEnvelope

Prototype: `LavError Lav_automationEnvelope(LavHandle nodeHandle, int slot, double time, double duration, int valuesLength, double* values)`

An automator that performs an envelope.

The specified points are stretched to fit the specified duration. At the scheduled time of this automator, the envelope will begin being performed, finishing at `time+duration`.

As described in the basics section, it is an error to schedule an automator during the range `(time, time+duration)`.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` slot The index of the property to automate. `double` time The time at which the envelope should begin. `double` duration The duration of the envelope. `int` valuesLength The length of the values array. `double*` values The points of the envelope, sampled every `duration/valuesLength` seconds.
##### Lav_automationLinearRampToValue

Prototype: `LavError Lav_automationLinearRampToValue(LavHandle nodeHandle, int slot, double time, double value)`

Sets up a linear ramp.

The value of a linear ramp begins at the end of the last automator and linearly increases to the start time of this automator, after which the property holds steady unless more automators are scheduled.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` slot The slot of the property to automate. `double` time The time at which we must be at the specified value. `double` value The value we must arrive at by the specified time.
##### Lav_automationSet

Prototype: `LavError Lav_automationSet(LavHandle nodeHandle, int slot, double time, double value)`

An automator that sets the property’s value to a specific value at a specific time.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` slot The slot of the property to automate. `double` time The time at which to set the value. `double` value The value to set the property to at the specified time.

#### Buffer Functions

The following functions manipulate buffers.

##### Lav_bufferGetDuration

Prototype: `LavError Lav_bufferGetDuration(LavHandle bufferHandle, float* destination)`

Get the duration of the buffer in seconds.

 Type Name Description `LavHandle` bufferHandle The buffer to retrieve the duration for. `float*` destination Holds the result of a call to this function.
##### Lav_bufferGetLengthInSamples

Prototype: `LavError Lav_bufferGetLengthInSamples(LavHandle bufferHandle, int* destination)`

Get the length of the specified buffer in samples.

The sample rate of a buffer is the sample rate of the server for which that buffer was created. This function is primarily useful for estimating ram usage in caching structures.

 Type Name Description `LavHandle` bufferHandle The buffer whose length is to be queried. `int*` destination Holds the result of a call to this function.
##### Lav_bufferGetServer

Prototype: `LavError Lav_bufferGetServer(LavHandle bufferHandle, LavHandle* destination)`

Get the handle of the server used to create this buffer.

 Type Name Description `LavHandle` bufferHandle The handle of the buffer. `LavHandle*` destination Holds the result of a call to this function.

Prototype: `LavError Lav_bufferLoadFromArray(LavHandle bufferHandle, int sr, int channels, int frames, float* data)`

Load data into the specified buffer from the specified array of floating point audio data.

 Type Name Description `LavHandle` bufferHandle The buffer to load data into. `int` sr The sampling rate of the data in the array. `int` channels The number of audio channels in the data; frames*channels is the total length of the array in samples. `int` frames The number of frames of audio data; frames*channels is the length of the array in samples. `float*` data A pointer to the beginning of the array to load from.

Prototype: `LavError Lav_bufferLoadFromFile(LavHandle bufferHandle, const char* path)`

Loads data into this buffer from a file. The file will be resampled to the sampling rate of the server. This will happen synchronously.

 Type Name Description `LavHandle` bufferHandle The buffer into which to load data. `const char*` path The path to the file to load data from.
##### Lav_bufferNormalize

Prototype: `LavError Lav_bufferNormalize(LavHandle bufferHandle)`

Normalize the buffer. This function divides by the sample whose absolute value is greatest. The effect is to make sounds as loud as possible without clipping or otherwise distorting the sound.

 Type Name Description `LavHandle` bufferHandle The buffer to normalize.
##### Lav_createBuffer

Prototype: `LavError Lav_createBuffer(LavHandle serverHandle, LavHandle* destination)`

Create an empty buffer.

 Type Name Description `LavHandle` serverHandle The simulation to manipulate. `LavHandle*` destination Holds the result of a call to this function.

## Libaudioverse Node Reference

This section is an overview of all Libaudioverse nodes.

For binding-specific references, see the bindings themselves. Python uses docstrings, for example.

Usually, the names of nodes can be inferred by mentally stripping the `Lav_OBJTYPE_` prefix from the identifying constant and looking for `suffix_object` or `SuffixObject` depending on the conventions of your language.

Any function not described in the C API section is a "extra function", a function which breaks the usual property model. Extra functions do any number of things and are documented with the node that they manipulate.

To determine the number of inputs and outputs a node has, as well as their channel counts, check the general description of the node and the description of its constructor in that order. No node’s output or input count can change after the node is created. A few nodes change the input and output channel counts depending on properties. The most notable node of this type is the amplitude panner.

### Generic Node

C Type Identifier: `Lav_OBJTYPE_GENERIC_NODE`

The properties and functionality described here are available on every Libaudioverse node without exception.

While an enumeration value is reserved for the generic node, it should not be possible to receive one publicly. This identifier is only used internally.

#### Properties

Type: float

Range: ['-INFINITY', 'INFINITY']

Default Value: 0.0

Rate: a

After mul is applied, we add the value to which this property is set to the node’s result.

##### channel_interpretation

C Enumeration Value: Lav_NODE_CHANNEL_INTERPRETATION

Type: int

Range: A value from the Lav_CHANNEL_INTERPRETATIONS enumeration.

Default Value: Lav_CHANNEL_INTERPRETATION_SPEAKERS

Rate: k

How to treat channel count mismatches. The default is to apply mixing matrices when possible.

If set to `Lav_CHANNEL_INTERPRETATION_SPEAKERS`, mixing matrices are applied to inputs. Otherwise, when set to `Lav_CHANNEL_INTERPRETATION_DISCRETE`, they are not.

This property is almost never needed.

##### mul

C Enumeration Value: Lav_NODE_MUL

Type: float

Range: ['-INFINITY', 'INFINITY']

Default Value: 1.0

Rate: a

After this node processes, the value to which mul is set is used as a multiplier on the result. The most notable effect of this is to change the node’s volume. A variety of other uses exist, however, especially as regards to nodes which are connected to properties. Mul is applied before add.

##### state

C Enumeration Value: Lav_NODE_STATE

Type: int

Range: A value from the Lav_NODE_STATES enumeration.

Default Value: Lav_NODESTATE_PLAYING

Rate: k

The node’s state. See the basics section in the Libaudioverse manual for details. The default is usually what you want.

C Type Identifier: `Lav_OBJTYPE_ADDITIVE_SAW_NODE`

Constructor: `LavError Lav_createAdditiveSawNode(LavHandle serverHandle, LavHandle* destination)`

This node has no inputs.

 Index Channels Description 0 1 A saw wave.

The most accurate, least featureful, and slowest saw oscillator.

This oscillator uses additive synthesis to produce saw waves. The efficiency therefore depends on the frequency. Sweeping this oscillator will perform poorly if you do not set the harmonics to a nonzero value.

This oscillator is slightly under the range -1 to 1. Of the additive oscillators, the sawtooth wave is the worst in this respect. For this reason, it is probably not suitable as a control signal. This is not fixable using additive synthesis and is a frequency dependent effect.

#### Properties

##### frequency

C Enumeration Value: Lav_OSCILLATOR_FREQUENCY

Type: float

Range: [0, 'INFINITY']

Default Value: 440.0

Rate: a

The frequency of the saw wave, in hertz.

##### frequency_multiplier

C Enumeration Value: Lav_OSCILLATOR_FREQUENCY_MULTIPLIER

Type: float

Range: ['-INFINITY', 'INFINITY']

Default Value: 1.0

Rate: a

An additional multiplicative factor applied to the frequency of the oscillator.

This is useful for creating instruments, as the notes of the standard musical scale fall on frequency multiples of a reference pitch, rather than a linear increase.

##### phase

C Enumeration Value: Lav_OSCILLATOR_PHASE

Type: float

Range: [0.0, 1.0]

Default Value: 0.0

Rate: k

The phase of the saw wave. This is measured in periods, not in radians.

##### harmonics

C Enumeration Value: Lav_SAW_HARMONICS

Type: int

Range: [0, 'MAX_INT']

Default Value: 0

Rate: k

The number of harmonics. 0 requests automatic adjustment. Use a nonzero value if you intend to sweep the saw wave.

While this property has no max value, any combination of frequency and harmonics that leads to aliasing will alias. To avoid this, make sure that `frequency*harmonics` never goes over half your chosen sampling rate.

C Type Identifier: `Lav_OBJTYPE_ADDITIVE_SQUARE_NODE`

Constructor: `LavError Lav_createAdditiveSquareNode(LavHandle serverHandle, LavHandle* destination)`

This node has no inputs.

 Index Channels Description 0 1 A square wave.

The most accurate, least featureful, and slowest square oscillator.

This oscillator uses additive synthesis to produce square waves. The efficiency therefore depends on the frequency. Sweeping this oscillator will perform poorly if you do not set the harmonics to a nonzero value.

This oscillator is slightly under the range -1 to 1. For this reason, it is probably not suitable as a control signal. This is not fixable using additive synthesis and is a frequency dependent effect.

#### Properties

##### frequency

C Enumeration Value: Lav_OSCILLATOR_FREQUENCY

Type: float

Range: [0, 'INFINITY']

Default Value: 440.0

Rate: k

The frequency of the square wave, in hertz.

##### frequency_multiplier

C Enumeration Value: Lav_OSCILLATOR_FREQUENCY_MULTIPLIER

Type: float

Range: ['-INFINITY', 'INFINITY']

Default Value: 1.0

Rate: a

An additional multiplicative factor applied to the frequency of the oscillator.

This is useful for creating instruments, as the notes of the standard musical scale fall on frequency multiples of a reference pitch, rather than a linear increase.

##### phase

C Enumeration Value: Lav_OSCILLATOR_PHASE

Type: float

Range: [0.0, 1.0]

Default Value: 0.0

Rate: k

The phase of the square wave. This is measured in periods, not in radians.

##### harmonics

C Enumeration Value: Lav_SQUARE_HARMONICS

Type: int

Range: [0, 'MAX_INT']

Default Value: 0

Rate: k

The number of harmonics. 0 requests automatic adjustment. Use a nonzero value if you intend to sweep the square wave.

While this property has no max value, any combination of frequency and harmonics that leads to aliasing will alias. To avoid this, make sure that `2*frequency*(2*harmonics-1)` never goes over half your chosen sampling rate.

C Type Identifier: `Lav_OBJTYPE_ADDITIVE_TRIANGLE_NODE`

Constructor: `LavError Lav_createAdditiveTriangleNode(LavHandle serverHandle, LavHandle* destination)`

This node has no inputs.

 Index Channels Description 0 1 A triangle wave.

The most accurate, least featureful, and slowest triangle oscillator.

This oscillator uses additive synthesis to produce triangle waves. The efficiency therefore depends on the frequency. Sweeping this oscillator will perform poorly if you do not set the harmonics to a nonzero value.

This oscillator is slightly under the range -1 to 1. Calibration scripts show that the worst case is -0.9 to 0.9, with the error increasing as frequency increases. For this reason, it is probably not suitable as a control signal. This is not fixable using additive synthesis and is a frequency dependent effect.

#### Properties

##### frequency

C Enumeration Value: Lav_OSCILLATOR_FREQUENCY

Type: float

Range: [0, 'INFINITY']

Default Value: 440.0

Rate: k

The frequency of the triangle wave, in hertz.

##### frequency_multiplier

C Enumeration Value: Lav_OSCILLATOR_FREQUENCY_MULTIPLIER

Type: float

Range: ['-INFINITY', 'INFINITY']

Default Value: 1.0

Rate: a

An additional multiplicative factor applied to the frequency of the oscillator.

This is useful for creating instruments, as the notes of the standard musical scale fall on frequency multiples of a reference pitch, rather than a linear increase.

##### phase

C Enumeration Value: Lav_OSCILLATOR_PHASE

Type: float

Range: [0.0, 1.0]

Default Value: 0.0

Rate: k

The phase of the triangle wave. This is measured in periods, not in radians.

##### harmonics

C Enumeration Value: Lav_TRIANGLE_HARMONICS

Type: int

Range: [0, 'MAX_INT']

Default Value: 0

Rate: k

The number of harmonics. 0 requests automatic adjustment. Use a nonzero value if you intend to sweep the triangle wave.

While this property has no max value, any combination of frequency and harmonics that leads to aliasing will alias. To avoid this, make sure that `2*frequency*(2*harmonics-1)` never goes over half your chosen sampling rate.

### Allpass Node

C Type Identifier: `Lav_OBJTYPE_ALLPASS_NODE`

Constructor: `LavError Lav_createAllpassNode(LavHandle serverHandle, int channels, int maxDelay, LavHandle* destination)`

 Index Channels Description 0 The number of channels for this input depends on parameters to this node’s constructor. The signal to filter.
 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. The filtered signal.

Implements a first-order allpass filter whose transfer function is $\frac{c+Z^{-d} }{1 + cZ^{-d} }$ where `c` is the coefficient and `d` the delay in samples.

This filter is useful in various reverb designs.

#### Properties

##### coefficient

C Enumeration Value: Lav_ALLPASS_COEFFICIENT

Type: float

Range: ['-INFINITY', 'INFINITY']

Default Value: See below

Rate: k

The coefficient of the allpass filter’s transfer function.

For those not familiar with digital signal processing, this controls how quickly the repeating echoes created by this filter decay.

##### delay_samples

C Enumeration Value: Lav_ALLPASS_DELAY_SAMPLES

Type: int

Range: dynamic

Default Value: 1

Rate: k

The delay of the delay line in samples. The range of this property depends on the maxDelay parameter to the constructor.

Note that values less than 1 sample still introduce delay.

##### delay_max

C Enumeration Value: Lav_ALLPASS_DELAY_SAMPLES_MAX

Type: int

The max delay as set at the node’s creation time.

##### interpolation_time

C Enumeration Value: Lav_ALLPASS_INTERPOLATION_TIME

Type: float

Range: [0.001, 'INFINITY']

Default Value: 0.001

Rate: k

When the delay_samples property is changed, the delay line crossfades between the old position and the new one. Essentially, this property sets how long it will take the allpass filter to settle after a delay change. Note that for this node, it is impossible to get rid of the crossfade completely.

### Amplitude Panner Node

C Type Identifier: `Lav_OBJTYPE_AMPLITUDE_PANNER_NODE`

Constructor: `LavError Lav_createAmplitudePannerNode(LavHandle serverHandle, LavHandle* destination)`

 Index Channels Description 0 1 The signal to pan
 Index Channels Description 0 Depends on a number of properties on this node. The result of panning the signal.

This panner pans for a set of regular speakers without any additional effects applied. Additionally, it understands surround sound speaker layouts and allows for the assignment of custom speaker mappings. The default configuration provides a stereo panner that can be used without any additional steps. The additional function Lav_amplitudePannerNodeConfigureStandardChannelMap can set the panner to output for a variety of standard configurations, so be sure to see its documentation.

#### Properties

##### azimuth

C Enumeration Value: Lav_PANNER_AZIMUTH

Type: float

Range: ['-INFINITY', 'INFINITY']

Default Value: 0.0

Rate: k

The horizontal angle of the panner in degrees. 0 is directly ahead, and positive values are clockwise.

##### channel_map

C Enumeration Value: Lav_PANNER_CHANNEL_MAP

Type: float_array

Default Value: [-90, 90]

Rate: k

The angles of the speakers in the order in which they are to be mapped to channels. The first speaker will be mapped to the first channel, the second to the second, etc. These channels are then combined and produced as the single output of the panner.

You can use floating point infinity to indicate a channel should be skipped. This functionality is used by all of the standard channel maps to skip the center and LFE channels.

##### elevation

C Enumeration Value: Lav_PANNER_ELEVATION

Type: float

Range: [-90.0, 90.0]

Default Value: 0.0

Rate: k

The vertical angle of the panner in degrees. 0 is horizontal and positive values are upwards. Note that, for amplitude panners, this has no effect and exists only to allow swapping with the HRTF panner without changing code.

Type: boolean

Default Value: 1

Rate: k

Whether or not to instantly move to the new position. If crossfading is disabled, large movements of the panner will cause audible clicks. Disabling crossfading can aid performance under heavy workloads, especially with the HRTF panner. If crossfading is enabled, moving the panner will slowly fade it to the new position over the next block.

#### Extra Functions

##### configure_standard_map

Prototype: `LavError Lav_amplitudePannerNodeConfigureStandardMap(LavHandle nodeHandle, unsigned int channels)`

Sets the channel map and other properties on this node to match a standard configuration. The possible standard configurations are found in the Lav_PANNING_STRATEGIES enumeration.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `unsigned int` channels A value from the Lav_PANNING_STRATEGIES enumeration.

C Type Identifier: `Lav_OBJTYPE_BIQUAD_NODE`

Constructor: `LavError Lav_createBiquadNode(LavHandle serverHandle, unsigned int channels, LavHandle* destination)`

 Index Channels Description 0 The number of channels for this input depends on parameters to this node’s constructor. The signal to process.
 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. The result of processing the audio via the filter.

Implementation of a biquad filter section, as defined by the Audio EQ Cookbook by Robert Bristo-Johnson. This node is capable of implementing almost every filter needed for basic audio effects, including equalizers. For the specific equations used, see the Audio EQ Cookbook. It may be found at: http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt

#### Properties

##### dbgain

Type: float

Range: ['-INFINITY', 'INFINITY']

Default Value: 0.0

Rate: k

This property is a the gain in decibals to be used with the peaking and shelving filters. It measures the gain that these filters apply to the part of the signal they boost.

##### filter_type

Type: int

Range: A value from the Lav_BIQUAD_TYPES enumeration.

Rate: k

The type of the filter. This determines the interpretations of the other properties on this node.

##### frequency

Type: float

Range: [0, 'INFINITY']

Default Value: 2000.0

Rate: k

This is the frequency of interest. What specifically this means depends on the selected filter type; for example, it is the cutoff frequency for lowpass and highpass.

##### q

Type: float

Range: [0.001, 'INFINITY']

Default Value: 0.5

Rate: k

Q is a mathematically complex parameter, a full description of which is beyond the scope of this manual. Naively, Q can be interpreted as a measure of resonation. For `Q⇐0.5`, the filter is said to be damped: it will cut frequencies. For Q>0.5, however, some frequencies are likely to be boosted.

Q controls the bandwidth for the bandpass and peaking filter types For everything except the peaking filter, this property follows the normal definition of Q in the electrical engineering literature. For more specifics, see the Audio EQ Cookbook. It is found here: http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt

### Blit Node

C Type Identifier: `Lav_OBJTYPE_BLIT_NODE`

Constructor: `LavError Lav_createBlitNode(LavHandle serverHandle, LavHandle* destination)`

This node has no inputs.

 Index Channels Description 0 1 A bandlimited impulse train.

Generates bandlimited impulse trains. These sound like a buzz, but have important applications in the alias-free synthesis of analog waveforms.

#### Properties

##### harmonics

C Enumeration Value: Lav_BLIT_HARMONICS

Type: int

Range: [0, 'MAX_INT']

Default Value: 0

Rate: k

The number of harmonics to include. 0 requests automatic adjustment. When 0, the algorithm this node represents will include as many harmonics as it can without aliasing.

##### should_normalize

C Enumeration Value: Lav_BLIT_SHOULD_NORMALIZE

Type: boolean

Default Value: 1

Rate: k

If false, the produced BLIT will have an integral of 1 over every period. If true, the produced blit will be normalized to be between 1 and -1, and suitable for audio. The default is true.

##### frequency

C Enumeration Value: Lav_OSCILLATOR_FREQUENCY

Type: float

Range: [0, 'INFINITY']

Default Value: 440.0

Rate: a

The frequency of the impulse train in HZ.

##### frequency_multiplier

C Enumeration Value: Lav_OSCILLATOR_FREQUENCY_MULTIPLIER

Type: float

Range: ['-INFINITY', 'INFINITY']

Default Value: 1.0

Rate: a

An additional multiplicative factor applied to the frequency of the oscillator.

This is useful for creating instruments, as the notes of the standard musical scale fall on frequency multiples of a reference pitch, rather than a linear increase.

##### phase

C Enumeration Value: Lav_OSCILLATOR_PHASE

Type: float

Range: [0.0, 1.0]

Default Value: 0.0

Rate: k

The phase of the impulse train. This is measured in periods, not in radians.

### Buffer Node

C Type Identifier: `Lav_OBJTYPE_BUFFER_NODE`

Constructor: `LavError Lav_createBufferNode(LavHandle serverHandle, LavHandle* destination)`

This node has no inputs.

 Index Channels Description 0 Depends on the currently playing buffer. The output from the buffer being played.

This node plays a buffer. The output of this node will have as many channels as the buffer does, so connecting it directly to the server will have the desired effect.

#### Properties

##### buffer

C Enumeration Value: Lav_BUFFER_BUFFER

Type: buffer

Default Value: See below

Rate: k

The currently playing buffer. Setting this property will reset position.

##### ended_count

C Enumeration Value: Lav_BUFFER_ENDED_COUNT

Type: int

Range: [0, 'MAX_INT']

Default Value: 0

Rate: k

Increments every time the buffer reaches it’s end. If the buffer is not looping, this can be used to determine when the buffer is ended, without using the callback. if the buffer is configured to loop, the counter will count up every time the end of a loop is reached. You can write to this property to reset it.

##### looping

C Enumeration Value: Lav_BUFFER_LOOPING

Type: boolean

Default Value: 0

Rate: k

If true, this node continues playing the same buffer from the beginning after it reaches the end.

##### position

C Enumeration Value: Lav_BUFFER_POSITION

Type: double

Range: dynamic

Default Value: 0.0

Rate: k

The position of playback, in seconds. The range of this property corresponds to the total duration of the buffer.

##### rate

C Enumeration Value: Lav_BUFFER_RATE

Type: double

Range: [0, 'INFINITY']

Default Value: 1.0

Rate: k

A multiplier that applies to playback rate. 1.0 is identity. Values less than 1.0 cause a decrease in pitch and values greater than 1.0 cause an increase in pitch.

#### Callbacks

##### end

Setter: LavError Lav_bufferNodeSetEndCallback(LavHandle nodeHandle, LavParameterlessCallback callback, void* userdata)

Callback Prototype: void (LavHandle nodeHandle, void* userdata)

 Type Name Description `LavHandle` nodeHandle The node which called this callback. `void*` userdata The userdata parameter as passed to the setter for this callback.

Called outside the audio threads every time the buffer reaches the end of the audio data.

### Buffer Timeline Node

C Type Identifier: `Lav_OBJTYPE_BUFFER_TIMELINE_NODE`

Constructor: `LavError Lav_createBufferTimelineNode(LavHandle serverHandle, int channels, LavHandle* destination)`

This node has no inputs.

 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. The sum of all playing buffers.

Represents timelines of buffers.

This node provides the ability to schedule buffers to play at any specific time in the future. This node supports pitch bending scheduled buffers. There is no limit to the number of buffers which may be scheduled at any given time, and polyphony is supported.

#### Extra Functions

##### schedule_buffer

Prototype: `LavError Lav_bufferTimelineNodeScheduleBuffer(LavHandle nodeHandle, LavHandle bufferHandle, double time, float pitchBend)`

Schedule a buffer, optionally with pitch bend. The time is relative to now.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `LavHandle` bufferHandle The buffer to schedule. `double` time The time to play the buffer. `float` pitchBend The pitch bend, which must be positive. Use 1.0 to disable.

### Channel Merger Node

C Type Identifier: `Lav_OBJTYPE_CHANNEL_MERGER_NODE`

Constructor: `LavError Lav_createChannelMergerNode(LavHandle serverHandle, int channels, LavHandle* destination)`

The number of inputs to this node depends on parameters to its constructor.

 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. The result of merging the input channels.

Libaudioverse inputs and outputs transport multiple channels of audio, which is usually the desired behavior. This node, coupled with the channel splitter node , allows advanced applications to manipulate the individual audio channels directly. The usual workflow is as follows: feed the output of a node through a channel splitter node, modify the channels individually, and then merge them with this node.

### Channel Splitter Node

C Type Identifier: `Lav_OBJTYPE_CHANNEL_SPLITTER_NODE`

Constructor: `LavError Lav_createChannelSplitterNode(LavHandle serverHandle, int channels, LavHandle* destination)`

 Index Channels Description 0 The number of channels for this input depends on parameters to this node’s constructor. The signal to split into component channels.

The number of outputs from this node depends on parameters to its constructor.

Libaudioverse inputs and outputs transport multiple channels of audio, which is usually the desired behavior. This node, coupled with the channel merger node, allows advanced applications to manipulate the individual audio channels directly. The usual workflow is as follows: feed the output of a node through this node, modify the channels individually, and then merge them with a channel merger node.

### Convolver Node

C Type Identifier: `Lav_OBJTYPE_CONVOLVER_NODE`

Constructor: `LavError Lav_createConvolverNode(LavHandle serverHandle, int channels, LavHandle* destination)`

 Index Channels Description 0 The number of channels for this input depends on parameters to this node’s constructor. The signal to be convolved.
 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. The convolved signal.

A simple convolver.

This implements convolution directly, without use of the FFT.

#### Properties

##### impulse_response

C Enumeration Value: Lav_CONVOLVER_IMPULSE_RESPONSE

Type: float_array

Default Value: [1.0]

Rate: k

The impulse response to convolve the input with.

C Type Identifier: `Lav_OBJTYPE_CROSSFADER_NODE`

Constructor: `LavError Lav_createCrossfaderNode(LavHandle serverHandle, int channels, int inputs, LavHandle* destination)`

The number of inputs to this node depends on parameters to its constructor.

 Index Channels Description 0 Depends on the channel count given to the constructor. The output of the crossfade.

A crossfader is a node which allows for selection of exactly one input. The selection can be changed by crossfading, a technique whereby the currently selected input is slowly faded out and the new one faded in.

By using crossfades of no duration, this node can also be made to function as a switch or selector, selecting an input from among the connected nodes. This particular case is optimized, and special support is implemented via allowing you to write directly to the `current_input` property.

This crossfader has a configurable number of inputs. All inputs and the single output have the same channel count. These are both configurable via parameters to the constructor.

#### Properties

##### current_input

Type: int

Range: dynamic

Default Value: 0

Rate: k

The currently active input.

Writing to this property is equivalent to crossfading with a time of 0. Note that the output is a combination of the current and target inputs while crossfading.

Type: boolean

Default Value: 0

Rate: k

True if we are crossfading, otherwise false.

##### target_input

Type: int

When not crossfading, this property is meaningless.

#### Callbacks

##### finished

Setter: LavError Lav_crossfaderNodeSetFinishedCallback(LavHandle nodeHandle, LavParameterlessCallback callback, void* userdata)

Callback Prototype: void (LavHandle nodeHandle, void* userdata)

 Type Name Description `LavHandle` nodeHandle The node which called this callback. `void*` userdata The userdata parameter as passed to the setter for this callback.

#### Extra Functions

Prototype: `LavError Lav_crossfaderNodeCrossfade(LavHandle nodeHandle, float duration, int input)`

if a crossfade is currently inn progress, it finishes immediately and fires the event.

Using a duration of 0 is an instantaneous crossfade, equivalent to writing directly to the current_input property. Crossfades of duration 0 do not fire the finished event.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `float` duration The duration of the crossfade. `int` input The input to crossfade to.

C Type Identifier: `Lav_OBJTYPE_CROSSFADING_DELAY_NODE`

Constructor: `LavError Lav_createCrossfadingDelayNode(LavHandle serverHandle, float maxDelay, int channels, LavHandle* destination)`

 Index Channels Description 0 The number of channels for this input depends on parameters to this node’s constructor. The signal to delay.
 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. The delayed signal.

Implements a crossfading delay line. Delay lines have uses in echo and reverb, as well as many more esoteric effects.

#### Properties

##### delay

C Enumeration Value: Lav_DELAY_DELAY

Type: float

Range: dynamic

Default Value: 0.0

Rate: k

The delay of the delay line in seconds. The range of this property depends on the maxDelay parameter to the constructor.

Note that values less than 1 sample still introduce delay.

##### delay_max

C Enumeration Value: Lav_DELAY_DELAY_MAX

Type: float

The max delay as set at the node’s creation time.

##### feedback

C Enumeration Value: Lav_DELAY_FEEDBACK

Type: float

Range: ['-INFINITY', 'INFINITY']

Default Value: 0.0

Rate: k

The feedback coefficient. The output of the delay line is fed back into the delay line, multiplied by this coefficient. Setting feedback to small values can make echoes, comb filters, and a variety of other effects.

##### interpolation_time

C Enumeration Value: Lav_DELAY_INTERPOLATION_TIME

Type: float

Range: [0.001, 'INFINITY']

Default Value: 0.001

Rate: k

When the delay property is changed, the delay line crossfades between the old position and the new one. This property sets how long this crossfade will take. Note that for this node, it is impossible to get rid of the crossfade completely.

### Dc Blocker Node

C Type Identifier: `Lav_OBJTYPE_DC_BLOCKER_NODE`

Constructor: `LavError Lav_createDcBlockerNode(LavHandle serverHandle, int channels, LavHandle* destination)`

 Index Channels Description 0 The number of channels for this input depends on parameters to this node’s constructor. A signal with some DC.
 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. The same signal with DC cut using a first-order filter.

A DC blocker. This is a first-order filter, the best possible within numerical limits. It consists of a zero at DC, and a pole as close to DC as we can put it. For any sampling rate, this node is the best first-order section for DC removal possible.

### Dopplering Delay Line Node

C Type Identifier: `Lav_OBJTYPE_DOPPLERING_DELAY_NODE`

Constructor: `LavError Lav_createDoppleringDelayNode(LavHandle serverHandle, float maxDelay, int channels, LavHandle* destination)`

 Index Channels Description 0 The number of channels for this input depends on parameters to this node’s constructor. The signal to delay.
 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. The delayed signal.

Implements a dopplering delay line, an interpolated delay line that intensionally bends pitch when the delay changes. Delay lines have uses in echo and reverb, as well as many more esoteric effects.

#### Properties

##### delay

C Enumeration Value: Lav_DELAY_DELAY

Type: float

Range: dynamic

Default Value: 0.0

Rate: k

The delay of the delay line in seconds. The range of this property depends on the maxDelay parameter to the constructor.

Note that values less than 1 sample still introduce delay.

##### delay_max

C Enumeration Value: Lav_DELAY_DELAY_MAX

Type: float

The max delay as set at the node’s creation time.

##### interpolation_time

C Enumeration Value: Lav_DELAY_INTERPOLATION_TIME

Type: float

Range: [0.001, 'INFINITY']

Default Value: 0.01

Rate: k

When the delay property is changed, the delay line moves the delay to the new position. This property sets how long this will take. Note that for this node, it is impossible to get rid of the crossfade completely.

On this delay line, the interpolation time is the total duration of a pitch bend caused by moving the delay.

### Environment Node

C Type Identifier: `Lav_OBJTYPE_ENVIRONMENT_NODE`

Constructor: `LavError Lav_createEnvironmentNode(LavHandle serverHandle, const char* hrtfPath, LavHandle* destination)`

This node has no inputs.

 Index Channels Description 0 Depends on the output_channels property. The output of the 3D environment.

This is the entry point to the 3D simulation capabilities. Environment nodes hold the information needed to pan sources, as well as acting as an aggregate output for all sources that use this environment.

Note that the various properties for default values do not affect already created sources. It is best to configure these first. Any functionality to change a property on all sources needs to be implemented by the app, and is not offered by Libaudioverse.

#### Properties

##### default_size

C Enumeration Value: Lav_ENVIRONMENT_DEFAULT_SIZE

Type: float

Range: [0.0, 'INFINITY']

Default Value: 0.0

Rate: k

The default size for new sources. Sources aare approximated as spheres, with 0 being the special case of a point source. Size is used to determine the listener’s distance from a source.

##### distance_model

C Enumeration Value: Lav_ENVIRONMENT_DISTANCE_MODEL

Type: int

Range: A value from the Lav_DISTANCE_MODELS enumeration.

Default Value: Lav_DISTANCE_MODEL_LINEAR

Rate: k

Distance models control how quickly sources get quieter as they move away from the listener.

By default, sources are configured to delegate to the environment when looking for values to use for the distance model parameters. This behavior may be changed by setting `Lav_SOURCE_CONTROL_DISTANCE_MODEL` to true.

##### max_distance

C Enumeration Value: Lav_ENVIRONMENT_MAX_DISTANCE

Type: float

Range: [0.0, 'INFINITY']

Default Value: 150.0

Rate: k

The maximum distance at which a source is audible. Consider this property to be in meters.

By default, sources are configured to delegate to the environment when looking for values to use for the distance model parameters. This behavior may be changed by setting `Lav_SOURCE_CONTROL_DISTANCE_MODEL` to true.

##### max_reverb_level

C Enumeration Value: Lav_ENVIRONMENT_MAX_REVERB_LEVEL

Type: float

Range: [0.0, 1.0]

Default Value: 0.6

Rate: k

The maximum amount of audio to be diverted to reverb sends, if any.

Behavior is undefined if this property is ever less than Lav_ENVIRONMENT_MIN_REVERB_LEVEL.

By default, sources look to their environmlent for the value of this property. If you wish to set it on a per-source basis, set `Lav_SOURCE_CONTROL_REVERB` to true on the source.

##### min_reverb_level

C Enumeration Value: Lav_ENVIRONMENT_MIN_REVERB_LEVEL

Type: float

Range: [0.0, 1.0]

Default Value: 0.15

Rate: k

The minimum reverb level allowed.

if a send is configured to be a reverb send, this is the minimum amount of audio that will be diverted to it.

Behavior is undefined if this property is ever greater than the value of Lav_ENVIRONMENT_MAX_REVERB_LEVEL.

By default, sources look to their environmlent for the value of this property. If you wish to set it on a per-source basis, set `Lav_SOURCE_CONTROL_REVERB` to true on the source.

##### orientation

C Enumeration Value: Lav_ENVIRONMENT_ORIENTATION

Type: float6

Default Value: [0.0, 0.0, -1.0, 0.0, 1.0, 0.0]

Rate: k

The orientation of the listener. The first three elements are a vector representing the direction in which the listener is looking and the second 3 a vector representing the direction in which a rod pointing out of the top of the listener’s head would be pointing

This property packs these vectors because they must never be modified separately. Additionally, they should both be unit vectors and must also be orthoganal.

the default situates the listener such that positive x is right, positive y is up, and positive z is behind the listener. The setting (0, 1, 0, 0, 0, 1) will situate the listener such that positive x is right and positive y is forward. For those not familiar with trigonometry and who wish to consider positive x east and positivve y north, the following formula will turn the listener to face a scertain direction specified in radians clockwise of north: (sin(theta), cos(theta), 0, 0, 0, 1). As usual, note that radians=degrees*PI/180.

##### output_channels

C Enumeration Value: Lav_ENVIRONMENT_OUTPUT_CHANNELS

Type: int

Range: [0, 8]

Default Value: 2

Rate: k

Environments are not smart enough to determine the number of channels their output needs to have. If you are using something greater than stereo, i.e. 5.1, you need to change this property. The specific issue solved by this property is the case in which one source is set to something different than all others, or where the app changes the panning strategies of sources after creation.

Values besides 2, 4, 6, or 8 do not usually have much meaning.

##### panning_strategy

C Enumeration Value: Lav_ENVIRONMENT_PANNING_STRATEGY

Type: int

Range: A value from the Lav_PANNING_STRATEGIES enumeration.

Default Value: Lav_PANNING_STRATEGY_STEREO

Rate: k

The panning strategy for any source configured to delegate to the environment. All new sources delegate to the environment by default.

If you want to change this property for a specific source, set `Lav_SOURCE_CONTROL_PANNING` on the source to true.

##### position

C Enumeration Value: Lav_ENVIRONMENT_POSITION

Type: float3

Default Value: [0.0, 0.0, 0.0]

Rate: k

The position of the listener, in world coordinates.

##### default_reverb_distance

C Enumeration Value: Lav_ENVIRONMENT_REVERB_DISTANCE

Type: float

Range: [0.0, 'INFINITY']

Default Value: 75.0

Rate: k

The distance at which a source will be heard only in the reverb.

See documentation on the source node node for a specific explanation. By default, sources get the value of this property from the environment. To control this property on a per-source basis, set `Lav_SOURCE_CONTROL_REVERB` to true on the source.

#### Extra Functions

Prototype: `LavError Lav_environmentNodeAddEffectSend(LavHandle nodeHandle, int channels, int isReverb, int connectByDefault, int* destination)`

Effect sends are aggregates of all sources configured to make use of them. This function’s return value is the index of the newly created effecct send.

The world gains an additional output for every added effect send. This output aggregates all audio of sources configured to send to it, including the panning effects on those sources. The returned index is the number of the newly created output.

Two special cases are worth noting.

First, a mono effect send includes all sources with only attenuation applied.

Second, if the effect send has 4 channels, it may be configured to be a reverb effect send with the isReverb parameter. Reverb effect sends are treated differently in terms of attenuation: as sources move away from the listener, their dry path becomes less but the audio sent to the reverb effect send becomes greater.

No effect send can include occlusion effects.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` channels The number of channels the effect send is to have. Must be 1, 2, 4, 6, or 8. `int` isReverb nonzero if this is a reverb effect send. `int` connectByDefault If nonzero, all existing and newly created sources will send to this effect send unless disabled. `int*` destination Holds the result of a call to this function.
##### play_async

Prototype: `LavError Lav_environmentNodePlayAsync(LavHandle nodeHandle, LavHandle bufferHandle, float x, float y, float z, int isDry)`

Play a buffer, using the specified position and the currently set defaults on the world for distance model and panning strategy. This is the same as creating a buffer and a source, but Libaudioverse retains control of these objects. When the buffer finishes playing, the source is automatically disposed of.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `LavHandle` bufferHandle The buffer to play. `float` x The x-component of the position. `float` y The y-component of the position. `float` z The z-component of the position. `int` isDry If true, we avoid sending to the effect sends configured as defaults.

### Fdn Reverb Node

C Type Identifier: `Lav_OBJTYPE_FDN_REVERB_NODE`

Constructor: `LavError Lav_createFdnReverbNode(LavHandle serverHandle, LavHandle* destination)`

 Index Channels Description 0 4 The signal to apply reverb to.
 Index Channels Description 0 4 The signal with reverb applied.

An 8 delay line FDN reverberator, based off a householder reflection.

This reverb takes as its input and outputs ats its output quadraphonic audio. Panning effects will still be observed at the output with some bias. If a stereo signal is fed into the reverb and the reverb is likewise connected to a stereo output, the input signal’s volume will effectively be halved.

#### Properties

##### cutoff_frequency

C Enumeration Value: Lav_FDN_REVERB_CUTOFF_FREQUENCY

Type: float

Range: dynamic

Default Value: 5000

Rate: k

Controls the frequencies of lowpass filters on the feedback path of the reverb. Lowering this property leads to softer and less harsh reverb.

##### delay_modulation_depth

C Enumeration Value: Lav_FDN_REVERB_DELAY_MODULATION_DEPTH

Type: float

Range: [0.0, 1.0]

Default Value: 0.0

Rate: k

Controls how deep the modulation of the delay lines is. Increasing this property slightly makes the late reverb sound less metallic, while extremely high values add chorus-like effects. This property acts as a multiplier, and the correspondance between it and physical units is intentionally left unspecified.

##### delay_modulation_frequency

C Enumeration Value: Lav_FDN_REVERB_DELAY_MODULATION_FREQUENCY

Type: float

Range: [0.0, 500.0]

Default Value: 10.0

Rate: k

Controls how fast the internal delay lines modulate.

##### density

C Enumeration Value: Lav_FDN_REVERB_DENSITY

Type: float

Range: [0.0, 1.0]

Default Value: 0.5

Rate: k

Controls the density of the reverb. Extremely low values sound "grainy"; extremely high values tend to resonate.

##### t60

C Enumeration Value: Lav_FDN_REVERB_T60

Type: float

Range: [0.0, 'INFINITY']

Default Value: 1.0

Rate: k

The `t60` is the time it takes the reverb to decay by 60 decibals.

### Feedback Delay Network Node

C Type Identifier: `Lav_OBJTYPE_FEEDBACK_DELAY_NETWORK_NODE`

Constructor: `LavError Lav_createFeedbackDelayNetworkNode(LavHandle serverHandle, float maxDelay, int channels, LavHandle* destination)`

The inputs of this node are described below.

The outputs of this node are described below.

Implements a feedback delay network. This is possibly the single-most complicated node in Libaudioverse, and full documentation of it goes well beyond the manual. Unless you know what a feedback delay network is and have a specific reason for using one, this node will probably not help you.

This node has `n` inputs and outputs, where `n` is the `lines` parameter to the constructor. Each input and output pair represent the input and output of a specific delay line, respectively.

#### Properties

##### delays

C Enumeration Value: Lav_FDN_DELAYS

Type: float_array

Default Value: See below

Rate: k

The lengths of the delay lines in seconds. This array must be `channels` long. All values must be positive and no more than the maximum delay specified to the constructor.

##### filter_frequencies

C Enumeration Value: Lav_FDN_FILTER_FREQUENCIES

Type: float_array

Default Value: See below

Rate: k

The frequencies of the filters. The range of this property is 0 to Nyquist, or half the sampling rate.

##### filter_types

C Enumeration Value: Lav_FDN_FILTER_TYPES

Type: int_array

Default Value: See below

Rate: k

Allows insertion of filters in the feedback paths. These filters can be individually enabled and disabled; the default is disabled.

##### matrix

C Enumeration Value: Lav_FDN_MATRIX

Type: float_array

Default Value: See below

Rate: k

The feedback matrix.

A column vector is formed by reading all delay lines. This vector is multiplied by this matrix, and then fed back into the delay lines.

The matrix is stored in row-major order. The supplied array must have a length equal to the square of the channels specified to the constructor.

##### max_delay

C Enumeration Value: Lav_FDN_MAX_DELAY

Type: float

The maximum delay any of the internal delay lines may be set to.

##### output_gains

C Enumeration Value: Lav_FDN_OUTPUT_GAINS

Type: float_array

Default Value: See below

Rate: k

Allows control of the individual gains of the output. These gains do not apply to the feedback path and are only for controlling relative output levels. The array for this property allows any floating point values, and must be exactly `channels` long.

### Fft Convolver Node

C Type Identifier: `Lav_OBJTYPE_FFT_CONVOLVER_NODE`

Constructor: `LavError Lav_createFftConvolverNode(LavHandle serverHandle, int channels, LavHandle* destination)`

 Index Channels Description 0 The number of channels for this input depends on parameters to this node’s constructor. The signal to be convolved.
 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. The convolved signal.

A convolver for long impulse responses.

This convolver uses the overlap-add convolution algorithm. It is slower than the convolver node for small impulse responses.

The difference between this node and the convolver node is the complexity of the algorithm. This node is capable of handling impulses longer than a second, a case for which the convolver node will fail to run in realtime.

Furthermore, as the most common operation for this node is reverb, it is possible to set each channel’s response separately.

#### Extra Functions

##### set_response

Prototype: `LavError Lav_fftConvolverNodeSetResponse(LavHandle nodeHandle, int channel, int length, float* response)`

Set the response for a specific channel.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` channel The channel to set the response for. `int` length The length of the response in samples. `float*` response The new response.
##### set_response_from_file

Prototype: `LavError Lav_fftConvolverNodeSetResponseFromFile(LavHandle nodeHandle, const char* path, int fileChannel, int convolverChannel)`

Set the impulse response for a specific channel of this node from a file.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `const char*` path The path to the file. `int` fileChannel The channel of the file to use as the response. `int` convolverChannel The channel for which the response is to be set.

### File Streamer Node

C Type Identifier: `Lav_OBJTYPE_FILE_STREAMER_NODE`

Constructor: `LavError Lav_createFileStreamerNode(LavHandle serverHandle, const char* path, LavHandle* destination)`

This node has no inputs.

 Index Channels Description 0 Depends on the file. The output of the stream.

Streams a file, which must be specified to the constructor and cannot be changed thereafter.

This node is a stopgap solution, and should be considered temporary. It will likely remain for backward compatibility. Libaudioverse plans to eventually offer a more generic streaming node that also supports web addresses; such a node will have a completely different, less buffer-like interface.

In order to stream a file, it must be passed through a resampler. Consequentlty, the position property is slightly inaccurate and the ended property and callback are slightly delayed.

#### Properties

##### ended

C Enumeration Value: Lav_FILE_STREAMER_ENDED

Type: boolean

Switches from false to true once the stream has ended completely and gone silent. This property will never go true unless looping is false.

##### looping

C Enumeration Value: Lav_FILE_STREAMER_LOOPING

Type: boolean

Default Value: 0

Rate: k

If true, this node repeats the file from the beginning once it reaches the end. Note that setting looping means that ended will never go true. If ended is already true, it may take until the end of the next processing block for ended to properly go false once more.

##### position

C Enumeration Value: Lav_FILE_STREAMER_POSITION

Type: double

Range: dynamic

Default Value: 0.0

Rate: k

The position of playback, in seconds. The range of this property corresponds to the total duration of the file. Note that this property may be slightly inaccurate because this node has to pass data through a resampler.

#### Callbacks

##### end

Setter: LavError Lav_fileStreamerNodeSetEndCallback(LavHandle nodeHandle, LavParameterlessCallback callback, void* userdata)

Callback Prototype: void (LavHandle nodeHandle, void* userdata)

 Type Name Description `LavHandle` nodeHandle The node which called this callback. `void*` userdata The userdata parameter as passed to the setter for this callback.

Called outside the audio threads after the stream has both reached its end and gone silent. When called, ended will be set to true,.

### Filtered Delay Node

C Type Identifier: `Lav_OBJTYPE_FILTERED_DELAY_NODE`

Constructor: `LavError Lav_createFilteredDelayNode(LavHandle serverHandle, float maxDelay, unsigned int channels, LavHandle* destination)`

 Index Channels Description 0 The number of channels for this input depends on parameters to this node’s constructor. The signal to process.
 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. The result of processing the audio via the filter and delay line.

This node consists of a delay line with a biquad filter attached. The output of the delay line is filtered. The difference between this node and a delay line and filter pair is that this node will use the filtered output for the feedback.

This node is equivalent to the delay line in the Karplus-strong algorithm.

#### Properties

##### dbgain

C Enumeration Value: Lav_FILTERED_DELAY_DBGAIN

Type: float

Range: ['-INFINITY', 'INFINITY']

Default Value: 0.0

Rate: k

This property is a the gain in decibals to be used with the peaking and shelving filters. It measures the gain that these filters apply to the part of the signal they boost.

##### delay

C Enumeration Value: Lav_FILTERED_DELAY_DELAY

Type: float

Range: dynamic

Default Value: 0.0

Rate: k

The delay of the delay line in seconds. The range of this property depends on the maxDelay parameter to the constructor.

##### delay_max

C Enumeration Value: Lav_FILTERED_DELAY_DELAY_MAX

Type: float

The max delay as set at the node’s creation time.

##### feedback

C Enumeration Value: Lav_FILTERED_DELAY_FEEDBACK

Type: float

Range: ['-INFINITY', 'INFINITY']

Default Value: 0.0

Rate: k

The feedback coefficient. The output of the filter is fed back into the delay line, multiplied by this coefficient.

##### filter_type

C Enumeration Value: Lav_FILTERED_DELAY_FILTER_TYPE

Type: int

Range: A value from the Lav_BIQUAD_TYPES enumeration.

Rate: k

The type of the filter. This determines the interpretations of the other properties on this node.

##### frequency

C Enumeration Value: Lav_FILTERED_DELAY_FREQUENCY

Type: float

Range: [0, 'INFINITY']

Default Value: 2000.0

Rate: k

This is the frequency of interest. What specifically this means depends on the selected filter type; for example, it is the cutoff frequency for lowpass and highpass.

##### interpolation_time

C Enumeration Value: Lav_FILTERED_DELAY_INTERPOLATION_TIME

Type: float

Range: [0.001, 'INFINITY']

Default Value: 0.001

Rate: k

When the delay property is changed, the delay line crossfades between the old position and the new one. This property sets how long this crossfade will take. Note that for this node, it is impossible to get rid of the crossfade completely.

##### q

C Enumeration Value: Lav_FILTERED_DELAY_Q

Type: float

Range: [0.001, 'INFINITY']

Default Value: 0.5

Rate: k

Q is a mathematically complex parameter, a full description of which is beyond the scope of this manual. For lowpass, bandpass, and high pass filters, Q can be interpreted as a measure of resonation. For Q⇐0.5, the filter is said to be damped: it will cut frequencies. For Q>0.5, however, some frequencies are likely to be boosted.

Q controls the bandwidth for the bandpass and peaking filter types as well as the slope for the shelving EQ.

For everything except the peaking filter, this property follows the normal definition of Q in the electrical engineering literature. For more specifics, see the Audio EQ Cookbook. It is found here: http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt

### First Order Filter Node

C Type Identifier: `Lav_OBJTYPE_FIRST_ORDER_FILTER_NODE`

Constructor: `LavError Lav_createFirstOrderFilterNode(LavHandle serverHandle, int channels, LavHandle* destination)`

 Index Channels Description 0 The number of channels for this input depends on parameters to this node’s constructor. The signal to filter.
 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. The filtered signal.

A first order filter section, implementing the transfer function $H(Z) = \frac{B_0 + B_1 Z^{-1} }{1+A_0 Z^{-1} }$

This filter is not your friend unless you know DSP or have a specific goal in mind. Most applications will want a biquad filter node or a One-Pole Filter node instead.

This filter is not controlled through frequency specifications. Instead, the position of the pole and the zero on the real axis are individually controllable with a-rate properties. Some helper functions exist to position them for common configurations, but other filter types do most of it better. The major advantage for this filter type is that it is incredibly inexpensive as compared to the IIR filter node and supports automation of the pole and zero’s position.

#### Properties

##### pole

C Enumeration Value: Lav_FIRST_ORDER_FILTER_POLE

Type: float

Range: ['-INFINITY', 'INFINITY']

Default Value: 0.0

Rate: a

The position of the pole on the real axis.

The pole may be positioned anywhere, but stable filters usually keep all poles inside the unit circle. For a stable filter, the value of this property should usually between -1 and 1.

##### zero

C Enumeration Value: Lav_FIRST_ORDER_FILTER_ZERO

Type: float

Range: ['-INFINITY', 'INFINITY']

Default Value: 0.0

Rate: a

The position of the zero on the real axis.

#### Extra Functions

##### configure_allpass

Prototype: `LavError Lav_firstOrderFilterNodeConfigureAllpass(LavHandle nodeHandle, float frequency)`

Configure this node as an allpass. You specify the $\frac{\pi}{2}$ frequency. You get a filter with a phase of $\pi$ at DC and 0 at Nyquist.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `float` frequency The frequency at which the filter has a phase of $\frac{\pi}{2}$. Must be between 0 and Nyquist.
##### configure_highpass

Prototype: `LavError Lav_firstOrderFilterNodeConfigureHighpass(LavHandle nodeHandle, float frequency)`

Configure the filter as a highpass with a roll-off of `6 DB` per octave. This is identical to the One-Pole Filter node highpass configuration.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `float` frequency The `-3 DB` frequency. Must be between 0 and Nyquist.
##### configure_lowpass

Prototype: `LavError Lav_firstOrderFilterNodeConfigureLowpass(LavHandle nodeHandle, float frequency)`

Configure the filter as a first-order Butterworth lowpass. This is equivalent to the One-Pole Filter node lowpass configuration.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `float` frequency The `-3 DB` frequency. Must be between 0 and nyquist.

### Gain Node

C Type Identifier: `Lav_OBJTYPE_GAIN_NODE`

Constructor: `LavError Lav_createGainNode(LavHandle serverHandle, int channels, LavHandle* destination)`

 Index Channels Description 0 The number of channels for this input depends on parameters to this node’s constructor. The signal whose gain is to be changed.
 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. The signal with its gain changed.

This node is essentially in instantiated generic node, offering only the functionality therein. Its purpose is to allow changing the gain or adding offset to a large collection of nodes. One possible use is as a simple mixer: point all the nodes to be mixed at the input, set mul, and then point the output at the destination for the mixed audio.

### Graph Listener Node

C Type Identifier: `Lav_OBJTYPE_GRAPH_LISTENER_NODE`

Constructor: `LavError Lav_createGraphListenerNode(LavHandle serverHandle, unsigned int channels, LavHandle* destination)`

 Index Channels Description 0 The number of channels for this input depends on parameters to this node’s constructor. The audio which will be passed to the associated callback.
 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. The same audio as connected to the input without modification.

This node defines a callback which is called every block. The callback is passed pointers to the audio data passing through this node for the current block. The effect is that this node allows observing audio passing through any location in the audio graph.

#### Callbacks

##### listening

Setter: LavError Lav_graphListenerNodeSetListeningCallback(LavHandle nodeHandle, LavGraphListenerNodeListeningCallback callback, void* userdata)

Callback Prototype: void (LavHandle nodeHandle, unsigned int frames, unsigned int channels, float* buffer, void* userdata)

 Type Name Description `LavHandle` nodeHandle The node which called this callback. `unsigned int` frames The number of frames of audio being made available to client code. This should always be the same as the server’s block size. `unsigned int` channels The number of channels of audio being made available to client code. `float*` buffer The data, stored in interleaved format. The length of this buffer is `frames*channels`. `void*` userdata The userdata parameter as passed to the setter for this callback.

When set, audio is passed to this callback every block. This callback is called inside the audio threads; do not block.

### Hard Limiter Node

C Type Identifier: `Lav_OBJTYPE_HARD_LIMITER_NODE`

Constructor: `LavError Lav_createHardLimiterNode(LavHandle serverHandle, int channels, LavHandle* destination)`

 Index Channels Description 0 The number of channels for this input depends on parameters to this node’s constructor. The signal to limit
 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. The limited signal: no sample shall have an absolute value greater than 1.0.

The input to this node is hard limited: values less than -1.0 are set to -1.0 and values above 1.0 are set to 1.0. Use the hard limiter in order to prevent oddities with audio hardware; it should usually be the last piece in your pipeline before the server. Note that the 3D API handles hard limiting appropriately, and you do not need to worry about this there.

### Hrtf Node

C Type Identifier: `Lav_OBJTYPE_HRTF_NODE`

Constructor: `LavError Lav_createHrtfNode(LavHandle serverHandle, const char* hrtfPath, LavHandle* destination)`

 Index Channels Description 0 1 The signal to pan.
 Index Channels Description 0 2 The signal with the HRTF applied.

This node implements an HRTF panner. You can use either Libaudioverse’s internal HRTF (The Diffuse MIT Kemar Dataset) by passing "default" as the HRTf file name, or an HRTF of your own.

#### Properties

##### azimuth

C Enumeration Value: Lav_PANNER_AZIMUTH

Type: float

Range: ['-INFINITY', 'INFINITY']

Default Value: 0.0

Rate: k

The horizontal angle of the panner in degrees. 0 is straight ahead and positive values are clockwise.

##### elevation

C Enumeration Value: Lav_PANNER_ELEVATION

Type: float

Range: [-90.0, 90.0]

Default Value: 0.0

Rate: k

The vertical angle of the panner in degrees. 0 is horizontal and positive values move upward.

Type: boolean

Default Value: 1

Rate: k

By default, panners crossfade their output. This property allows such functionality to be disabled. Note that for HRTF nodes, crossfading is more important than for other panner types. Unlike other panner types, the audio artifacts produced by disabling crossfading are noticeable, even for updates of only a few degrees.

### Iir Filter Node

C Type Identifier: `Lav_OBJTYPE_IIR_NODE`

Constructor: `LavError Lav_createIirNode(LavHandle serverHandle, int channels, LavHandle* destination)`

 Index Channels Description 0 The number of channels for this input depends on parameters to this node’s constructor. The signal to filter.
 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. The signal with the IIR filter applied.

Implements arbetrary IIR filters. The only restriction on the filter is that the first element of the denominator must be nonzero. To configure this node, use the function Lav_iirNodeSetCoefficients.

#### Extra Functions

##### set_coefficients

Prototype: `LavError Lav_iirNodeSetCoefficients(LavHandle nodeHandle, int numeratorLength, double* numerator, int denominatorLength, double* denominator, int shouldClearHistory)`

Configure the coefficients of the IIR filter.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` numeratorLength The number of coefficients in the numerator of the filter’s transfer function. `double*` numerator The numerator of the transfer function. `int` denominatorLength The number of coefficients in the denominator of the transfer function. Must be at least 1. `double*` denominator The denominator of the transfer function. The first coefficient must be nonzero. `int` shouldClearHistory 1 if we should reset the internal histories, otherwise 0.

### Leaky Integrator Node

C Type Identifier: `Lav_OBJTYPE_LEAKY_INTEGRATOR_NODE`

Constructor: `LavError Lav_createLeakyIntegratorNode(LavHandle serverHandle, int channels, LavHandle* destination)`

 Index Channels Description 0 The number of channels for this input depends on parameters to this node’s constructor. A signal to integrate.
 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. The integral of the signal.

A leaky integrator. Leaky integrators integrate their input signals, while leaking over time. Introducing the leak allows for avoiding DC offset problems. If you feed this node a signal that is zero, it will slowly decrease the output in accordance with the Lav_LEAKY_INTEGRATOR_LEAKYNESS property.

#### Properties

##### leakyness

C Enumeration Value: Lav_LEAKY_INTEGRATOR_LEAKYNESS

Type: double

Range: [0.0, 1.0]

Default Value: 1.0

Rate: k

The leakyness (or time constant) of the integrator.

If you feed the leaky integrator a constant signal of 0, then this property’s value is the percent decrease as observed after 1 second.

### Multipanner Node

C Type Identifier: `Lav_OBJTYPE_MULTIPANNER_NODE`

Constructor: `LavError Lav_createMultipannerNode(LavHandle serverHandle, char* hrtfPath, LavHandle* destination)`

 Index Channels Description 0 1 The signal to pan.
 Index Channels Description 0 Depends on the currently set panning strategy. The signal, panned according to the configured panning strategy.

A panner which can have the algorithm it uses changed at runtime. The use for multipanners is for applications in which we may wish to change the speaker configuration at runtime. Capabilities include switching from HRTF to stereo and back, a useful property for games wherein the user might or might not be using headphones.

#### Properties

##### azimuth

C Enumeration Value: Lav_PANNER_AZIMUTH

Type: float

Range: ['-INFINITY', 'INFINITY']

Default Value: 0.0

Rate: k

The horizontal angle of the panner, in degrees. 0 is straight ahead and positive values are clockwise.

##### elevation

C Enumeration Value: Lav_PANNER_ELEVATION

Type: float

Range: [-90.0, 90.0]

Default Value: 0.0

Rate: k

The vertical angle of the panner, in degrees. 0 is horizontal and positive values are upward.

Type: boolean

Default Value: 1

Rate: k

Whether or not this panner should crossfade. Lack of crossfading introduces audible artifacts when the panner is moved. You usually want this on.

##### strategy

C Enumeration Value: Lav_PANNER_STRATEGY

Type: int

Range: A value from the Lav_PANNING_STRATEGIES enumeration.

Default Value: Lav_PANNING_STRATEGY_STEREO

Rate: k

What type of panning to use. Possibilities include HRTF, stereo, 5.1, and 7.1 speaker configurations. For something more nontraditional, use an amplitude panner.

### Noise Generator Node

C Type Identifier: `Lav_OBJTYPE_NOISE_NODE`

Constructor: `LavError Lav_createNoiseNode(LavHandle serverHandle, LavHandle* destination)`

This node has no inputs.

 Index Channels Description 0 1 The noise generated by this node.

Generates any of a variety of types of noise.

#### Properties

##### noise_type

C Enumeration Value: Lav_NOISE_NOISE_TYPE

Type: int

Range: A value from the Lav_NOISE_TYPES enumeration.

Default Value: Lav_NOISE_TYPE_WHITE

Rate: k

The type of noise to generate.

##### should_normalize

C Enumeration Value: Lav_NOISE_SHOULD_NORMALIZE

Type: boolean

Default Value: 0

Rate: k

Whether or not to normalize the output. Some types of noise are quieter without this enabled. Turning it on is sometimes helpful and sometimes not.

### One-Pole Filter Node

C Type Identifier: `Lav_OBJTYPE_ONE_POLE_FILTER_NODE`

Constructor: `LavError Lav_createOnePoleFilterNode(LavHandle serverHandle, int channels, LavHandle* destination)`

 Index Channels Description 0 The number of channels for this input depends on parameters to this node’s constructor. The signal to filter.
 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. The filtered signal.

A one-pole filter section, implementing the transfer function $H(Z) = rac{1}{1+A_0 Z^{-1} }$

This filter is capable of implementing either a lowpass or highpass filter and is extremmely cheep. The produced filter rolls off at about 6 DB per octave.

The default filter configuration is a lowpass at 500 HZ. The type of the filter is controlled via the `is_highpass` property. If said property is true, the filter becomes a highpass.

Note that this filter can be swept with a-rate accuracy.

#### Properties

##### frequency

C Enumeration Value: Lav_ONE_POLE_FILTER_FREQUENCY

Type: float

Range: dynamic

Default Value: 500.0

Rate: a

The -3 DB frequency of the filter.

The range of this property is from 0 to half the sampling rate.

##### is_highpass

C Enumeration Value: Lav_ONE_POLE_FILTER_IS_HIGHPASS

Type: boolean

Default Value: 0

Rate: k

True if the filter is a highpass.

If this property is false, the filter is a lowpass.

### Pull Node

C Type Identifier: `Lav_OBJTYPE_PULL_NODE`

Constructor: `LavError Lav_createPullNode(LavHandle serverHandle, unsigned int sr, unsigned int channels, LavHandle* destination)`

This node has no inputs.

 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. The result of the configured callback.

This node calls the audio callback whenever it needs more audio. The purpose of this node is to inject audio from an external source that Libaudioverse does not support, for example a custom network protocol.

#### Callbacks

##### audio

Setter: LavError Lav_pullNodeSetAudioCallback(LavHandle nodeHandle, LavPullNodeAudioCallback callback, void* userdata)

Callback Prototype: void (LavHandle nodeHandle, int frames, int channels, float* buffer, void* userdata)

 Type Name Description `LavHandle` nodeHandle The node which called this callback. `int` frames The number of frames of audio needed. This is not guaranteed to be the same on every call. `int` channels The number of channels as set when the pull node is created. `float*` buffer The destination to which audio should be written. This is a buffer that is `frames*channels` long. Write interleaved audio data to it and do not assume that it is zeroed. `void*` userdata The userdata parameter as passed to the setter for this callback.

Called when the node needs more audio.

### Push Node

C Type Identifier: `Lav_OBJTYPE_PUSH_NODE`

Constructor: `LavError Lav_createPushNode(LavHandle serverHandle, unsigned int sr, unsigned int channels, LavHandle* destination)`

This node has no inputs.

 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. Either audio from the internal queue or zero.

The purpose of this node is the same as the pull node, but it is used in situations wherein we do not know when we are going to get audio. Audio is queued as it is pushed to this node and then played as fast as possible. This node can be used to avoid writing a queue of audio yourself, as it essentially implements said functionality. If you need low latency audio or the ability to run something like the Opus encoder’s ability to cover for missing frames, you need a pull node.

#### Properties

##### threshold

C Enumeration Value: Lav_PUSH_THRESHOLD

Type: float

Range: [0.0, 'INFINITY']

Default Value: 0.03

Rate: k

When the remaining audio in the push node has a duration less than this property, the low callback is called.

#### Callbacks

##### low

Setter: LavError Lav_pushNodeSetLowCallback(LavHandle nodeHandle, LavParameterlessCallback callback, void* userdata)

Callback Prototype: void (LavHandle nodeHandle, void* userdata)

 Type Name Description `LavHandle` nodeHandle The node which called this callback. `void*` userdata The userdata parameter as passed to the setter for this callback.

Called once per block and outside the audio thread when there is less than the specified threshold audio remaining.

##### underrun

Setter: LavError Lav_pushNodeSetUnderrunCallback(LavHandle nodeHandle, LavParameterlessCallback callback, void* userdata)

Callback Prototype: void (LavHandle nodeHandle, void* userdata)

 Type Name Description `LavHandle` nodeHandle The node which called this callback. `void*` userdata The userdata parameter as passed to the setter for this callback.

Called exactly once and outside the audio thread when the node runs out of audio completely.

#### Extra Functions

##### feed

Prototype: `LavError Lav_pushNodeFeed(LavHandle nodeHandle, unsigned int length, float* frames)`

Feed more audio data into the internal queue.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `unsigned int` length The length of the buffer, in samples. `float*` frames The buffer to feed into the node. This memory is copied.

### Recorder Node

C Type Identifier: `Lav_OBJTYPE_RECORDER_NODE`

Constructor: `LavError Lav_createRecorderNode(LavHandle serverHandle, int channels, LavHandle* destination)`

 Index Channels Description 0 The number of channels for this input depends on parameters to this node’s constructor. The signal to record.
 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. The same as the input signal.

Records audio to files.

The usage pattern for this node is simple: connect something to the input, call Lav_recorderNodeStartRecording, and ensure that the node is processed. In order to avoid potential problems with blocks of silence at the beginning of the recording, this node’s default state is playing. You should connect the output to something that will demand the recorder node’s audio or change the state to always playing, usually after a call to Lav_recorderNodeStartRecording. If you don’t, no recording will take place.

Unlike most other nodes in Libaudioverse, it is important that you call Lav_recorderNodeStopRecording when done recording. Failure to do so may lead to any of a number of surprising results.

#### Extra Functions

##### start_recording

Prototype: `LavError Lav_recorderNodeStartRecording(LavHandle nodeHandle, const char* path)`

Begin recording to the specified files. The sample rate is the same as that of the server. The channel count is the same as this node was initialized with. The format of the file is determined from the extension: this function recognizes ".wav" and ".ogg" on all platforms.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `const char*` path The path of the file to record to.
##### stop_recording

Prototype: `LavError Lav_recorderNodeStopRecording(LavHandle nodeHandle)`

Stops recording.

Be sure to call this function. Failure to do so may lead to any of a number of undesirable problems.

 Type Name Description `LavHandle` nodeHandle The node to manipulate.

### Ring Modulator Node

C Type Identifier: `Lav_OBJTYPE_RINGMOD_NODE`

Constructor: `LavError Lav_createRingmodNode(LavHandle serverHandle, LavHandle* destination)`

 Index Channels Description 0 1 The first signal. 1 1 The second signal.
 Index Channels Description 0 1 The result of multiplying the two input signals together.

This node has two inputs and one output. The two inputs will be converted to mono and then multiplied, before being sent to the output.

### Sine Node

C Type Identifier: `Lav_OBJTYPE_SINE_NODE`

Constructor: `LavError Lav_createSineNode(LavHandle serverHandle, LavHandle* destination)`

This node has no inputs.

 Index Channels Description 0 1 A sine wave.

A simple sine oscillator.

#### Properties

##### frequency

C Enumeration Value: Lav_OSCILLATOR_FREQUENCY

Type: float

Range: [0, 'INFINITY']

Default Value: 440.0

Rate: a

The frequency of the sine wave in HZ.

##### frequency_multiplier

C Enumeration Value: Lav_OSCILLATOR_FREQUENCY_MULTIPLIER

Type: float

Range: ['-INFINITY', 'INFINITY']

Default Value: 1.0

Rate: a

An additional multiplicative factor applied to the frequency of the oscillator.

This is useful for creating instruments, as the notes of the standard musical scale fall on frequency multiples of a reference pitch, rather than a linear increase.

##### phase

C Enumeration Value: Lav_OSCILLATOR_PHASE

Type: float

Range: [0.0, 1.0]

Default Value: 0.0

Rate: k

The phase of the sine node. This is measured in periods, not in radians.

### Source Node

C Type Identifier: `Lav_OBJTYPE_SOURCE_NODE`

Constructor: `LavError Lav_createSourceNode(LavHandle serverHandle, LavHandle environmentHandle, LavHandle* destination)`

 Index Channels Description 0 1 The audio to enter the 3D environment.

This node has no outputs.

The source node allows the spatialization of sound that passes through it. Sources have one input which is mono, to which a node should be connected. The audio from the input is spatialized according both to the source’s properties and those on its environment, and passed directly to the environment. Sources have no outputs. To hear a source, you must connect its environment to something instead.

Since the source communicates with the environment through a nonstandard mechanism, environments do not keep their sources alive. If you are in a garbage collected language, failure to hold on to the source nodes will cause them to go silent.

#### Properties

##### control_distance_model

C Enumeration Value: Lav_SOURCE_CONTROL_DISTANCE_MODEL

Type: boolean

Default Value: 0

Rate: k

In order to make working with sources easier for simple applications, some properties of source objects are ignored in favor of values on the environment. This property is used to disable this behavior for properties related to the distance model.

##### control_panning

C Enumeration Value: Lav_SOURCE_CONTROL_PANNING

Type: boolean

Default Value: 0

Rate: k

In order to make working with sources easier for simple applications, some properties of source objects are ignored in favor of values on the environment. This property is used to disable this behavior for properties related to panning.

##### control_reverb

C Enumeration Value: Lav_SOURCE_CONTROL_REVERB

Type: boolean

Default Value: 0

Rate: k

In order to make working with sources easier for simple applications, some properties of source objects are ignored in favor of values on the environment. This property is used to disable this behavior for properties related to reverb.

##### distance_model

C Enumeration Value: Lav_SOURCE_DISTANCE_MODEL

Type: int

Range: A value from the Lav_DISTANCE_MODELS enumeration.

Default Value: Lav_DISTANCE_MODEL_LINEAR

Rate: k

The distance model determines how quickly sources get quieter as they move away from the listener. The default value of this property is set from the corresponding property on the environment at source creation. By default, sources ignore this property in favor of the value provided by their environment. Set Lav_SOURCE_CONTROL_DISTANCE_MODEL to true to control it yourself.

Type: boolean

Default Value: 0

Rate: k

Whether or not to consider this source’s position to always be relative to the listener.

Sources which are head relative interpret their positions in the default coordinate system, relative to the listener. Positive x is right, positive y is up, and positive z is behind the listener. The orientation and position properties of an environment do not affect head relative sources, making them ideal for such things as footsteps and/or HUD effects that should be panned.

##### max_distance

C Enumeration Value: Lav_SOURCE_MAX_DISTANCE

Type: float

Range: [0.0, 'INFINITY']

Default Value: 150.0

Rate: k

The maximum distance from the listener at which the source will be audible. The default value of this property is set from the corresponding property on the environment at source creation. By default, sources do not respect this property and use the corresponding value from their environment. Set Lav_SOURCE_CONTROL_DISTANCE_MODEL to true to control it yourself.

##### max_reverb_level

C Enumeration Value: Lav_SOURCE_MAX_REVERB_LEVEL

Type: float

Range: [0.0, 1.0]

Default Value: 0.6

Rate: k

The maximum amount of audio to be diverted to reverb sends, if any.

Behavior is undefined if this property is ever less than Lav_SOURCE_MIN_REVERB_LEVEL.

The default value of this property is set from the corresponding property on the environment at source creation. By default, this property is ignored in favor of the value provided by this source’s environment. Set Lav_SOURCE_CONTROL_REVERB to true to control it yourself.

##### min_reverb_level

C Enumeration Value: Lav_SOURCE_MIN_REVERB_LEVEL

Type: float

Range: [0.0, 1.0]

Default Value: 0.15

Rate: k

The minimum reverb level allowed.

if a send is configured to be a reverb send, this is the minimum amount of audio that will be diverted to it.

Behavior is undefined if this property is ever greater than the value you give to Lav_SOURCE_MAX_REVERB_LEVEL.

The default value of this property is set from the corresponding property on the environment at source creation. By default, this property is ignored in favor of the value provided by this source’s environment. Set Lav_SOURCE_CONTROL_REVERB to true to control it yourself.

##### occlusion

C Enumeration Value: Lav_SOURCE_OCCLUSION

Type: float

Range: [0.0, 1.0]

Default Value: 0.0

Rate: k

A scalar representing how occluded this source is.

This property controls internal filters of the source that make occluded objects sound muffled. A value of 1.0 is a fully occluded source, which will be all but silent; a value of 0.0 has no effect.

It is extremely difficult to map occlusion to a physical quantity. As a consequence, this property is unitless.

##### orientation

C Enumeration Value: Lav_SOURCE_ORIENTATION

Type: float6

Default Value: [0.0, 0.0, -1.0, 0.0, 1.0, 0.0]

Rate: k

The orientation of the source. This is not currently used. In future, it will be used for sound cones and filters on sources facing away. The interpretation is the same as that for the listener: the first 3 values are the direction of the front and the second 3 the direction of the top. Note that these must both be unit vectors and that they must be orthoganal. They are packed because, also like the listener, they must never be modified separately.

##### panning_strategy

C Enumeration Value: Lav_SOURCE_PANNING_STRATEGY

Type: int

Range: A value from the Lav_PANNING_STRATEGIES enumeration.

Default Value: Lav_PANNING_STRATEGY_STEREO

Rate: k

The strategy for the internal multipanner. The default value of this property is set from the corresponding property on the environment at source creation. By default, this property is ignored and sources use the value provided by their environment. Set Lav_SOURCE_CONTROL_PANNING to true to control it yourself.

##### position

C Enumeration Value: Lav_SOURCE_POSITION

Type: float3

Default Value: [0.0, 0.0, 0.0]

Rate: k

The position of the source in world coordinates.

##### reverb_distance

C Enumeration Value: Lav_SOURCE_REVERB_DISTANCE

Type: float

Range: [0.0, 'INFINITY']

Default Value: 75.0

Rate: k

The distance at which the source will only be heard through the reverb effect sends.

If this source is not feeding any effect sends configured as reverbs, this property has no effect.

For values greater than Lav_SOURCE_MAX_DISTANCE, the source will always be heard at least somewhat in the dry path. Lav_SOURCE_DISTANCE_MODEL controls how this crossfading takes place.

The default value of this property is set from the corresponding property on the environment at source creation. By default, sources ignore this property in favor of the value provided by their environment. Set Lav_SOURCE_CONTROL_REVERB to true to control it yourself.

##### size

C Enumeration Value: Lav_SOURCE_SIZE

Type: float

Range: [0.0, 'INFINITY']

Default Value: 0.0

Rate: k

The size of the source. Sources are approximated as spheres. The size is used to determine the closest point on the source to the listener, and is the radius of this sphere. Size currently has no other effect.

The default value of this property is set from the corresponding property on the environment at source creation.

#### Extra Functions

##### feed_effect

Prototype: `LavError Lav_sourceNodeFeedEffect(LavHandle nodeHandle, int effect)`

Begin feeding the specified effect send.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` effect The index of the effect send to feed.
##### set_properties_from_environment

Prototype: `LavError Lav_sourceNodeSetPropertiesFromEnvironment(LavHandle nodeHandle)`

A convenience function for working with properties on sources. When called, this function sets the values of all properties which have corresponding properties on the environment to the values from the environment.

 Type Name Description `LavHandle` nodeHandle The node to manipulate.
##### stop_feeding_effect

Prototype: `LavError Lav_sourceNodeStopFeedingEffect(LavHandle nodeHandle, int effect)`

Stop feeding an effect send.

 Type Name Description `LavHandle` nodeHandle The node to manipulate. `int` effect The send to stop feeding.

### Three Band Eq Node

C Type Identifier: `Lav_OBJTYPE_THREE_BAND_EQ_NODE`

Constructor: `LavError Lav_createThreeBandEqNode(LavHandle serverHandle, int channels, LavHandle* destination)`

 Index Channels Description 0 The number of channels for this input depends on parameters to this node’s constructor. The signal to equalize.
 Index Channels Description 0 The number of channels for this output depends on parameters to this node’s constructor. The equalized signal.

A three band equalizer.

This node consists of a peaking filter and a highshelf filter in series, such that the frequency spectrum may be equalized in three, configurable bands.

The lowest of these bands begins at `lowband_frequency` and continues down to `0 hz`. The highest is from `highband_frequency` and continues until nyquist. The middle is the remaining space between the low and high band. If the high band begins below the low band, behavior is undefined, but will almost certainly not do what you want. Libaudioverse does not check for this case.

The slopes that this node institutes are not perfect and cannot increase effectively beyond a certain point. This is the least expensive of the Libaudioverse equalizers, and is sufficient for many simpler applications.

#### Properties

##### highband_dbgain

C Enumeration Value: Lav_THREE_BAND_EQ_HIGHBAND_DBGAIN

Type: float

Range: ['-INFINITY', 'INFINITY']

Default Value: 0.0

Rate: k

The gain to apply to the highest frequency band as decibals.

##### highband_frequency

C Enumeration Value: Lav_THREE_BAND_EQ_HIGHBAND_FREQUENCY

Type: float

Range: dynamic

Default Value: 1000.0

Rate: k

The frequency that divides the middle band from the high band.

##### lowband_dbgain

C Enumeration Value: Lav_THREE_BAND_EQ_LOWBAND_DBGAIN

Type: float

Range: ['-INFINITY', 'INFINITY']

Default Value: 0.0

Rate: k

The gain of the lowest frequency band as decibals.

##### lowband_frequency

C Enumeration Value: Lav_THREE_BAND_EQ_LOWBAND_FREQUENCY

Type: float

Range: dynamic

Default Value: 300.0

Rate: k

The frequency that divides the low and middle bands.

This ranges from 0 to nyquist.

##### midband_dbgain

C Enumeration Value: Lav_THREE_BAND_EQ_MIDBAND_DBGAIN

Type: float

Range: ['-INFINITY', 'INFINITY']

Default Value: 0.0

Rate: k

The gain to apply to the middle band of the equalizer.

## Enumerations

The following section lists some of Libaudioverse’s enumerations. This section concerns itself only with those enumerations that are important by themselves.

Indicates a biquad filter type, used with the biquad filter node and in a few other places.

### Lav_CHANNEL_INTERPRETATIONS

Specifies how to treat inputs to this node for upmixing and downmixing.

 Member Description Lav_CHANNEL_INTERPRETATION_DISCRETE If channel counts mismatch, don’t apply mixing matrices. Either drop or fill with zeros as appropriate. Lav_CHANNEL_INTERPRETATION_SPEAKERS Apply mixing matrices if needed.

### Lav_DISTANCE_MODELS

used in the 3D components of this library. Indicates how sound should become quieter as objects move away from the listener.

Libaudioverse computes the distance from the center of the source to the listener, then subtracts the size. In the following, `distance` refers to this distance. Libaudioverse also computes a second value called `distancePercent`; specifically, `distancePercent = distance/maxDistance`.

 Member Description Lav_DISTANCE_MODEL_INVERSE Sounds fall off as `1/(1+315*distancePercent)`. Just before `maxDistance`, the gain of the sound will be approximately -25 DB. This distance model emphasizes distance changes when sounds are close, but treats distance changes of further away sources more subtly. For full benefit of the effect of close sounds, this distance model must be used with fairly large values for `maxDistance`, usually around 300. Lav_DISTANCE_MODEL_INVERSE_SQUARE Sounds fall off as `1.0/(1+315*distancePercent*distancePercent)`. This is a standard inverse square law, modified such that the sound volume just before `maxDistance` is about -25 DB. Of the available distance models, this is the closest to an accurate simulation of large, wide-open places such as fields and stadiums. Lav_DISTANCE_MODEL_LINEAR Sound falls off as `1-distancePercent`.

### Lav_ERRORS

All functions in this library return one of the following enum values, indicating their error condition.

 Member Description Lav_ERROR_BUFFER_IN_USE Indicates an attempt to modify a buffer while something is reading its data. Lav_ERROR_CANNOT_CONNECT_TO_PROPERTY Attempt to connect a node to a property which cannot be automated. Lav_ERROR_CANNOT_CROSS_SERVERS An attempt was made to relate two objects from different servers. This could be assigning to buffer properties, connecting nodes, or any other such condition. Lav_ERROR_CANNOT_INIT_AUDIO The audio subsystem could not be initialized. Lav_ERROR_CAUSES_CYCLE The requested operation would cause a cycle in the graph of nodes that need processing. Lav_ERROR_FILE Represents a miscelaneous file error. Lav_ERROR_FILE_NOT_FOUND Libaudioverse could not find a specified file. Lav_ERROR_HRTF_INVALID An attempt to use an invalid HRTF database. Lav_ERROR_INTERNAL If you see this error, it’s a bug. Lav_ERROR_INVALID_HANDLE A value passed in as a handle is not currently a handle which is valid. Lav_ERROR_INVALID_POINTER Attempt to free a pointer that Libaudioverse doesn’t know about. Lav_ERROR_INVALID_PROPERTY An attempt to access a property which does not exist on the specified node. Lav_ERROR_MEMORY Libaudioverse triedd to allocate a pointer, but could not. Lav_ERROR_NO_SUCH_DEVICE Attempt to use an I/O device that doesn’t exist. In addition to being caused by your code, this can happen if the user unplugs the device. Lav_ERROR_NONE No error occured. Lav_ERROR_NOT_INITIALIZED Failure to call `Lav_initialized`. Lav_ERROR_NULL_POINTER You passed a null pointer into Libaudioverse in a context where null pointers are not allowed. Lav_ERROR_OVERLAPPING_AUTOMATORS An attempt to schedule an automator within the duration of another. Lav_ERROR_PROPERTY_IS_READ_ONLY Attempt to set a read-only property. Lav_ERROR_RANGE A function parameter is not within a valid range. This could be setting property values outside their range, accessing inputs and outputs that do not exist, or any of a variety of other range error conditions. Lav_ERROR_TYPE_MISMATCH Indicates an attempt to manipulate a property through a function that does not work with that property’s type. Lav_ERROR_UNKNOWN Something went wrong. This error indicates that we couldn’t figure out what.

### Lav_FDN_FILTER_TYPES

Possible filter types for a feedback delay network’s feedback path.

 Member Description Lav_FDN_FILTER_TYPE_DISABLED Don’t insert filters on the feedback path. Lav_FDN_FILTER_TYPE_HIGHPASS Insert highpass filters on the FDN’s feedback path. Lav_FDN_FILTER_TYPE_LOWPASS Insert lowpass filters on the FDN’s feedback path.

### Lav_LOGGING_LEVELS

Possible levels for logging.

 Member Description Lav_LOGGING_LEVEL_CRITICAL Logs critical messages such as failures to initialize and error conditions. Lav_LOGGING_LEVEL_DEBUG Logs everything possible. Lav_LOGGING_LEVEL_INFO Logs informative messages. Lav_LOGGING_LEVEL_OFF No log messages will be generated.

### Lav_NODE_STATES

used to indicate the state of a node. This is the value of the node’s state property and determins how the node is processed.

 Member Description Lav_NODESTATE_ALWAYS_PLAYING This node advances always. Lav_NODESTATE_PAUSED This node is paused. Lav_NODESTATE_PLAYING This node advances if other nodes need audio from it.

### Lav_NOISE_TYPES

Specifies types of noise.

 Member Description Lav_NOISE_TYPE_BROWN Brown noise. Brown noise decreases at 6 DB per octave. Lav_NOISE_TYPE_PINK Pink noise. Pink noise falls off at 3 DB per octave. Lav_NOISE_TYPE_WHITE gaussian white noise.

### Lav_PANNING_STRATEGIES

Indicates a strategy to use for panning. This is mostly for the multipanner node and the 3D components of this library.

 Member Description Lav_PANNING_STRATEGY_HRTF Indicates HRTF panning. Lav_PANNING_STRATEGY_STEREO Indicates stereo panning. Lav_PANNING_STRATEGY_SURROUND40 Indicates 4.0 surround sound (quadraphonic) panning. Lav_PANNING_STRATEGY_SURROUND51 Indicates 5.1 surround sound panning. Lav_PANNING_STRATEGY_SURROUND71 Indicates 7.1 surround sound panning.

### Lav_PROPERTY_TYPES

Indicates the type of a property.

 Member Description Lav_PROPERTYTYPE_BUFFER Property holds a handle to a buffer. Lav_PROPERTYTYPE_DOUBLE Property holds a 64-bit double. Lav_PROPERTYTYPE_FLOAT Property holds a 32-bit floating point value. Lav_PROPERTYTYPE_FLOAT3 Property holds a float3, a vector of 3 floats. Lav_PROPERTYTYPE_FLOAT6 Property holds a float6, a vector of 6 floats. Lav_PROPERTYTYPE_FLOAT_ARRAY Property is an array of floats. Lav_PROPERTYTYPE_INT Property holds a 32-bit integer. Lav_PROPERTYTYPE_INT_ARRAY Property is an array of ints. Lav_PROPERTYTYPE_STRING Property holds a string.