如何从已知点产生声音?

时间:2017-07-14 09:56:05

标签: java audio

我有10个点列表(每个点是时间 - 幅度对),其中每个列表属于已知频率

所以我有一个类InputValue,包含两个字段sampleDate(long)和sampleValue(double),以及10个列表 - List samples800Hz,samples400Hz等等。

800Hz列表包含大约1600个点(不是固定值,因为数据采样器可能具有不可预测的延迟),每秒钟400Hz列表包含大约800个点,依此类推。

我怎么能:

  • 从积分列表中生成声音
  • 在一个声音中混合几个或所有列表?

如果我说得对,我需要将每个列表重新采样为一个采样率(java声音格式可以采用自定义采样率,如1600,或者我应该使用标准值,最低值为8000?)然后填充样本缓冲区,如< / p>

AudioFormat af = new AudioFormat( (float )1600, 8, 1, true, false );
SourceDataLine sdl = AudioSystem.getSourceDataLine( af );
sdl.open();
sdl.start();
for( int i = 0; i < 1600; i++ ) {
    buf[ 0 ] = ???
    sdl.write( buf, 0, 1 );
}
sdl.drain();
sdl.stop();

但是我怎么能告诉sdl我的aplitude值属于某个频率?以及如何混合不同的频率?

BTW,我可以不用重新采样每个列表,创建10个不同采样率的音频格式(800Hz为1600,400Hz为800等等),之后将10个sdls混合在一起?

1 个答案:

答案 0 :(得分:1)

听起来你正在尝试使用波表来发声。如果您只是简单地重新创建一个800 Hz的音调,这很容易:

static int sample = 0;
for (int i = 0; i < 1600; i++) {
    buf[i] = samples800Hz[sample];
    sample = (sample + 1) % SAMPLES_800HZ_SIZE; 
}

让我们假设您想要将800 Hz和1600 Hz音调组合在一起......只需将它们加在一起(您可能需要混合这些值以便它们不会剪辑):

static int sample1 = 0, sample2 = 0;
for (int i = 0; i < 1600; i++) {
    // Multiply each sample by 0.5; this gives us a 50% mix between the two
    buf[i] = (samples800Hz[sample1] * 0.5) + (samples1600Hz[sample2] * 0.5);
    sample1 = (sample1 + 1) % SAMPLES_800HZ_SIZE; 
    sample2 = (sample2 + 1) % SAMPLES_1600HZ_SIZE; 
}

现在我的回答并没有考虑系统运行其回调的帧数/次数。你必须自己解决这个问题。此外,如果你想要多个音调生成而不是无休止地制作列表,我会敦促你查找波表振荡器。波表基本上是创建一个音调阵列,然后调整读取表格的速度/相位以生成所需的频率。

祝你好运!