如何在Android上创建50hz方波并播放它

时间:2014-09-05 11:24:37

标签: java android audio audiotrack android-audiomanager

我目前正在为手机编写一款Android应用来控制2台伺服电机。

因此我需要在50hz处创建一个高振幅的方波。 我已经看了一下AudioManager和AudioTrack类的一些示例代码,但我真的不知道如何在50hz下实现具有可测量振幅的基本方波。

这是我到目前为止所得到的:

package com.example.rollerball;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.support.v7.app.ActionBarActivity;

public class ToneGenerator
{   
    Thread t;
    int sr = 44100;
    boolean isRunning = true;

    public void startTone()
    {
        isRunning = true;
        t = new Thread() {
            public void run() {
                // set process priority
                setPriority(Thread.MAX_PRIORITY);
                int buffsize = AudioTrack.getMinBufferSize(sr,
                        AudioFormat.CHANNEL_OUT_MONO,
                        AudioFormat.ENCODING_PCM_16BIT);
                // create an audiotrack object
                AudioTrack audioTrack = new AudioTrack(
                        AudioManager.STREAM_MUSIC, sr,
                        AudioFormat.CHANNEL_OUT_MONO,
                        AudioFormat.ENCODING_PCM_16BIT, buffsize,
                        AudioTrack.MODE_STREAM);

                short samples[] = new short[buffsize];
                int amp = 10000;
                double twopi = 8. * Math.atan(1.);
                double fr = 440.f;
                double ph = 0.0;
                // start audio
                audioTrack.play();

                while (isRunning) {

                    for (int i = 0; i < buffsize; i++) {
                        samples[i] = (short) (amp * Math.sin(ph));
                        ph += twopi * fr / sr;
                    }
                    audioTrack.write(samples, 0, buffsize);
                }
                audioTrack.stop();
                audioTrack.release();
            }
        };
        t.start();
    }

    public void stopTone(){   
           isRunning = false;
           try {
             t.join();
           } catch (InterruptedException e) {
             e.printStackTrace();
           }    
          t = null;
        }
}

也许你们中的一些人可以帮助我!

提前致谢!

2 个答案:

答案 0 :(得分:2)

现在,您的代码会产生一个漂亮的干净正弦波,峰值幅度为±10000。可以用16位PCM表示的最大样本值是±1^15-1 = ±32767,它是FSD的〜-10dB。

你想要一个方波。下面的代码实现了它(不是特别有效)。

for (int i = 0; i < buffsize; i++) {
    short s = (amp * Math.sin(ph));
    if (s > 0.0) {
        sample[i] = 32767;
    };

    if (s < 0.0) {
        sample[i] = -32767;
    }
    ph += twopi * fr / sr;
}

答案 1 :(得分:0)

我有一个来自我的项目的代码示例。生成的音调的开始/结束由开关控制。我认为Thread部分对你有用。

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Switch;
import android.widget.CompoundButton;

public class MainActivity extends AppCompatActivity {

    Thread t; //Object that hold the audio processing thread
    int sr = 44100; //sampling rate
    boolean isRunning = true; //means of switching on and off

    public Switch switch1;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //switch
        switch1 = (Switch) findViewById(R.id.switch1);

        //attach a listener to it
        switch1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    isRunning = true;
                    t = createToneThread();
                    t.start();
                } else {
                    isRunning = false;
                }
            }
        });

    }

    Thread createToneThread()
    {
        t = new Thread() {
        public void run() {
            //set process priority to maximum to get good performance
            setPriority(Thread.MAX_PRIORITY);
            //set the buffer size
            int buffsize = AudioTrack.getMinBufferSize(sr, AudioFormat.CHANNEL_OUT_MONO,
                    AudioFormat.ENCODING_PCM_16BIT);
            //create an audiotrack  object
            AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sr,
                    AudioFormat.CHANNEL_OUT_MONO,
                    AudioFormat.ENCODING_PCM_16BIT, buffsize,
                    AudioTrack.MODE_STREAM);

            //create signal buffer and define the parameters
            short samples[] = new short[buffsize];
            short amp = 10000;

            for (int i = 0; i < buffsize; i+=4) {
                samples[i]   = (short)-amp;
                samples[i+1] = (short)-amp;
                samples[i+2] =  amp;
                samples[i+3] =  amp;
            }

            //start audio
            audioTrack.play();

            //define the synthesis loop
            while (isRunning) {

                audioTrack.write(samples, 0, buffsize);
            }
            //closing  of the audio device
            audioTrack.stop();
            audioTrack.release();

            }
        };
        return t;
    }
}