gpt4 book ai didi

Java 将麦克风录制到字节数组并播放声音

转载 作者:搜寻专家 更新时间:2023-10-30 19:41:36 45 4
gpt4 key购买 nike

我想用 Java 制作一个实时语音聊天程序,但我对用 Java 录制/播放声音一无所知,所以在 Google 的帮助下,我想我已经能够从我的麦克风录制到一个字节数组以下内容:

AudioFormat format = new AudioFormat(8000.0f, 16, 1, true, true);
TargetDataLine microphone;
try{
microphone = AudioSystem.getTargetDataLine(format);

DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
microphone = (TargetDataLine)AudioSystem.getLine(info);
microphone.open(format);

ByteArrayOutputStream out = new ByteArrayOutputStream();
int numBytesRead;
byte[] data = new byte[microphone.getBufferSize()/5];
microphone.start();

int bytesRead =0;

try{
while(bytesRead<100000){ //Just so I can test if recording my mic works...
numBytesRead = microphone.read(data, 0, data.length);
bytesRead = bytesRead + numBytesRead;
// System.out.println(bytesRead);
out.write(data, 0, numBytesRead);
}
catch(Exception e){
e.printStackTrace();
}
microphone.close();

catch(LineUnavailibleException e){
e.printStackTrace();
}

现在,根据我的理解,如果我调用 out.toByteArray();,我应该得到我刚刚从麦克风录制的声音的字节数组。 (我运行上面没有错误,但是无法证明它是否真的被记录了,因为我不想将它输出到一个文件并且没有这样做)

现在,如果以上是正确的,那么下面就是我遇到问题的地方:我现在想播放我刚刚创建的字节数组......(在我的真实程序中,我会通过我已经能够做到的 Java 套接字将字节发送到我的“接收程序”,但现在我只想制作一个记录麦克风并播放的小程序)。为了播放字节数组中的声音信息,我遵循了这个:http://www.wikijava.org/wiki/Play_a_wave_sound_in_Java并提出以下内容:(这位于上面的 microphone.close() 之后)

try{
DataLine.Info info2 = DataLine.Info(SourceDataLine.class, format);
SourceDataLine dataLine = (SourceDataLine)AudioSystem.getLine(info2);
int bufferSize = 2200;
soundLine.open(format, bufferSize);
soundLine.start();
AudioInputStream audioInputStream = null;

InputStream input = new ByteArrayInputStream(out.toByteArray());
audioInputStream = AudioSystem.getAudioInputStream(input);

...

其余的几乎都是从这个链接的 playSound.java 复制粘贴的: http://www.wikijava.org/wiki/Play_a_wave_sound_in_Java

当我运行上面的代码时...录音似乎工作正常,但我收到以下错误:

javax.sound.sampled.UnsupportedAudioFileException: 无法从输入流中获取音频输入流

对于这一行 audioInputStream = AudioSystem.getAudioInputStream(input);

根据我有限的知识,我假设这是因为我不知何故弄乱了录音方法,我需要某种“音频格式头?” https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ (我以为我不需要那样的东西,因为我从来没有保存到文件中,只是将它全部保存为字节数组),或者我只是完全误解了 java 的 AudioInputStream 是如何读取和解析数据的……

这是我第一次在 Java 中处理任何与声音相关的事情,所以如果我完全误解和破坏这段代码,我深表歉意(是的,我知道代码看起来很糟糕而且没有组织,但我只是想让它工作) ...我在 Google/StackOverflow 上尝试了多次搜索,并找到了一个非常相似的问题:

java byte array play sound

但它也没有答案(唯一的答案是将它保存到文件中,但我们都想要的是直接将它作为字节数组流式传输,而不是将它变成文件)

我所知道的:

可以使用 TargetDataLine 录制音频,并录制麦克风,可以使用 ByteArrayOutputStream 将其输出到字节数组

通过使用 AudioInputStream 读取文件并使用 SourceDataLine 播放数据,可以将音频保存到文件并播放。

如果我想写一个文件,我可以使用 AudioSystem.write(new AudioInputStream(microphone), AudioFileFormat.Type.WAVE, new File("recording.wav");//我已经通过替换 while 测试了这个用这一行循环,它记录得很好(除了它永远不会停止,所以我不得不手动终止它),但我不希望这样,因为输出到文件意味着不可能通过套接字将它发送到另一端实时。

我不知道的/我的问题:

如何使用 Java 录制和流式传输从麦克风录制的音频到另一台可以尽可能少延迟播放的计算机(非常类似于类似于 Skype 的语音聊天)。

在此先感谢您提供的帮助或能为我指明正确方向的人。另外,如果有人知道更简单的方法,那么也请告诉我。

最佳答案

编辑:这是与下面相同的想法的稍微好一点的版本,它将在您录制时直接播放

AudioFormat format = new AudioFormat(8000.0f, 16, 1, true, true);
TargetDataLine microphone;
SourceDataLine speakers;
try {
microphone = AudioSystem.getTargetDataLine(format);

DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
microphone = (TargetDataLine) AudioSystem.getLine(info);
microphone.open(format);

ByteArrayOutputStream out = new ByteArrayOutputStream();
int numBytesRead;
int CHUNK_SIZE = 1024;
byte[] data = new byte[microphone.getBufferSize() / 5];
microphone.start();

int bytesRead = 0;
DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, format);
speakers = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
speakers.open(format);
speakers.start();
while (bytesRead < 100000) {
numBytesRead = microphone.read(data, 0, CHUNK_SIZE);
bytesRead += numBytesRead;
// write the mic data to a stream for use later
out.write(data, 0, numBytesRead);
// write mic data to stream for immediate playback
speakers.write(data, 0, numBytesRead);
}
speakers.drain();
speakers.close();
microphone.close();
} catch (LineUnavailableException e) {
e.printStackTrace();
}

请耐心等待,因为这真的很粗糙,但它可以通过扬声器播放录制的音频;

为了让它听起来更好,您将需要添加线程,并优化输入/输出流。

http://www.developer.com/java/other/article.php/1579071/Java-Sound-Getting-Started-Part-2-Capture-Using-Specified-Mixer.htm

package audio;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;

public class AudioTest {

public static void main(String[] args) {

AudioFormat format = new AudioFormat(8000.0f, 16, 1, true, true);
TargetDataLine microphone;
AudioInputStream audioInputStream;
SourceDataLine sourceDataLine;
try {
microphone = AudioSystem.getTargetDataLine(format);

DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
microphone = (TargetDataLine) AudioSystem.getLine(info);
microphone.open(format);

ByteArrayOutputStream out = new ByteArrayOutputStream();
int numBytesRead;
int CHUNK_SIZE = 1024;
byte[] data = new byte[microphone.getBufferSize() / 5];
microphone.start();

int bytesRead = 0;

try {
while (bytesRead < 100000) { // Just so I can test if recording
// my mic works...
numBytesRead = microphone.read(data, 0, CHUNK_SIZE);
bytesRead = bytesRead + numBytesRead;
System.out.println(bytesRead);
out.write(data, 0, numBytesRead);
}
} catch (Exception e) {
e.printStackTrace();
}
byte audioData[] = out.toByteArray();
// Get an input stream on the byte array
// containing the data
InputStream byteArrayInputStream = new ByteArrayInputStream(
audioData);
audioInputStream = new AudioInputStream(byteArrayInputStream,format, audioData.length / format.getFrameSize());
DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, format);
sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
sourceDataLine.open(format);
sourceDataLine.start();
int cnt = 0;
byte tempBuffer[] = new byte[10000];
try {
while ((cnt = audioInputStream.read(tempBuffer, 0,tempBuffer.length)) != -1) {
if (cnt > 0) {
// Write data to the internal buffer of
// the data line where it will be
// delivered to the speaker.
sourceDataLine.write(tempBuffer, 0, cnt);
}// end if
}
} catch (IOException e) {
e.printStackTrace();
}
// Block and wait for internal buffer of the
// data line to empty.
sourceDataLine.drain();
sourceDataLine.close();
microphone.close();
} catch (LineUnavailableException e) {
e.printStackTrace();
}
}
}

关于Java 将麦克风录制到字节数组并播放声音,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25798200/

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