流式传输时Java Sound不太清楚

时间:2012-04-01 22:35:52

标签: java javasound audio

您好我一直在编写聊天客户端,并希望测试Java Sound API。我已经设法通过UDP从麦克风到不同计算机上的扬声器工作。然而声音不是很清楚。为了检查这是否是因为UDP协议中丢失的数据包等,我写了一个小测试,声音转到与麦克风在同一台机器上的扬声器。声音没有任何不同,这让我觉得我在读取或写入声音方面有些错误。任何人都可以查看我的代码并告诉我如何让声音更清晰吗?

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 个答案:

答案 0 :(得分:2)

您应该尝试更高的sampling rate并尝试为音频流找到可接受的质量/尺寸比率。

检查AudioFormat参考也是获得想法的良好开端。

尝试将getAudioFormat()方法中的局部变量更改为:

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

这相当于一个256 kbps的Mono音频文件。