Marketplace

Your one-stop shop for JUCE modules, tools, assets and resources

Hybrid Android / JUCE Audio Library Targeting Music Applications

Maqam

Mobile App Quick Audio & MIDI

Maqam is a graph-based audio processing library for the Android platform. It leverages JUCE for DSP development while leaving the choice of UI frameworks up to the programmer.

It is developed by TAQS.IM and distributed under a friendly MIT license.

Features

  • Prebuilt nodes: SFZ player, reverb, delay, low pass filter
  • Support for custom nodes
  • Compose friendly
  • Automatic state persistence

Architecture

The Kotlin AudioGraph and AudioNode classes are backed by juce::AudioGraph and juce::AudioProcessor respectively. JUCE is only used for DSP, by design JUCE is used as little as possible. All I/O is managed by Maqam through the standard Oboe and AMidi Android libraries and bridged to a JUCE AudioGraph instance, which in turns manages the individual AudioProcessor instances. This way JUCE does not impose any kind of restriction over the native Android app, it is just a part of it.

The library deliberately does not an attempt to map JUCE interfaces one to one. It uses JUCE to implement some aspects of iOS' AVAudioEngine while not reinventing the wheel.

Since Android lacks an official audio plugin architecture like AudioUnit on iOS, Maqam's primary use case are standalone applications that generate sound, like for example synthesizers.

Usage

Initialization

Library.init(this) // loads the dynamic link library val audio = AudioRoot(this)

Creating an audio graph is done following the builder pattern

val testTone = TestTone() audio.graph = AudioGraph.Builder() .add(testTone) .build()

Finally audio is started

audio.start()

Importing this extension exposes node parameters as flows, so creating a slider composable that controls the test tone frequency in the above example is simple:

val frequency by testTone.sineWaveFrequency.valueFlow().collectAsStateWithLifecycle(0f) Column { Text( text = "${frequency.roundToInt()} Hz" ) Slider( value = frequency, valueRange = testTone.sineWaveFrequency.valueRange, onValueChange = { testTone.sineWaveFrequency.value = it } ) }

Custom DSP

Creating a custom node is done by extending the Kotlin AudioNode and C++ juce::AudioProcessor classes. The former is a wrapper that handles all JNI calls and the latter implements the actual DSP. Both must be linked somehow, this is done by editing nodes.h. See TestTone.kt for an example wrapper.

It is also possible to implement custom nodes outside the library namespace by setting up NDK in the parent project and calling the functions defined in maqam.h

Links

A complete example is available here

For a real world app implementing Maqam check our flagship Android app World Piano at the Google Play Store

A similar project named AudioKit is available for iOS

Tags

This product has no tags.

About
Published by
OrganisationTAQS.IM
Added onSat Jan 17 2026
LicenseMIT License

Something wrong with this product?

Report

Are you the owner of this product?

Request Ownership