Java蜂鸣声:产生某些特定频率的声音

时间:2016-01-05 11:54:47

标签: java audio javasound beep

我正在尝试使用Java生成蜂鸣声。我在SO上找到了this回答。

我正在使用该答案的代码来产生哔哔声。代码是:

import javax.sound.sampled.*;
public class Sound
{
    public static float SAMPLE_RATE = 8000f;
    public static void tone(int hz, int msecs) 
    throws LineUnavailableException 
    {
        tone(hz, msecs, 1.0);
    }

    public static void tone(int hz, int msecs, double vol)
    throws LineUnavailableException 
    {
        byte[] buf = new byte[1];
        AudioFormat af = new AudioFormat(SAMPLE_RATE,8,1,true,false);     
        SourceDataLine sdl = AudioSystem.getSourceDataLine(af);
        sdl.open(af);
        sdl.start();
        for (int i=0; i < msecs*8; i++) {
              double angle = i / (SAMPLE_RATE / hz) * 2.0 * Math.PI;
              buf[0] = (byte)(Math.sin(angle) * 127.0 * vol);
              sdl.write(buf,0,1);
        }
        sdl.drain();
        sdl.stop();
        sdl.close();
    }

    public static void main(String[] args) throws Exception {
        Sound.tone(15000,1000); 
    }
}

main方法中,我使用Sound.tone(15000,1000);产生频率 15000 Hz 的声音来播放 1000 ms

但是,如果我将其更改为:

,我可以听到声音
  • Sound.tone(1,1000);,。
  • Sound.tone(19999,1000);

科学地说,这是不可能的。

  • 在第一种情况下,声音应该是次声,而我应该无法察觉它。
  • 在第二种情况下,我仍然无法听到声音,因为随着年龄的增长,听觉能力会下降,而我这个年龄段的人应该只能听到大约<强的声音> 16000 Hz 。

此外,我听不到:

  • Sound.tone(0,1000);(有点像预期的那样)
  • Sound.tone(20000,1000);

那么,如何制作某些特定频率的声音?
我在网上搜索过,但找不到任何关于它的信息。

在此编辑之前给出的答案解释了为什么会发生,但不提供我想要的答案。

2 个答案:

答案 0 :(得分:8)

您遇到的是一种称为锯齿现象。您可能已经在视频中看到了这样的示例,其中旋转轮似乎缓慢旋转或甚至反向旋转。这是因为车轮仅旋转了略多于或小于每个视频帧完整匝数的倍数。同样,如果车轮每帧旋转一个精确的圈数,它将显得静止不动。这称为混叠的原因是没有办法知道如何它实际旋转了多少次。

音频采样具有相同的伪像,被称为奈奎斯特采样定理,它基本上表明您只能表示高达采样率(奈奎斯特频率)一半的频率。超出此频率,音调开始向下折叠(例如向后转)。

在8kHz采样率下,0Hz至4kHz的频率将恢复正常(4 kHz正弦波每个周期将有2个样本)。超过4kHz时,频率将开始向后折叠,以便听到4001Hz为3999,5000Hz为3000Hz,最终为8000Hz为0Hz(因此为静音)。超过8kHz时,它将再次开始折叠,以便8001Hz为1Hz,依此类推。

需要注意的是,您需要选择的采样率至少是您计划播放的最高频率的两倍。

答案 1 :(得分:3)

只需在我的扬声器前面使用吉他调音器重新检查 - 您提供的方法对于低频率是准确的。

然而,如果你太低,你可能听到泛音或“口吃”的声音,因为扬声器在次声中不能工作得太厉害(至少我知道了)

频率上,您的代码计算得不太好 - 采样率为每秒8000个样本,您将为更高频率快速创建“无效”音调 - 正弦波振荡将只是意外地与您的采样率保持一致。因此,您可以听到一些高频率(主要是因为您的样本总是达到非零值)或听不到(所有样本都出现在wave通过null时。

检查此循环(开启扬声器):

 public static void main(String[] args) throws Exception {
    for(int freq = 400; freq < 20000; freq *= 2) {
        Sound.tone(freq,500);
    }
 }

由于上述原因,你最后会听到低 - 高 - 低 - 高。

另一项测试:

  Sound.tone(8000,500);   

绝对安静,

  Sound.tone(8001,500);

产生非常时髦的声音。