Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FLAC audio support #80160

Closed
wants to merge 1 commit into from
Closed

Add FLAC audio support #80160

wants to merge 1 commit into from

Conversation

fire
Copy link
Member

@fire fire commented Aug 2, 2023

Fixes: godotengine/godot-proposals#1190

  1. There is a working GDExtension version by DeleteSystem32 here.
  2. dr_flac is a manageable code length.
  3. Positive support from Godot Engine users in the godot-proposal for adding to Godot Engine.

EDIT: Added reference to the working GDExtension

@fire fire requested a review from a team as a code owner August 2, 2023 09:27
@fire fire force-pushed the flac-4.2 branch 3 times, most recently from 4012c01 to a68635c Compare August 2, 2023 09:36
@Faless
Copy link
Collaborator

Faless commented Aug 2, 2023

DeleteSystem32 was unable to create a GDExtension for audio streams due to strict audio code requirements.

Can you expand on this? We definitely should allow custom audio formats to be implemented via GDExtension (even if we decide to include flac support in core).

@fire
Copy link
Member Author

fire commented Aug 2, 2023

I only found this mention by @DeleteSystem32: godotengine/godot-proposals#1190 (comment)

@DeleteSystem32
Copy link
Contributor

I only found this mention by @DeleteSystem32: godotengine/godot-proposals#1190 (comment)

That was for GDNative, but I've tried reimplementing it as a GDExtension a few days ago and it works fine, here.

@Faless
Copy link
Collaborator

Faless commented Aug 2, 2023

That was for GDNative, but I've tried reimplementing it as a GDExtension a few days ago and it works fine, here.

Thanks, I've edited the PR description to link to it.

Copy link
Member

@Calinou Calinou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally (rebased on top of master 237bd0a), it works as expected.

The import options provided are consistent with Ogg Vorbis and MP3, which makes sense as these are designed to be used for music and ambient sounds.

Testing project: test_pr_80160.zip1

FLAC Ogg Vorbis 412 Kb/s2 MP3 320 Kb/s
Screenshot_20230803_012138 Screenshot_20230803_012153 Screenshot_20230803_012147

The impact of this PR on binary size is 103 KB (70,337,792 -> 70,440,320 bytes) on a stripped Linux x86_64 release export template (with LTO). This is fairly significant for mobile/web platforms – I wonder if this PR's impact could be reduced somehow.

Footnotes

  1. Music in the testing project by Marc A. Pullen.

  2. I didn't know Ogg Vorbis could go past 320 Kb/s, but it can when exported from Audacity 🙂

@Calinou
Copy link
Member

Calinou commented Aug 2, 2023

Note that dr_flac supports metadata access, in case we want to implement godotengine/godot-proposals#3307.

@fire fire force-pushed the flac-4.2 branch 4 times, most recently from 2f02ec4 to f0bd879 Compare August 3, 2023 01:13
@akien-mga akien-mga changed the title Support FLAC Add FLAC audio support Aug 3, 2023
Co-authored-by: Vincent <[email protected]>
@ellenhp
Copy link
Contributor

ellenhp commented Aug 4, 2023

I don't think I support this. I'd guess maybe 0.1% of games will use this, and if it adds 100k that's an enormous dependency to bring on for such a small group of users. There's a working GDExtension for it right? If not, we should figure out how to support it in GDExtension. I think the necessary methods are exposed.

@ParadoxV5
Copy link

ParadoxV5 commented Aug 27, 2023

Are we certain that FLAC is niche? It’s both popular enough and underütilized to me.

[P.S.] It’s an entire audio codec after all, a few KiBs to a few dozen KiBs is expected. Though yes, not a hundred.

@Calinou
Copy link
Member

Calinou commented Aug 27, 2023

Are we certain that FLAC is niche? It’s both popular enough and underütilized to me.

In the context of game development, it is considered a niche format as you don't benefit from lossless audio that much:

  • In a game, audio often plays with other samples at the same time, so it's usually indistinguishable from high-quality lossy audio. It's hard to appreciate music quality at its fullest when there are sound effects, voices and ambient sounds playing at the same time.
  • High-quality lossy audio (such as Ogg Vorbis at 320 Kb/s) is already not distinguishable for most users, while being significantly smaller in size. Add attenuation and audio effects to the mix, and it becomes even more difficult (for audio samples/ambient sounds).
    • While MP3 at 320 Kb/s can be distinguished from lossless by people with high-end audio equipment and good ears, this is much more challenging with Ogg Vorbis already. It would be pretty much impossible if Godot added Opus support, which I think is a more worthwhile effort as it's also VOIP-friendly (and works well at very low bitrates too).
  • It's even less noticeable for users using wireless audio solutions, especially Bluetooth with its audio stack being subpar on desktop platforms. High-quality Bluetooth audio is only available on mobile platforms, and not without some fiddling.

The main use cases for FLAC in games are:

  • Loading user-provided music libraries, which I'd say is a niche scenario in itself 🙂
    • With the rise of audio streaming, local music storage is becoming less common. I still do it personally, but I never use in-game audio library features.
  • Using as a storage format that is smaller than WAV and can be iterated upon without any generation loss. This use case is somewhat more common, but not essential when WAV can also do it (with larger file sizes). We also don't have any audio encoders in the Godot editor, so you can't choose to encode it to a lossy format after importing to reduce file size.

Adding 100 KB of binary size is only worth it if you're certain a majority of exported projects will be able to save at least 100 KB of file size. In practice, this isn't the case for a lot of projects (e.g. if they only use lossy audio, or no audio at all for non-game applications).

@DeeJayLSP
Copy link
Contributor

DeeJayLSP commented Aug 27, 2023

For comparison, I did a quick release build on DeleteSystem32's GDExtension implementation.

The stripped lib sizes are the following:

Platform Size
Windows (MinGW) 3034.00 KiB
Linux 4443.84 KiB

I must add however that I built it as it was provided (not even sure if it's well optimized), only changing to release and stripping.
If anyone is able to achieve smaller sizes I would like to see the difference.

@DeeJayLSP
Copy link
Contributor

DeeJayLSP commented Aug 28, 2023

The impact of this PR on binary size is 103 KB (70,337,792 -> 70,440,320 bytes) on a stripped Linux x86_64 release export template (with LTO). This is fairly significant for mobile/web platforms

Out of curiosity, I decided to do a minimal release production build for the web (some modules ended up being built, but the difference is what matters more here).

The command used was scons -j$(nproc) platform=web target=template_release production=yes <disable_copypastes_from_docs_optimizing_for_size>, with and without flac enabled.

The resulting .wasm file got increased by 58.48KB (25,345,358 to 25,403,838 bytes).

The resulting .zip file got increased by 19.8KB (6,036,845 to 6,056,647).

One thing to be aware of is that builds for web are optimized for size by default, and dr_flac includes SIMD optimizations for Desktop and Mobile platforms. Therefore, this decrease is likely not valid for mobile.

@ellenhp
Copy link
Contributor

ellenhp commented Aug 28, 2023

Godot is not audiophile software, so I don't personally see the need to take on even 1k of extra binary size for audiophile codecs considering the fact that there is a working GDExtension for games that require it. Is there anyone out there who absolutely needs this to be in core? I've seen a few people say FLAC support would benefit them. Maybe one of those people could explain why the GDExtension doesn't satisfy their needs? This feels hypothetical right now and we don't generally merge PRs that solve hypothetical problems.

I know I posted this earlier but useful context for anyone skimming: https://godotengine.org/article/will-your-contribution-be-merged-heres-how-tell/

@DeeJayLSP
Copy link
Contributor

It isn't just for audiophile purposes.

In context of sound effects, using formats like MP3 or Vorbis isn't really good for when someone wants to play lots of sound effects at the same time. While FLAC doesn't decrease the file size at the same level, it is capable of decoding about 1.4-1.5x faster (at least that's what libFLAC on ffmpeg shows when decoding to PCM) therefore being less demanding than those.

This is a possible use case for FLAC. A game with lots of sound effects (which certainly isn't just a few cases) could benefit by having those as FLAC instead.

For that context, I don't think a GDExtension helps when it's over 30x larger than a built-in implementation.

@ellenhp
Copy link
Contributor

ellenhp commented Aug 29, 2023

Some disorganized thoughts.

  1. I stand by my statement that FLAC is an audiophile format, for reasons to follow a few bullet points down.
  2. If you're playing lots of sound effects, the mix is going to be very muddy. It doesn't sound good to play lots of sound effects at once. We do want to support this use-case anyway because sometimes it's really funny to play a game that plays a bunch of sfx at once, and we definitely don't want underruns ever, even if the sound ends up being unpleasant to listen to. But this is a thing to consider when we're talking about audiophile codecs where quality is the primary concern (which I will back up with some data at the end).
  3. If a game needs lots of overlapping sounds without it being intelligible which sounds are which (humans can't keep track of more than like 10-20 different sounds at once IIRC) I think it's common practice to combine them in a DAW, because then the sound engineer can equalize things, use compressors to increase intelligibility, pitch shift, stretch individual sounds in time, and generally just create a nice chaotic sound. You can't do this (artistically) at runtime.
  4. Using FLAC for short sound effects doesn't generally decrease their size compared to a WAV as far as I can tell, and sometimes increases their size. I tested several different sound effects distributed as WAVs. I'm not sure of the licensing so I'm not going to post these specific sfx, but I'd love to see testing by others on this too. Results at the end of this comment.
  5. The break-even point on compressing a sound effect with FLAC purely in terms of size seems to be about 5-10 seconds long at 11k sample rate. Playing more sounds than can be decoded by vorbis on a given system, each of which is about 5-10 seconds long is going to result in an absolute cacophony. It will sound terrible. If someone doesn't mind things sounding terrible, or if they want that, and they can't overlay the sounds in a DAW, they should use ADPCM wavs. There was some talk about removing this but reduz didn't want to because it's very light on binary size and has zero maintenance burden. In retrospect that makes a lot of sense.
  6. I think libFLAC does allocation during decoding based on what I've seen here, which we have a strict rule against to the point that we even went to the trouble of avoiding the use of libogg on the audio thread 😬 I don't think the rule should be as strict as it is, but that's a discussion for another time.

I'm sorry about the wall of text and I promise I'm not trying to be difficult, I just don't think this is a useful feature for most people who use Godot. The main benefit here seems to be compatibility with user-provided sounds. I know someone is working on a DAW in Godot and this seems like a good feature for them, but I think for that application a GDExtension is probably fine?

  Duration: 00:00:04.96, bitrate: 88 kb/s
  Stream #0:0: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 11025 Hz, 1 channels, u8, 88 kb/s
-rw-r--r--. 1 ellen ellen 54297 Aug 28 17:56 car_crash2.flac
-rw-r--r--. 1 ellen ellen 23438 Aug 28 17:57 car_crash2.ogg
-rw-r--r--. 1 ellen ellen 54701 Aug 28 17:55 car_crash2.wav
  Duration: 00:00:02.13, bitrate: 89 kb/s
  Stream #0:0: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 11127 Hz, 1 channels, u8, 89 kb/s
-rw-r--r--. 1 ellen ellen 23846 Aug 28 17:52 aaa.flac
-rw-r--r--. 1 ellen ellen 11492 Aug 28 17:52 aaa.ogg
-rw-r--r--. 1 ellen ellen 23744 Aug 28 17:52 aaa.wav
  Duration: 00:00:09.13, bitrate: 88 kb/s
  Stream #0:0: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 11025 Hz, 1 channels, u8, 88 kb/s
-rw-r--r--. 1 ellen ellen  78687 Aug 28 17:55 carpentry.flac
-rw-r--r--. 1 ellen ellen  39876 Aug 28 17:55 carpentry.ogg
-rw-r--r--. 1 ellen ellen 100732 Aug 28 17:55 carpentry.wav

@DeeJayLSP
Copy link
Contributor

DeeJayLSP commented Aug 29, 2023

Out of curiosity, I decided to do the same test with a pack of 51 UI sound effects from Kenney, which does include some really short sound effects.

In total, the total WAV size got to 2.3MiB, while the total FLAC size got to 1.1MiB.

I can confirm, however, that some sound effects increased in size upon conversion. Those are really short effects (less than 0.1s duration).

All of the following files are 44100Hz 2 channels:

-rw-rw-r-- 1 douglas douglas 13803 ago 28 22:32 click1.flac
-rw-rw-r-- 1 douglas douglas 18766 ago 28 22:32 click1.wav
-rw-rw-r-- 1 douglas douglas 12586 ago 28 22:32 click2.flac
-rw-rw-r-- 1 douglas douglas 10062 ago 28 22:32 click2.wav
-rw-rw-r-- 1 douglas douglas 17343 ago 28 22:32 click3.flac
-rw-rw-r-- 1 douglas douglas 16206 ago 28 22:32 click3.wav
-rw-rw-r-- 1 douglas douglas 11456 ago 28 22:32 click4.flac
-rw-rw-r-- 1 douglas douglas  8526 ago 28 22:32 click4.wav
-rw-rw-r-- 1 douglas douglas 10987 ago 28 22:32 click5.flac
-rw-rw-r-- 1 douglas douglas  8526 ago 28 22:32 click5.wav
-rw-rw-r-- 1 douglas douglas 12714 ago 28 22:32 mouseclick1.flac
-rw-rw-r-- 1 douglas douglas 14158 ago 28 22:32 mouseclick1.wav
-rw-rw-r-- 1 douglas douglas 13083 ago 28 22:32 mouserelease1.flac
-rw-rw-r-- 1 douglas douglas 16206 ago 28 22:32 mouserelease1.wav
-rw-rw-r-- 1 douglas douglas 20719 ago 28 22:32 rollover1.flac
-rw-rw-r-- 1 douglas douglas 41806 ago 28 22:32 rollover1.wav
-rw-rw-r-- 1 douglas douglas 12860 ago 28 22:32 rollover2.flac
-rw-rw-r-- 1 douglas douglas 11086 ago 28 22:32 rollover2.wav
-rw-rw-r-- 1 douglas douglas 14985 ago 28 22:32 rollover3.flac
-rw-rw-r-- 1 douglas douglas 13646 ago 28 22:32 rollover3.wav
-rw-rw-r-- 1 douglas douglas 13458 ago 28 22:32 rollover4.flac
-rw-rw-r-- 1 douglas douglas 22350 ago 28 22:32 rollover4.wav
-rw-rw-r-- 1 douglas douglas 13225 ago 28 22:32 rollover5.flac
-rw-rw-r-- 1 douglas douglas 19790 ago 28 22:32 rollover5.wav
-rw-rw-r-- 1 douglas douglas 14431 ago 28 22:32 rollover6.flac
-rw-rw-r-- 1 douglas douglas 31054 ago 28 22:32 rollover6.wav
-rw-rw-r-- 1 douglas douglas 23344 ago 28 22:32 switch10.flac
-rw-rw-r-- 1 douglas douglas 64846 ago 28 22:32 switch10.wav
-rw-rw-r-- 1 douglas douglas 21826 ago 28 22:32 switch11.flac
-rw-rw-r-- 1 douglas douglas 55630 ago 28 22:32 switch11.wav
-rw-rw-r-- 1 douglas douglas 14613 ago 28 22:32 switch12.flac
-rw-rw-r-- 1 douglas douglas 12622 ago 28 22:32 switch12.wav
-rw-rw-r-- 1 douglas douglas 12774 ago 28 22:32 switch13.flac
-rw-rw-r-- 1 douglas douglas  8526 ago 28 22:32 switch13.wav
-rw-rw-r-- 1 douglas douglas 12598 ago 28 22:32 switch14.flac
-rw-rw-r-- 1 douglas douglas  9038 ago 28 22:32 switch14.wav
-rw-rw-r-- 1 douglas douglas 23415 ago 28 22:32 switch15.flac
-rw-rw-r-- 1 douglas douglas 47438 ago 28 22:32 switch15.wav
-rw-rw-r-- 1 douglas douglas 29279 ago 28 22:32 switch16.flac
-rw-rw-r-- 1 douglas douglas 67406 ago 28 22:32 switch16.wav
-rw-rw-r-- 1 douglas douglas 25430 ago 28 22:32 switch17.flac
-rw-rw-r-- 1 douglas douglas 62798 ago 28 22:32 switch17.wav
-rw-rw-r-- 1 douglas douglas 31928 ago 28 22:32 switch18.flac
-rw-rw-r-- 1 douglas douglas 79182 ago 28 22:32 switch18.wav
-rw-rw-r-- 1 douglas douglas 27175 ago 28 22:32 switch19.flac
-rw-rw-r-- 1 douglas douglas 70478 ago 28 22:32 switch19.wav
-rw-rw-r-- 1 douglas douglas 27054 ago 28 22:32 switch1.flac
-rw-rw-r-- 1 douglas douglas 57166 ago 28 22:32 switch1.wav
-rw-rw-r-- 1 douglas douglas 27241 ago 28 22:32 switch20.flac
-rw-rw-r-- 1 douglas douglas 65870 ago 28 22:32 switch20.wav
-rw-rw-r-- 1 douglas douglas 29426 ago 28 22:32 switch21.flac
-rw-rw-r-- 1 douglas douglas 74574 ago 28 22:32 switch21.wav
-rw-rw-r-- 1 douglas douglas 28541 ago 28 22:32 switch22.flac
-rw-rw-r-- 1 douglas douglas 66894 ago 28 22:32 switch22.wav
-rw-rw-r-- 1 douglas douglas 29831 ago 28 22:32 switch23.flac
-rw-rw-r-- 1 douglas douglas 70990 ago 28 22:32 switch23.wav
-rw-rw-r-- 1 douglas douglas 23770 ago 28 22:32 switch24.flac
-rw-rw-r-- 1 douglas douglas 51022 ago 28 22:32 switch24.wav
-rw-rw-r-- 1 douglas douglas 28105 ago 28 22:32 switch25.flac
-rw-rw-r-- 1 douglas douglas 67918 ago 28 22:32 switch25.wav
-rw-rw-r-- 1 douglas douglas 21684 ago 28 22:32 switch26.flac
-rw-rw-r-- 1 douglas douglas 42318 ago 28 22:32 switch26.wav
-rw-rw-r-- 1 douglas douglas 24759 ago 28 22:32 switch27.flac
-rw-rw-r-- 1 douglas douglas 53070 ago 28 22:32 switch27.wav
-rw-rw-r-- 1 douglas douglas 20713 ago 28 22:32 switch28.flac
-rw-rw-r-- 1 douglas douglas 39758 ago 28 22:32 switch28.wav
-rw-rw-r-- 1 douglas douglas 25559 ago 28 22:32 switch29.flac
-rw-rw-r-- 1 douglas douglas 56654 ago 28 22:32 switch29.wav
-rw-rw-r-- 1 douglas douglas 25515 ago 28 22:32 switch2.flac
-rw-rw-r-- 1 douglas douglas 56142 ago 28 22:32 switch2.wav
-rw-rw-r-- 1 douglas douglas 27822 ago 28 22:32 switch30.flac
-rw-rw-r-- 1 douglas douglas 66382 ago 28 22:32 switch30.wav
-rw-rw-r-- 1 douglas douglas 34048 ago 28 22:32 switch31.flac
-rw-rw-r-- 1 douglas douglas 79182 ago 28 22:32 switch31.wav
-rw-rw-r-- 1 douglas douglas 34003 ago 28 22:32 switch32.flac
-rw-rw-r-- 1 douglas douglas 79182 ago 28 22:32 switch32.wav
-rw-rw-r-- 1 douglas douglas 37745 ago 28 22:32 switch33.flac
-rw-rw-r-- 1 douglas douglas 90958 ago 28 22:32 switch33.wav
-rw-rw-r-- 1 douglas douglas 34428 ago 28 22:32 switch34.flac
-rw-rw-r-- 1 douglas douglas 81742 ago 28 22:32 switch34.wav
-rw-rw-r-- 1 douglas douglas 25682 ago 28 22:32 switch35.flac
-rw-rw-r-- 1 douglas douglas 61774 ago 28 22:32 switch35.wav
-rw-rw-r-- 1 douglas douglas 23561 ago 28 22:32 switch36.flac
-rw-rw-r-- 1 douglas douglas 55630 ago 28 22:32 switch36.wav
-rw-rw-r-- 1 douglas douglas 24948 ago 28 22:32 switch37.flac
-rw-rw-r-- 1 douglas douglas 56654 ago 28 22:32 switch37.wav
-rw-rw-r-- 1 douglas douglas 30786 ago 28 22:32 switch38.flac
-rw-rw-r-- 1 douglas douglas 75598 ago 28 22:32 switch38.wav
-rw-rw-r-- 1 douglas douglas 30781 ago 28 22:32 switch3.flac
-rw-rw-r-- 1 douglas douglas 64846 ago 28 22:32 switch3.wav
-rw-rw-r-- 1 douglas douglas 29457 ago 28 22:32 switch4.flac
-rw-rw-r-- 1 douglas douglas 76110 ago 28 22:32 switch4.wav
-rw-rw-r-- 1 douglas douglas 29904 ago 28 22:32 switch5.flac
-rw-rw-r-- 1 douglas douglas 56142 ago 28 22:32 switch5.wav
-rw-rw-r-- 1 douglas douglas 27009 ago 28 22:32 switch6.flac
-rw-rw-r-- 1 douglas douglas 65358 ago 28 22:32 switch6.wav
-rw-rw-r-- 1 douglas douglas 21615 ago 28 22:32 switch7.flac
-rw-rw-r-- 1 douglas douglas 34126 ago 28 22:32 switch7.wav
-rw-rw-r-- 1 douglas douglas 21338 ago 28 22:32 switch8.flac
-rw-rw-r-- 1 douglas douglas 60238 ago 28 22:32 switch8.wav
-rw-rw-r-- 1 douglas douglas 20440 ago 28 22:32 switch9.flac
-rw-rw-r-- 1 douglas douglas 46926 ago 28 22:32 switch9.wav

@ellenhp
Copy link
Contributor

ellenhp commented Aug 29, 2023

In total, the total WAV size got to 2.3MiB, while the total FLAC size got to 1.1MiB.

Curious if you could try IMA-ADPCM. In Godot it's an import option and you'd just normal use the WAV. In ffmpeg you can just add -acodec adpcm_ima_wav.

I bet it will be substantially smaller than FLAC, so if your primary concern is some combination of speed and size it will outperform FLAC in both, while sounding mediocre. But again, if your mix is muddy that really isn't going to matter IMO.

@Calinou
Copy link
Member

Calinou commented Aug 29, 2023

If you need a higher-quality alternative to IMA-ADPCM (still lossy), QOA could be worth considering. The impact on binary size should be minimal, similar to #80768.

@akien-mga
Copy link
Member

For that context, I don't think a GDExtension helps when it's over 30x larger than a built-in implementation.

For the record, that's a known godot-cpp bug which will be solved eventually. godotengine/godot-cpp#1160

We shouldn't hyperfocus on size as the sole deciding factor anyway. 1k or 100k or even a megabyte can totally be justified for a feature that's going to be used by most Godot users. For a niche feature, the size matters but what's a lot more important is the maintenance burden, compilation time, etc. "Death by a thousand cuts" impacts both binary size and compilation time, and the more thirdparty libraries we add, the more we need to be aware of security vulnerabilities reported against them, or even just bugfixes we need to bring downstream.

The actual use case for FLAC doesn't seem to have been well identified yet. I see engineers reasoning about whether it makes sense or not from a size or a decompression time point of view, but I don't see yet sound designers telling us that they're using FLAC in their professional pipeline and would need it in Godot.

@ParadoxV5
Copy link

What roles do audio quality play in Music/Rhythm games? 🤔

@YYF233333
Copy link
Contributor

What roles do audio quality play in Music/Rhythm games? 🤔

Commercial rhythm games typically use ogg just as other games(take a look at arcaea), however community rhythm games definitely need FLAC support as they support import chart pack from outside.

In my opinion audio quality doesn't matter that much, if a beat can only be recognized in lossless format, then it is just too soft to add a key on it. If you just want to listen the music you can always go and download a FLAC version.

@DeeJayLSP
Copy link
Contributor

DeeJayLSP commented Sep 11, 2023

This implementation outputs a glitchy audio if the file has only one channel, and won't play at all if it's 3 or above;

@YuriSizov YuriSizov requested a review from a team September 14, 2023 12:24
@DeeJayLSP
Copy link
Contributor

Coming here two months later just to say: forget anything I said about FLAC for sound effects.

Turns out FFmpeg decodes FLAC with multithreading by default (as phoboslab claims). And I ended up testing exactly like that.

QOA is a better format than FLAC except in quality, and better than IMA-ADPCM except in decoding speed, but both are reasonably good enough.

@YuriSizov
Copy link
Contributor

@DeeJayLSP Should we close this PR then as you've reached a consensus that FLAC support is not valuable in core?

@DeeJayLSP
Copy link
Contributor

For the purpose I was defending, FLAC isn't viable. After all, why use a sound effect in FLAC when you could use Vorbis at a reasonable bitrate to save space and have the same decoding speed?

The other purpose pointed out here was rhythm games where FLAC music might need support, but for a very specific purpose like this it can be easily implemented through a non-core third-party module or a GDExtension (both already exist by the way).

My conclusion is that FLAC as a core module isn't strictly needed.

@YuriSizov
Copy link
Contributor

Okay then. Given the concerns from the audio team members as well, I'm going to close this issue. But I hope to see a GDExtension for FLAC for those who need it 🙂

@YuriSizov YuriSizov closed this Oct 30, 2023
@YuriSizov YuriSizov removed this from the 4.x milestone Oct 30, 2023
@ParadoxV5
Copy link

There are two topics in this PR thread.
The more prominent one is rather whether FLAC is worthy of joining Core and if alternative options are more suitable.
We should rather host this discussion in the proposal – godotengine/godot-proposals#1190. I didn’t read it, just thought the consensus is positive because this PR existed.

That said, for this PR specifically, the implementation isn’t great. Over a hundred KBs, yet it’s still only half-baked.

This implementation outputs a glitchy audio if the file has only one channel, and won't play at all if it's 3 or above;

Even if we deem FLAC Core-worthy, perhaps another better implementation can make this PR obsolete.

@fire
Copy link
Member Author

fire commented Sep 4, 2024

Fixed an issue that caused single channel MP3 files to play badly.

@DeeJayLSP What was the fix?

@DeeJayLSP
Copy link
Contributor

DeeJayLSP commented Sep 4, 2024

@fire drflac_read_pcm_frames_f32 decodes directly to F32 sample data, without caring about the number of channels. And the buffer we're passing to it is always stereo, which means something like this will happen if the audio is mono:

AudioFrame[f1, f2]
AudioFrame[f3, f4]
AudioFrame[f5, f6]
AudioFrame[f7, f8]

When it should be:

AudioFrame[f1, f1]
AudioFrame[f2, f2]
AudioFrame[f3, f3]
AudioFrame[f4, f4]

The fix consists on declaring a fixed-size buffer (let's call it buf_frame), reading 1 frame at a time using that buffer, then manually assign the decoded samples on buf_frame to the corresponding p_buffer index (always get buf_frame[0] for left channel, then perform an operation to find what should be provided to the right channel.

You can essentially do the same as the dr_mp3 implementation, just swap everything to the corresponding dr_flac functions.

Note that unlike minimp3 or dr_mp3, dr_flac has channel limit of 8 instead of 2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for FLAC decoding