I need to create a android application which is for recording voice while showing the voice(sound) level visualization.
I already created an audio recording application
My approach to this is based on activedecay's and Ali's answers, and I added a display DPI scale, since dp is scaled by the screen density so, 1 pixel in 320 dpi is not 1 pixel in 420 dpi. I had that problem that the visualizer was not moving at the same rate in different screens.
I also haven't found out, why the canvas doesn't start drawing from the beginning of the view API 28 only. But is not looking bad in any way.
Info about dpi scaling: Android Developers/Support different pixel densities
package com.example.mediarecorderdemo.views;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import static com.example.mediarecorderdemo.RecordingActivity.DEBUG;
public class VisualizerView extends View {
private static final int MAX_AMPLITUDE = 32767;
private ArrayList amplitudes;
private Paint linePaint;
private int width;
private int height;
private int density;
private float stroke;
public VisualizerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
density = this.getResources().getDisplayMetrics().densityDpi; //Get the display DPI
linePaint = new Paint();
linePaint.setColor(Color.GREEN);
linePaint.setAntiAlias(true); //Add AntiAlias for displaying strokes that are less than 1
}
@Override
protected void onSizeChanged(int w, int h, int oldW, int oldH) {
width = w;
height = h;
amplitudes = new ArrayList<>(width * 2);
stroke =(width * ((float)density / 160)) / 1000; //Calculate actual pixel size for the view based on view width and dpi
linePaint.setStrokeWidth(stroke);
}
/**
* Add a new value of int to the visualizer array
* @param amplitude Int value
*/
public void addAmplitude(int amplitude){
invalidate();
float scaledHeight = ((float) amplitude / MAX_AMPLITUDE) * (height -1);
amplitudes.add(scaledHeight);
}
/**
* Clears Visualization
*/
public void clear(){
amplitudes.clear();
}
@Override
protected void onDraw(Canvas canvas) {
int middle = height / 2; // get the middle of the View
float curX = 0; // start curX at zero
// for each item in the amplitudes ArrayList
for (float power : amplitudes) {
// draw a line representing this item in the amplitudes ArrayList
canvas.drawLine(curX, middle + power / 2, curX, middle
- power / 2, linePaint);
curX += stroke; // increase X by line width
}
}
}