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

FL Studio .wav's cannot be read #170

Open
kangalio opened this issue Dec 22, 2022 · 7 comments
Open

FL Studio .wav's cannot be read #170

kangalio opened this issue Dec 22, 2022 · 7 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@kangalio
Copy link

Trying to read music production software FL Studio's built-in sample file "FPC 1 Kick.wav" throws an Unsupported("wav: unsupported wave format") error

Sample file (rename .png to .wav): FPC 1 Kick

Audacity can read this file already

@kangalio
Copy link
Author

Would a PR be accepted which fixes this?

@pdeljanov
Copy link
Owner

Was a bit hard finding information about this, but it looks like it's a WAV file with Vorbis encoded audio.

ffmpeg has a similar issue here that's kinda useful.

No reason why it couldn't be supported, but WavReader may need some rework to support reading encoded data. The changes made to support ADPCM may be enough, but hard to say until it's actually implemented.

If this is something you want to work on, I'll accept a PR for adding this support.

Thanks!

@pdeljanov pdeljanov added enhancement New feature or request help wanted Extra attention is needed labels Jan 13, 2023
@kangalio
Copy link
Author

Interesting. Symphonia currently supports 7 types of .wav formats

// The definition of these format identifiers can be found in mmreg.h of the Microsoft
// Windows Platform SDK.
const WAVE_FORMAT_PCM: u16 = 0x0001;
const WAVE_FORMAT_ADPCM: u16 = 0x0002;
const WAVE_FORMAT_IEEE_FLOAT: u16 = 0x0003;
const WAVE_FORMAT_ALAW: u16 = 0x0006;
const WAVE_FORMAT_MULAW: u16 = 0x0007;
const WAVE_FORMAT_ADPCM_IMA: u16 = 0x0011;
const WAVE_FORMAT_EXTENSIBLE: u16 = 0xfffe;

But the mentioned mmreg.h file has 265 formats. Would Symphonia ideally eventually support them all?

@kangalio
Copy link
Author

kangalio commented Jan 14, 2023

I'm currently trying to work on this. Question: how to get a MediaSourceStream from a ReadBytes in order to plug it in to OggReader::try_new? (Is there a better place for questions like this, like a support channel?)

@pdeljanov
Copy link
Owner

But the mentioned mmreg.h file has 265 formats. Would Symphonia ideally eventually support them all?

Probably not, most are not used anymore or are proprietary codecs with no available specifications. The most likely contenders for inclusion would be the ADPCM codecs since they tend be used in games. I'll likely be leaving these up to contributors though since I don't have any of these files.

I'm currently trying to work on this. Question: how to get a MediaSourceStream from a ReadBytes in order to plug it in to OggReader::try_new?

This wouldn't be correct way to go about this. OGG and WAVE are both distinct container formats so it is not possible to parse a WAVE file as an OGG file.

If you look at the Vorbis specification, it specifies how Vorbis encoded audio data should be packaged in an OGG stream, but there's no specification for how it's packaged in a WAVE file. This Vorbis-in-WAVE format is non-standard. Therefore, some reverse engineering or educated guesses would need to be made on how it's packaged.

I looked at the hex dump of the file and to me it looks like the WAVE DATA chunk contains a single logical OGG stream packaged as per the specification linked above. I imagine there are some limitations placed on the OGG pages and packets to make decoding easier, but hard to know without a large corpus of files or a specification.

You can lift some code from symphonia-format-ogg for experimentation, but it's not possible to use OggReader directly.

(Is there a better place for questions like this, like a support channel?)

Discussions are enabled on this repo., but an issue seems like the right place for this one.

@kangalio
Copy link
Author

When I use a hex editor to remove the bytes up to OggS it seems to become a perfectly OGG Vorbis file and plays in anything I've tried. Suggesting that we can indeed parse a WAVE file as an OGG file. This also matches the FL Studio forum thread I found

Should I still just copy paste all the OGG container code? That seems suboptimal at best

One thing I'm still confused about is the bytes inbetween the WAV signature and the OGG file.
image
As mentioned above, I can strip it straight off, and the remaining cyan part is a perfectly valid .ogg file. But there must be some purpose to the green in-between bytes. Should I just experiment, i.e. change the bytes and re-open the file in FL Studio? Or compare the green bytes of multiple of these ogg-in-wav files against each other?

@pdeljanov
Copy link
Owner

Those bytes are part of the WAVE file format. A WAVE is split up into a tree of chunks. There are many different chunks, some of which are ignored entirely for our use-case, but others contain information about the codec, duration, metadata, and audio data.

The DATA chunk contains the audio data. In this case, it contains the Vorbis audio data, packetized in OGG packets. Tricky thing is, there can be a chunk after the audio data chunk which means it's not possible to consider the remainder of the file as an OGG file.

This also means that simply calling into OggReader is not a workable solution. I am also hesitant to add symphonia-format-ogg as a dependency of symphonia-format-wav. If we want to share some code, then the correct crate to put that shared code in would be symphonia-xiph-utils. However, I also have a similar file that contains MP3 encoded data so that would create a related problem.

The OGG bitstream format is actually pretty simple which is why I suggested some code duplication. It only gets bad if you can stuff complex OGG streams into a WAVE file. It'd be a bit surprising if you could considering WAVE doesn't have the concept of tracks, but without a spec. it's hard to know for sure.

Unfortunately, this is rapidly becoming a very complex and convoluted problem. Given the niche use-case, I'm feeling that this moment may not be the best time for the project to implement this. I'm too short on bandwidth to give this issue the attention and support it needs. :(

The best way forward would likely be for you to implement your own FormatReader that supports your immediate needs. You can register this with the Symphonia format registry and it should work as usual from there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants