带有Android事物的PCM5122 DAC

时间:2018-01-31 11:32:58

标签: raspberry-pi raspberry-pi3 android-things

我有一个使用PCM5122 DAC的Raspberry Pi 3B和Suptronics X920 Expansion Board。所以我在通过该板播放声音时遇到了麻烦。

配置文件是默认设置,显示配置部分除外:

kernel=u-boot-dtok.bin
framebuffer_depth=16

# Prevent the firmware from loading HAT overlays now that we handle pin muxing.
# ourselves. See:
# https://www.raspberrypi.org/documentation/configuration/device-tree.md#part3.4
dtoverlay=

dtparam=i2c_arm=on
dtparam=spi=on
dtparam=audio=on

# pwm and I2S are mutually-exclusive since they share hardware clocks.
dtoverlay=pwm-2chan-with-clk,pin=18,func=2,pin2=13,func2=4
dtoverlay=generic-i2s

start_x=1

# Tell U-boot to always use the "serial0" interface for the console, which is
# set to whichever uart (uart0 or uart1) is set to the header pins. This doesn't
# interfere with the uart selected for Bluetooth.
dtoverlay=chosen-serial0

# Enable skip-init on the UART interfaces, so U-Boot doesn't attempt to
# re-initialize them.
dtoverlay=rpi-uart-skip-init

# Add pin devices to the system for use by the runtime pin configuration driver.
dtoverlay=runtimepinconfig
dtoverlay=uart1
dtoverlay=bcm2710-rpi-3-b-spi0-pin-reorder

# Tell the I2S driver to use the cprman clock.
dtoverlay=bcm2710-rpi-3-b-i2s-use-cprman

# Uncomment to disable serial port on headers, use GPIO14 and GPIO15
# as gpios and to allow the core_freq to change at runtime.
enable_uart=1
core_freq=400

# Support official RPi display.
dtoverlay=i2c-rtc,ds3231
dtoverlay=rpi-ft5406
hdmi_force_hotplug=1

# Set framebuffer to support RGBA colors.
framebuffer_swap=0

# Waveshare display settings
max_usb_current=1
hdmi_group=2
hdmi_mode=87
hdmi_cvt 1024 600 60 6 0 0 0
hdmi_drive=1

这是播放声音文件的代码:

fun playSound(file: File) {
    val audioEncoding = AudioFormat.ENCODING_PCM_16BIT
    val sampleRate = 16000

    val audioOutputFormat = AudioFormat.Builder()
            .setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
            .setEncoding(audioEncoding)
            .setSampleRate(16000)
            .build()

    val audioOutputBufferSize = AudioTrack.getMinBufferSize(sampleRate, audioOutputFormat.channelMask, audioEncoding)

    val audioOutputDevice = findAudioDevice(AudioManager.GET_DEVICES_OUTPUTS, AudioDeviceInfo.TYPE_BUS)

    val audioTrack = AudioTrack.Builder()
            .setAudioFormat(audioOutputFormat)
            .setBufferSizeInBytes(audioOutputBufferSize)
            .setTransferMode(AudioTrack.MODE_STREAM)
            .build()

    audioTrack.preferredDevice = audioOutputDevice

    val buffer = ByteArray(audioOutputBufferSize)

    audioTrack.play()
    audioTrack.setVolume(1f)

    val stream = file.inputStream().buffered()
    try {
        while (stream.read(buffer) > 0) {
            val out = audioTrack.write(buffer, 0, buffer.size, AudioTrack.WRITE_BLOCKING)
            d { "audioTrack.write = $out" }
        }
    } catch (error: Throwable) {
        e(error) { "Error playing audio $file" }
    } finally {
        stream.close()
    }

    audioTrack.stop()
    audioTrack.release()
}

private fun findAudioDevice(deviceFlag: Int, deviceType: Int): AudioDeviceInfo? {
    val manager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
    val adis = manager.getDevices(deviceFlag)
    for (adi in adis) {
        if (adi.type == deviceType) {
            return adi
        }
    }
    return null
}

我用常规的Raspberry Pi音频输出(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER)测试了代码,它运行正常。但是对于AudioDeviceInfo.TYPE_BUS,它只会产生没有任何错误的声音。

我尝试了各种配置选项,例如dtoverlay=hifiberrydtoverlay=hifiberry-dacplus但没有运气。

请帮忙。

1 个答案:

答案 0 :(得分:2)

看起来您可能正在使用Google Assistant sample的一些代码,并且您认为TYPE_BUS是启用音频路由以使用I2S总线而不是内置音频插孔。

然而,这可能不是整个故事。 DAC可能需要额外的配置命令和/或外部触发器。例如,查看similar HAT with the same DAC,还有一个I2C总线连接以及DAC设置命令。我们的助手示例使用VoiceHAT driver来完成DAC在该外设上所需的额外触发。

在Raspbian中,您通过dtoverlay启用的驱动程序可能会处理这两个部分。在这里,您的代码需要手动管理设置位。请看一下如何在Assistant示例中使用VoiceHAT驱动程序作为示例。

另外,请确保未将任何I2S引脚用作GPIO或PWM,因为这将禁用音频路由per the documentation

旁注: Android Things不支持通过config.txt进行内核更改,因此预计在那里添加驱动程序不会产生任何影响。