java - 使用 Java Sound API 通过 UDP 发送语音

标签 java audio udp voip javasound

我使用 Java Sound API 开发了一个 Java 应用程序。它的作用是捕获来自麦克风的数据并通过 UDP 将其发送到其他计算机以便在那里播放。现在,我遇到了音量、质量和速度问题。我无法找出问题的根源,因此我需要帮助找出程序出了什么问题。

更新
似乎速度问题是由于 Java Sound API 很慢。我尝试了没有 UDP 套接字的程序,并且存在相同类型的延迟,因此 UDP 不会在 LAN 中引入额外的延迟。当程序与耳机一起使用时,回声问题就会消失。声音的质量总体来说还不算太差。唯一剩下的问题是音量。
以下是发件人:

import javax.sound.sampled.*;
import java.io.ByteArrayOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class VoipApp
{
    public static void main(String[]args) throws Exception
    {
        AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED;
        float rate = 44100.0f;
        int sampleSize = 16;
        int channels = 2;
        int frameSize = 4;
        boolean bigEndian = true;

        AudioFormat format = new AudioFormat(encoding, rate, sampleSize, channels, (sampleSize / 8)
                * channels, rate, bigEndian);

        TargetDataLine line;
        DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
        if(!AudioSystem.isLineSupported(info)){
            System.out.println("Not Supported");
            System.exit(1);
        }

        DatagramSocket socket = new DatagramSocket(8081);
        //InetAddress IPAddress = InetAddress.getLocalHost();
        InetAddress IPAddress = InetAddress.getByName("192.168.0.14");

        try
        {
            line = (TargetDataLine) AudioSystem.getLine(info);
            line.open(format);

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

            line.start();
            while(true){
                numBytesRead = line.read(data,0, data.length);
                DatagramPacket sendPacket = new DatagramPacket(data, data.length, IPAddress, 8080);
               // totalBytesRead += numBytesRead;
                socket.send(sendPacket);
               //out.write(data, 0, numBytesRead);
               // System.out.println("Debug");
            }

        }
        catch(LineUnavailableException e)
        {
            e.printStackTrace();
        }
    }
}
以下是接收者:
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class VoipAppTwo
{
    public static void main(String[]args) throws Exception
    {
        AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED;
        float rate = 44100.0f;
        int sampleSize = 16;
        int channels = 2;
        int frameSize = 4;
        boolean bigEndian = true;

        AudioFormat format = new AudioFormat(encoding, rate, sampleSize, channels, (sampleSize / 8)
                * channels, rate, bigEndian);

        SourceDataLine speakers;
        DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, format);

        speakers = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
        speakers.open(format);

        DatagramSocket socket = new DatagramSocket(8080);
        byte[] data = new byte[speakers.getBufferSize() / 5];
        speakers.start();
        while(true)
        {
            DatagramPacket receivePacket = new DatagramPacket(data, data.length);
            socket.receive(receivePacket);
            speakers.write(data, 0, data.length);
        }
    }
}

最佳答案

一些想法,但需要注意的是我没有尝试使用 UDP 的直接经验。
在我看来,必须“处理”丢失和乱序的数据包(假设为 UDP),否则预期的不连续性将不断产生破坏性的响亮咔嗒声。但是 IDK 这通常是如何完成的。过滤器?缓冲?将数据包数据封装到窗口(Hann 或 Hamming?)帧中以桥接数据包不连续性?
javax.sound.sampled 非常接近原生声音。 Here is a good article to reference on considerations pertaining to real time, low latency Java-based audio.

关于java - 使用 Java Sound API 通过 UDP 发送语音,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62645354/

相关文章:

audio - 下载 mp3 的最后 30 秒

c - 如何将recvfrom()中的缓冲区值保存到数组中?

java - 从 HttpServletRequest 中提取上下文路径和其他 URL 信息

swift - 即使其类别设置为播放(Swift), Audio Session 也会与其他 session 混合?

java - 在 java 中为什么总是子类调用父类(super class)构造函数?我要内流

audio - Pacmd 命令全部静音,打开声音文件,然后全部取消静音

使用::write 的 C++ UDP 广播

C++ UDP RecvFrom、SendTo 不同套接字

java - 从 JavaFX 中的 PasswordField 获取密码的安全方法

java - 乘法/移位优化是否应该在 Java 字节码中可见