iiVisu

A player/ recorder visualizer with the swipe to seek functionality

A player/ recorder visualizer with the swipe to seek functionality.

Demo

A player/ recorder visualizer with the swipe to seek functionality

Setup

Step 1. Add the JitPack repository to your build file

Add it in your root build.gradle at the end of repositories:

allprojects {
  repositories {
    ...
    maven { url 'https://jitpack.io' }
  }
}

Step 2. Add the dependency

dependencies {
  implementation 'com.github.imnirdst:iivisu:1.0.0'
}

Usage

This repostory contains a sample app that shows how to use iiVisu.

Recorder

RecorderVisualizer doesn't support swipe to seek functionality.

<com.imn.iivisu.RecorderVisualizer
    android:id="@+id/visualizer"
    android:layout_width="0dp"
    android:layout_height="256dp"
    app:maxAmp="100"
    app:barWidth="3dp"
    app:spaceBetweenBar="2dp"
    app:loadedBarPrimeColor="@color/primaryLight"
    app:backgroundBarPrimeColor="@color/gray"
    app:layout_constraintBottom_toTopOf="@id/timeline_text_view"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent" />
binding.visualizer.ampNormalizer = { sqrt(it.toFloat()).toInt() }

recorder.apply {
    onStop = { binding.visualizer.clear() }
    onAmpListener = {
        runOnUiThread {
            binding.visualizer.addAmp(it)
        }
    }
}

Player

<com.imn.iivisu.PlayerVisualizer
    android:id="@+id/visualizer"
    android:layout_width="0dp"
    android:layout_height="256dp"
    app:barWidth="3dp"
    app:spaceBetweenBar="2dp"
    app:approximateBarDuration="50"
    app:loadedBarPrimeColor="@color/primaryLight"
    app:backgroundBarPrimeColor="@color/gray"
    app:layout_constraintBottom_toTopOf="@id/timeline_text_view"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent" />
binding.visualizer.apply {
    onStartSeeking = { player.pause() }
    onSeeking = { binding.timelineTextView.text = it.formatAsTime() }
    onFinishedSeeking = { time, isPlayingBefore ->
        player.seekTo(time)
        if (isPlayingBefore) {
            player.resume()
        }
    }
}

binding.visualizer.ampNormalizer = { sqrt(it.toFloat()).toInt() }

player.onProgress = { time, isPlaying ->
    binding.visualizer.updateTime(time.toInt(), isPlaying)
}

Documentation

  • maxAmp: Maximum amp that you expected to recieve from the mic. Amps with higher than maxAmp are shown as a full height bar. This is calculated automatically in the PlayerVisualizer.

  • barWidth: Width of each bar.

  • spaceBetweenBar: Space between each bar.

  • approximateBarDuration: Defines aproximate duration of each bar. The exact duration of each bar is calculated and stored in the barDuration variable. This is only used in PlayerVisualizer. RecorderVisualizer draws a bar per each recieved amp.

  • loadedBarPrimeColor: Defines loaded bar color.

  • backgroundBarPrimeColor: Defines background (unloaded) bar color.

  • ampNormalizer: Recieves a lambda method for normalizing amps. (for better visualization)

  • addAmp: Used for adding an amp to RecorderVisualizer and its bar gets drawn Immediately.

  • updateTime: Used for updating PlayerVisualizer timeline to specified location. isPlaying param is used for defining behaviour of onFinishedSeeking callback.

  • onStartSeeking : Recieves a callback for the action needed to happen when seeking starts.

  • onSeeking : Recieves a callback for the action needed to happen during the seeking process and contains current time position of the visualizer.

  • onFinishedSeeking: Recieves a callback for the action needed to happen after the seeking finishes and contains time position of the visualizer and a variable for deciding whether you need to resume player after seeking or not.

GitHub