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

Support wavetables with more than 1024 samples/frame #461

Closed
mkruselj opened this issue Feb 2, 2019 · 31 comments
Closed

Support wavetables with more than 1024 samples/frame #461

mkruselj opened this issue Feb 2, 2019 · 31 comments
Milestone

Comments

@mkruselj
Copy link
Collaborator

mkruselj commented Feb 2, 2019

Most recent wavetable synths (u-he Hive, Serum, Kontakt 6's wavetable engine) support wavetables with 2048 samples/frame, whereas Surge goes up to 1024. It might be a good idea to support wavetables with more than that. Say up to 8192 samples.

@theofficialajyoung
Copy link

As requested via this comment on issue #872, Here is an example file of a Serum wavetable.

Inside the Zip are 3 things.

  1. Wavetable.wav - The wavetable file that Serum reads.
  2. Wavetable - Individual Frames - a folder containing the individual waves in the wavetable as exported from Serum. 32-bit Mono WAV at 44.1khz, 2048 Samples each.
  3. Wavetable Sound E2.mp3 a recording of scanning through the wavetable. Played on an E2 (midi note 28) for 4 seconds.

Wavetable Example.zip

@baconpaul
Copy link
Collaborator

Thank you very much!

@baconpaul
Copy link
Collaborator

Oh now that I have dynamic memory allocation this should be entirely doable with .wt files. Let me tag this for 1.6.2 and I'll do it this summer.

@baconpaul baconpaul modified the milestones: 1.6.n, 1.6.2 Jun 16, 2019
@baconpaul
Copy link
Collaborator

So this is notes to myself more than anything else

  1. I downloaded the "all the free serum waveforms from reddit" pack https://www.reddit.com/r/edmproduction/comments/2jhew1/1700_waveforms_for_serums_wavetable_download_link/
  2. I also downloaded your Wavetable.wav

Basically it seems Serum uses non-standard RIFF chunks to indicate looping and so on. Those chunks have two flavors

  1. Flavor one is the smpl chunk. A couple of the reddit ones I tried have that. Luckily our surge code has that laid out in Sample.h but reads it using the windows only mmio code. But we can change that to be binary reads if we need to without problem and grab the data on mac and linux. That would mean we could open the .wav sample files

  2. There's a clm chunk. That's 48 bytes long - sounds like 12 longs to me. Not sure what that is yet. Notably the example here has a clm but no smpl.

My raw python reader to decode is on my branch expanded-wt-461

So seems this is integrally linked with #198 also - namely once I know how to parse these serum wav files I will end up using basically raw binary readers I write myself, since libsndfile doesn't read other chunks and neither does windows (hence the mmio) even though macOS sndfile api will. So probably just end up writing code which does it all with ::read to be portable.

If I can figure out what's in that clm chunk of course. Google google google...

@baconpaul
Copy link
Collaborator

baconpaul commented Aug 5, 2019

The CLM block has content which looks like this

b'<i>2048 00000000 wavetable (www.xferrecords.com)data'

or

'<i>2048 11000000 wavetable (Audio-Term)\x00\x00\x00\x00\x00\x00\x00\x00\x00data'

Wonder what that string of binary means up front. Probably something about the size of the loop in the wavetable.

Notably the Wavetable.wav file here contains no block saying anything about the size of the sub-samples other than the CLM chunk. So you get a standard wav fmt chunk, you get the clm chunk shown above, and then you get 2MB of PCM data. How you break that up must be described by that clm block somehow.

@baconpaul
Copy link
Collaborator

baconpaul added a commit to baconpaul/surge that referenced this issue Aug 6, 2019
This diff supports WAV file in several important ways

1. Read WAV file portably so mac and linux get them
2. Allow direct open of a wav file so you don't have to move them
   to documents/surge
3. Reliably support the information in the smpl block to allow
   sampler wave files to be wavetables
4. Support the Serum 'clm ' block meaning Serum files work
5. Increase the surge max wavetable size to 4096 and have that
   interact properly with dynamic memory management.

I am going to tag these issues as "addresses" rather than "closes" for
some of them since we want some testing, but I think this gets us
the path to wav done except for 511 and 509.

Addresses surge-synthesizer#461
Addresses surge-synthesizer#835
Addresses surge-synthesizer#198
Addresses surge-synthesizer#509
baconpaul added a commit to baconpaul/surge that referenced this issue Aug 6, 2019
This diff supports WAV file in several important ways

1. Read WAV file portably so mac and linux get them
2. Allow direct open of a wav file so you don't have to move them
   to documents/surge
3. Reliably support the information in the smpl block to allow
   sampler wave files to be wavetables
4. Support the Serum 'clm ' block meaning Serum files work
5. Increase the surge max wavetable size to 4096 and have that
   interact properly with dynamic memory management.

I am going to tag these issues as "addresses" rather than "closes" for
some of them since we want some testing, but I think this gets us
the path to wav done except for 511 and 509.

Addresses surge-synthesizer#461
Addresses surge-synthesizer#835
Addresses surge-synthesizer#198
Addresses surge-synthesizer#509
baconpaul added a commit that referenced this issue Aug 6, 2019
This diff supports WAV file in several important ways

1. Read WAV file portably so mac and linux get them
2. Allow direct open of a wav file so you don't have to move them
   to documents/surge
3. Reliably support the information in the smpl block to allow
   sampler wave files to be wavetables
4. Support the Serum 'clm ' block meaning Serum files work
5. Increase the surge max wavetable size to 4096 and have that
   interact properly with dynamic memory management.

I am going to tag these issues as "addresses" rather than "closes" for
some of them since we want some testing, but I think this gets us
the path to wav done except for 511 and 509.

Addresses #461
Addresses #835
Addresses #198
Addresses #509
@baconpaul
Copy link
Collaborator

Just an update: I just merged a change which reads .wav files with serum extensions properly on all platforms, including the one you shared here. The nightly should be available in an hour or so. Any testing greatly appreciated!

@theofficialajyoung
Copy link

Oh that's some exciting news! I'll test the nightly once it's up.

@theofficialajyoung
Copy link

Currently I am getting an error saying "File is not a standard RIFF/WAVE file" with anything I try, and it fails to import. I am currently just testing standard Serum Wavetables, including both Factory ones and ones I've created myself.

Attached is a table that is freshly exported from Serum, but does not import.

@baconpaul
Copy link
Collaborator

Yeah sorry! Just saw that on slack too. Have a fix coming in right now.

(The windows optimizer was re-ordering an operation validly that made that test fail because my code was wrong-in-a-way-that-worked-on-mac and I tested in windows only on the second to last change).

Another nightly in about an hour. Apologize for the noise.

@theofficialajyoung
Copy link

Haha not a problem. I'm happy for the noise, I've been excited for this for a while.

@baconpaul
Copy link
Collaborator

Great. Well I just merged the pull request. Was a simple change. The nightlies usually take 30-45 minutes to get to the website. If you grab a nightly which is today and has hash 721bfa2 in the name you have the new one. Very interested if it works for you generally once this dumb step 0 bug is gone. Thanks!

@baconpaul
Copy link
Collaborator

New nightly up

@theofficialajyoung
Copy link

Been testing the nightly for about half an hour, and on preliminary inspection: it works!! Pretty much anything exported from Serum works flawlessly. You can't believe how excited I am. Having a Free, Open-Source synth with the ability to load custom wavetables is incredible.

Thank you!

Now, a Couple of cleanup notes:

I purposely tried to load things that weren't Serum wavetables, and the results were mixed.

Case 1: When loading most .wav files that are NOT Serum wavetables, Surge crashes, and brings down Reaper too. No error message, just hard crash to the desktop. This is the most common case.

Case 2: Occasionally I've come across a file that when attempting to load it, brings up the following error message:

"Sorry we can only read power of 2 wavetables right now but sample support coming soon!q"
(yes, the q is in the error message lol).

Surge's oscillator then shows (Patch Sample) as the displayed wavetable name. The only sound it makes is a click when played. Important to note is that it clears whatever wavetable was there previously. I would expect that an error would keep the current wavetable.

Attached is an example of a file that triggers case 2.
AdditivMix I.zip

^That is an export/rip of one of the original NI Massive wavetables, before it was run through Serum and re-saved. This one and a handful of others trigger case 2 consistently, although other wavetables in the set just crash Surge.

Case 2 is also triggered by all of the single-cycle waveforms in the Adventure Kid (AKWF) set (at least the ones I've tested, there's a lot. Those are found here:
https://www.adventurekid.se/akrt/waveforms/adventure-kid-waveforms/

@baconpaul
Copy link
Collaborator

Super thanks for the detailed feedback. I will look in the next day or so!

@baconpaul
Copy link
Collaborator

Ahh those adventurekid sample sets are all 600 sample long cycles (he sampled everything at “D2+2” to get to 600). For a couple of reasons, surge assumes wavetables align on power of 2 boundaries. Breaking that is hard but since I’m in this code anyway, no reason I couldn’t do a resampling at load time to the nearest higher power of 2 on load time using a good resampler (probably like https://en.m.wikipedia.org/wiki/Lanczos_resampling). That’s a bit more code but I will keep this issue open to track that.

And of course the crashes shouldnt’ crash. I bet I just freak out and abort if I don’t have any loop data in the wav header at all.

And the error messages shouldn’t have random “q” characters in them either. LOL! Just saw that.

@baconpaul
Copy link
Collaborator

Alright I just took a look at that AdditiveNative1.wav file. I have a few questions

  1. What is the structure that file is supposed to have? it has 8192 bytes of data (so 4096 samples of int16 great
  2. It has an smpl block which says there is one loop point.
  3. the 'smpl' block has one sample in it which says the start and end point of the loop is at 4096

It looks to me a bit like this wav file has an invalid smpl block (or at least non-standard). Entry one of the smpl is '255' but that is supposedly a manufacturer specific type.

So when you convert this properly into serum here's my questions

  1. Do you get 1 table of 4096, 2 tables of 2048 samples or do you get 16 tables (either of side 255 or 2048)?
  2. Do you have one or two other similarly generated wave files so I can compare?

Thank you!

@baconpaul
Copy link
Collaborator

Oh and (duh me for not trying this) opening the .wav in audacity makes it clear that the intent is 4 tables of 1024 blocks.

Let me dig into the 'cue' block which the data format has. Maybe the answer is there...

@baconpaul
Copy link
Collaborator

baconpaul commented Aug 6, 2019

Yeah sorry to answer my own question. That file comes through the cue segment which inserts queues at 0, 1024, 2048, and 3072. All clear. I can support that format information.

baconpaul added a commit to baconpaul/surge that referenced this issue Aug 6, 2019
1. Support a `cue ` block of metadata as indicating loop points
   if the loop points are regular. Apparently some NI files have
   this format

2. Generally clean up error reporting with
   - cleaner error messages
   - don't reset the wavetable if we don't have a wavetable
   - don't crash if we don't have a loop

Addresses surge-synthesizer#461
baconpaul added a commit to baconpaul/surge that referenced this issue Aug 6, 2019
1. Support a `cue ` block of metadata as indicating loop points
   if the loop points are regular. Apparently some NI files have
   this format

2. Generally clean up error reporting with cleaner reporting

3. Support .wav files with no loop data by correctly configuring
   them as 1024 window single shot samples which load properly
   into the oscillator.

Addresses surge-synthesizer#461
Closes surge-synthesizer#511
baconpaul added a commit to baconpaul/surge that referenced this issue Aug 6, 2019
1. Support a `cue ` block of metadata as indicating loop points
   if the loop points are regular. Apparently some NI files have
   this format

2. Generally clean up error reporting with cleaner reporting

3. Support .wav files with no loop data by correctly configuring
   them as 1024 window single shot samples which load properly
   into the oscillator.

4. Allow .wav as well as .wt files to come through the drag n drop
   path (which only works on windows right now)

Addresses surge-synthesizer#461
Closes surge-synthesizer#511

sq
baconpaul added a commit that referenced this issue Aug 6, 2019
1. Support a `cue ` block of metadata as indicating loop points
   if the loop points are regular. Apparently some NI files have
   this format

2. Generally clean up error reporting with cleaner reporting

3. Support .wav files with no loop data by correctly configuring
   them as 1024 window single shot samples which load properly
   into the oscillator.

4. Allow .wav as well as .wt files to come through the drag n drop
   path (which only works on windows right now)

Addresses #461
Closes #511
@baconpaul
Copy link
Collaborator

OK @theofficialajyoung I just pushed a change which fixes all the issues you posted, and reinstates the .wav file as single shot working properly (which hasn't really worked since 1.5.0). New nightly is building now.

@baconpaul
Copy link
Collaborator

New nightly up!

@theofficialajyoung
Copy link

Nice! I'll get to testing.

Clarification on that Additive wavetable:
I don't actually know how that was created. It is a table from Native Instruments Massive, which doesn't store its wavetables as WAV files. That comes from an old pack where community members basically cracked open Massive's resource file to get the raw Wavetables.

I almost guarantee you'll never see that type of file structure/format in actual use, as the Massive Wavetables were converted to Serum-style years ago and that's what everyone uses instead. I just included it as an example of "Oh hey, here's a file that Surge does something weird with".

@baconpaul
Copy link
Collaborator

Ha. Well if I do ever see that particularly weird form of loop marker again, I'll read it fine. Seems to make sense to me anyway. But appreciate the context. Look forward to hearing how testing goes. Appreciate the clear feedback - thank you. Good bug reports make good software!

@theofficialajyoung
Copy link

theofficialajyoung commented Aug 6, 2019

Thanks! It's looking good so far, no crashes yet! I'll let you know if I encounter anything.

The sample import is cool for WAV files that aren't tables. It's unfortunate that Stereo files don't work though, as that's what most sample packs are. It makes sense though, as Surge's audio path isn't true stereo.

(EDIT: It feels like it should almost be it's own oscillator type, outside of Wavetable. thoughts?)

I've actually been thinking lately of writing up a feature request for a fully stereo signal path. The "Wide" filter routing is nice, but I find myself wishing to be able to use the other filter routings while still having stereo information. Currently there's no way to use dual/parallel filter routing except in mono.

@theofficialajyoung
Copy link

Also, just as a follow up, here's some formats you may actually encounter. Attached is a Wavetable in WAV format from each of the other Wavetable Synths I own: Hive 2, Dune 3, and Rapid.

Synth Wavetable Examples.zip

@baconpaul
Copy link
Collaborator

Thank you. I'll run those through the system and see what happens!

Oh don't know if you saw: Drag n Drop is back for wav files also. Just drag a .wav onto the picture of the oscillator and it will load. May be faster than the menu. (Should work on windows but only tested on mac tbh)

@theofficialajyoung
Copy link

It does indeed work!

@baconpaul
Copy link
Collaborator

OK of these three

  1. The DUNE one is just a straight wav file with no metadata at all. Nothing Surge can do to tell that from a wave intended as a sample :(

  2. The DUNE one has a chunk called 'uhWT' which I suspect will contain some data but I am ignoring

  3. The Rapid one has a 'smpl' block but it doesn't seem to contain what I expect

Super useful. I bet I can get at least some of these working. Thank you.

@theofficialajyoung
Copy link

Good to know! Dune is the only one of the 3 that has a wavetable editor to make custom wavetables, so that would be the only one commonly encountered. The other 2 are mostly "hey, maybe some crazy person would try this".

As far as Dune goes, the synth doesn't have sampling abilities, and I assume just goes "don't put anything that isn't the expected format in this folder". Probably doesn't even bother with headers of its wavetables.

@baconpaul
Copy link
Collaborator

Alright literally nothing to be done with the DUNE one; but the HIVe and RAPID ones I was able to load and based on metadata choose a reasonable default guess as to what they mean.

Getting a PR in now. Would appreciate more testing for course. If the CI builds probably another hour to the nightly.

Yeah the DUNE comment makes sense. I suppose I could add an "Open wav as 2048 wavetable" option which forces the format. Since surge does single shot and wavetables it relies on the file to indicate which is which. If I had a better UI framework than VSTGUI I would write a proper importer of course. But I don't...

@baconpaul
Copy link
Collaborator

OK so I'm going to go ahead a close this issue - I think the current WAV support is pretty robust. I'm sure we'll find bugs but let me add new issues for those as we go as opposed to just splatting this long one which is basically finished.

@theofficialajyoung thank you very very much for both the testing and the .wav samples. They were critical in getting this feature put together. Greatly appreciated.

Also: I fixed some more wav bugs which are especially annoying - including never closing the wav file (!!) - so you want to upgrade to the latest nightly if you have an older nightly on your system.

Thanks again

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

No branches or pull requests

4 participants