How to show/draw the spectrum frequency from line into bar shape (android)?


#1

I am learning how to make a spectrum analyzer. I learn from tutorial and here’s the code:

package com.example.prasetyo.spectrumanalyzer;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import ca.uol.aig.fftpack.RealDoubleFFT;



/*public class SpectrumActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_spectrum);
    }*/

public class SpectrumActivity extends Activity implements OnClickListener {

    public void onClick(View v) {
        if (started) {
            started = false;
            startStopButton.setText("Start");
            recordTask.cancel(true);
        } else {
            started = true;
            startStopButton.setText("Stop");
            recordTask = new RecordAudio();
            recordTask.execute();
        }
    }

    int frequency = 8000;
    int channelConfiguration = AudioFormat.CHANNEL_IN_MONO;
    int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;


    private RealDoubleFFT transformer;
    int blockSize = 256;
    Button startStopButton;
    boolean started = false;

    RecordAudio recordTask;
    ImageView imageView;
    Bitmap bitmap;
    Canvas canvas;
    Paint paint;



    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_spectrum);

        startStopButton = (Button) this.findViewById(R.id.StartStopButton);
        startStopButton.setOnClickListener(this);
        transformer = new RealDoubleFFT(blockSize);
        imageView = (ImageView) this.findViewById(R.id.ImageView01);
        bitmap = Bitmap.createBitmap(256, 100, Bitmap.Config.ARGB_8888);
        canvas = new Canvas(bitmap);
        paint = new Paint();
        paint.setColor(Color.GREEN);
        imageView.setImageBitmap(bitmap);
    }

    /*public void onClick(View v) {
        if (started) {
            started = false;
            startStopButton.setText("Start");
            recordTask.cancel(true);
        } else {
            started = true;
            startStopButton.setText("Stop");
            recordTask = new RecordAudio();
            recordTask.execute();
        }
    }*/


    private class RecordAudio extends AsyncTask<Void, double[], Void> {
        @Override
        protected Void doInBackground(Void... params) {


            if(isCancelled()){
                return null;
            }

            //try {
                int bufferSize = AudioRecord.getMinBufferSize(frequency, channelConfiguration, audioEncoding);
                AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, frequency, channelConfiguration, audioEncoding, bufferSize);
                short[] buffer = new short[blockSize];
                double[] toTransform = new double[blockSize];

            try {
                audioRecord.startRecording();
            }
            catch (IllegalStateException e) {
                Log.e("Recording Failed", e.toString());
            }
                while (started) {
                    int bufferReadResult = audioRecord.read(buffer, 0, blockSize);
                    for (int i = 0; i < blockSize && i < bufferReadResult; i++) {
                        toTransform[i] = (double) buffer[i] / 32768.0; // signed 16 bit
                    }
                    transformer.ft(toTransform);
                    publishProgress(toTransform);
                    //Log.e("AudioRecord", "Recording Failed");
                    //return null;
                }
            return null;
        }


        protected void onProgressUpdate(double[]... toTransform) {
            canvas.drawColor(Color.BLACK);
            for (int i = 0; i < toTransform[0].length; i++) {
                int x;
                x = i;
                int downy = (int) (100 - (toTransform[0][i] * 10));
                int upy = 100;
                canvas.drawLine(x, downy, x, upy, paint);
                imageView.invalidate();
            }
        }

        /*public void onClick(View v) {
            if (started) {
                started = false;
                startStopButton.setText("Start");
                recordTask.cancel(true);
            } else {
                started = true;
                startStopButton.setText("Stop");
                recordTask = new RecordAudio();
                recordTask.execute();
            }
        }*/
    }
}

Spectrum will show up as line each frequency. If i’m not mistaken, the showed up line appear because of drawLine method. Is there any way to show the frequency in other shape (bar)? Really need help :slight_smile:

Here’s the illustration here is the ilustration https://drive.google.com/open?id=0B3jsXXkRa7pLclFYMDdmUlk5MEU&authuser=0


#2

Hi pras,

I’m not able to view the illustration at the link you provided but it sounds like you could easily use shinobicharts to display your data.

In short I would expect you to include a ChartView or ChartFragment in your layout, giving it axes and a Series in the onCreateMethod - in shinobicharts a ColumnSeries is used for vertical bars and a BarSeries is used for horizontal bars.  Then in the onProgressUpdate method I would expect you to create DataPoints which you would add to a DataAdapter and give to the Series.

You can download a 30-day free trial from shinobicontrols.com - in the download bundle there are full Javadocs of the API as well as a User Guide and numerous sample apps with accompanying How-to guides.

Hope that helps!

Patrick


#3

Thanks for your advice :slight_smile:

Really helpfull