使用AudioTrack提高音符合成的性能

我正在尝试构建一个综合和播放音符的安卓应用程序。 我正在使用AudioTrack。 由于生成音频信息的延迟,我的程序似乎无法足够快地填充轨道缓冲区。 我正在从音符的fourier系数生成音频信息。 因此,在每次写入之前,程序必须创建并采样2048个正弦波,每个正弦波的采样大小为2400,采样率为44100!

因此,而不是连续的声音,我听到间歇性的嘟嘟声 Logcat在蜂鸣声之间给出以下警告:

W/AudioTrack﹕ obtainBuffer() track 0x177ff80 disabled, restarting

我的代码如下。 任何人都可以确定我可以优化代码的方式吗?

package com.alantaar.alantaar;

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

import java.util.Arrays;

public class AudioGenerator {
    private AudioTrack audio;
    private double[] coefficients;
    private int bufferSize;
    private int sampleRate;
    private double[] phases;
    private double frequency;


public AudioGenerator(double[] coefficients, double frequency, int sampleRate, int bufferSize){
    int minBufferSize = AudioTrack.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_OUT_MONO,
            AudioFormat.ENCODING_PCM_16BIT);
    this.bufferSize = bufferSize > minBufferSize ? bufferSize : minBufferSize;
    audio = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, AudioFormat.CHANNEL_OUT_MONO,
            AudioFormat.ENCODING_PCM_16BIT, this.bufferSize, AudioTrack.MODE_STREAM);

    this.coefficients = coefficients;
    this.sampleRate = sampleRate;
    this.frequency = frequency;
    this.phases = new double[coefficients.length];
    Arrays.fill(this.phases, 0.0);
    Log.i("length", Integer.toString(coefficients.length));

    audio.play();
}

public void playNote(){
    while(true){
        short[] waveSample = sampleWave();
        audio.write(waveSample, 0, waveSample.length);
    }
}

private short[] sampleWave(){
    short [] waveSample = new short[bufferSize];
    Arrays.fill(waveSample, (short)0);
    for(int i = 0; i < coefficients.length; i++){
        double coefficient = coefficients[i];
        short[] sineSamples = sampleSineWave(coefficient, i);
        for(int j = 0; j < waveSample.length; j++){
            waveSample[j] += sineSamples[j];
        }
    }
    return waveSample;
}

private short [] sampleSineWave(double coefficient, int index){
    double freq = frequency * index;
    short [] samples = new short[bufferSize];
    for(int i = 0; i < bufferSize; i++){
        samples[i] = (short) (coefficient * Short.MAX_VALUE * Math.cos(phases[index]));
        phases[index] += 2 * Math.PI * freq/sampleRate;
    }
    return samples;
}

public void pauseNote(){
    audio.stop();
}

public void stopNote(){
    audio.release();
}

}


以下是我弹出的一些内容:

  • 将计算移出内部循环。 例如, 2*pi*freq/sampleRate可以在for之前完成。 与coefficient * Short.MAX_VALUE相同。
  • 我敢打赌,你的笔记实际上并不包含2048个不同的有意义的正弦分量。一个选项是当系数低于某个阈值时不产生音调。
  • 使用FFT! 您正在实施的是D(n ^ 2)。 FFT运行在O(n log n)。
  • audio.write被阻塞时使用时间来生成更多样本。 我不知道AudioTrack的流式传输模式的行为,但很可能您的程序将大部分时间用于阻塞呼叫。
  • 链接地址: http://www.djcxy.com/p/33861.html

    上一篇: Improve performance of musical note synthesis using AudioTrack

    下一篇: Key repeat delay in SDL