Hackster is hosting Hackster Holidays, Ep. 5: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Friday!Stream Hackster Holidays, Ep. 5 on Friday!
Gautier Mechling
Published © Apache-2.0

Decibels Indicator

A way to visualize how noisy is our open space office.

BeginnerFull instructions provided2 hours1,599
Decibels Indicator

Things used in this project

Hardware components

Raspberry Pi 3 Model B
Raspberry Pi 3 Model B
Or any Android Things compatible board
×1
Adafruit Mini USB Microphone
×1
APA102 RGB LED Strip (60 LEDs/m)
You can use any APA102 LED strip
×1
SparkFun Breadboard Power Supply 5V/3.3V
SparkFun Breadboard Power Supply 5V/3.3V
×1
Breadboard (generic)
Breadboard (generic)
×1

Software apps and online services

Android Things
Google Android Things

Story

Read more

Schematics

Schematics

Code

DecibelsLiveData

Java
// Every 250ms, we will get the decibel value
class DecibelsLiveData(private val frequencyMs: Long = 250) : LiveData<Float>() {

    companion object {
        private const val HANDLER_MSG_GET_DECIBELS = 1
    }

    private val mediaRecorder = MediaRecorder()
    private var handler: Handler? = null
    private var handlerThread: HandlerThread? = null

    private val handlerCallback = { msg: Message ->
        if (msg.what == HANDLER_MSG_GET_DECIBELS) {
            // Get the sound pressure value
            val volume = mediaRecorder.maxAmplitude
            if (volume != 0) {
                // Change the sound pressure value to the decibel value and post it
                val decibels = 20 * Math.log10(volume.toDouble()).toFloat()
                postValue(decibels)
            }

            handler?.sendEmptyMessageDelayed(HANDLER_MSG_GET_DECIBELS, frequencyMs)
        }
        true
    }

    override fun onActive() {
        startRecording()
    }

    override fun onInactive() {
        stopRecording()
    }

    // Records to /dev/null (we don't need to keep the recording, we only need to get the sound pressure value)
    fun startRecording() {
        with(mediaRecorder) {
            try {
                reset()
                setAudioSource(MediaRecorder.AudioSource.MIC)
                setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
                setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
                setOutputFile("/dev/null")

                prepare()
                start()

                // Start handler thread
                handlerThread = HandlerThread(TAG).also { handlerThread ->
                    handlerThread.start()
                    handler = Handler(handlerThread.looper, handlerCallback).also { handler ->
                        handler.sendEmptyMessage(HANDLER_MSG_GET_DECIBELS)
                    }
                }
            } catch (e: Exception) {
                Log.e("TAG", "Error initializing mediaRecorder", e)
            }
        }
    }

    fun stopRecording() {
        handler?.removeMessages(HANDLER_MSG_GET_DECIBELS).also { handler = null }
        handlerThread?.quitSafely().also { handlerThread = null }

        try {
            mediaRecorder.stop()
            mediaRecorder.release()
        } catch (e: IllegalStateException) {
            Log.e("TAG", "Error stopping mediaRecorder")
        }
    }
}

LedStrip

Java
class LedStrip : LifecycleObserver {

    companion object {
        private const val SPI_NAME = "SPI0.0"
        private const val NUM_LEDS = 60
        private const val LED_BRIGHTNESS = 6 // 0 ... 31

        private const val HSV_GREEN = 90
        private const val HSV_RED = 0

        private const val MIN_DECIBELS = 30
        private const val MAX_DECIBELS = 90

        private val LED_MODE = Apa102.Mode.BGR
    }

    private var ledStrip: Apa102? = null
    private val colors = IntArray(NUM_LEDS)

    // Initialize the Apa102 LED strip
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun start() {
        ledStrip = Apa102(SPI_NAME, LED_MODE).apply {
            brightness = LED_BRIGHTNESS
            write(IntArray(NUM_LEDS))
        }
    }

    // Close the LED strip
    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun stop() {
        ledStrip?.close().also { ledStrip = null }
    }

    // Show the decibels "progress bar"
    fun showDecibels(decibels: Float) {
        var decibelLevel: Float

        for (i in 0 until NUM_LEDS) {
            decibelLevel = i.toFloat() * (MAX_DECIBELS - MIN_DECIBELS) / (NUM_LEDS - 1) + MIN_DECIBELS

            colors[i] = if (decibels > decibelLevel) {
                Color.HSVToColor(255, floatArrayOf((HSV_GREEN - (i.toFloat() * (HSV_GREEN - HSV_RED) / (NUM_LEDS - 1)) + 360) % 360, 1.0f, 1.0f))
            } else {
                0
            }
        }
        ledStrip!!.write(colors)
    }
}

Full project on GitHub

Credits

Gautier Mechling

Gautier Mechling

2 projects • 13 followers
Software Craftsman

Comments