gpt4 book ai didi

android - 在 Android 中与 Thread 同时录制和处理音频

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:06:23 25 4
gpt4 key购买 nike

我正在编写一个小应用程序,它从 android MIC 捕获音频,对输入执行 FFT,然后将图表绘制成图表给用户。我正在尝试同时进行记录和绘图(很明显,从记录到绘图之间有一小段延迟)。我正在尝试启动两个线程,一个用于读取,一个用于处理。但是,当我处理似乎只接收(或不接收)零时,我遇到了同步问题。任何建议将不胜感激。 :)

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

编辑:添加了完整的定义。

最佳答案

  • 一些想法...

类似示例代码,Audalyzer

不幸的是,作者已经停止了这个项目的开发,但是源代码压缩包仍然可以在线获得。特别注意:org.hermit.android.io.AudioReader.java。您读取音频并通过 Stack 对象传递它,作者使用 short [] 数组。 (仍然看起来不应该是你的问题来源......) http://code.google.com/p/moonblink/downloads/detail?name=SourceTarball.zip

BUF_SIZE 个想法

您的音频缓冲区 (BUF_SIZE = 8192) 感觉有点小。这与 AudioRecord.getMinBufferSize() 有什么关系?我使用了 2x minBufferSize,并且没有对其进行任何计算(仅读/写)。

Handler 想法

我仍在审查您的代码,不清楚您的线程如何通信。但是,您的问题听起来好像需要一种方法让线程与 Handler 进行通信。

以下是我一直在查看的链接,以了解如何使用 Handler 并有效地在线程之间进行通信:

关于android - 在 Android 中与 Thread 同时录制和处理音频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13712433/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com