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 声音采样器未完成获取缓冲区的主要内容,如果未能解决你的问题,请参考以下文章

机器学习集成学习(未完成)

GLSL:采样器上传仅在删除未使用的采样器时有效

sed 学习笔记(未完成)

如何在 Avfoundation 中正确更改采样率

说一下 tcp 粘包是怎么产生的?(未完成)

Java面试之网络