SonixMixer

Multi-track audio mixer with synchronized playback.

Quick Start

Kotlin

val mixer = SonixMixer.create()
mixer.addTrack("backing", "/path/to/backing.mp3") // Auto-decodes
mixer.addTrack("vocal", "/path/to/vocal.mp3")
mixer.play()

// Control individual tracks
mixer.setTrackVolume("vocal", 0.5f) // Reduce vocal volume
mixer.fadeTrackVolume("vocal", 0f, 2000) // Fade out over 2 seconds

// Release when done
mixer.release()

Swift

let mixer = SonixMixer.create(
config: .default,
audioSession: .playback
)
await mixer.addTrack(name: "backing", filePath: "/path/to/backing.mp3")
await mixer.addTrack(name: "vocal", filePath: "/path/to/vocal.mp3")
mixer.play()

// Control individual tracks
mixer.setTrackVolume(name: "vocal", volume: 0.5)
mixer.fadeTrackVolume(name: "vocal", targetVolume: 0, durationMs: 2000)

// Release when done
mixer.release()

Builder Pattern (Advanced)

Kotlin

val config = SonixMixerConfig.Builder()
.loopCount(3)
.onPlaybackComplete { println("All loops done!") }
.onLoopComplete { index -> println("Completed loop $index") }
.build()
val mixer = SonixMixer.create(config)

StateFlows

StateFlowTypeDescription
currentTimeLongCurrent playback time in ms
isPlayingBooleanTrue while playing
errorSonixError?Error state

Platform Notes

iOS

  • Uses AVAudioEngine for synchronized playback

  • Automatically configures audio session

Android

  • Uses AudioTrack with synchronized playback

  • Automatically configures audio focus

Common Pitfalls

  1. addTrack is suspend: Call from coroutine or use addTrack(name, data, rate, channels)

  2. Forgetting to release: Call release() when done

  3. Track names must be unique: Adding a track with same name replaces it

  4. Different sample rates: Tracks are automatically resampled to match

See also

For single-file playback

For click track playback

For configuration options

Types

Link copied to clipboard
object Companion
Link copied to clipboard

Listener interface for playback events.

Properties

Link copied to clipboard

Number of completed loop iterations.

Link copied to clipboard
val currentTime: StateFlow<Long>

Current playback time in milliseconds.

Link copied to clipboard

Total duration in milliseconds (based on longest track).

Link copied to clipboard
val error: StateFlow<SonixError?>

Error state, null if no error.

Link copied to clipboard
val isPlaying: StateFlow<Boolean>

Whether playback is currently active.

Link copied to clipboard

Current loop count setting.

Functions

Link copied to clipboard
suspend fun addTrack(name: String, filePath: String): Boolean

Add track from file path (auto-decodes).

fun addTrack(name: String, data: ByteArray, sampleRate: Int, channels: Int): Boolean

Add track from raw PCM data (for advanced use cases).

Link copied to clipboard
fun fadeTrackVolume(name: String, targetVolume: Float, durationMs: Long)

Fade a track's volume smoothly from current to target.

fun fadeTrackVolume(name: String, startVolume: Float, endVolume: Float, durationMs: Long)

Fade a track's volume smoothly from start to end value.

Link copied to clipboard

Get names of all loaded tracks.

Link copied to clipboard
fun hasTrack(name: String): Boolean

Check if a track is loaded.

Link copied to clipboard
fun pause()

Pause playback of all tracks.

Link copied to clipboard
fun play()

Start playback of all tracks.

Link copied to clipboard
fun release()

Release all resources.

Link copied to clipboard
fun removeTrack(name: String)

Remove a track from the mixer.

Link copied to clipboard
fun reset()

Reset playback position to the beginning without stopping.

Link copied to clipboard
fun seek(positionMs: Long)

Seek all tracks to a specific position.

Link copied to clipboard

Set a listener for playback events.

Link copied to clipboard
fun setTrackVolume(name: String, volume: Float)

Set volume for a specific track.

Link copied to clipboard
fun stop()

Stop playback and reset to beginning.