如何创建连续运行调谐器? [英] How to create tuner that runs continuously?

查看:152
本文介绍了如何创建连续运行调谐器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建为Android调谐器(类似于吉他调谐器),我想知道如何让调谐器连续运行(一两分钟左右)。我不希望它在后台运行,只是当用户在我的应用程序的服务。

I am creating a tuner for Android (similar to a guitar tuner) and I am wondering how to allow the tuner to run continuously (for a couple minutes or so). I don't want it to be a service that runs in the background, just while the user is in my app.

我已经成功地使用了 AudioRecord 类和我获得这似乎正确的数据。我在过滤该数据,并找到输入信号的基本频率的过程中,但需要帮助找出如何让我的调谐器连续地运行。

I have successfully used the AudioRecord class and am obtaining data that seems correct. I am in the process of filtering this data and finding the fundamental frequency of the input signal, but need help figuring out how to allow my tuner to run continuously.

这是我的code样子至今:

This is what my code looks like so far:

import android.app.Activity;
import android.graphics.Color;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.dustin.tuner2.FFT;
import com.dustin.tuner2.Complex;


public class Tuner2 extends Activity implements OnClickListener {
    Button btnTune;
    TextView fft;
    TextView freq;
    TextView results;
    MediaRecorder recorder;
    AudioRecord tuner;
    boolean startTuning = true;
    int audioSource = MediaRecorder.AudioSource.MIC;
    int sampleRateInHz = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_SYSTEM);
    int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
    int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
    int bufferSizeInBytes;
    int samples;
    short[] audioBuffer;
    short[] audioData;
    double[] temp;
    String fileName;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        btnTune = (Button)findViewById(R.id.btnTune);
        freq = (TextView)findViewById(R.id.freq);
        btnTune.setOnClickListener(this);
        bufferSizeInBytes = 4096;
        //bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat);
        results = (TextView)findViewById(R.id.results);
        fft = (TextView)findViewById(R.id.fft);
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub

        if (v == btnTune)
        {
            onTune(startTuning);
            if (startTuning) {
                ((Button)v).setText("Stop Tuning");
            }
            else {
                ((Button)v).setText("Start Tuninig");
            }
            startTuning = !startTuning;
        }
    }

    //------------------------------------------------------------>
    private void onTune(boolean start) {
        if(start) {
            startTuning();
        } else {
            Toast.makeText(getApplicationContext(), "Tuning Stopped", Toast.LENGTH_SHORT).show();
            tuner.stop();
        }
    }

    private void startTuning()
    {
        tuner = new AudioRecord(audioSource, sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes);

        audioData = new short[bufferSizeInBytes];
        trigger();
    }

    public void trigger(){
        acquire();
        computeFFT();
        display();
    }

    public void acquire(){
        try {
            tuner.startRecording();
            samples = tuner.read(audioData, 0, bufferSizeInBytes);
        }
        catch (Throwable t){

        }   
    }

    public void computeFFT(){
        //Conversion from short to double
        double[] micBufferData = new double[bufferSizeInBytes];//size may need to change
        final int bytesPerSample = 2; // As it is 16bit PCM
        final double amplification = 100.0; // choose a number as you like
        for (int index = 0, floatIndex = 0; index < bufferSizeInBytes - bytesPerSample + 1; index += bytesPerSample, floatIndex++) {
            double sample = 0;
            for (int b = 0; b < bytesPerSample; b++) {
                int v = audioData[index + b];
                if (b < bytesPerSample - 1 || bytesPerSample == 1) {
                    v &= 0xFF;
                }
                sample += v << (b * 8);
            }
            double sample32 = amplification * (sample / 32768.0);
            micBufferData[floatIndex] = sample32;
        }

        //Create Complex array for use in FFT
        Complex[] fftTempArray = new Complex[bufferSizeInBytes];
        for (int i=0; i<bufferSizeInBytes; i++)
        {
            fftTempArray[i] = new Complex(micBufferData[i], 0);
        }

        //Obtain array of FFT data
        final Complex[] fftArray = FFT.fft(fftTempArray);
        final Complex[] fftInverse = FFT.ifft(fftTempArray);

        //Create an array of magnitude of fftArray
        double[] magnitude = new double[fftArray.length];
        for (int i=0; i<fftArray.length; i++){
            magnitude[i]= fftArray[i].abs();
        }

        fft.setTextColor(Color.GREEN);
        fft.setText("fftArray is "+ fftArray[500] +" and fftTempArray is "+fftTempArray[500] + " and fftInverse is "+fftInverse[500]+" and audioData is "+audioData[500]+ " and magnitude is "+ magnitude[1] + ", "+magnitude[500]+", "+magnitude[1000]+" You rock dude!");
        for(int i = 2; i < samples; i++){
            fft.append(" " + magnitude[i] + " Hz");
        }
    }

    public void display(){
        results.setTextColor(Color.BLUE);
        results.setText(audioData[1]+"");
        for(int i = 2; i < samples; i++){
            results.append(" " + audioData[i]);
        }
        results.invalidate();
        //fft.setTextColor(Color.GREEN);
        //fft.setText("Buffer size is "+bufferSizeInBytes);
        //fft.setText(fftArray[1]+" Hz");
        //for(int i = 2; i < samples; i++){
        //fft.append(" " + fftArray[i] + " Hz");
        //}
        //fft.invalidate();
    }

我是否需要改变有关按钮,并在pressed它做了什么事?它只是涉及到缓冲区的大小?我多久计算FFT?

Do I need to change something concerning the button and what it does when pressed? Would it just involve the buffer size? How often I compute the FFT?

推荐答案

除非我误解,你可以只使用一个while循环,检查一个布尔变量。当用户点击停止按钮变量设置为false。

Unless I am misunderstanding, you could just use a while loop that checks a boolean variable. When the user clicks the stop button set that variable to false.

while (tuning) {
    trigger();
}

您也应该可能引入这些调用之间的延迟。这也将是明智的运行比在UI线程的线程上该code。请参见 http://developer.android.com/resources/articles/painless-threading。 HTML

you should also probably introduce a delay between these calls. It would also be wise to run this code on a thread other than the UI thread. See http://developer.android.com/resources/articles/painless-threading.html

我的意思一个简单的例子是做

A simple example of what I mean would be to do

new Thread(new Runnable() {
    @Override
    public void run() {
        while (tuning) {
            trigger();
            try {
                Thread.sleep(SLEEP_TIME_MS);
            } catch (InterruptedException e) {
                // handle exception
            }
        }
    }
}).start();

但你不必担心更新,你可以这样做,从该线程的UI。最好的办法是使用的AsyncTask http://developer.android.com/reference/android/os/AsyncTask.html

这篇关于如何创建连续运行调谐器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆