0

我想在安卓设备的音频插孔上放一个可控的直流电压。我当前的解决方案是创建一个 1 秒的数组,其中包含要输出的波形的 PCM 信息(在这种情况下是一条扁平线)。

问题在于,每一秒,都会出现输出瞬间降至零伏的故障。我相信这是在创建音频资源实例时发生的。

您可以看到音频是在其自己的线程中处理的。我将在另一个线程中更改 generatedSnd 数组。

有没有更流畅的方法来做到这一点?我有一种感觉,流媒体是最好的选择,但我无法理解它。

private class OutDACrunnable
    implements Runnable {

    public void run() {
        while (! done) {

        audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                sampleRate, AudioFormat. CHANNEL_OUT_STEREO,
                AudioFormat.ENCODING_PCM_16BIT, generatedSnd.length,
                AudioTrack.MODE_STATIC);

        audioTrack.write(generatedSnd, 0, generatedSnd.length);

        if (audioManager.isWiredHeadsetOn()) { } // use this later

        audioTrack.play();

        // wait until playback is complete
        int x = 0;
        do {
            if (audioTrack == null) {
                x = numSamples;
            } else {
                x = audioTrack.getPlaybackHeadPosition(); 
            }
        } while (x < numSamples);

        if (audioTrack != null) audioTrack.release();

        }
    }

} // OutDACrunbable

谢谢。

4

2 回答 2

0

Unfortunately, you can't output DC from the audio jack. The audio I/o is designed to pass changing signals, generally speaking above 20 Hz. If you try to output DC, you will get something more like a pulse, which is what it sounds like you are getting.

于 2013-06-06T13:37:14.480 回答
0

在 Bjorn 提供有关按需写入阻塞的提示之后,我调整了我的代码。所以,基本上,我每 15 毫秒向它扔 20 毫秒的样本。一旦缓冲区已满,它就会丢弃,所以我也将缓冲区设置为 20 毫秒。这样它就可以与我的要求保持同步,并且不会出现任何问题...

        audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                sampleRate, AudioFormat. CHANNEL_OUT_STEREO,
                AudioFormat.ENCODING_PCM_16BIT, generatedSnd.length,
                AudioTrack.MODE_STREAM);

        audioTrack.play();

    private class OutDACrunnable
        implements Runnable {

        public void run() {
            while (! done) {
                playTone();
                try {
                    Thread.sleep((int) (750 * duration));
                } catch (InterruptedException e) {
                    Log.e(MyTag, "OutDACrunnable: " + e.toString());
                }
            }
        }

    } // OutDACrunbable

    void playTone() {

    //      Log.d(MyTag, "playTone: start");

            audioTrack.write(generatedSnd, 0, generatedSnd.length);

            if (audioManager.isWiredHeadsetOn()) { } // use this later

    //      Log.d(MyTag, "playTone: done");

    } // playTone

    public static void genTone(double amp1, double amp2) {

//      Log.d(MyTag, "genTone: start");

        // convert to 16 bit pcm sound array
        // assumes the sample buffer is normalised.
        int idx = 0;
        for (int i = 0; i < numSamples; i++) {
            // scale to maximum amplitude
            // in 16 bit wav PCM, first byte is the low order byte, first short is left ch
            short val = (short) ((amp1 * 32767));
            generatedSnd[idx++] = (byte) (val & 0x00ff);
            generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);
            val = (short) ((amp2 * 32767));
            generatedSnd[idx++] = (byte) (val & 0x00ff);
            generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);

        }
//      Log.d(MyTag, "genTone: done");
    }

我只是在需要的时候调用 GenTone,使用我想要输出的两个 DC...

于 2013-06-06T22:16:33.817 回答