Java 声音采样器未完成获取缓冲区
Posted
技术标签:
【中文标题】Java 声音采样器未完成获取缓冲区【英文标题】:Java sound sampler does not finish getting buffer 【发布时间】:2020-11-18 23:38:09 【问题描述】:我有一个使用麦克风获取随机字节的 Java 代码。
我在尝试使用 Java 提供的类从麦克风采样缓冲区时遇到问题。 该代码一直适用于我拥有的旧麦克风。 但是最近我买了一个更现代的网络摄像头(AUKEY PC-W1),其中包括一个麦克风,当我将 Windows 10 配置为默认使用该输入声音设备时,采样声音的功能并没有结束,因此无法获得声音缓冲区。
这是代码:
class CaptureAudioThread extends Thread
protected final static int BYTES_TO_READ = 64000;
protected AudioFormat _audioFormat = null;
protected TargetDataLine _targetDataLine = null;
protected int _bytesRead = 0;
protected byte[] _buffer = null;
public CaptureAudioThread( )
_buffer = new byte[ BYTES_TO_READ ];
protected AudioFormat getAudioFormat()
float sampleRate = 22000.0F;
//8000,11025,16000,22050,44100
int sampleSizeInBits = 16;
//8,16
int channels = 1;
//1,2
boolean signed = true;
//true,false
boolean bigEndian = true;
//true,false
return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);
//end getAudioFormat
@Override
public void run()
try
_audioFormat = getAudioFormat();
DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, _audioFormat);
if (!Audiosystem.isLineSupported(dataLineInfo))
throw( new RuntimeException( "Not supported audio format") );
_targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
_targetDataLine.open(_audioFormat);
_targetDataLine.start();
_bytesRead = _targetDataLine.read(_buffer, 0, _buffer.length);
catch( Exception th )
th.printStackTrace();
_bytesRead = 0;
finally
if( _targetDataLine != null )
_targetDataLine.stop();
_targetDataLine.close();
当我将程序与旧麦克风一起使用时,它可以完美运行。 但是当我用新麦克风启动前一个线程时,它永远不会结束它的执行。
我检查了该代码是否适用于其他音频格式(例如使用 samplerate = 44100.0F 和 channels=2),获得相同的结果
有人知道这个问题是否可以通过任何方式避免吗?
【问题讨论】:
我想看看调试好吗??以及为什么要在前面使用下划线?像叉车吗 感谢 gpasch,如果您需要我提供任何额外信息,请询问。我通常在非静态类属性中使用下划线,这就是它们在示例代码中使用它们的原因。 【参考方案1】:为什么代码应该使用一个麦克风而不是另一个?在我看来,只要线路打开,任何麦克风都会继续传输数据。
为了使用麦克风的输入线,在将字节组装到 PCM 后,我将输入并将浮点数组发送到并发安全的 FIFO 队列:ConcurrentLinkedQueue<Float[]>
。这样,就可以在不阻塞输入进程的情况下对传入的 PCM 执行操作。从此队列轮询不会影响输入行添加到队列的能力。
IDK 如果这是处理麦克风输入的最有效方式,或者如果它适合您的情况(您将其用作随机数生成器?),但也许这是一个值得考虑的计划/模式。
【讨论】:
感谢您的回答。我从您的回答中了解到,输入行继续获取字节,但我认为执行不应陷入:_bytesRead = _targetDataLine.read(_buffer, 0, _buffer.length);如果该句子永远不会返回,我如何获得缓冲区?可能有些事情我没有考虑到,我不知道 程序在读取方法行“挂起”?如果 read 方法使用阻塞算法并且仅在填充请求的缓冲区时才返回数据,我可以看到理论上可能的结果在哪里。如果这是正在发生的事情,则暗示您尝试从中读取的行没有获取读取方法请求的表单的数据。 IDK 是否真的发生了这种情况,或者如何处理这种情况。该行是否可能是某种捆绑的 AV 格式并且必须提取音频? 对不起,我不熟悉那个词汇……你说的AV格式是什么意思?我既不知道设备如何获取缓冲区,也不知道它是否以任何方式编码,但Java用户期望的是获取解码的缓冲区......这可能是设备被另一个应用程序用于采样的问题吗? 是的,程序此时挂起(读取函数) 菲尔,谢谢你的帮助。我只是想获取您提到的数据。我开始了新的执行,令人惊讶的是,读取功能不再阻塞。我什么都没做,但它已经开始工作了……我不知道……问题可能是那条线被另一个正在使用它的应用程序阻塞了,现在它已经停止使用它了。不管怎样,问题似乎已经解决了。以上是关于Java 声音采样器未完成获取缓冲区的主要内容,如果未能解决你的问题,请参考以下文章