# What I have learned from Disco Lights app development

I decided to make an app that will change display color while music playing. Kind of disco lights. Just to practice Android app development.

Sounds pretty simple. You just need to enable a microphone and respond to sound. But you need to implement a beat detection algorithm.

During development, I studied what is sound and how electronic devices work with it. Let’s get started.

# How a microphone works

Since I used 16 bit per sample, it is represented as an integer in the range from -32768 to 32767. The default format of sample representation is PCM (Pulse-Code Modulation).

When you record audio on 44KHz frequency, you will have 44000 samples in one second.

Next task was to detect a beat.

# How to detect a beat

There are a number of algorithms to detect beats. I used one from there: link

Here is my implementation in Java of that algorithm:

`boolean isBeat(short[] samples) {    float instantEnergy = getInstantEnergy(samples);    float[] values = ringBuffer.getValues();    float localAverage = getAverage(values);    float variance = getVariance(values, localAverage);    float constant = (-0.0025714f * variance) + 1.5142857f;    if (constant < 1.2f) {        constant = 1.2f;    } else if (constant > 2f) {        constant = 2f;    }    ringBuffer.add(instantEnergy);    return instantEnergy > constant * localAverage;}`

First, I calculate instant energy. It is a sum of pow of buffered samples.

`float getInstantEnergy(short[] samples) {    float sum = 0;    for (short sample : samples) {        sum += Math.pow(sample, 2);    }    return sum;}`

Then I get an average of previously calculated instant energies (storing them in Circular buffer).

`float getAverage(float[] values) {    float sum = 0;    for (float value : values) {        sum += value;    }    return sum / values.length;}`

Next, I get an average variance, which is the difference between every previous instant energy and average instant energy:

`float getVariance(float[] values, float avg, int blockNum) {    // blockNum = circular buffer size    float diffSum = 0;    for (int i = 0; i < blockNum; i++) {        diffSum += Math.pow(values[i] - avg, 2);    }    return diffSum / blockNum;}`

If current instant energy is more than average instant energy multiplied to coefficient, then we treat this buffer as the beat.

`instantEnergy > constant * localAverage`

In my case sometimes coefficient was an extremely low number, so I limit it with that values:

`if (constant < 1.2f) {    constant = 1.2f;} else if (constant > 2f) {    constant = 2f;}`

# Conclusion

You can try app here: