2012-12-04 7 views
5

Sto scrivendo una piccola app che cattura l'audio dal microfono Android, esegue un FFT sull'input e quindi traccia il grafico per l'utente. Sto provando a fare simultaneamente la registrazione e la grafica (ovviamente con un piccolo ritardo dall'essere registrati alla grafica). Sto tentando di avviare due thread, uno da leggere e uno da elaborare. Tuttavia, sto riscontrando problemi di sincronizzazione durante l'elaborazione sembra che stia solo ricevendo (o non) zeri. Qualsiasi consiglio sarebbe molto apprezzato. :)Registrare ed elaborare l'audio contemporaneamente a Thread in Android

public class Plotter extends Activity { 

/* plotting objects */ 
private static GraphicalView mView; 
private LineGraph line = new LineGraph(); 

private boolean recordAudio = true; // record? 
private AudioRecord mRecorder = null; // audio object 
private Menu mMenu; // app menu 

private static final String LOG_TAG = "Frequency Plotter"; // debug tag 

private Mfft mfft = null; // FFT class 
private static final int BUF_SIZE = 8192; // amount to read in 

private Thread listener = null; 
private Thread processor = null; 

Stack<Float> items = new Stack<Float>(); 

/* colors for line */ 
private int[] colors = {Color.BLUE,Color.CYAN,Color.DKGRAY,Color.GRAY, 
     Color.GREEN,Color.LTGRAY,Color.MAGENTA,Color.RED,Color.WHITE,Color.YELLOW}; 

private void processAudio(){ 

    ArrayList<Double> real = new ArrayList<Double>(); 

    try{ 

     Random randomGenerator = new Random(); 
     float[] in = new float[2048]; 
     Arrays.fill(in,1); 

     while(true){ 

      synchronized(items){ 

       while(items.size() < 2048) 
        items.wait(); 

       items.notifyAll(); 

       for(int i=0; i < 2048; i++){ 

        in[i] = items.pop();  
       } 
      } 

      double[] ret = mfft.fft(2048,44100,in); // get FFT of data 
      TimeSeries dataset = new TimeSeries((real.size()+1)/2048 + ""); 
      XYSeriesRenderer renderer = new XYSeriesRenderer(); // customized renderer 

      // Customization time 
      renderer.setColor(colors[randomGenerator.nextInt(10)]); 
      renderer.setPointStyle(PointStyle.SQUARE); 
      renderer.setFillPoints(true); 
      line.addRenderer(renderer); // add custom renderer 

      for(int i = 0; i < 2048; i++){ 
       real.add(ret[i]); 
       dataset.add(real.size()-1,ret[i]); // Add it to our graph 
      } 

      line.addDataset(dataset); // add data to line 
      mView.repaint(); // render lines 
     } 

    }catch(Exception e){ 
     Log.e(LOG_TAG, e + " "); 
    } 
} 

private void writeToBuffer(short[] in) { 

    synchronized(items){ 

     for(int i = 0; i < BUF_SIZE; i++){ // copy to create float 
      items.push((float)in[i]); 
     } 
     items.notifyAll(); 
    } 
} 

private void listen(){ 

    final short[] in = new short[BUF_SIZE]; 
    mRecorder = new AudioRecord(
      MediaRecorder.AudioSource.MIC, // source 
      44100, // frequency (HERTZ) 
      AudioFormat.CHANNEL_IN_MONO, // channel 
      AudioFormat.ENCODING_PCM_16BIT, // format 
      BUF_SIZE // size data packet 
      ); 

    mRecorder.startRecording(); 

    while(recordAudio){ 
     try{  
      /* read next part */ 
      mRecorder.read(in,0,BUF_SIZE); // read from device 
      writeToBuffer(in); 

     }catch(Exception t){ 
      /* something went horribly wrong!!!*/ 
      recordAudio = false; 
      Log.e(LOG_TAG, "Failure reading" + t.getMessage()); 
     } 
    } 
} 

private void startRecording(){ 

    /* create a new thread that will run the recording in the background */ 

    listener = new Thread(
     new Runnable(){ 

      public void run(){ 
       listen(); 
      } 
    }); 
    listener.start(); 

    /* small delay to produce */ 
    try { 
     Thread.sleep(100); 
    } catch (InterruptedException e1) { 
     e1.printStackTrace(); 
    } 

    /* create a thread to process the audio */ 
    processor = new Thread(
     new Runnable(){ 
      public void run(){ 
       processAudio(); 
      } 
    }); 
    processor.start(); 
} 

private void stopRecording(){ 

    recordAudio = false; 
    mRecorder.stop(); 
    mRecorder.release(); 
    mRecorder = null; 
} 

/** clear the current chart */ 
private void clearChart(){ 

    line = new LineGraph(); 
    this.onStart(); 
} 

/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
} 

@Override 
protected void onStart() { 

    super.onStart(); 

    /* instantiate */ 
    mfft = new Mfft(); // instance of the FFT class 
    mView = line.getView(this); // get the chart view 

    /* new horizontal layout */ 
    LinearLayout ll = new LinearLayout(this); 
    ll.setOrientation(LinearLayout.HORIZONTAL); 

    ll.addView(mView); // add chart to layout 

    setContentView(ll); // set layout 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 

    // Handle item selection 

    switch (item.getItemId()) { 
     case R.id.record: 

      startRecording(); 

      item.setEnabled(false); // disable start 
      mMenu.findItem(R.id.stop).setEnabled(true); // enable stop 

      return true; 
     case R.id.stop: 

      stopRecording(); 

      item.setEnabled(false); // disable stop 
      mMenu.findItem(R.id.clear).setEnabled(true); // enable stop 

      return true; 
     case R.id.clear: 

      clearChart(); // clear chart 

      item.setEnabled(false); // disable clear 
      mMenu.findItem(R.id.record).setEnabled(true); // enable stop 

      return true; 
     default: 
      return super.onOptionsItemSelected(item); 
    } 

} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 

    mMenu = menu; 
    MenuInflater inflater = getMenuInflater(); 
    inflater.inflate(R.menu.my_menu, menu); 
    return true; 
} 
} 

Modifica: aggiunte definizioni complete.

+0

stai scrivendo i dati diversi da zero, in primo luogo? Il registratore funziona davvero? E puoi pubblicare la tua dichiarazione di 'articoli', per favore? – emrys57

+0

Il registratore funziona, l'ho provato senza elaborazione. Non sto scrivendo dati diversi da zero nell'array. – user1877132

risposta

2
  • diversi pensieri ...

codice di esempio simile, Audalyzer

Purtroppo l'autore si è fermato lo sviluppo di questo progetto, ma l'archivio dei sorgenti è ancora disponibile on-line. In particolare nota: org.hermit.android.io.AudioReader.java. Si legge l'audio e lo si passa tramite un oggetto Stack, questo autore utilizza gli array short []. (Ancora che non sembra come dovrebbe essere la vostra fonte problema ...) http://code.google.com/p/moonblink/downloads/detail?name=SourceTarball.zip

pensieri buf_size

tuo buffer audio (buf_size = 8192) si sente un po 'piccola. Come si riferisce a AudioRecord.getMinBufferSize()? Ho usato 2x minBufferSize, e questo senza fare calcoli (solo lettura/scrittura).

Handler pensieri

sto ancora rivedendo il codice, chiaro come le discussioni che comunicano. Ma il tuo problema sembra che abbia bisogno di un modo per i thread di comunicare un Handler.

Qui di seguito sono i link che ho rivedendo a cogliere come utilizzare Handler s e comunicare tra i thread in modo efficace:

Problemi correlati