我正在尝试理解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 pacakge提供的各种API,例如Executor,ThreadPoolExecutor和FutureTask。 (直接来自文档)来自:How to execute other threads from doinbackground()