gpt4 book ai didi

将音频发送到 UDP 服务器的 Java 客户端

转载 作者:可可西里 更新时间:2023-11-01 02:39:33 28 4
gpt4 key购买 nike

我正在寻找一些关于如何实现能够将音频发送到服务器的 Java 客户端的链接/源代码/教程(如下)。它将能够发送一个音频文件,然后由服务器接收并通过计算机扬声器播放。

我还想问一下,对于这种情况,使用 UDP 或 TCP 服务器会更好吗?因为我要开发一个 Android 应用程序,它可以录制声音,然后将其发送到服务器,以便通过计算机扬声器实时播放。

package com.datagram;

import java.io.ByteArrayInputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.SourceDataLine;

class Server {

AudioInputStream audioInputStream;
static AudioInputStream ais;
static AudioFormat format;
static boolean status = true;
static int port = 50005;
static int sampleRate = 44100;

public static void main(String args[]) throws Exception {

DatagramSocket serverSocket = new DatagramSocket(50005);
byte[] receiveData = new byte[4000];

format = new AudioFormat(sampleRate, 16, 1, true, false);

while (status == true) {

DatagramPacket receivePacket = new DatagramPacket(receiveData,
receiveData.length);

serverSocket.receive(receivePacket);
System.out.println("It works");

ByteArrayInputStream baiss = new ByteArrayInputStream(
receivePacket.getData());

ais = new AudioInputStream(baiss, format, receivePacket.getLength());

toSpeaker(receivePacket.getData());


}
}

public static void toSpeaker(byte soundbytes[]) {
try {

DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, format);
SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);

sourceDataLine.open(format);

FloatControl volumeControl = (FloatControl) sourceDataLine.getControl(FloatControl.Type.MASTER_GAIN);
volumeControl.setValue(100.0f);

sourceDataLine.start();
sourceDataLine.open(format);

sourceDataLine.start();

System.out.println("format? :" + sourceDataLine.getFormat());

sourceDataLine.write(soundbytes, 0, soundbytes.length);
System.out.println(soundbytes.toString());
sourceDataLine.drain();
sourceDataLine.close();
} catch (Exception e) {
System.out.println("Not working in speakers...");
e.printStackTrace();
}
}
}

最佳答案

首先要澄清一点:您想要做的是音频流(如您所知 - 它将帮助您进行任何 future 的谷歌搜索)。

好的,一次一个答案:

  1. “使用 UDP 还是 TCP 服务器更好?”

    • TCP 协议(protocol)的特殊性使其不是流式传输的真正好选择(除非您知道如何正确使用它,这并不容易但可能)。 TCP不好的原因是重传机制的存在。当数据包在网络中损坏或丢失时,TCP 协议(protocol)会请求重传该数据包(这是模型的简化,但足以满足解释的目的)。在传输需要实时播放的音频数据时,重传效果不佳。想象一下,您正在聆听某人的声音,突然声音停止,然后又重新开始(有延迟)。

    • 基本上 UDP 更好,但您必须意识到 UDP 协议(protocol)无法保证数据报(UDP 协议(protocol)的消息)到达接收方的顺序与从发送方发出的顺序相同。因此,您必须确保丢弃任何顺序错误的数据报或缓冲传入的数据报并重新建立正确的顺序。此外,您还必须记住,UDP 协议(protocol)不提供任何保护传输的机制 - 我的意思是您不能确定数据报将安全地通过网络(它们可能会丢失,UDP 协议(protocol)无法控制它)。

    • 最好的办法是不使用它们。你应该尝试实现 RTP 协议(protocol)。

  2. “如何创建能够向上述服务器发送音频的 android 客户端?”

    • 据我所知,您正在使用 AudioFormat作为处理音频的东西。

    • 您需要做的是找到可以从您的服务器应用程序中的 AudioFormat 可以播放的相同格式从 android 麦克风抓取音频的东西。

    • 从 AudioFormat 文档中我可以看到您正在使用特定的采样率(变量 sampleRate),您使用的是默认编码,即 PCM,16 位样本大小、有符号值和 Little Endian 位约定。

    • 您应该在 Android 中关注的是 AudioRecord,它可以从麦克风中获取原始音频帧。有很多关于如何使用 AudioRecord 的示例,其中大多数使用 PCM 16 编码。他们中的大多数会将音频写入文件,但没有什么能阻止您将其推送到某种网络套接字。只需谷歌一下。

    • 请记住使用与您在服务器中使用的采样率相同的 AudioRecord。

    • 最后需要说明的是字节序。 Endianness 取决于 cpu 体系结构。大多数 Android 设备都使用 Little Endian 约定,因此您无需更改服务器代码中的任何内容。但是,您应该意识到某些设备可能正在使用 Big Endian。更多解释 here .

关于将音频发送到 UDP 服务器的 Java 客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23458344/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com