Aradine User Manual

Mark Raynsford

Book Metadata

CREATOR | Mark Raynsford
DATE | 2023-02-26T20:18:22+00:00
DESCRIPTION | Documentation for the Aradine system.
IDENTIFIER | ded07ce8-21a9-4226-bfb8-261e7a1895f7
LANGUAGE | en
RIGHTS | Public Domain
TITLE | Aradine User Manual

License

Copyright © 2023 Mark Raynsford <code@io7m.com> https://www.io7m.com

This book is placed into the public domain for free use by anyone for any purpose. It may be freely used, modified, and distributed.

In jurisdictions that do not recognise the public domain this book may be freely used, modified, and distributed without restriction.

This book comes with absolutely no warranty.

Table Of Contents

Cover

Colophon

Table Of Contents

1. Introduction

2. Design And Implementation

2.1. Overview

2.2. Audio Model

2.2.1. Overview

2.2.2. Continuous Signals

2.2.3. Discrete Signals

2.2.4. Sample

2.2.5. Sample Rate

2.2.6. Sample Period

2.2.7. Buffer

2.2.8. Frame Index

2.2.9. Buffer Underrun

2.2.10. Audio Callback

2.3. Instrument Model

2.3.1. Overview

2.3.2. Ports

2.3.3. Events

2.3.4. Parameters

3. Command Line

3.1. Overview

3.2. help

3.2.1. Name

3.2.2. Description

3.2.3. Examples

3.3. info

3.3.1. Name

3.3.2. Description

3.3.3. Parameters

3.3.4. Examples

3.4. check

3.4.1. Name

3.4.2. Description

3.4.3. Parameters

3.4.4. Examples

3.5. codegen

3.5.1. Name

3.5.2. Description

3.5.3. Parameters

3.5.4. Examples

3.6. install-instrument

3.6.1. Name

3.6.2. Description

3.6.3. Parameters

3.6.4. Examples

3.7. install-sample-map

3.7.1. Name

3.7.2. Description

3.7.3. Parameters

3.7.4. Examples

3.8. list-instruments

3.8.1. Name

3.8.2. Description

3.8.3. Parameters

3.8.4. Examples

3.9. list-sample-maps

3.9.1. Name

3.9.2. Description

3.9.3. Parameters

3.9.4. Examples

3.10. uninstall-instrument

3.10.1. Name

3.10.2. Description

3.10.3. Parameters

3.10.4. Examples

3.11. uninstall-sample-map

3.11.1. Name

3.11.2. Description

3.11.3. Parameters

3.11.4. Examples

3.12. version

3.12.1. Name

3.12.2. Description

3.12.3. Examples

4. DSP Modules

4.1. com.io7m.aradine.envelope.table1

4.1.1. Overview

4.1.2. Interpolation

4.1.2.1. Overview

4.1.2.2. CONSTANT_CURRENT

4.1.2.3. CONSTANT_NEXT

4.1.2.4. COSINE

4.1.2.5. EXPONENTIAL

4.1.2.6. LINEAR

4.1.2.7. LOGARITHMIC

4.2. com.io7m.aradine.filter.biquad1

4.2.1. Overview

4.2.2. Applications

4.2.2.1. Cascading

4.2.2.2. Uses

4.2.3. References

4.3. com.io7m.aradine.filter.recursive1

4.3.1. Overview

4.3.2. Applications

4.3.3. References

4.4. com.io7m.aradine.filter.statevar1

4.4.1. Overview

4.4.2. Applications

4.4.2.1. Overview

4.4.2.2. Stability

4.4.3. References

5. API

5.1. JavaDoc

1. Introduction

The aradine package provides a modular system for digital signal processing with an emphasis on musical applications.

2. Design And Implementation

2.1. Overview

2.2. Audio Model

2.2.1. Overview

2.2.2. Continuous Signals

2.2.3. Discrete Signals

2.2.4. Sample

2.2.5. Sample Rate

2.2.6. Sample Period

2.2.7. Buffer

2.2.8. Frame Index

2.2.9. Buffer Underrun

2.2.10. Audio Callback

2.3. Instrument Model

2.3.1. Overview

2.3.2. Ports

2.3.3. Events

2.3.4. Parameters

2.1. Overview

This section of the documentation describes the design and implementation of the aradine package.

2.2. Audio Model

2.2.1. Overview

The aradine package works in terms of a standard discretized sampled audio model. Informally, the system generates a buffer of audio samples at a fixed rate determined by the underlying audio hardware.

2.2.2. Continuous Signals

A continuous signal in the time domain can be considered as a function from time to amplitude. At any given time t, we can evaluate a continuous time domain signal A(t) to obtain the amplitude of the signal A at time t.

2.2.2.2. Continuous Signal Example

2.2.3. Discrete Signals

A discrete signal can be considered as a discretized form of a continuous signal. In digital audio systems, in modern computing environments, both time and amplitude are treated as discrete values. Time is discretized by dividing it into a fixed sample rate (typically specified in samples per second). Amplitude values are discretized by expressing them as either machine integer values of a chosen size, or floating-point values of a chosen size. The aradine package expresses amplitude values as 64-bit IEEE754 floating point values.

As an example, a continuous signal A could be discretized as the discrete signal Q as follows:

2.2.3.3. Discrete Signal Example

2.2.4. Sample

A sample is a single amplitude value in a discrete signal.

2.2.5. Sample Rate

The sample rate of a discrete signal is the number of samples that comprise one second of the signal. The unit of measurement is hertz (hz).

At the time of writing, most consumer audio hardware works in terms of a 48000 hz sample rate.

2.2.6. Sample Period

The sample period of a discrete signal is the length of time represented by one sample in the signal. This is a function of the sample rate of the signal. In a signal with sample rate r, the sample period p of the signal is p = 1 / r.

For example, in a signal that has a 48000 hz sample rate, the sample period is 1 / 48000 ≈ 0.00002083 seconds ≈ 20.83 microseconds.

2.2.7. Buffer

The physical realities of digital audio hardware and software mean that audio signals are not typically produced one-sample-at-a-time. There are many different limitations at all parts of the hardware and software stack that ultimately mean that it is more efficient to produce a buffer of samples less frequently, than a single sample more frequently. At a configurable (but constant) rate, the audio hardware and software will request a buffer of samples from applications. The buffer size specifies the number of samples that must be produced in a single request, and is typically configurable (although most hardware will have a minimum buffer size that it can handle).

The buffer duration of a buffer is simply the number of samples in the buffer multiplied by the sample period of the samples.

Buffering increases latency in the system. If an audio system is configured such that the buffer duration equals 10 milliseconds, then each time the system requests a buffer of samples, the system is essentially saying "Produce the most recent 10 milliseconds of audio for playback right now". This means that a listener is necessarily going to hear the audio 10 milliseconds later than the events that actually produced it. There is, therefore, a tension between specifying a larger buffer size in order to reduce the hardware and software overhead of producing the audio, and specifying a smaller buffer size in order to reduce the effective latency of the system.

For example, in a system with sample duration P and a buffer duration B, at Time = 8, the listener is going to hear the contents of the sample buffer SB0, even though the first sample in that buffer occurred at Time = 0:

2.2.7.5. Buffered Audio

At the time of writing, on most consumer and professional hardware, typical buffer sizes are in the 64-512 range. This implies a typical latency of around 2 milliseconds, which is mostly below the threshold of human perception.

2.2.8. Frame Index

A frame index is an integer index that refers to a set of samples across a set of buffers. A frame index is a non-negative relative index, with a value of 0 referring to the first sample in a buffer.

As an example, assume a buffer size of 8, and three signals S0, S1, and S2. At Time = 16, a frame index of 4 refers to the sample values in the buffers at Time = 20:

2.2.8.3. Frame Index

The term frame comes from the general term sampling frame in DSP. In other systems, audio signals are often divided into multiple channels. For example, stereo audio is divided into left and right channels. In an audio signal with n channels, the individual sample values in each of the channels at a given time are collectively referred to as a sampling frame (or frame, in short). For example, in a stereo audio signal A, the sample value x in the left channel at time 0, and the sample value y in the right channel at time 0 can be viewed as the frame (x, y) at time 0. Conceptually, the audio signal A can be seen as a function A(t) = (p, q), where t is time, and (p, q) is the sampling frame at time t. The aradine package only works with audio signals that have a single channel, but re-uses the term frame to refer to samples across coincident audio buffers.

2.2.9. Buffer Underrun

Much of the practical aspect of digital signal processing is concerned with avoiding buffer underrun. This occurs when the operations required to produce a buffer of samples take longer to execute than the buffer duration. Essentially, the system has asked for a buffer of samples, but it has taken the application code longer than this duration to actually produce the buffer. Therefore, the buffer of samples is not ready in time and the audio system has nothing to play! This manifests as audible glitches in the audio output.

2.2.10. Audio Callback

In the aradine package, the underlying audio system periodically requests that a buffer of samples be produced for each audio output in the system. We refer to this request as the audio callback. More precisely, we say that the underlying audio system periodically calls the aradine audio callback, and the code in the aradine package referenced by the callback performs all of the required processing and then writes out the resulting buffer of samples.

2.3. Instrument Model

2.3.1. Overview

The aradine package collects DSP code into instruments, and instruments can be connected together arbitrarily to form an ensemble.

Within an ensemble, the ports of the instruments are connected together to form a graph. A target port may be connected to at most one source port at any given time. An source port may be connected to zero or more target ports at any given time. The types of ports must match; it is not permitted to try to connect a port of an audio type to a port of a note type, for example.

2.3.2. Ports

Instruments have zero or more ports. A port may either be a source port or a target port. A target port consumes data, while a source port produces data.

Ports have a type. Currently, ports may have either an audio type or a note type.

A target port I of an audio type will, at audio callback time, consume a buffer of audio samples that was produced by whatever source port O is connected to I. If no source port is connected to I, then I will be presented with a buffer of audio samples where every sample value is equal to 0.0.

A target port I of a note type will, at audio callback time, consume a buffer of note events that was produced by whatever source port O is connected to I. If no source port is connected to I, then I will be presented with an empty buffer.

A source port O of a audio type will, at audio callback time, produce a buffer of audio samples that is then consumed by each of the target ports connected to O.

A source port O of a note type will, at audio callback time, produce a buffer of note events that is then consumed by each of the target ports connected to O.

2.3.3. Events

An event is a discrete, typed, timestamped value delivered to an instrument.

An event may be one of the following base types:

2.3.3.3. Event Base Types

A note event type.

A configuration event type.

A note-typed event may be one of the following types:

2.3.3.5. Note Event Types

A note-on event type. This event type is published when the user presses a key on a musical keyboard.

A note-off event type. This event type is published when the user releases a key on a musical keyboard.

A pitch-bend event type. This event type is published when the user touches the pitch bend control on a musical keyboard.

A configuration-typed event may be one of the following types:

2.3.3.7. Configuration Event Types

A buffer-size-changed event type. This event type is published when the underlying audio system is reconfigured to use a different buffer size.

A sample-rate-changed event type. This event type is published when the underlying audio system is reconfigured to use a different sample rate.

A parameter-changed event type. This event type is published when the value of a parameter is changed on an instrument.

Events are typically delivered to instruments via an event buffer. An event buffer is an opaque buffer type that, given a frame index, returns all events that occurred at that frame index.

2.3.4. Parameters

Instruments have zero or more parameters. A parameter is effectively a named and typed mutable variable, the value of which can be read and/or modified (atomically) at any time. Parameters have unique (within an instrument) integer identifiers, and humanly-readable string labels. Additionally, parameters that are of numeric types are declared with minimum and maximum value range constraints. All parameters also have defined default values.

A parameter may be of one of the following types:

2.3.4.3. Parameter Types

64-bit integer.

64-bit floating point.

Sample map.

3. Command Line

3.1. Overview

3.2. help

3.2.1. Name

3.2.2. Description

3.2.3. Examples

3.3. info

3.3.1. Name

3.3.2. Description

3.3.3. Parameters

3.3.4. Examples

3.4. check

3.4.1. Name

3.4.2. Description

3.4.3. Parameters

3.4.4. Examples

3.5. codegen

3.5.1. Name

3.5.2. Description

3.5.3. Parameters

3.5.4. Examples

3.6. install-instrument

3.6.1. Name

3.6.2. Description

3.6.3. Parameters

3.6.4. Examples

3.7. install-sample-map

3.7.1. Name

3.7.2. Description

3.7.3. Parameters

3.7.4. Examples

3.8. list-instruments

3.8.1. Name

3.8.2. Description

3.8.3. Parameters

3.8.4. Examples

3.9. list-sample-maps

3.9.1. Name

3.9.2. Description

3.9.3. Parameters

3.9.4. Examples

3.10. uninstall-instrument

3.10.1. Name

3.10.2. Description

3.10.3. Parameters

3.10.4. Examples

3.11. uninstall-sample-map

3.11.1. Name

3.11.2. Description

3.11.3. Parameters

3.11.4. Examples

3.12. version

3.12.1. Name

3.12.2. Description

3.12.3. Examples

3.1. Overview

The aradine package provides a command-line interface for performing tasks such as managing the local inventory, checking instrument files, and etc. The base aradine-cli command is broken into a number of subcommands which are documented over the following sections.

3.1.2. Command-Line Overview

aradine-cli: usage: aradine-cli [command] [arguments ...]

  Modular programmable synthesis (Command-line).

  Use the "help" command to examine specific commands:

    $ aradine-cli help help.

  Command-line arguments can be placed one per line into a file, and
  the file can be referenced using the @ symbol:

    $ echo help > file.txt
    $ echo help >> file.txt
    $ aradine-cli @file.txt

  Commands:
    help          Show usage information for a command.
    info          Display system information.
    instrument    Instrument commands.
    inventory     Inventory commands.
    version       Show the application version.

  Documentation:
    https://www.io7m.com/software/aradine

All subcommands accept a --verbose parameter that may be set to one of trace, debug, info, warn, or error. This parameter sets the lower bound for the severity of messages that will be logged. For example, at debug verbosity, only messages of severity debug and above will be logged. Setting the verbosity to trace level effectively causes everything to be logged, and will produce large volumes of debugging output.

The aradine-cli command-line tool uses quarrel to parse command-line arguments, and therefore supports placing command-line arguments into a file, one argument per line, and then referencing that file with @. For example:

3.1.5. @ Syntax

$ aradine-cli instrument check --file sampler.jar
{
  "Message" : "Instrument passed all checks.",
  "Level" : "INFO"
}

$ (cat <<EOF
instrument
check
--file
sampler.jar
EOF
) > args.txt

$ aradine-cli @args.txt
{
  "Message" : "Instrument passed all checks.",
  "Level" : "INFO"
}

All subcommands, unless otherwise specified, yield an exit code of 0 on success, and a non-zero exit code on failure.

3.2. help

3.2.1. Name

3.2.2. Description

3.2.3. Examples

3.2.1. Name

help - Show usage information for a command.

3.2.2. Description

The help command shows the help for a given command.

3.2.3. Examples

3.2.3.1. Example

$ aradine-cli help instrument check
aradine-cli: usage: check [named-arguments ...]

  Check an instrument file.

  Named parameters:
  * --file
      Description       : The instrument jar file.
      Type              : Path
      Cardinality       : [1]; Specify exactly once.
      Syntax            : <platform-specific path syntax>
    --verbose
      Description       : Set the logging level of the application.
      Type              : QLogLevel
      Cardinality       : [1]; Specify exactly once, or use the default.
      Default value     : info
      Syntax            : trace|debug|info|warn|error

  The command does not accept any positional arguments.

3.3. info

3.3.1. Name

3.3.2. Description

3.3.3. Parameters

3.3.4. Examples

3.3.1. Name

info - Display system information.

3.3.2. Description

The info command displays information about the current system.

3.3.3. Parameters

3.3.3.1. --verbose

Attribute | Value
Name | --verbose
Type | com.io7m.quarrel.ext.logback.QLogLevel
Default Value | info
Cardinality | [1, 1]
Description | Set the logging level of the application.

3.3.4. Examples

3.3.4.1. Example

{
  "CacheDirectory" : "/opt/aradine/com.io7m.aradine/cache",
  "ConfigurationDirectory" : "/opt/aradine/com.io7m.aradine/config",
  "DataDirectory" : "/opt/aradine/com.io7m.aradine/data",
  "InventoryDatabase" : "/opt/aradine/com.io7m.aradine/data/inventory/inventory.db",
  "InventoryBlobDirectory" : "/opt/aradine/com.io7m.aradine/data/inventory/blobs"
}

3.4. check

3.4.1. Name

3.4.2. Description

3.4.3. Parameters

3.4.4. Examples

3.4.1. Name

check - Check an instrument file.

3.4.2. Description

The check command checks a given instrument file for validity.

3.4.3. Parameters

3.4.3.1. --file

Attribute | Value
Name | --file
Type | java.nio.file.Path
Default Value |
Cardinality | [1, 1]
Description | The instrument jar file.

3.4.3.2. --verbose

Attribute | Value
Name | --verbose
Type | com.io7m.quarrel.ext.logback.QLogLevel
Default Value | info
Cardinality | [1, 1]
Description | Set the logging level of the application.

3.4.4. Examples

3.4.4.1. Example

$ aradine-cli instrument check --file sampler.jar
{
  "Message" : "Instrument passed all checks.",
  "Level" : "INFO"
}

3.5. codegen

3.5.1. Name

3.5.2. Description

3.5.3. Parameters

3.5.4. Examples

3.5.1. Name

codegen - Generate code for an instrument file.

3.5.2. Description

The codegen command generates code from an instrument description.

3.5.3. Parameters

3.5.3.1. --file

Attribute | Value
Name | --file
Type | java.nio.file.Path
Default Value |
Cardinality | [1, 1]
Description | The instrument description file.

3.5.3.2. --output-resource-directory

Attribute | Value
Name | --output-resource-directory
Type | java.nio.file.Path
Default Value |
Cardinality | [1, 1]
Description | The output resource directory.

3.5.3.3. --output-source-directory

Attribute | Value
Name | --output-source-directory
Type | java.nio.file.Path
Default Value |
Cardinality | [1, 1]
Description | The output Java source directory.

3.5.3.4. --package-name

Attribute | Value
Name | --package-name
Type | com.io7m.lanark.core.RDottedName
Default Value |
Cardinality | [1, 1]
Description | The Java package name.

3.5.3.5. --verbose

Attribute | Value
Name | --verbose
Type | com.io7m.quarrel.ext.logback.QLogLevel
Default Value | info
Cardinality | [1, 1]
Description | Set the logging level of the application.

3.5.4. Examples

3.5.4.1. Example

$ aradine-cli instrument codegen \
--package-name com.io7m.example
--output-source-directory src
--output-resource-directory res
--file sampler.json

{
  "Message" : "Generated class: src/com/io7m/example/Parameters.java",
  "Level" : "INFO"
}
{
  "Message" : "Generated class: src/com/io7m/example/Ports.java",
  "Level" : "INFO"
}
{
  "Message" : "Generated instrument file: res/com/io7m/example/instrument.json",
  "Level" : "INFO"
}

3.6. install-instrument

3.6.1. Name

3.6.2. Description

3.6.3. Parameters

3.6.4. Examples

3.6.1. Name

install-instrument - Install instruments into the local inventory.

3.6.2. Description

The install-instrument command installs an instrument into the local inventory.

3.6.3. Parameters

3.6.3.1. --file

Attribute | Value
Name | --file
Type | java.nio.file.Path
Default Value |
Cardinality | [1, 1]
Description | The instrument jar file.

3.6.3.2. --verbose

Attribute | Value
Name | --verbose
Type | com.io7m.quarrel.ext.logback.QLogLevel
Default Value | info
Cardinality | [1, 1]
Description | Set the logging level of the application.

3.6.4. Examples

3.6.4.1. Example

$ aradine-cli inventory install-instrument --file sampler.jar

3.7. install-sample-map

3.7.1. Name

3.7.2. Description

3.7.3. Parameters

3.7.4. Examples

3.7.1. Name

install-sample-map - Install sample maps into the local inventory.

3.7.2. Description

The install-sample-map command installs a sample map into the local inventory.

3.7.3. Parameters

3.7.3.1. --file

Attribute | Value
Name | --file
Type | java.nio.file.Path
Default Value |
Cardinality | [1, 1]
Description | The sample map file.

3.7.3.2. --verbose

Attribute | Value
Name | --verbose
Type | com.io7m.quarrel.ext.logback.QLogLevel
Default Value | info
Cardinality | [1, 1]
Description | Set the logging level of the application.

3.7.4. Examples

3.7.4.1. Example

$ aradine-cli inventory install-sample-map --file drums.aam

3.8. list-instruments

3.8.1. Name

3.8.2. Description

3.8.3. Parameters

3.8.4. Examples

3.8.1. Name

list-instruments - List instruments in the local inventory.

3.8.2. Description

The list-instruments command lists instruments installed in the local inventory.

3.8.3. Parameters

3.8.3.1. --verbose

Attribute | Value
Name | --verbose
Type | com.io7m.quarrel.ext.logback.QLogLevel
Default Value | info
Cardinality | [1, 1]
Description | Set the logging level of the application.

3.8.4. Examples

3.8.4.1. Example

$ aradine-cli inventory list-instruments
[ {
  "Type" : "Instrument",
  "Group" : "com.io7m.aradine",
  "Name" : "com.io7m.aradine.instrument.sampler_m0",
  "Version" : "0.0.2",
  "Identifier" : "com.io7m.aradine:com.io7m.aradine.instrument.sampler_m0:0.0.2",
  "Title" : "Sampler M0",
  "Description" : "The simplest monophonic sampler."
} ]

3.9. list-sample-maps

3.9.1. Name

3.9.2. Description

3.9.3. Parameters

3.9.4. Examples

3.9.1. Name

list-sample-maps - List sample maps in the local inventory.

3.9.2. Description

The list-sample-maps command lists sample maps installed in the local inventory.

3.9.3. Parameters

3.9.3.1. --verbose

Attribute | Value
Name | --verbose
Type | com.io7m.quarrel.ext.logback.QLogLevel
Default Value | info
Cardinality | [1, 1]
Description | Set the logging level of the application.

3.9.4. Examples

3.9.4.1. Example

$ aradine-cli inventory list-sample-maps
[ {
  "Type" : "SampleMap",
  "Group" : "com.io7m.example_group",
  "Name" : "com.io7m.example",
  "Version" : "1.0.0",
  "Identifier" : "com.io7m.example_group:com.io7m.example:1.0.0",
  "Title" : "",
  "Description" : "",
  "MIMEType" : "application/vnd.com.io7m.aurantium.sample_map",
  "Size" : "7139504"
} ]

3.10. uninstall-instrument

3.10.1. Name

3.10.2. Description

3.10.3. Parameters

3.10.4. Examples

3.10.1. Name

uninstall-instrument - Uninstall instruments from the local inventory.

3.10.2. Description

The uninstall-instrument command uninstalls an instrument from the local inventory.

3.10.3. Parameters

3.10.3.1. --id

Attribute | Value
Name | --id
Type | com.io7m.aradine.api.instrument.ARInstrumentID
Default Value |
Cardinality | [1, 1]
Description | The instrument identifier.

3.10.3.2. --verbose

Attribute | Value
Name | --verbose
Type | com.io7m.quarrel.ext.logback.QLogLevel
Default Value | info
Cardinality | [1, 1]
Description | Set the logging level of the application.

3.10.4. Examples

3.10.4.1. Example

$ aradine-cli inventory uninstall-instrument --id com.io7m.aradine:com.io7m.aradine.instrument.sampler_m0:0.0.2

3.11. uninstall-sample-map

3.11.1. Name

3.11.2. Description

3.11.3. Parameters

3.11.4. Examples

3.11.1. Name

uninstall-sample-map - Uninstall sample maps from the local inventory.

3.11.2. Description

The uninstall-sample-map command uninstalls a sample map from the local inventory.

3.11.3. Parameters

3.11.3.1. --id

Attribute | Value
Name | --id
Type | com.io7m.aradine.api.sample_map.ARSampleMapID
Default Value |
Cardinality | [1, 1]
Description | The sample map identifier.

3.11.3.2. --verbose

Attribute | Value
Name | --verbose
Type | com.io7m.quarrel.ext.logback.QLogLevel
Default Value | info
Cardinality | [1, 1]
Description | Set the logging level of the application.

3.11.4. Examples

3.11.4.1. Example

$ aradine-cli inventory uninstall-sample-map --id com.io7m.example_group:com.io7m.example:1.0.0

3.12. version

3.12.1. Name

3.12.2. Description

3.12.3. Examples

3.12.1. Name

version - Show the application version.

3.12.2. Description

The version command shows the application version.

3.12.3. Examples

3.12.3.1. Example

$ aradine-cli version
com.io7m.aradine.cmdline 0.0.2-SNAPSHOT 776ce9dc06476debd406813b753e27d8b64b0754

4. DSP Modules

4.1. com.io7m.aradine.envelope.table1

4.1.1. Overview

4.1.2. Interpolation

4.1.2.1. Overview

4.1.2.2. CONSTANT_CURRENT

4.1.2.3. CONSTANT_NEXT

4.1.2.4. COSINE

4.1.2.5. EXPONENTIAL

4.1.2.6. LINEAR

4.1.2.7. LOGARITHMIC

4.2. com.io7m.aradine.filter.biquad1

4.2.1. Overview

4.2.2. Applications

4.2.2.1. Cascading

4.2.2.2. Uses

4.2.3. References

4.3. com.io7m.aradine.filter.recursive1

4.3.1. Overview

4.3.2. Applications

4.3.3. References

4.4. com.io7m.aradine.filter.statevar1

4.4.1. Overview

4.4.2. Applications

4.4.2.1. Overview

4.4.2.2. Stability

4.4.3. References

4.1. com.io7m.aradine.envelope.table1

4.1.1. Overview

4.1.2. Interpolation

4.1.2.1. Overview

4.1.2.2. CONSTANT_CURRENT

4.1.2.3. CONSTANT_NEXT

4.1.2.4. COSINE

4.1.2.5. EXPONENTIAL

4.1.2.6. LINEAR

4.1.2.7. LOGARITHMIC

4.1.1. Overview

The com.io7m.aradine.envelope.table1 module contains a table-based envelope implementation.

4.1.2. Interpolation

4.1.2.1. Overview

The envelope supports a number of different interpolation functions to produce amplitude values between breakpoints. For a hypothetical breakpoint B at frame frame(B) with amplitude amplitude(B), and a hypothetical breakpoint C at frame frame(C) with amplitude amplitude(C), where frame(B) < frame(C), the interpolation function specified for B is used to produce interpolated amplitude values for all frames greater than frame(B) and less than frame(C).

The definitions below are explained in terms of a pair of breakpoints B and C where frame(B) = 0, amplitude(B) = 0, frame(C) = 1000, and amplitude(C) = 1.

4.1.2.2. CONSTANT_CURRENT

If a breakpoint B uses the interpolation function CONSTANT_CURRENT, then all frames between B and C will have an amplitude equal to amplitude(B).

4.1.2.2.2. CONSTANT_CURRENT Graph

4.1.2.3. CONSTANT_NEXT

If a breakpoint B uses the interpolation function CONSTANT_NEXT, then all frames between B and C will have an amplitude equal to amplitude(C).

4.1.2.3.2. CONSTANT_NEXT Graph

4.1.2.4. COSINE

If a breakpoint B uses the interpolation function COSINE, then all frames between B and C will have amplitudes produced by a cosine interpolation of amplitude(B) and amplitude(C).

4.1.2.4.2. COSINE Graph

4.1.2.5. EXPONENTIAL

If a breakpoint B uses the interpolation function EXPONENTIAL, then all frames between B and C will have amplitudes produced by an exponential interpolation of amplitude(B) and amplitude(C).

4.1.2.5.2. EXPONENTIAL Graph

This is equivalent to linear interpolation where the interpolation factor is the square of the normal linear factor.

4.1.2.6. LINEAR

If a breakpoint B uses the interpolation function LINEAR, then all frames between B and C will have amplitudes produced by a linear interpolation of amplitude(B) and amplitude(C).

4.1.2.6.2. LINEAR Graph

4.1.2.7. LOGARITHMIC

If a breakpoint B uses the interpolation function LOGARITHMIC, then all frames between B and C will have amplitudes produced by a logarithmic interpolation of amplitude(B) and amplitude(C).

4.1.2.7.2. LOGARITHMIC Graph

This is equivalent to linear interpolation where the interpolation factor is the square root of the normal linear factor.

4.2. com.io7m.aradine.filter.biquad1

4.2.1. Overview

4.2.2. Applications

4.2.2.1. Cascading

4.2.2.2. Uses

4.2.3. References

4.2.1. Overview

The com.io7m.aradine.filter.biquad1 module contains biquad filter implementations.

4.2.2. Applications

4.2.2.1. Cascading

Biquad filters can be composed to produce stronger filters. The output signal of one filter is fed into the input of another filter in a process known as cascading. The main filter implementation included in the com.io7m.aradine.filter.biquad1 module is a filter of order 2 (specifically, it has two poles, and two zeroes). It would be theoretically possible to use the same algorithm with more filter coefficients to produce a single filter of order N, but in practice it is better to cascade N / 2 filters of order 2; the resulting filter will be much more numerically stable and less subject to issues such as those involving floating point precision.

For example, the following code uses four filters of order 2 to produce an effective filter of order 8:

4.2.2.1.3. Order 8

final var stage0 = new ARBQ1BiquadBPFO2();
final var stage1 = new ARBQ1BiquadBPFO2();
final var stage2 = new ARBQ1BiquadBPFO2();
final var stage3 = new ARBQ1BiquadBPFO2();

final var s0 = stage0.processOneFrame(input);
final var s1 = stage1.processOneFrame(s0);
final var s2 = stage2.processOneFrame(s1);
final var out = stage3.processOneFrame(s2);

4.2.2.2. Uses

Biquad filters are relatively suitable for use in EQ applications, or when the filter cutoff value is not expected to be modulated over time. For rapidly modulating filter cutoff values, a state variable filter may be more suitable.

4.2.3. References

The filter implementation is loosely based upon the C++ implementation provided at https://www.earlevel.com/main/2012/11/26/biquad-c-source-code/.

4.3. com.io7m.aradine.filter.recursive1

4.3.1. Overview

4.3.2. Applications

4.3.3. References

4.3.1. Overview

The com.io7m.aradine.filter.recursive1 module contains simple recursive filter implementations.

4.3.2. Applications

The filter implementations provided in the com.io7m.aradine.filter.recursive1 module are extremely simple 1-pole filters. They represent the bare minimum in terms of filter implementations and may be useful in terms of eliminating low frequency grounds hum from audio, or reducing high frequency noise.

4.3.3. References

The filter implementations are based on the descriptions given in The Scientist and Engineer's Guide to Digital Signal Processing by Steven W. Smith (ISBN-13 978-0966017632).

4.4. com.io7m.aradine.filter.statevar1

4.4.1. Overview

4.4.2. Applications

4.4.2.1. Overview

4.4.2.2. Stability

4.4.3. References

4.4.1. Overview

The com.io7m.aradine.filter.statevar1 module contains state variable filter implementations.

4.4.2. Applications

4.4.2.1. Overview

The filter implementations provided in the com.io7m.aradine.filter.statevar1 module are fairly direct translations of the hardware filters used on many analogue synthesizers. They offer good resolution at all frequencies, but can become unstable at certain frequencies unless oversampling is used.

4.4.2.2. Stability

State variable filters accept separate Q and C parameters, where Q is a positive real value, and C is a real value in the range [0, 1]. Filters may become unstable in the sense that particular combinations of Q and C values may cause the filter to start oscillating and massively increase the gain of the signal passing through it. This can be directly observed by running the filter on a sample of white noise, picking various Q and C values, and seeing if the resulting output contains one or more frequency bands where the amplitude is greater than or equal to 0.6. In an unfiltered white noise sample, every frequency band should have an amplitude of roughly 0.5, so any band with a value much greater than this can indicate that the filter has begun to self oscillate. The following diagram shows an increasing Q downwards along the Y axis, and an increasing C rightwards along the X axis:

4.4.2.2.2. Stability (1)

In the diagram, a green square indicates that no frequency band in the output had an amplitude of greater than or equal to 0.6, whilst a red square indicates that one or more frequency bands had an amplitude of greater than or equal to 0.6. As should be fairly obvious, much of the parameter space is essentially unusable. Fortunately, this problem can be mitigated through oversampling; simply evaluate the filter multiple times per input sample, and discard all but the output sample from the last evaluation.

4.4.2.2.4. Oversampling

final var input = sampleBuffer.frameGetExact(index);
for (int oversample = 0; oversample < sampleCount; ++oversample) {
  f.processOneFrame(input);
}
final var output = f.highPassOutput();

Applying the exact same Q and C values as in the original diagram, but evaluating the filter four times instead of one, yields the following output instead:

4.4.2.2.6. Stability (4)

The resulting audio output is not drastically different than for the single sample case, but it is clear from the diagram that a much wider range of Q and C values have become usable.

4.4.3. References

The filter implementation is derived from the description given in Musical Applications Of Microprocessors by Hal Chamberlin (ISBN 0-8104-5768-7).

5. API

5.1. JavaDoc

5.1. JavaDoc

The entire aradine API is documented the included JavaDoc.