我想生成具有组合频率的正弦波。我要这样:
public static byte[] combineSineWave(Collection<Double> frequencies) {
double[] sample = new double[SAMPLE_RATE];
byte[] result = new byte[2 * SAMPLE_RATE];
double coefficient = 2 * Math.PI;
for (int i = 0; i < SAMPLE_RATE; i++) {
double sum = 0;
for (double frequency : frequencies) {
sum += Math.sin(coefficient * i * frequency / SAMPLE_RATE);
}
sample[i] = sum / frequencies.size();
}
convertToPCM16Bit(sample, result);
return result;
}
private static void convertToPCM16Bit(double[] sample, byte[] result) {
int idx = 0;
for (final double dVal : sample) {
// scale to maximum amplitude
final short val = (short) ((dVal * 32767));
// in 16 bit wav PCM, first byte is the low order byte
result[idx++] = (byte) (val & 0x00ff);
result[idx++] = (byte) ((val & 0xff00) >>> 8);
}
}
并通过此代码播放生成的字节:
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, SoundWaveGenerator.SAMPLE_RATE,
AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, 2 * SoundWaveGenerator.SAMPLE_RATE,
AudioTrack.MODE_STREAM);
audioTrack.play();
while (true) {
byte[] bytes = SoundWaveGenerator.combineSineWave(frequencies);
audioTrack.write(bytes, 0, bytes.length);
}
但是问题是我听到了每秒的咔嗒声。怎么了?
最佳答案
您听到的点击是每次调用CombineSineWave之间的中断。在每次调用CombineSineWave时,每个频率将以零度相位开始。但是,根据频率,到1秒间隔结束时,可能不会产生偶数个周期。假设其中一个频率是第二个频率的最后一个采样点为90度(1.0),则在生成下一个间隔时会出现间断。
要解决此问题,您需要跟踪连续调用之间的某些状态。我在下面编写了一个示例,但是我不知道如何在Java中通过引用传递。另外,您还需要处理i滚动的可能性。
int i = 0;
while (true) {
byte[] bytes = SoundWaveGenerator.combineSineWave(frequencies, ref i);
audioTrack.write(bytes, 0, bytes.length);
}
public static byte[] combineSineWave(Collection<Double> frequencies, ref int i) {
double[] sample = new double[SAMPLE_RATE];
byte[] result = new byte[2 * SAMPLE_RATE];
double coefficient = 2 * Math.PI;
for (int j = 0; j < SAMPLE_RATE; j++) {
double sum = 0;
for (double frequency : frequencies) {
sum += Math.sin(coefficient * i++ * frequency / SAMPLE_RATE);
}
sample[i] = sum / frequencies.size();
}
convertToPCM16Bit(sample, result);
return result;
}
附言您可以在循环外部按
SAMPLE_RATE
进行划分。double coefficient = 2 * Math.PI / SAMPLE_RATE;
关于android - 安卓产生的正弦波每秒产生一次爆震噪声,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26609416/