godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
88.88k stars 20.15k forks source link

Cannot record audio on Linux when compiled with -fPIC #55315

Open rcorre opened 2 years ago

rcorre commented 2 years ago

Godot version

3.4.stable

System information

Linux 5.15.4-arch1-1

Issue description

The following code captures audio from a mic and plays it back:

extends Node

var capture := AudioEffectCapture.new()
var playback: AudioStreamGeneratorPlayback

func _ready():
    var idx := AudioServer.get_bus_count()
    AudioServer.add_bus(idx)
    AudioServer.set_bus_mute(idx, true)
    AudioServer.add_bus_effect(idx, capture)

    var mic := AudioStreamPlayer.new()
    mic.stream = AudioStreamMicrophone.new()
    mic.bus = AudioServer.get_bus_name(idx)
    add_child(mic)
    mic.play()

    var player := AudioStreamPlayer.new()
    player.stream = AudioStreamGenerator.new()
    playback = player.get_stream_playback()
    add_child(player)
    player.play()

func _physics_process(_delta: float):
    var n := capture.get_frames_available()
    var recorded := capture.get_buffer(n)
    var maxval := 0.0
    for i in range(n):
        playback.push_frame(recorded[i])

    capture.clear_buffer()

In godot 3.3.4, it works as expected. In godot 3.4, I hear nothing.

Steps to reproduce

  1. Run the example project with godot 3.3.4
  2. Talk into your mic
  3. Verify you hear your voice played back
  4. Run the example project with Godot 3.4
  5. Talk into your mic
  6. Hear nothing played back

Minimal reproduction project

example.zip

rcorre commented 2 years ago

Changes since 3.3.4:

[rcorre@midgar godot]$ git log --oneline 3.3.4-stable..3.4-stable -- servers/audio/audio_stream.cpp servers/audio/effects/audio_effect_capture.cpp servers/audio_server.cpp
b800438efb [HTML5] Use browser mix rate by default on the Web.
999159c12c Fix Godot's cubic resampling algorithm
840c0e57fb Revert "Implement a new resampling algorithm in AudioStreamPlaybackResampled"
7e03bd1671 Remove duplicate WARN_PRINTS macro
140350d767 Style: Enforce braces around if blocks and loops
a828398655 Style: Replaces uses of 0/NULL by nullptr (C++11)
b5e1e05ef2 Style: clang-format: Disable KeepEmptyLinesAtTheStartOfBlocks
64a63e0861 Style: clang-format: Disable AllowShortCaseLabelsOnASingleLine
70ae90e0e8 Core: Drop custom `copymem`/`zeromem` defines
c5e8a81737 Fix AudioServer Crash when bus count equals 0
Calinou commented 2 years ago

Does it work on the 3.x branch? https://github.com/godotengine/godot/pull/54789 was merged shortly after 3.4 was released.

rcorre commented 2 years ago

I'm getting extrememly confused. This problem seems specific to the godot 3.4 PKGBUILD for ArchLinux. If I download that PKGBUILD and run makepkg -s, the resulting godot binary cannot capture audio. If I unpack the source .tgz and compile with the same flags, it seems to work fine:

scons -j16 bits=64 colored=yes platform=x11 pulseaudio=yes system_certs_path=/etc/ssl/certs/ca-certificates.crt target=release_debug tools=yes use_llvm=no CFLAGS=-fPIC -Wl,-z,relro,-z,now CXXFLAGS=-fPIC -Wl,-z,relro,-z,now builtin_bullet=no builtin_certs=no builtin_freetype=no builtin_libpng=no builtin_libvorbis=no builtin_libwebp=no builtin_miniupnpc=no builtin_pcre2=no builtin_zlib=no builtin_zstd=no

I'll keep investigating, but it seems like this is probably an Arch-specific packaging issue and not a Godot bug.

rcorre commented 2 years ago

The issue seems to be -fPIC in the CFLAGS and CXXFLAGS

rcorre commented 2 years ago

I just double-checked and confirmed -- removing -fPIC from https://github.com/archlinux/svntogit-community/blob/packages/godot/trunk/PKGBUILD#L49-L50 fixes the issue. Is this a bug in Godot or in the Arch packaging? It seems like compiling with -fPIC should work, though I also see this line https://github.com/archlinux/svntogit-community/blob/packages/godot/trunk/PKGBUILD#L23 messing with the automatically-added pie flags.

rcorre commented 2 years ago

I'm trying to figure out if I should report this as an Arch packaging bug. Is it expected that -fPIC would interfere with audio recording?

extremety1989 commented 2 years ago

@rcorre hey, i got some questions about your code var n := capture.get_frames_available() var recorded := capture.get_buffer(n) does recorded contain data captured from microphone ? i can not find any documentation about how can i send microphone recorded data to server and then back to client in realtime,

rcorre commented 2 years ago

@extremety1989 if you're asking about this issue in particular, n is nonzero but the data from capture.get_frames_available() is all 0 (if compiled with -fPIC).

If you're asking for general help, this issue isn't the place. Check out some of the community resources, the docs, the godot-voip plugin, or the audio recording demo

SoapSpangledGames commented 2 years ago

Just out of curiosity, has Godot audio recording on Linux ever worked? I have never gotten any recording examples to ever record audio. Not even fully self contained example projects.

Calinou commented 2 years ago

Just out of curiosity, has Godot audio recording on Linux ever worked? I have never gotten any recording examples to ever record audio. Not even fully self contained example projects.

It works, but only on certain system configurations. The exact reason for it breaking is on certain systems is unknown, but it could be linked to build-time options or a race condition. (See the above mention of -fPIC.)

Are you using official Godot Linux binaries, distribution-packaged binaries, the Flatpak from Flathub or a self-compiled build?

SoapSpangledGames commented 2 years ago

Are you using official Godot Linux binaries, distribution-packaged binaries, the Flatpak from Flathub or a self-compiled build?

I almost always use official Godot Linux binaries. At the moment, though, I'm using 3.4 beta 5 (I should download the latest official release).

I just downloaded 3.4.3 official, and the godot-voip demonstration program still doesn't work. Kubuntu 18.04.6 LTS, kernel 4.15.0-118-generic.

aanishacharyaa commented 2 years ago

@Calinou @rcorre Is there a way to record/capture the audio output of the system/speakers? Not microphone but the output.

Zireael07 commented 2 years ago

@aanishacharyaa: 99% there is no way to do it either in Godot or the OS. The way I did it when I needed to was install one of the loopback driver thingies (some OS have it out of the box, some need them installed) and then record the input

rcorre commented 2 years ago

Just out of curiosity, has Godot audio recording on Linux ever worked? I have never gotten any recording examples to ever record audio. Not even fully self contained example projects.

Yes, audio recording on Linux works fine as long as I compile without -fPIC.

Calinou commented 2 years ago

@Calinou @rcorre Is there a way to record/capture the audio output of the system/speakers? Not microphone but the output.

You can install and configure "virtual sink" software which creates a microphone that matches the output of the system audio. You can then record this microphone from Godot.