Control audio looping behavior programmatically for background music, sound effects, and rhythmic audio segments.
Audio looping restarts an audio block from the beginning when playback reaches the end. When you set a block duration longer than the audio length and enable looping, CE.SDK repeats the audio to fill the whole duration.
This guide covers how to enable and disable audio looping, read the current looping state, combine looping with duration settings, and loop trimmed audio segments using the Android Engine API.
Setting Up the Scene#
Start with a video scene and a page that acts as the timeline container. The sample sizes the page after loading audio metadata so the timeline covers every audio block.
val scene = engine.scene.createForVideo()val page = engine.block.create(DesignBlockType.Page)engine.block.appendChild(parent = scene, child = page)engine.block.setWidth(page, value = 1280F)engine.block.setHeight(page, value = 720F)Audio blocks must be children of the page to participate in the timeline. The sample appends playable copies to the page in the sections below.
Understanding Audio Looping#
When looping is enabled on an audio block, CE.SDK repeats the audio content from the beginning each time it reaches the end. This continues until the block’s duration is filled. For example, setting a block duration to three times the source duration makes the clip play three complete times.
Loop transitions are immediate. The audio content determines how smooth the result sounds, so files with matching start and end points create the cleanest loops.
Creating Audio Blocks#
Adding Audio Content#
Audio blocks use file URIs to reference audio sources. We create a reusable source block and assign the audio URI with the audio/fileURI property.
val audioBlock = engine.block.create(DesignBlockType.Audio)// Android exposes the audio source as the `audio/fileURI` property key.engine.block.setString(block = audioBlock, property = "audio/fileURI", value = audioUri)CE.SDK supports common audio formats including MP3, M4A, WAV, and AAC.
Enabling Audio Looping#
Loading Audio Resources#
Before working with audio metadata, load the resource so the engine can read its duration.
engine.block.forceLoadAVResource(audioBlock)
val audioDuration = engine.block.getAVResourceTotalDuration(audioBlock)println("Audio duration: $audioDuration seconds")getAVResourceTotalDuration() returns the source audio duration in seconds. Use it when you need to calculate how many repetitions fit into a block duration.
Sizing the Timeline#
Derive block durations from the loaded source duration instead of assuming a fixed clip length. The sample also sets the page duration to the latest block end time, including each block’s timeOffset + duration.
val loopingTimeOffset = 0.0val loopingDuration = audioDuration * 3.0
val nonLoopingTimeOffset = loopingTimeOffset + loopingDuration + 1.0val nonLoopingDuration = audioDuration + 12.0
val trimmedTimeOffset = nonLoopingTimeOffset + nonLoopingDuration + 1.0val trimOffset = 1.0val trimLength = 2.0val trimmedDuration = trimLength * 4.0
val pageDuration = maxOf( loopingTimeOffset + loopingDuration, nonLoopingTimeOffset + nonLoopingDuration, trimmedTimeOffset + trimmedDuration,)engine.block.setDuration(page, duration = pageDuration)The looping block spans three full source-length passes. The non-looping block lasts one source duration plus 12 seconds, so playback stops after the source ends and the rest remains silent.
Setting Looping State#
Enable looping by calling setLooping() with true. When the block duration is longer than the audio length, the audio repeats until that duration is filled.
val loopingAudio = engine.block.duplicate(block = audioBlock, attachToParent = false)engine.block.appendChild(parent = page, child = loopingAudio)engine.block.setTimeOffset(loopingAudio, offset = loopingTimeOffset)engine.block.setLooping(loopingAudio, looping = true)engine.block.setDuration(loopingAudio, duration = loopingDuration)In this example, the block duration is calculated as audioDuration * 3.0, so the loaded source loops three times.
Querying and Controlling Looping#
Checking Looping State#
Read the current looping state whenever your app manages multiple audio tracks or needs to reflect state in custom controls.
val isLooping = engine.block.isLooping(loopingAudio)println("Is looping: $isLooping")The returned Boolean reports whether the block is configured to restart from the beginning during playback.
Disabling Looping#
Set looping to false when an audio block should play once.
val nonLoopingAudio = engine.block.duplicate(block = audioBlock, attachToParent = false)engine.block.appendChild(parent = page, child = nonLoopingAudio)engine.block.setTimeOffset(nonLoopingAudio, offset = nonLoopingTimeOffset)engine.block.setLooping(nonLoopingAudio, looping = false)engine.block.setDuration(nonLoopingAudio, duration = nonLoopingDuration)With looping disabled and a duration longer than the source audio, playback stops after the source audio ends and leaves silence for the remaining block duration.
Looping with Trim Settings#
Trimming Looped Audio#
Combine trim settings with looping to repeat a short segment from a longer audio file.
val trimmedLoopAudio = engine.block.duplicate(block = audioBlock, attachToParent = false)engine.block.appendChild(parent = page, child = trimmedLoopAudio)engine.block.setTimeOffset(trimmedLoopAudio, offset = trimmedTimeOffset)
engine.block.setTrimOffset(trimmedLoopAudio, offset = trimOffset)engine.block.setTrimLength(trimmedLoopAudio, length = trimLength)
engine.block.setLooping(trimmedLoopAudio, looping = true)engine.block.setDuration(trimmedLoopAudio, duration = trimmedDuration)This trims the audio to a 2-second segment from 1.0s to 3.0s of the source. The 8-second block duration repeats that segment four times, and the page duration includes the trimmed block’s offset plus its duration.
Choosing Loop Points#
For smoother loops, choose trim points where the audio flows naturally from end to beginning. Consistent rhythm, tone, and volume at trim boundaries reduce audible transitions.
Exporting the Scene#
After configuring audio looping, save the scene for storage, later editing, or rendering in another CE.SDK environment.
val sceneString = engine.scene.saveToString(scene = scene)println("Scene saved (${sceneString.length} characters)")The serialized scene preserves the audio blocks, timing, trim values, and looping configuration.
Troubleshooting#
Audio not looping: Verify isLooping() returns true and that the block duration exceeds the source audio or trimmed segment length.
Audible gaps at loop points: Choose trim points where the end of the segment can flow back into the beginning. Matching volume and rhythm at both boundaries creates smoother loops.
Resource metadata unavailable: Call forceLoadAVResource() before reading source duration or changing trim values.
API Reference#
| Method | Purpose |
|---|---|
engine.scene.createForVideo() | Create a video scene for timeline audio |
engine.block.create(blockType=DesignBlockType.Page) | Create the timeline page |
engine.block.create(blockType=DesignBlockType.Audio) | Create an audio block |
engine.block.appendChild(parent=_, child=_) | Add a block to the scene hierarchy |
engine.block.setWidth(block=_, value=_) | Set the page width |
engine.block.setHeight(block=_, value=_) | Set the page height |
engine.block.setString(block=_, property="audio/fileURI", value=_) | Set the audio source URI |
engine.block.forceLoadAVResource(block=_) | Load audio metadata |
engine.block.getAVResourceTotalDuration(block=_) | Read the source audio duration |
engine.block.duplicate(block=_, attachToParent=false) | Reuse the loaded audio source for another block |
engine.block.setTimeOffset(block=_, offset=_) | Set when audio starts on the timeline |
engine.block.setLooping(block=_, looping=_) | Enable or disable audio looping |
engine.block.isLooping(block=_) | Check whether audio is set to loop |
engine.block.setDuration(block=_, duration=_) | Set playback duration in seconds |
engine.block.getDuration(block=_) | Read playback duration in seconds |
engine.block.setTrimOffset(block=_, offset=_) | Set the start of the trimmed source segment |
engine.block.setTrimLength(block=_, length=_) | Set the trimmed segment length |
engine.block.destroy(block=_) | Remove a temporary block |
engine.scene.saveToString(scene=_) | Serialize the scene with audio settings |