2013-07-15 200 views
2

我正试图编写一个小程序,当用户说话时会有反应。就像有一个圆圈变大或类似的东西。从麦克风记录的声音的音量

即时通讯使用此代码访问麦克风,但我如何才能使其反应只有当用户说话?例如当录制的音量大于某个数量时。

TargetDataLine line = null; 
    AudioFormat format = new AudioFormat(16000, 16, 1, true, true); 
    DataLine.Info info = new DataLine.Info(TargetDataLine.class, format); 

    if(! AudioSystem.isLineSupported(info)){ 
     System.out.println("Line is not supported"); 
    } 

    try{ 
     line = (TargetDataLine) AudioSystem.getLine(info); 
     line.open(); 
    }catch(LineUnavailableException e){ 
     System.out.println("Failed to get line"); 
     System.exit(-1); 
    } 

    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    int numBytesRead; 
    byte[] data = new byte[line.getBufferSize()/5]; 

    // Begin audio capture. 
    line.start(); 

    int i = 0; 

    // Here, stopped is a global boolean set by another thread. 
    while (i<100) { 
     // Read the next chunk of data from the TargetDataLine. 
     numBytesRead = line.read(data, 0, data.length); 
     // Save this chunk of data. 
     out.write(data, 0, numBytesRead); 
     i++; 
     System.out.println(i); 
    }  
+0

可能出现[录制时检测到静音]的副本(http://stackoverflow.com/questions/5800649/detect-silence-when-recording) –

回答

0

在last while循环中,您正在将声音数据收集到名为“data”的缓冲区变量中。你需要做的是把这些字节组装成可用的DSP值。这样做的代码取决于格式。最常见的是16位编码,立体声,小端。在这种情况下,您必须将字节对组合成值,其中第一个字节是较低位,第二个字节是较高位。关于这个问题有几个帖子,详细介绍了如何处理这个问题。

这些值的范围从-32768到32767(我从内存中写入并可能关闭,但它是一个短的范围)。由于音量不仅取决于绝对值(越大越大),而且取决于较大值所花费的时间量,因此很难说您会在哪里设置阈值。 “安静”的声音可能具有非常大的瞬变值。此外,这些数字并不直接与分贝对应,因此需要一个转换公式。

所以,有几个问题需要解决,但是如果你只是进入while循环并解码“数据”,你可能会得到一些快速和肮脏的工作“足够好”。

+0

因此从行读取的字节流由2byte值组成。我必须找到一个门槛来看看我有多大的声音,并将其设置为数字? – Pita

+0

是的,没有。 (1)如果你有立体声,它可能是左边2bytes和右边通道2bytes。 (2)你可能会想要做某种平均的滚动,这样你就不会对每一个超过极限的瞬态做出反应。 –