Android Open Source - Spectograph Spectogram






From Project

Back to project page Spectograph.

License

The source code is released under:

Copyright (c) 2013 Salman aljammaz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the So...

If you think the Android project Spectograph listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package net.x65.spectograph;
//w ww.j av  a 2 s .  c  o  m
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.util.ArrayList;
import android.media.audiofx.Visualizer;

public class Spectogram
extends SurfaceView
implements SurfaceHolder.Callback {
  private static final String TAG = Spectogram.class.getSimpleName();

  ArrayList<int[]> hist;
  private DrawThread worker = new DrawThread(this, getHolder());
  
  public Spectogram(Context context, AttributeSet attrs) {
    super(context, attrs);
    
    this.hist = ((SpectographApp)((Activity) context).getApplication()).hist;
    
    getHolder().addCallback(this);
    setFocusable(true);

    //rec.startRecording();
    v.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);
    v.setEnabled(true);
    
    Log.d(TAG, "View initialised");
  }

  public void release() {
  }
  
  @Override
  public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
  }
 
  @Override
   public void surfaceCreated(SurfaceHolder holder) {
    Log.d(TAG, "surfaceCreated");
    worker.start();
  }
 
  @Override
  public void surfaceDestroyed(SurfaceHolder holder) {
    Log.d(TAG, "surfaceDestroyed");
    worker.interrupt();
    while (true) {
      try {
        worker.join();
        return;
      } catch (InterruptedException e) {
      }
    }

  }
    
  Paint fg = new Paint();
  Bitmap mCanvasBitmap;
  Canvas mCanvas;
  
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    mCanvasBitmap = Bitmap.createBitmap(w, h, Config.ARGB_8888);
    mCanvas = new Canvas(mCanvasBitmap);
    mCanvas.drawColor(0xff000000);
  }

  double maxAmp = 1;
  void drawGraph() {
    if (hist.size() == 0) {
      return;
    }
    
    int end = hist.size();
    
    int start = end - getWidth();
    if (start < 0) {
      start = 0;
    }
    
    for (int cur = start; cur < end ; cur++) {
      //TODO scaling here
      int x = hist.size() - cur;
      int[] notes = hist.get(cur);
      
      
      maxAmp /= 2;
      for (int i = 0; i < notes.length; i++) {
        if (notes[i] > maxAmp) {
          maxAmp = notes[i];
        }
      }
      
      if (maxAmp > 0) {
      }
      
      // TODO proper colour scaling
      float cy = 0;
      for (int i = 0; i < notes.length; i++) {
        float y = (float) (getHeight() * i) / notes.length;
      
        int color = 0xff;
        color &= 255 * (int)(((double)notes[i])/maxAmp);
      
        fg.setColor(0xff000000 + (color<<16));
        
        mCanvas.drawLine(x, cy, x, y, fg);
        cy = y;
      }
    }
  }
  
  void drawLines() {
    for (int i = 0; i < 12*7; i += 1) {
      if (i%12 == 0) {
        fg.setColor(0x8fffffff);
      } else {
        fg.setColor(0x3fffffff);
      }
    
      float y = (float) (getHeight() * i) / (12*7);
      mCanvas.drawLine(0, y, getWidth(), y, fg);
    }
  }
  
  void render(Canvas c) {
    drawGraph();
    drawLines();
    c.drawBitmap(mCanvasBitmap, new Matrix(), null);
  }
  
  static int sampleRate = 44100;
  static int captureSize = 1024; //8192*2;
  static int tet = 12;
  static double baseFreq = 32.7;
  
  //AudioRecord rec = new AudioRecord(MediaRecorder.AudioSource.DEFAULT,
  //  sampleRate,
  //  AudioFormat.CHANNEL_CONFIGURATION_MONO,
  //  AudioFormat.ENCODING_PCM_16BIT,
  //  captureSize * 2);

  Visualizer v = new Visualizer(0);

  FFT fft = new FFT(captureSize);
  byte[] audioData = new byte[captureSize];
  double[] waveform = new double[captureSize];
  byte[] freqs = new byte[captureSize];
  void update() {
    //rec.read(audioData, 0, captureSize);
    //for (int i = 0; i < audioData.length; i++) {
    //  waveform[i] = audioData[i];
    //}
    //fft.fft(waveform, freqs);
    
    v.getFft(freqs);
    
    
    int[] notes = new int[tet*7];
    
    for (int k = 0; k < notes.length; k++) {
      double f = freqAtNote(k);
      double fNext = freqAtNote(k+1);
      
      int start = indexAtFreq(f)+1;
      int end = indexAtFreq(fNext)+1;
      int len = end-start;
      int mag = 0;
      
      for (int j = start; j < end; j+=2) {
        mag += (freqs[j] * freqs[j] + freqs[j+1] * freqs[j+1] ) / len;
      }
      notes[k] = mag;
      
      /*  if (hist.size() % 30 == 0) Log.d(TAG, "note:" + k +
                      " start:" + start +
                      " end:" + end +
                      " mag:" + mag +
                      " f:" + f
                      );*/
      
    }
    
    hist.add(notes);
  }
  
  static int indexAtFreq(double f) {
     // possible off by 1 error here
    return (int) (f * captureSize / sampleRate);
  }
  
  static double freqAtIndex(int i) {
    return i * sampleRate / captureSize;
  }
  
  static double freqAtNote(int n) {
    return baseFreq * Math.pow(2, (double)n/tet);
  }
}




Java Source Code List

net.x65.spectograph.DrawThread.java
net.x65.spectograph.FFT.java
net.x65.spectograph.Spectogram.java
net.x65.spectograph.SpectographApp.java
net.x65.spectograph.Spectograph.java