# How to Animate Lottie in Response to Audio

*By Naail Abdul Rahman · June 8, 2021*

Making a Lottie animation interactive is cool... but making it interactive in response to audio is even cooler!

---

The Lottie format is exceptionally well suited for animation tasks both on web and mobile, especially where it involves a sequential progression. We rely on this capability in our [interactivity library](https://lottiefiles.com/interactivity), which uses scroll events to progress an animation in response.

Today we’re going to quickly look at another set of events that can also be used to make a Lottie animation interactive in a fun way - Audio! An audio signal is in essence a continuous stream of signal values over time. So what we’re going to try to do is take those signal values, and use it to animate a Lottie.

Before we go further, let’s have a look at the results. The embed below is for the web version of this tutorial.

The code in this tutorial itself however, applies to Android, but we've also created versions for iOS and the Web. [You can find the code for our demo apps on our GitHub](https://github.com/LottieFiles/demo-audio-visualisation)**.**

If you'd like to test drive it first, skip towards the end and find our web demo embedded in this post. Looks good? Let's get started!

### Obtaining an audio signal

Android offers a number of ways to read audio. For this tutorial, we’ll be reading audio directly from the microphone.

![](https://assets-blog.lottiefiles.dev/2021/04/giphy.gif)

[via Gify](https://giphy.com/gifs/workingtitlefilms-renee-zellweger-bridget-jones-joness-diary-kGcnRxB5dg0rnCcRbY/links)

We initialise an instance of AudioRecord, and start recording audio. _Note: You will need to ensure runtime permissions for RECORD\_AUDIO first._

```kotlin
private var recorder: AudioRecord? = null
private val minBuffer = AudioRecord.getMinBufferSize(
        16000,
        AudioFormat.CHANNEL_IN_MONO,
        AudioFormat.ENCODING_PCM_16BIT
)

private fun listen() {
    // lazy init audio recorder
    if(recorder == null) {
        recorder = AudioRecord(
            MediaRecorder.AudioSource.MIC,
            16000,
            AudioFormat.CHANNEL_IN_MONO,
            AudioFormat.ENCODING_PCM_16BIT,
            minBuffer
        )
    }

    // start recording and sampling
    recorder.startRecording()
}
```

That should allow us to start listening for audio on our microphone. Now we need to get some measurements from it to use with our Lottie.

### Measuring the input signal

Now that we have our signal source, we will need to periodically sample the signal to obtain a measurement to which our animation will respond.

![](https://lh5.googleusercontent.com/qB2L4RVDaLbjbsXX-i_uSn3mZ1WErRMZ1NKAsDgPG7NYQE3qcqromh3oaUqxczUkb1eZ_xxFAP_pTLWTQU8pdxwwF8MmeCl2Z7_sogMVCLSDEtkCUHJ7R_JgdrFX6UeSDnnJwp17)

The Root Mean Square Algorithm

We will be considering the RMS (root mean square) value of the amplitude in decibels (dB) for this. [Wikipedia has a good explanation here](https://en.wikipedia.org/wiki/Root_mean_square).

```kotlin
private fun sampleAudio(): Double {

    // read audio buffer from the recorder
    val buffer = ShortArray(minBuffer)
    recorder.read(buffer, 0, minBuffer)

    val rms = buffer.map { abs(it.toDouble()).pow(2) }
                    .average()
                    .let { sqrt(it) }

    val rmsdB = 20.0 * log10(rms)
    return rmsdB
    
}
```

Selecting an appropriate sampling method is probably the most difficult part. Depending on your needs, you may need to tweak this a little. For our purposes though, the RMS value works well.

### Cleaning up the input signal for a smoother animation

When sampling the audio, we expect there to be quite a bit of fluctuations. This does not translate very well for an animation so we will need to post-process our signal a little bit. In the demo, we apply these two methods:

1.  Apply exponential smoothing over subsequent samples. Once again, Wikipedia has a [good explanation](https://en.wikipedia.org/wiki/Exponential_smoothing). The end result is less flickering, meaning a smoother animation.
2.  Apply a small gain to the input signal. We will use this to control the sensitivity of the animation to sounds.

```kotlin
private var ema = 0.0
private val alpha = 0.8
private val preGain = 0.3

private fun sampleAudio(): Double {

    // read audio buffer from the recorder
    val buffer = ShortArray(minBuffer)
    recorder.read(buffer, 0, minBuffer)

    val rms = buffer.map { abs(it.toDouble()).pow(2) }
                    .average()
                    .let { sqrt(it) }

    ema = ema * alpha + (1 - alpha) * rms
    val preGained = preGain * ema
    return 20.0 * log10(preGained)
    
}
```

We should now have a pretty good set of values coming out of our signal source. We still need to call these methods at specified intervals.

### Continuously sampling the audio and animating the Lottie

Now that we are able to obtain a value to use to animate the Lottie with, we can start sampling the audio signal at regular intervals and apply that value to animate the Lottie.

To animate the Lottie, we will need to convert the dB level into a fraction so we can set the animation progress.

```kotlin
fun getProgress(input_dB: Double): Double {
    var perc = input_dB.coerceAtLeast(min_dB) - min_dB
    perc /= (max_dB - min_dB) 
    return perc
}
```

Here, the values for _min\_dB_ and _max\_dB_ represent a range limit for the input signal. As a reference, average human speak is about 60 dB and anything above 80 dB is considered “loud” and “unpleasant”.

Continuous sampling can be achieved in a number of ways. Here we use a simple Handler to call our _sampleAudio()_ method at specified intervals. You can also use a Timer to similar effect.

```kotlin
val handler = new Handler(mainLooper);
val SAMPLING_RATE = 100L;

private fun sampleAndAnimate() {
    val inputdB = sampleAudio()
    val progress = getProgress(inputDb)
    lottieView.progress = progress
}

// The handler will call itself at sampling intervals
handler.postDelayed({
        sampleAndAnimate()
        handler.postDelayed(this, SAMPLING_RATE);
}, SAMPLING_RATE);
```

Here's our web demo that incorporates everything up to this point.

Not bad at all! You will probably notice that while the Lottie progresses to the desired points in response to audio, and as a result the animation isn’t very smooth. This is because we’re jumping from one point to another with no intermediate steps. Let's see if we can fix that!

### Making the Lottie animate between progress values

To make the final animation smooth, we need to ensure that the animation progresses between each value gradually. For this, we can use a standard android ValueAnimator like so;

```kotlin
val animator = with(ValueAnimator.ofFloat(0.0f)) {
    interpolator = AccelerateInterpolator()
    duration = SAMPLING_RATE

    addUpdateListener {
        val progress = it.animatedValue as Float
        binding.lottieView.progress = progress
    }

    this
}
```

This allows the animator to be responsible for progressing our animation. So we need to change our previous method accordingly. We set it up so that whenever a new progress value is obtained, the animation stops in its tracks, and then proceeds to the new value from there.

```kotlin
private fun sampleAndAnimate() {
    val inputdB = sampleAudio()
    val progress = getProgress(inputDb)
    
    with(animator){
        cancel()
        val currentStop = animatedValue as Float
        val maxStop = progress.coerceAtMost(1.0).toFloat()
        setFloatValues(currentStop, maxStop)
        start()
    }
}
```

And that’s it! We now have a nice, visually pleasing Lottie animation interacting with us! Here's a demo of the web version for you to try out!

![](https://assets-blog.lottiefiles.dev/2021/04/screenshot-1.gif)

A screen-grab from our Android demo app

Once again, [you can find the code for our demo apps on our GitHub](https://github.com/LottieFiles/demo-audio-visualisation). A tutorial video on how to make a Lottie animation sync with audio is also included as below.

[How to make a Lottie animation sync with audio](https://player.vimeo.com/video/548702659?app_id=122963)

## Did you find this useful? Let us know!

As you saw, making a Lottie interesting and interactive can be a simple matter animating its progress! We think the technique broadly described above can be used in a number of applications ranging from Audio recorders to your podcasting app!  
  
As always, we are interested to know how you use Lottie animations in your apps! Join our [Discord](https://lottiefiles.com/discord)! We love to hear from you.

---

## Related Articles

- [How to Create Animations with AI Using Lottie Creator WebMCP](/blog/working-with-lottie-animations/how-to-create-animations-with-ai-using-lottie-creator-webmcp)
- [How to Build Your First Lottie Creator Plugin: Create and Animate a Rectangle](/blog/working-with-lottie-animations/how-to-build-lottie-creator-plugin-create-and-animate-a-rectangle)
- [How to Develop and Publish a Plugin for Lottie Creator](/blog/working-with-lottie-animations/how-to-develop-and-publish-a-plugin-for-lottie-creator)
- [How to Publish a Lottie Creator Plugin to Extensions](/blog/working-with-lottie-animations/how-to-publish-a-lottie-creator-plugin-to-extensions)