gpt4 book ai didi

java - 在 Java 中,通过 TCP 套接字从 C# 应用程序接收音频数据流并在接收时播放流媒体

转载 作者:行者123 更新时间:2023-12-02 09:56:37 24 4
gpt4 key购买 nike

我在 C# 应用程序中有一些用于音频的原始 PCM 数据。我需要将其放入 Java 应用程序并作为音频播放。

作为第一步,我希望 Java 应用程序在音频流入时立即播放音频(不是保存临时文件并播放它,而是在收到音频时播放)。

我在正确格式化 C# 中的 PCM 音频数据并将其发送到 Java 应用程序时遇到问题。我目前仅使用一个简单的 TCP 套接字系统来执行此操作,将 C# 应用程序(在 Unity 中制作)称为“客户端”,将 Java 应用程序称为“服务器”。

在 Unity C# 客户端上,我使用 NatMic 获取麦克风的原始 PCM 数据。当数据进入时,该函数每秒被调用多次:

void IAudioProcessor.OnSampleBuffer(float[] sampleBuffer, int sampleRate, int channelCount, long timestamp)

我有一个 float 组和两个整数来描述音频数据。

如何将此数据打包为字节发送到 Java?

我设置了一个 TCP,可以将字节发送到 Java,当我测试在客户端和服务器之间来回发送简单的字符串消息时,它似乎工作正常。

但是当我尝试打包音频并将其发送过来时,它永远无法工作。我总是收到这样的错误:

javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input stream

这是 Java 端的一个片段,展示了我如何尝试在 Java 端播放音频作为测试(当客户端连接时,我运行一次):

    inputStream = client.getInputStream();
bInputStream = new BufferedInputStream(inputStream);
Clip clip = AudioSystem.getClip();
audioStream = AudioSystem.getAudioInputStream(bInputStream);
clip.open(audioStream);
clip.start();

我应该如何打包 float[]、int 和 int 以发送到 Java 服务器,以便它将其识别为音频流?

最佳答案

首先,您需要将数据输出为 SourceDataLine,而不是 ClipClip 在收到整个声音文件之前无法播放。

通常的计划是以任何您想要的方式读取输入行,并在调用 sdl.write() 方法的循环中将其转换为正确的格式。

对于传入数据,以下内容应该有效

while(playerRunning)
{
readBuffer = getInputPCM();
audioBytes = convertToFollowAudioFormat(readBuffer);
sourceDataLine.write(audioBytes, 0, sdlBufferSize);
}

如果您的传入数据是 float ,范围从 -1 到 1,并且您以基本的“CD 质量”Java 格式(44100 fps、16 位、立体声、小端)输出,则转换可能如下所示以下内容:

for (int i = 0, n = buffer.length; i < n; i++)
{
buffer[i] *= 32767;
audioBytes[i*2] = (byte) buffer[i];
audioBytes[i*2 + 1] = (byte)((int)buffer[i] >> 8 );
}
return audioBytes;

根据 PCM 的形式,您可能需要做更多或更少的事情。例如,如果您正在读取范围从 -32767 到 32767 的整数或短整型,则不需要乘法步骤。

要获取在默认音频线路上输出“CD 质量”音频格式的 SourceDataLine:

AudioFormat audioFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 
44100, 16, 2, 4, 44100, false);
Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
SourceDataLine sdl = (SourceDataLine)AudioSystem.getLine(info);

就您的 getInputPCM 方法而言,我假设您只能在流中呈现 PCM 数据,并且不需要进一步解析。如果您想在发布之前在 C# 中完成将 PCM 转换为字节的任务,这也是完全有效的。

Java 教程的 Sampled Package 上有更多关于各种输出格式的文章。踪迹。

对于上述内容,我主要是从我的 github 项目 AudioCue 复制/编辑代码,这是一种增强版 Clip

关于java - 在 Java 中,通过 TCP 套接字从 C# 应用程序接收音频数据流并在接收时播放流媒体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55957417/

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