Java 一次从2个进程接收来自麦克风的输入

Java 一次从2个进程接收来自麦克风的输入,java,speech-recognition,speech-to-text,javasound,sphinx4,Java,Speech Recognition,Speech To Text,Javasound,Sphinx4,我一直在使用sphynx4开发java语音识别,目前我已经发布了 我有一个应用程序,可以使用Sphynx4的LiveSpeechRecognizer类识别麦克风输入,它工作正常。问题是,在我添加了一个类之后,这个类还可以监听麦克风,转换并可视化输出 两个类分别工作正常。但当组合到一个应用程序中时,我会得到错误: LineUnavailableException:不支持PCM_签名格式为44100.0 Hz、8位、单声道、1字节/帧的线路 我已经检查了这个问题,它似乎是由同时接触麦克风引起的。我有

我一直在使用
sphynx4
开发java语音识别,目前我已经发布了

我有一个应用程序,可以使用Sphynx4的LiveSpeechRecognizer类识别麦克风输入,它工作正常。问题是,在我添加了一个类之后,这个类还可以监听麦克风,转换并可视化输出

两个类分别工作正常。但当组合到一个应用程序中时,我会得到错误:

LineUnavailableException:不支持PCM_签名格式为44100.0 Hz、8位、单声道、1字节/帧的线路

我已经检查了这个问题,它似乎是由同时接触麦克风引起的。我有一个想法使用StreamSpeechRecognizer而不是Live,但我无法从麦克风输入中检索流。为此尝试了AudioInputStream

您能建议我如何调整我的代码,使语音识别和示波器同时使用麦克风吗

提前谢谢

UPD:

这是我尝试将麦克风输入拆分为在两个应用程序中使用

....
     byte[] data = new byte[dataCaptureSize];   
            line.read(data, 0, data.length);

            ByteArrayOutputStream out = new ByteArrayOutputStream();
            out.write(data);
            byte audioData[] = out.toByteArray();
            InputStream byteArrayInputStream = new ByteArrayInputStream(audioData);
            AudioInputStream audioInputStream = new AudioInputStream(byteArrayInputStream,
                    inputFormat,
                    audioData.length / inputFormat.getFrameSize());
....
这就是我如何将其转换为输入流,然后将其传递到
StreamSpeechRecognitor
,并使用快速傅立叶变换对字节数组进行变换,然后传递到图形。这不起作用,因为它只是一直冻结图形,因此显示的数据不是实际数据

我尝试在单独的线程中运行识别,但它根本没有提高性能

我的线程拆分代码如下所示:

Thread recognitionThread = new Thread(new RecognitionThread(configuration,data));
    recognitionThread.join();
    recognitionThread.run();
UPD 2: 输入来自麦克风。 上述音频输入流被传递到StreamSpeechRecognizer:

StreamSpeechRecognizer nRecognizer=新的StreamSpeechRecognizer(配置);
nRecognitor.startRecognition(音频流)

字节数组通过FFT转换并传递到图形: ` double[]arr=FastFourierTransform.TransformRealPart(数据)

for(inti=0;i

< /P> < P>这是一个合理的考虑方法。

首先,编写您自己的麦克风读取器。(有关于如何执行此操作的教程。)然后将该数据重新打包为两条平行线,以便其他应用程序可以读取

另一种方法是检查任一应用程序是否启用了某种“传递”功能

编辑:添加以澄清

这会打开麦克风的
TargetDataLine
,并将其中的数据存储到一个数组中(第69、70行)。我建议您不要将数据存储在数组中,而是创建两个
SourceDataLine
对象,并将数据写入每个对象

recordBytes = new ByteArrayOutputStream();
secondStreamBytes = new ByteArrayOutputStream();

isRunning = true;

while (isRunning) {
    bytesRead = audioLine.read(buffer, 0, buffer.length);
    recordBytes.write(buffer, 0, bytesRead);
    secondStreamBytes.write(buffer, 0, bytesRead);
}
希望您不会太难理解如何将两个程序配置为从创建的行而不是从麦克风的行中读取。我无法提供有关如何执行此操作的指导

编辑2: 我希望其他人也能加入进来。我对流做任何花哨的事情都有点不知所措。而且你给出的代码太少了,我仍然不知道发生了什么或者事情是如何连接的

FWTW:(1)您正在添加到“系列”中的数据是流数据吗?如果是,您是否可以在
for
循环中添加一行,并将相同的数据写入另一类使用的流中?(这将是一种使用麦克风数据“串联”而不是“并联”的方法。)

(2) 由于cpu在任务之间切换的方式不可预测,数据流通常包含阻塞或以不同速度运行的代码。因此,如果您确实编写了“拆分器”(正如我试图通过修改前面链接的麦克风读取代码来说明的那样)可能会出现这样的情况:在给定时刻,代码的运行速度仅与两个“拆分”中速度较慢的一个一样快。您可能需要合并某种缓冲,并为两个数据接收者使用单独的线程

我最近写了我的第一个缓冲代码,用于麦克风读取线路向另一个线程上的音频混合功能发送流的情况。我几周前才写了这篇代码,这是我第一次处理试图跨线程屏障运行流的问题,所以我不知道我提出的想法是否是解决问题的最佳方法o这类事情。但它确实设法保持从麦克风到混合器的喂料稳定,没有脱落和损失

mike阅读器读取数据缓冲区,然后将该
字节[]
缓冲区添加到
ConcurrentLinkedQueue

从另一个线程,音频混合代码轮询
ConcurrentLinkedQueue
以获取数据

我做了一点实验,目前byte[]缓冲区的大小为512字节,
ConcurrentLinkedQueue
设置为最多可容纳12个“缓冲区”,然后才开始丢弃最旧的缓冲区(结构为FIFO)。当麦克风处理代码暂时领先于混音器时,这些小缓冲区似乎足以容纳

ConcurrentLinkedQueue
内置了允许在不引发异常的情况下从两个线程同时进行添加和轮询的规定。这是否是您必须编写以帮助切换的内容,以及最佳缓冲区大小可能是什么,我不能说。可能是一个更大的缓冲区,而Q中保留的缓冲区更少ueue会更好

也许其他人会参与进来,或者这个建议值得尝试


无论如何,考虑到我在这方面的有限经验,这是我能做的最好的了。我希望你能解决一些问题。

我不太确定我是否理解你的意思。问题是我有一个麦克风读取器,它工作得很好。但对于另一个过程——从语音到文本,麦克风读取器装在罐子里,当n识别方法为ca
recordBytes = new ByteArrayOutputStream();
secondStreamBytes = new ByteArrayOutputStream();

isRunning = true;

while (isRunning) {
    bytesRead = audioLine.read(buffer, 0, buffer.length);
    recordBytes.write(buffer, 0, bytesRead);
    secondStreamBytes.write(buffer, 0, bytesRead);
}