Java - 通过 Java 套接字广播语音

2023-12-04

我创建了一个从客户端接收声音的服务器应用程序,然后广播该声音,该声音以字节形式存储,并将字节发送回连接到服务器的客户端。现在我只使用一个客户端进行测试,该客户端正在接收回语音,但声音一直断断续续。有人可以告诉我我做错了什么吗?

我想我理解声音播放不流畅的部分原因,但不知道如何解决问题。

代码如下。

客户端:

将语音发送到服务器的部分

     public void captureAudio()
     {


      Runnable runnable = new Runnable(){

     public void run()
     {
          first=true;
          try {
           final AudioFileFormat.Type fileType = AudioFileFormat.Type.AU;                      
           final AudioFormat format = getFormat();
           DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
           line = (TargetDataLine)AudioSystem.getLine(info);               
           line.open(format);
           line.start();
                int bufferSize = (int) format.getSampleRate()* format.getFrameSize();
                byte buffer[] = new byte[bufferSize];           

                    out = new ByteArrayOutputStream();
                    objectOutputStream = new BufferedOutputStream(socket.getOutputStream());
                    running = true;
                    try {                      
                        while (running) {                         
                            int count = line.read(buffer, 0, buffer.length);
                            if (count > 0) {
                                objectOutputStream.write(buffer, 0, count);
                                out.write(buffer, 0, count);
                                InputStream input = new ByteArrayInputStream(buffer);
                                final AudioInputStream ais = new AudioInputStream(input, format, buffer.length /format.getFrameSize());

                            }                           
                        }
                        out.close();
                        objectOutputStream.close();
                    }
                    catch (IOException e) {                    
                        System.exit(-1);
                        System.out.println("exit");
                    }
          }
          catch(LineUnavailableException e) {
            System.err.println("Line Unavailable:"+ e);
            e.printStackTrace();
            System.exit(-2);
          }
          catch (Exception e) {
           System.out.println("Direct Upload Error");
           e.printStackTrace();
          }
     }

     };

     Thread t = new Thread(runnable);
     t.start();

     }

从服务器接收数据字节的部分

    private void playAudio() {
     //try{


    Runnable runner = new Runnable() {

    public void run() {
        try {
            InputStream in = socket.getInputStream();
            Thread playTread = new Thread();

            int count;
            byte[] buffer = new byte[100000];
            while((count = in.read(buffer, 0, buffer.length)) != -1) {

                PlaySentSound(buffer,playTread);
            }
        }
        catch(IOException e) {
                System.err.println("I/O problems:" + e);
                System.exit(-3);
        }
      }
    };

    Thread playThread  = new Thread(runner);
    playThread.start();
  //}
  //catch(LineUnavailableException e) {
   //System.exit(-4);
  //}
    }//End of PlayAudio method

    private void PlaySentSound(final byte buffer[], Thread playThread)
    {

    synchronized(playThread)
    {

    Runnable runnable = new Runnable(){

    public void run(){
        try
        {

                InputStream input = new ByteArrayInputStream(buffer);
                final AudioFormat format = getFormat();
                final AudioInputStream ais = new AudioInputStream(input, format, buffer.length /format.getFrameSize());
                DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
                sline = (SourceDataLine)AudioSystem.getLine(info);
                sline.open(format);
                sline.start();              
                Float audioLen = (buffer.length / format.getFrameSize()) * format.getFrameRate();

                int bufferSize = (int) format.getSampleRate() * format.getFrameSize();
                byte buffer2[] = new byte[bufferSize];
                int count2;


                ais.read( buffer2, 0, buffer2.length);
                sline.write(buffer2, 0, buffer2.length);
                sline.flush();
                sline.drain();
                sline.stop();
                sline.close();  
                buffer2 = null;


        }
        catch(IOException e)
        {

        }
        catch(LineUnavailableException e)
        {

        }
    }
    }; 
   playThread = new Thread(runnable);
   playThread.start();
   }


   }

除了 HefferWolf 的回答之外,我还想补充一点,发送从麦克风读取的音频样本会浪费大量带宽。您没有说您的应用程序是否仅限于本地网络,但如果您要通过互联网,则在发送/接收时压缩/解压缩音频是很常见的。

常用的压缩方案是SPEEX编解码器(Java 实现可用here),尽管如果您不熟悉音频采样/压缩,文档看起来有点吓人,但它相对容易使用。

在客户端,您可以使用org.xiph.speex.SpeexEncoder进行编码:

  • Use SpeexEncoder.init()初始化编码器(这必须与您的采样率、通道数和字节序相匹配)AudioFormat) 进而
  • SpeexEncoder.processData()对帧进行编码,
  • SpeexEncoder.getProcessedDataByteSize() and SpeexEncoder.getProcessedData()获取编码数据

在客户端使用org.xiph.speex.SpeexDecoder解码您收到的帧:

  • SpeexDecoder.init()使用与编码器相同的参数初始化解码器,
  • SpeexDecoder.processData()解码帧,
  • SpeexDecoder.getProcessedDataByteSize() and SpeexDecoder.getProcessedData()获取编码数据

我已经概述了更多的内容。例如,您必须将数据吐出为正确的编码大小,这取决于采样率、通道和每个样本的位数,但您会发现通过编码发送的字节数急剧下降网络。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java - 通过 Java 套接字广播语音 的相关文章

随机推荐

  • Android Studio build.gradle 警告消息[重复]

    这个问题在这里已经有答案了 在我成功更新到 Android Studio 3 1 Canary 9 后 我收到警告消息 Warning Configuration compile is obsolete and has been repla
  • 如何使用 BigInteger 修复 Polynomial 类中的这个“加”方法

    我很感激你的帮助 除了 compose 方法之外 我能够完成将此类中的所有内容修改为 BigInteger 格式 谁能帮我解决最后一部分为什么它不能正常工作 我真的很感激 谢谢 import java math BigInteger pub
  • Java SSL Streaming - 分割应用程序数据

    我尝试通过已建立的 SSL 连接发送 byte 握手等已完成 结果 byte 被分成两个数据包 参见下面的调试 第一个数据包 只是应用程序数据的第一个字节 01 第二个数据包 其余 fe db 01 00 650 字节 有没有一种方法可以将
  • Qt - 编辑 QListWidget 行时的信号?

    我正在使用 Qt4 7 并且我的对话框中有一个 QListWidget 我有一个 QString 需要匹配current该小部件行中的文本 各个行是可编辑的 查看与 QListWidget 关联的信号 似乎有选择不同索引时的信号 但没有当前
  • 如何将json数组数据附加到html表tbody中

    我对 jQuery 和 JSON 很陌生 我需要解析以下格式的 JSON 以便填充 html 表 tbody response name0 id0 amt0 name1 id1 amt1 但我不知道如何访问它们 因此可以通过以下方式获取 h
  • 当数据库为空时,mongodb 创建 80 多个文件,每个文件 2GB

    背景 我设置了replicaSet并使用不同的端口在本地主机上启动了3个mongod实例 1个arbiterOnly 我没有注意到 mongodb 创建了太多数量和大小的文件 这根本没有意义 See 从来没有数据插入到 mongodb 中
  • 在代码隐藏中从 Page_Load 调用 javascript 函数

    如何从代码隐藏中的 Page Load 方法调用 aspx 页面中的 javascript 函数 简单的答案是 你不能 Page Load方法中的代码在服务器上执行 javascript在客户端上执行 如果您想要做的是添加对 javascr
  • 使用 VSTS 任务创建 AD 应用程序

    我正在尝试创建一个 VSTS 任务 它应该创建一个 AD 应用程序 以 DeployAzureResouceGroup 作为示例 我创建了以下脚本 CmdletBinding param Trace VstsEnteringInvocati
  • 返回局部变量的地址与返回指向局部变量的指针

    我的testing cpp中有这个 class Supp public virtual Supp add Supp val 0 class SubA public Supp public int val SubA int a val a i
  • jooq 多重集通过多重集上的条件对结果集进行排序

    收集 mit jooq 的多重集的第一次经验 我尝试弄清楚如何根据多重集的某些标准对结果集进行排序 考虑带有产品表的数据结构 每个产品都可以分配任意数量的存储空间 使用此查询获取产品时 List
  • Apache Solr 快速入门教程 - 加载主类 SimplePostTool 时出错

    我正在关注Apache Solr 快速入门教程 本教程遇到了对丰富文件的目录进行索引的情况 这需要实现java Dauto Drecursive org apache solr util SimplePostTool docs 我收到一条错
  • 重置主屏幕的导航堆栈(React Navigation 和 React Native)

    我的导航有问题反应导航和反应本机 这是关于重置导航并返回主屏幕 我已经在 DrawerNavigator 内部构建了 StackNavigator 并且主屏幕和其他屏幕之间的导航正在工作 但问题是 导航堆栈不断增长 我不知道如何从堆栈中删除
  • ScheduledActionService.Find 抛出 ArgumentException

    我在市场中部署了一个 Windows Phone 7 应用程序 该应用程序通过周期性任务后台代理更新其动态磁贴 一位用户报告了磁贴在工作一段时间后不再更新的问题 当他们检查手机上的后台任务时 它被禁用 并且 下次打开该应用程序时重新打开后台
  • Prolog:比较列表列表中的列表

    我现在很长时间试图找出我的错误是什么 但我无法做到 任务 我们必须弄清楚如何找到包含列表列表形式的 9 个元素的列表的三种排列 每个列表列表应包含三个子列表 每个子列表包含三个元素 但不允许任何元素与两个不同子列表中的另一个元素在一起 对于
  • Rust 中如何检查函数是否被调用?

    我有一个功能如下 pub fn registration student id T StudentId registrar T RegistrarID More code here if num of students lt student
  • d3-force 初始化图后更新forceCollide的半径

    这个问题是上一个题为 初始化图后强制更新参数 的问题的后续问题 D3 初始化图后强制更新参数 并且 altocumulus 回答了 我试图在修改某些节点的半径后更新模拟力 然而 当我呼吁forceCollide来解释它不起作用的变化 该图首
  • 使用反射修改字符串的目的是什么?

    我正在读一本article这就是说 Java 字符串并不是完全不可变的 但是 在本文修改字符串的示例代码中 它调用了 string toUpperCase toCharArray 这会返回一个新字符串 那么 如果您无论如何调用 toUppe
  • 向 sys.excepthook 添加函数

    假设我有这样的东西 它会向logging critical import sys def register handler orig excepthook sys excepthook def error catcher exc info
  • 如何在 64 位 Windows 上安装 SciPy?

    如何在我的系统上安装 SciPy 对于 NumPy 部分 SciPy 所依赖的 实际上有一个适用于 64 位 Windows 的安装程序 numpy 1 3 0 win amd64 py2 6 msi 是直接下载URL 2310144字节
  • Java - 通过 Java 套接字广播语音

    我创建了一个从客户端接收声音的服务器应用程序 然后广播该声音 该声音以字节形式存储 并将字节发送回连接到服务器的客户端 现在我只使用一个客户端进行测试 该客户端正在接收回语音 但声音一直断断续续 有人可以告诉我我做错了什么吗 我想我理解声音