2011-04-01 10 views
8

Soy nuevo en Android y estoy tratando de crear un programa que capture un sonido de audio y luego muestre las frecuencias que existen dentro de él. Encontré un ejemplo que dibuja la parte gráfica de un ecualizador gráfico. En este ejemplo, se utiliza un objeto de tipo AudioRecord para capturar sonido de audio. La técnica utilizada para dividir una señal de audio en frecuencias de componentes emplea una transformación matemática llamada transformada discreta de Fourier (DFT) y para realizar DFT se usa una transformada rápida de Fourier (FFT). Este ejemplo utiliza un paquete que implementa la FFT. El paquete está vinculado aquí www.netlib.org/fftpack/jfftpack.tgz. El problema es que después de ejecutar este ejemplo, el ecualizador gráfico no aparece en la pantalla después de presionar el botón de inicio.Captura de sonido para análisis y visualización de frecuencias en Android

Aquí está el código fuente de la clase de actividad:

package com.audio.processing; 
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 AudioProcessing extends Activity implements OnClickListener{ 
    int frequency = 8000; 
    int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_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; 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     startStopButton = (Button) this.findViewById(R.id.StartStopButton); 
     startStopButton.setOnClickListener(this); 

     transformer = new RealDoubleFFT(blockSize); 

     imageView = (ImageView) this.findViewById(R.id.ImageView01); 
     bitmap = Bitmap.createBitmap((int)256,(int)100,Bitmap.Config.ARGB_8888); 
     canvas = new Canvas(bitmap); 
     paint = new Paint(); 
     paint.setColor(Color.GREEN); 
     imageView.setImageBitmap(bitmap); 
    } 

    private class RecordAudio extends AsyncTask<Void, double[], Void> { 
     @Override 
     protected Void doInBackground(Void... params) { 
     try { 
      int bufferSize = AudioRecord.getMinBufferSize(frequency, 
        channelConfiguration, audioEncoding); 
        AudioRecord audioRecord = new AudioRecord(
        MediaRecorder.AudioSource.DEFAULT, frequency, 
        channelConfiguration, audioEncoding, bufferSize); 

        short[] buffer = new short[blockSize]; 
        double[] toTransform = new double[blockSize]; 
        audioRecord.startRecording(); 
        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); 
        } 
        audioRecord.stop(); 
        } catch (Throwable t) { 
        Log.e("AudioRecord", "Recording Failed"); 
        } 
        return null; 
        } 
     } 

    protected void onProgressUpdate(double[]... toTransform) { 
     canvas.drawColor(Color.BLACK); 
     for (int i = 0; i < toTransform[0].length; i++) { 
     int 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(); 
     } 
     } 
} 

Aquí es el main.xml:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:orientation="vertical" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
> 
<TextView 
android:layout_width="fill_parent" 
android:layout_height="wrap_content" 
android:text="@string/hello" 
/> 
<ImageView android:id="@+id/ImageView01" android:layout_width="wrap_content" 
android:layout_height="wrap_content"></ImageView><Button android:text="Start" 
android:id="@+id/StartStopButton" android:layout_width="wrap_content" 
android:layout_height="wrap_content"></Button> 
</LinearLayout> 

En el AndroidManifest.xml fijo el permiso RECORD_AUDIO. ¡Gracias de antemano!

+1

donde isthe image view tag in the xml? – codeScriber

Respuesta

2

Sí, también tuve este proyecto y tuve el mismo error que tú, pero después de agregar el permiso a continuación todo está bien ahora. Lo más probable es que no lo haya agregado en el lugar correcto en androidmanifest.xml. Debe estar fuera de la etiqueta de la aplicación.

<uses-permission android:name="android.permission.RECORD_AUDIO"> 
    </uses-permission> 
2

método onProgressUpdate debe pertenecer a RecordAudio, como en su código es propiedad de AudioProcessing. Verifique las llaves, debería funcionar según la corrección anterior

12

Aquí está el código de trabajo. Lo intenté yo mismo. Funciona bien.

package com.example.frequencytest; 

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.Menu; 
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 MainActivity extends Activity implements OnClickListener { 

    int frequency = 8000; 
    int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_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; 

    //AudioRecord audioRecord; 

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

     startStopButton = (Button) this.findViewById(R.id.start_stop_btn); 
     startStopButton.setOnClickListener(this); 

     transformer = new RealDoubleFFT(blockSize); 

     imageView = (ImageView) this.findViewById(R.id.imageView1); 
     bitmap = Bitmap.createBitmap((int) 256, (int) 100, 
       Bitmap.Config.ARGB_8888); 
     canvas = new Canvas(bitmap); 
     paint = new Paint(); 
     paint.setColor(Color.GREEN); 
     imageView.setImageBitmap(bitmap); 

    } 

    public class RecordAudio extends AsyncTask<Void, double[], Void> { 

     @Override 
     protected Void doInBackground(Void... arg0) { 

      try { 
       // int bufferSize = AudioRecord.getMinBufferSize(frequency, 
       // AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); 
       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]; 

       audioRecord.startRecording(); 

       // started = true; hopes this should true before calling 
       // following while loop 

       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); 



       } 

       audioRecord.stop(); 

      } catch (Throwable t) { 
       t.printStackTrace(); 
       Log.e("AudioRecord", "Recording Failed"); 
      } 
      return null; 
     } 

     @Override 
     protected void onProgressUpdate(double[]... toTransform) { 

      canvas.drawColor(Color.BLACK); 

      for (int i = 0; i < toTransform[0].length; i++) { 
       int x = i; 
       int downy = (int) (100 - (toTransform[0][i] * 10)); 
       int upy = 100; 

       canvas.drawLine(x, downy, x, upy, paint); 
      } 

      imageView.invalidate(); 

      // TODO Auto-generated method stub 
      // super.onProgressUpdate(values); 
     } 

    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     getMenuInflater().inflate(R.menu.activity_main, menu); 
     return true; 
    } 

    public void onClick(View arg0) { 
     // TODO Auto-generated method stub 
     if (started) { 
      started = false; 
      startStopButton.setText("Start"); 
      recordTask.cancel(true); 
     } else { 
      started = true; 
      startStopButton.setText("Stop"); 
      recordTask = new RecordAudio(); 
      recordTask.execute(); 
     } 
    } 
} 
+0

muchas gracias, estaba buscando algo como esto! – Larphoid

+1

Después de experimentar ... en actividad principal (solo para que sea más fácil seguir lo que sucede, y para usar ALTURA siempre que se usó 100): \t estática final int ALTURA = 100; \t estática final int MIDDLE = HEIGHT/2; \t static final int PEAK = MIDDLE/10; // fue HEIGHT/10 luego en onProgressUpdate: \t int x = 0; \t for (int i = 0; i Larphoid

Cuestiones relacionadas