sfztools / sfizz

SFZ parser and synth c++ library, providing a JACK standalone client
https://sfz.tools/sfizz/
BSD 2-Clause "Simplified" License
401 stars 58 forks source link

Add oscillator subtables #330

Open jpcima opened 4 years ago

jpcima commented 4 years ago

There are some audio formats which permit extraction of multiple wavetables from a single file. It is a starting point to implement multi-wavetable in a way which doesn't yet require SFZ extensions.

In the basic implementation, it's possible to implement the playback as a round robin in the sequence of wavetables.

baconpaul commented 4 years ago

Hey @jpcima

so the only authors on WavSupport.cpp are me (for 98% of it) and @mkruselj for 2 lines. I spoke with @mkruselj and he and I are fine for you to take a copy of that cpp file and use it in a non-GPL3 setting. Or if you want to make it a submodule with an MIT license we can work on that too. It's more an art than a science ... I just got people to send me various wavetables which worked in various synths and plucked apart what I thought they meant.

Pretty sure you would want to eject different data structures anyway so a copy probably makes sense, but zero problem from either of us with an (attributed) copy in a BSD, MIT, Apache, or GPL<3 licensed open source product.

What I really wanted to do was to push non-format block reading code up into libsndfile so I didn't have to parse the wav myself. But libsndfile won't give you non-standard CHUNKs in any way - it just (correctly) ignores them. So had to write that code :(

The WT are much simpler but only surge uses them. Some python code exists https://github.com/surge-synthesizer/surge/tree/main/scripts/wt-tool also to do some relabeling and stuff.

jpcima commented 4 years ago

This is great, thank you to both.

These are familiar, we already deal with 'smpl' chunks to some extent. We made this discovery that flag, ogg, and opus files can contain these very same 'smpl' blocks that riff has, and we have already some code to deal with the libsndfile insufficiency in this regard (for flac).

Do you know if these RIFF blocks apply to wav files only, or these other products will also use them from flac and others?

I have made an implementation of this one some ago, submitted as PR into Andrew Belt's WaveEdit, which does not seem to get any interest there. (but might be of interest for some users)

baconpaul commented 4 years ago

Yeah I really wish Andrew's WaveEdit would put some metadata in the file but he writes with libsndfile - I thought about a PR but realized it would be a bigger lift than I think he would accept. With surge we can have tables from size 32 -> 8192 so some sort of organizing metadata matters. We are also thinking, with surge 1.7.1, of popping up a small gui if you drop a wav file in with no data to ask "do you want to make it a WT vs a one shot".

I do know know if you can load a RIFF FLAC into other tools. I certainly know you couldn't in surge right now!

The author of Serum is pretty active on KVR; I wonder if this is an opportunity for us to all just bite the bullet with a standard? But also: xkcd 927.

jpcima commented 4 years ago

I'll rather deal with existing standards. (unless the new specification has some specific advantages to bring?) Xfer's provides the most interesting feature, with the indication of the spectral interpolation mode. https://www.kvraudio.com/forum/viewtopic.php?p=7266103#p7266103

"do you want to make it a WT vs a one shot"

According to some Cakewalk SFZ documents, their products are detecting a file as wavetable if size is < 3000 frames. it's not subject to the power of 2 size restriction.

Which it reminds me, we lack this feature in current sfizz and the best way to handle this detection is possibly that we make an external piece of code to extract these RIFF chunks independently of sndfile, and of file format. (and with this, a way to deal with these wavetable blocks in a way not entirely tied to the sound loader)

baconpaul commented 4 years ago

Yeah i think that’s right. Outside of libsndfile grab riff chunks and separate the binary implementation from the interpretation. We didn’t do that in surge (and didn’t need to) but if we libraryized it i think that would be what to do

jpcima commented 4 years ago

@baconpaul I've a question on the "cue" one.

0x10 | 4 | Block Start | Byte Offset to sample of First Channel https://sites.google.com/site/musicgapi/technical-documents/wav-file-format#cue

If I'm understanding correctly, the difference of 2 successive cues will produce a result expressed in bytes. WavSupport will use this byte (supposedly) quantity as the length, where it should be frames. Is this not a Surge bug?

Are there some samples of this format to grab somewhere? I found none in the Surge tree.

baconpaul commented 4 years ago

I think that is a bug yes! I will have to dig on my laptop. I didn’t have any open license files with that format, but I did have one that a user loaned to me, but I may not have it.

jpcima commented 4 years ago

May it be the case that your NI files match to the info of this document? https://github.com/perivar/ExtractMassiveWavetables/blob/61d0ae7bbbf493cb535c12da61d03d1f4369a981/WTINFO%20description.txt

There may exist a "SingleWAV=" indication in the sampler-specific part of the 'smpl' block. EDIT actually not in smpl block, it's just concatenated at file end