3

我正在尝试了解 Android 中的 AudioTrack 类,并且我想了解如何正确调制我正在生成的声波。

我正在使用异步任务类在 UI 的背景中运行 wave,并且能够生成声音。我也可以很容易地改变频率,但是当我动态地这样做时,音高会突然从一个转变到另一个,而不是像我希望的那样逐渐转变。还有模拟合成器的一些基本功能的问题。我试图创建一个 lfo 循环来调制波,但我不确定这是否是处理它的最佳方法,所以基本上有三个问题:

1):有什么方法可以在两种类型的音高转换,渐变/步进之间进行选择。

2):我是否正确实施了 LFO?

3):如果我想要有质感的声音,我必须运行不同的轨道吗?(例如:高频和低频)或者我应该在这个“doInBackground”方法中全部完成,我应该为每个创建一个类吗?我的想法最初是创建一个正弦波并相应地处理它以创建我需要的声音,基本上我不确定如何在线程和信号处理方面为声波添加纹理。

一些背景:我想要完成的是构建一个应用程序,它可以通过用户输入每隔一段时间生成谐波,有点像动态音序器。

我如何组织和构建处理它所需的滤波器?

抱歉,我知道这很多,但这对我来说非常迷人,并且非常感谢任何在正确方向上的帮助。

这是我的代码:它当前会生成一个声音流,但带有一些可听的伪影。

 private class AudioSynthesisTask extends AsyncTask<Void, Void, Void> {
    @Override
    protected Void doInBackground(Void... params) {
        final int SAMPLE_RATE = 44100;
        int minSize = AudioTrack.getMinBufferSize( //Sample size. Individual sample.
                SAMPLE_RATE,                    // Numerical cycles per second
                AudioFormat.CHANNEL_OUT_MONO,   // Channel to output
                AudioFormat.ENCODING_PCM_16BIT  // pulse code modulation giving you
                // encoding at 16 bits per cycle to define a sample rate.
        );
        AudioTrack audioTrack = new AudioTrack( //connects the calculation to the hardware
                AudioManager.STREAM_MUSIC,
                SAMPLE_RATE,
                AudioFormat.CHANNEL_OUT_MONO,
                AudioFormat.ENCODING_PCM_16BIT,
                minSize,
                AudioTrack.MODE_STREAM);
        audioTrack.play();
        AudioTrack audioTrack2 = new AudioTrack( //connects the calculation to the hardware
                AudioManager.STREAM_MUSIC,
                SAMPLE_RATE,
                AudioFormat.CHANNEL_OUT_MONO,
                AudioFormat.ENCODING_PCM_16BIT,
                minSize,
                AudioTrack.MODE_STREAM);
        audioTrack2.play();

        short[] sample_buffer = new short[minSize]; //will be fed as a string.
        float angle = 0;
        while (true) {
            if (play) {//On touch
                for (int j = 0; j < sample_buffer.length; j++) {
                    float frequency = (float) ((2 * Math.PI) * low_frequency_oscillator / SAMPLE_RATE); 
                    angle += frequency;

                    sample_buffer[j] = (short) (low_frequency_oscillator * 2 * (-0.02 / 1200 + 0.5 * angle));
                    sample_buffer[j] = (short) (amplitude * Math.cos(angle)); 
                }
                audioTrack.write(sample_buffer, 0, sample_buffer.length);
            }

            if (play) {
                for (int i = 0; i < sample_buffer.length; i++) {
                    float angular_frequency = (float) (2 * Math.PI) * synth_frequency / SAMPLE_RATE;
                    angle += angular_frequency;
                    sample_buffer[i] = (short) (amplitude * ((float) Math.cos(angle)));
                }
                audioTrack2.write(sample_buffer, 0, sample_buffer.length);//test track
            }
        }
    }
}

所以我读了这篇文章,我想知道它是否适用于我正在尝试做的事情:AsyncTask 被设计为围绕 Thread 和 Handler 的辅助类,并不构成通用线程框架。AsyncTasks 最好用于短时间的操作(最多几秒钟)。如果您需要保持线程长时间运行,强烈建议您使用 java.util.concurrent 包提供的各种 API,例如Executor、ThreadPoolExecutor 和 FutureTask。(直接来自文档)来自:如何从 doinbackground() 执行其他线程

4

0 回答 0