天天看點

跟蹤手指在螢幕上的位置生成音頻樣本并播放

此示例根據使用者手指在螢幕的x軸方向上的位置,來選擇頻率并生成音頻樣本。

因為代碼比較簡單,那麼話不多說,直接上代碼。

public class FingerSynthesis extends Activity implements OnTouchListener
{
 
    AudioSynthesisTask audioSynth;//播放音頻樣本的線程
 
    static final float BASE_FREQUENCY = 440;//基準音頻頻率
 
 
    float synth_frequency = BASE_FREQUENCY; // 440 Hz, 随着手指的移動會發生改變
    boolean play = false;//控制是否生成音頻樣本
 
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
 
        setContentView(R.layout.main);
 
        View mainView = this.findViewById(R.id.MainView);
        mainView.setOnTouchListener(this);
 
        audioSynth = new AudioSynthesisTask();
        audioSynth.execute();
    }
 
    @Override
    public void onPause()
    {
        super.onPause();
        play = false;
 
        finish();
    }
 
    public boolean onTouch(View v, MotionEvent event)
    {
        int action = event.getAction();
        switch (action)
        {
            case MotionEvent.ACTION_DOWN:
                play = true;//根據使用者操作将play設定為true或者false
                synth_frequency = event.getX() + BASE_FREQUENCY;//跟蹤使用者手指的位置,做出相應的改變
                Log.v("FREQUENCY", "" + synth_frequency);
                break;
            case MotionEvent.ACTION_MOVE:
                play = true;
                synth_frequency = event.getX() + BASE_FREQUENCY;
                Log.v("FREQUENCY", "" + synth_frequency);
                break;
            case MotionEvent.ACTION_UP:
                play = false;
                break;
            case MotionEvent.ACTION_CANCEL:
                break;
            default:
                break;
        }
        return true;
    }
 
    private class AudioSynthesisTask extends AsyncTask<Void, Void, Void>
    {
        @Override
        protected Void doInBackground(Void... params)
        {
            final int SAMPLE_RATE = 11025;
 
            int minSize = AudioTrack.getMinBufferSize(SAMPLE_RATE,
                    AudioFormat.CHANNEL_CONFIGURATION_MONO,
                    AudioFormat.ENCODING_PCM_16BIT);
 
            AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                    SAMPLE_RATE, AudioFormat.CHANNEL_CONFIGURATION_MONO,
                    AudioFormat.ENCODING_PCM_16BIT, minSize,
                    AudioTrack.MODE_STREAM);
 
            audioTrack.play();
 
            short[] buffer = new short[minSize];
 
            float angle = 0;
 
            while (true)
            {
 
                if (play)
                {
                    for (int i = 0; i < buffer.length; i++)
                    {
                        float angular_frequency = (float) (2 * Math.PI)
                                * synth_frequency / SAMPLE_RATE;
 
                        buffer[i] = (short) (Short.MAX_VALUE * ((float) Math
                                .sin(angle)));//生成音頻樣本
                        angle += angular_frequency;
                    }
                    audioTrack.write(buffer, 0, buffer.length);
                } else
                {
                    try
                    {
                        Thread.sleep(50);
                    } catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}