我正在尝试使用AudioTrack生成正弦波,方波和锯齿波。然而,这个创建的音频听起来并不像纯正弦波,但它有一些其他的波形覆盖。在第一个例子中使用方法时,我将如何获得纯正弦波,就像在第二个代码示例中那样?由于顶部示例仅围绕第二个中使用的某些算法移动,它们不应该产生相同的波吗?
@Override
protected Void doInBackground(Void... foo) {
short[] buffer = new short[1024];
this.track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM);
float samples[] = new float[1024];
this.track.play();
while (true) {
for (int i = 0; i < samples.length; i++) {
samples[i] = (float) Math.sin( (float)i * ((float)(2*Math.PI) * frequency / 44100)); //the part that makes this a sine wave....
buffer[i] = (short) (samples[i] * Short.MAX_VALUE);
}
this.track.write( buffer, 0, samples.length ); //write to the audio buffer.... and start all over again!
}
}
注意:这确实给了我一个纯粹的正弦波:
@Override
protected Void doInBackground(Void... foo) {
short[] buffer = new short[1024];
this.track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM);
float increment = (float)(2*Math.PI) * frequency / 44100; // angular increment for each sample
float angle = 0;
float samples[] = new float[1024];
this.track.play();
while (true) {
for (int i = 0; i < samples.length; i++) {
samples[i] = (float) Math.sin(angle); //the part that makes this a sine wave....
buffer[i] = (short) (samples[i] * Short.MAX_VALUE);
angle += increment;
}
this.track.write( buffer, 0, samples.length ); //write to the audio buffer.... and start all over again!
}
}
感谢Martijn:问题是波形在缓冲区中的波长之间被切断了。增加缓冲区大小可以解决第二个示例中的问题。似乎Math.PI * 2算法是循环中最密集的算法,因此将该值移动到仅计算一次的外部变量将解决所有问题。
答案 0 :(得分:2)
尝试通过
优化代码为什么呢?因为我怀疑缓冲区需要很长时间才能准备好,导致两次缓冲区推送之间的延迟变大,这可能会导致噪声。
答案 1 :(得分:1)
我在两个代码示例中看到的唯一不同之处在于,第一个示例中的等式包含一个整数(I
),因此您可能正在执行整数(非浮点)算术。这会产生阶梯效应,为波形添加不需要的谐波。
我怀疑如果你只是将I
转换成等式中的浮点数,它将产生纯正弦波。
samples[i]
= (float) Math.sin( (float)i * ((float)(2*Math.PI) * frequency / 44100));
答案 2 :(得分:0)
这些anwers都没有解决问题。缓冲区长度应为采样率的倍数,或至少为一次旋转的长度。让我们在很多变量中打破它,以表明我们理解的事情:
int sampleRate = 44100;
int bitsPerChannel = 16;
int bytesPerChannel = bitsPerChannel / 8;
int channelCount = 1;
int bytesPerSample = channelCount * bytesPerChannel;
int bytesPerRotation = sampleRate * bytesPerSample * (1d / (double) frequency);
然后你可以将这个bytesPerRotation
乘以任何东西,它不会改变一个事实:声音不会出现故障。