Android Audiotrack在声音之前和之后点击

时间:2016-04-14 13:46:43

标签: android audio signal-processing audiotrack

我让合成器能够产生三种基本类型的声音,当我播放声音时,在完成播放之前和之后,点击就会发生。我无法弄清楚原因。

每种类型的声音都会发生..正弦声音最大。

以下是我用于生成声音的代码

int amp = 32767;
double phase = 0.0;

protected void onCreate(Bundle savedInstanceState) {
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        AudioManager myAudioMgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        String nativeParam = myAudioMgr.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
        sampleRate = Integer.parseInt(nativeParam);
        nativeParam = myAudioMgr.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
        bufSize = Integer.parseInt(nativeParam);
    }
    else {
        sampleRate = 44100;
        bufSize = AudioTrack.getMinBufferSize(sampleRate,
                AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
    }

    audioOutput = new AudioOutput();
    audioOutput.Start(sampleRate, bufSize);

    samples = new short[bufSize];    // buffer size is 512

    playTask.execute();
}

class PlayTask extends AsyncTask<Object, Void, Void> {
    @Override
    protected Void doInBackground(Object[] params) {
        android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND + Process.THREAD_PRIORITY_MORE_FAVORABLE);

        while (!this.isCancelled()) {
            while (touched) {
                generateTone();
                audioOutput.write(samples, 0, samples.length);
            }
        }
        return null;
    }
}

private void generateTone() {
    double phaseIncrement = (2 * Math.PI) / sampleRate;
    switch (currentShape) {
        case SINE:
            for (int i = 0; i < bufSize; i++) {
                samples[i] = (short) (amp * Math.sin(phase));
                phase += phaseIncrement * freq;
                if (phase > 2 * Math.PI)
                    phase -= 2 * Math.PI;
            }
            break;
        case SAWTOOTH:
            for (int i = 0; i < bufSize; i++) {
                samples[i] = (short) (amp * (phase - amp));
                phase += phaseIncrement * freq;
                if (phase > 2 * Math.PI)
                    phase -= 2 * Math.PI;
            }
            break;
        case SQUARE:
            for (int i = 0; i < bufSize; i++) {
                if (phase < Math.PI)
                    samples[i] = (short) amp;
                else
                    samples[i] = (short) -amp;
                phase += phaseIncrement * freq;
                if (phase > 2 * Math.PI)
                    phase -= 2 * Math.PI;
            }
            break;
    }
}

public class AudioOutput {
    private AudioTrack mAudioTrack;
    private int mFrameRate;

    public void Start(int sampleRate, int bufferSize) {
        Stop();
        mFrameRate = sampleRate;
        mAudioTrack = createAudioTrack(bufferSize);

        mAudioTrack.play();
    }

    private AudioTrack createAudioTrack(int buffsize) {
        return new AudioTrack(AudioManager.STREAM_MUSIC,
                mFrameRate, AudioFormat.CHANNEL_OUT_MONO,
                AudioFormat.ENCODING_PCM_16BIT, buffsize,
                AudioTrack.MODE_STREAM);
    }

    public int write(short[] buffer, int offset, int length) {
        return write = mAudioTrack.write(buffer, offset, length);
    }

    public void Stop() {
        if (mAudioTrack != null) {
            mAudioTrack.stop();
            mAudioTrack.release();
            mAudioTrack = null;
        }
    }
}

音频示例:https://soundcloud.com/syntey/sinewavetest

任何人都知道哪里可能有问题?

由于

2 个答案:

答案 0 :(得分:1)

您没有在过零点处开始和结束每个缓冲区。每个缓冲区开始时的随机相位可能会在第一个样本中产生过于急剧的上升时间。锥度(升余弦锥度)从零到零的第一个和最后几个样本也可能有所帮助。

答案 1 :(得分:0)

我遇到了同样的问题,我暂停了 AudioTrack 而不是停止它。问题得到解决。