2012-04-01 131 views
3

嗨,我一直在写一个聊天客户端,想测试Java Sound API。我已经设法通过UDP从麦克风到不同计算机上的扬声器工作。但声音不是很清楚。为了检查这是否是因为在UDP协议中丢失了数据包等原因,我编写了一个小测试,以便将声音发送到麦克风所在机器上的扬声器。声音没有什么不同,这让我觉得我在读取或写入声音时有些设置错误。任何人都可以看看我的代码,并告诉我如何让声音更清晰?Java声音流式传输不太清晰

package test; 

import java.awt.*; 
import java.awt.event.*; 
import java.io.*; 
import javax.sound.sampled.*; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class VoiceTest extends JFrame { 
    private JButton chat = new JButton("Voice"); 
    private GUIListener gl = new GUIListener(); 
    private IncomingSoundListener isl = new IncomingSoundListener(); 
    private OutgoingSoundListener osl = new OutgoingSoundListener(); 
    private boolean inVoice = true; 
    private boolean outVoice = false; 
    AudioFormat format = getAudioFormat(); 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 

public VoiceTest() throws IOException { 
    super ("Test"); 
    //new Thread(tl).start(); 
    new Thread(isl).start(); 
    Container contentPane = this.getContentPane(); 
    this.setSize(200,100); 
    this.setLocationRelativeTo(null); 
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    chat.setBounds(10,10,80,30); 
    chat.addActionListener(gl); 
    contentPane.add(chat); 
    this.setVisible(true); 
} 

private AudioFormat getAudioFormat() { 
    float sampleRate = 8000.0F; 
    int sampleSizeBits = 16; 
    int channels = 1; 
    boolean signed = true; 
    boolean bigEndian = false; 
    //AudioFormat.Encoding.ULAW 
    return new AudioFormat(sampleRate, sampleSizeBits, channels, signed, bigEndian); 
} 

class GUIListener implements ActionListener { 

    public void actionPerformed(ActionEvent actionevent) { 
     String action = actionevent.getActionCommand(); 
     switch (action) { 
      case "Mute": 
       outVoice = false; 
       chat.setText("Voice"); 
       break; 
      case "Voice": 
       new Thread(osl).start(); 
       outVoice = true; 
       chat.setText("Mute"); 
       break; 
     } 
    } 
} 

class IncomingSoundListener implements Runnable { 
    @Override 
    public void run() { 
     try { 
      System.out.println("Listening for incoming sound"); 
      DataLine.Info speakerInfo = new DataLine.Info(SourceDataLine.class, format); 
      SourceDataLine speaker = (SourceDataLine) AudioSystem.getLine(speakerInfo); 
      speaker.open(format); 
      speaker.start(); 
      while(inVoice) { 
       byte[] data = baos.toByteArray(); 
       baos.reset(); 
       ByteArrayInputStream bais = new ByteArrayInputStream(data); 
       AudioInputStream ais = new AudioInputStream(bais,format,data.length); 
       int numBytesRead = 0; 
       if ((numBytesRead = ais.read(data)) != -1) speaker.write(data, 0, numBytesRead); 
       ais.close(); 
       bais.close(); 
      } 
      speaker.drain(); 
      speaker.close(); 
      System.out.println("Stopped listening for incoming sound"); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

class OutgoingSoundListener implements Runnable { 
    @Override 
    public void run() { 
     try { 
      System.out.println("Listening for outgoing sound"); 
      DataLine.Info micInfo = new DataLine.Info(TargetDataLine.class, format); 
      TargetDataLine mic = (TargetDataLine) AudioSystem.getLine(micInfo); 
      mic.open(format); 
      byte tmpBuff[] = new byte[mic.getBufferSize()/5]; 
      mic.start(); 
      while(outVoice) { 
       int count = mic.read(tmpBuff,0,tmpBuff.length); 
       if (count > 0) baos.write(tmpBuff, 0, count); 
      } 
      mic.drain(); 
      mic.close(); 
      System.out.println("Stopped listening for outgoing sound"); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

} 

/** 
* @param args 
* @throws IOException 
*/ 
public static void main(String[] args) throws IOException { 
    new VoiceTest();  
} 
} 
+1

你试过改变音频格式吗? – 2012-04-01 22:52:41

+0

我没有完全得到音频格式。对于什么使声音质量更好,这只是试错吗?对所有电脑来说还是只对一些电脑更好? – MachoChild 2012-04-01 23:02:08

回答

2

你应该尝试更高sampling rate S和试图找到可接受的质量/大小比为您的音频流。

检查AudioFormat参考也是获得这个想法的好开始。

尝试改变局部变量在getAudioFormat()方法是:

private AudioFormat getAudioFormat() { 
    float sampleRate = 16000.0F; 
    int sampleSizeBits = 16; 
    int channels = 1; 
    ... 
} 

这相当于一个256 kbps的单声道的音频文件。

+0

谢谢你解决了,现在更清晰了。出于好奇,你如何计算比特率? – MachoChild 2012-04-01 23:59:53

+0

按采样率乘以采样大小位。 16000 * 16 = 256000. – 2012-04-02 00:01:51

+0

ahh好的,非常感谢您的帮助。 – MachoChild 2012-04-02 00:03:24