Wavetable - How to create1 cycle wavetable tutorial w. examples


#16

ANyway you can already set the table siezes dynamically......

Just set denominator for 2 instead of 1. And change the tablesize to 2048.. Then you can play 1024 samples WT in a 2048 samples table.... Use the position to test it:

  1. First test the position with table of 1024 sample size and denominator to 1 and and scan through the 1cycle with the position. with 1024 samplesize wave of course.

  2. Then change the tablesize to 2048 and denominator to 2 and scan though it again with the position.. These two setting sounds EXACTLY identilcal......

But yeah, regarding the Adventure kid samples. I had them already... and they are not all same sample sizes. some are 1024, some are 2048 some are 4096, etc.... So batch converting is still not the best idea for this.. Like Mtyas mention it is better to do it by hand, cause there are many variables that can go wrong, which wil jst leave them useless.

For example a lot of the Serum wavetables you find are morphed wavetables so they actually consist of only very few waves,, like 4-6 waves. These I dont know how to import to Axoloti yet..


#17

from his website

Really, perhaps we are talking about different ones...
Im looking at the AKWF set, these have a a readme which says they are all 600 samples long, and and all Ive looked at are 44.1/16 bit.

perhaps your looking at a different version?
anyway no matter, it was just a passing comment anyway.

I discussed this with Johannes the other day, as I thought it would be 'relatively straightforward',
and his answer was very interesting...
the reason he hadn't done this so far, is due to block sizes on the SD cards, essentially the wave headers offset the real wave data, such that streaming it would be less efficient.

so what we thought was:
a) perhaps have this 'inefficiency' but warning, that raw files are better... the issue with this, is no matter how many times you remind people, they will use wav files as its the easy way :smile:

b) conversion... this is the better way, but more work, provide some kind of conversion mechanism such that when you transfer the files they are converted from wav to raw. this makes more sense since potentially we can then expand the conversion formats (or resampling), and also means its done once, with the powerful cpu of the computer rather than the limited resources of the STM32F4.
this is probably also in line with thinking on package management etc.


#18

ah yes.. Maybe the ones I had was different format :smile: And not sure I actually got them form his site. Myabe some one else already did some conversion on them.. Gonna check it...


#19

Oh, forgot to explain a bit here. The divremc c makes it play only 1 cycle at a time. The 1 cycle length is set by the phasor oscs frequency.

The no interp make sure the position knob only controls position and not the pitch.. the pitch is controlled by the phasor osc... So it is basicly to seperate pitch and position control :smile:

Hope that helps :smile:


#20

Finally finished up my new enclosure and had a go at the wavetable stuff tonight. Seems to work well! I'm still downloading the 1.0.6 patcher (github seems to be throttled on my ISP?) so I have to use the old file browser to add the files for now. :expressionless:

However the bulk import/export functions in audacity seem to be working well for the adventurekid waveforms so far. Importing/exporting 10 at a time is a breeze, so should be able to finish up a batch quickly. I may be truncating the files on playback, but they sound good to me – will have to test accuracy against some other WT player (maybe in max msp?). My enclosure has a 2-digit seven segment display so I'll try to winnow it down to 100 of my favorites and then be able to scroll through them on the synth.

Also interested in the "morph" functions I've seen on Serum and Massive (don't have either myself), I wonder if it'd be possible to build a feature like that into a synth patch. If it's a simple x-fade, it might be as easy as having 2 selectable waveforms and a fade control. Would be great to hook up to an envelope I suspect.

Any thoughts on wavetable synths I should check out for design ideas? Have been meaning to snag the demo of NI massive anyway, but I'm a complete n00b to the wavetable game, so all recommendations are welcome!


#21

Hey @matthewcieplak

Nice. Wavetables are the best :smile: I never use regular oscillators anymore. Only wavetables :smile:

I just checked a few of the adventure kid 1 cycle waves and they are all 600 samples long each and they are 16 bit 44.1khz. That is great. They can be used in different ways in Axoloti:

  1. This is in my opinion the best way.
    Open up Audacity and load up one of the 600 samples long waves.
    Next highlight the whole file and go to effect and choose change speed.
    Change the speed to Axolotis closest table size in SAMPLES. That would be 512 samples. Then you know for a FACT that the file fit perfectly in the table.

  2. This is the easiest way, since you already changed the files to raw and it would be a hassle to go back to Audacity and strecth all one by one. But this is NOT perfect and will definatly create clicks in many situations, cause it is not always 100% precise like first way I suggested.
    The solution is to calcualte how many percentage of the table/alloc the raw file actually fills up.
    You do that this way. For this you HAVE to set tabelsize to be bigger than the file:
    Tablesize = 1024 samples
    .raw adventure kid samplesize = 600 samples

Dividide the .raw files samplesize with tables:
600/1027 = 0,5859375 which is 58,59375 %

You see not precise. This percentage would be rounded to 58,59% in Axoloti. Anyway to set it up this way you would have to connect an attentuator between the phasor osc and the table/play object and set the attenuator to 58.59%

It is a solution, but I wouldnt use it. I would personally go back and change the speed of every single file individually. That way you get the best result. And even better, just make it a habit doing them one by one. Wavetables are very different and for example for especially multi wavetablesl Serums morhped wavetable will not work in axoloti(as for now), cause they basicly only consist of 4-8 waves. So if you try to use a wavetable that was morphed and you are not aware it wont sound right. Also a lot of the wavetable pack out there, the individual files are not same size, length etc. Som there are god reason to go through them manually. It can be a lot of work, but very rewarding when done :wink:

About the morph waves. I believe it can be done with Axoloti as it is now. I already build a wavetable creator patch which you can check out here. Need to do the final work on it before i can share final version with saving included. Anyway, check the patch here and a small video that shows it in action :smile:

But yeah, got a few ideas how to implement morphed waves in a more controlled fashion than the one from the link. WOuld like to make a version which moprhes a few waves at a time. For example start out as a saw wave and moprh into a sine wave. Actually think it can be done with the one I posed already now that I think of it.


#22

mhehehehehe, this is sweet:
1. download AKWF waveforms (4358 different waveforms), "advanced renamer" and audacity v2 (v1 crashes!)

  1. throw all the AKWF waveforms in the same map (they come in different maps) and rename them using Advanced Renamer to W0000 to W4358.

  2. Load the waveforms into audacity (my computer only handles 500 at a time, nope, re-edit (again), you'll probably have to restart the computer after around 1000 files to clear the cache....sighs)

  3. set audacity internal rate to 48K

  4. resample all waveforms to 48K (this may take quite a while)

  5. adjust the playback speed: percentage= -36.23 for 1024 samples length

  6. go to "export multiple", select "other uncompressed files" and set to Raw (headerless), signed 16-bit-PCM

  7. now you'll need to press down the enter button a couple of minutes, to press "yes" for each file repeatedly (when closing in on the last file, go easy, otherwise it might restart the whole saving process and you'll need to go around one more time haha)

now you've got 4358 raw waveforms to build yourself a massive wavetable oscillator :stuck_out_tongue:
Use the index string module, enter W0, W1, W2, W3 or W4 in the name, or load 5 index string modules with W0 to W4 as their names and use a mux to select one of them, Raw as extension and use the index to select any of the waveforms (000 to 999). Remember though.. W4 "only" has 358 samples under it's hood.. :wink:

Another edit:
I've just send all the waveforms to "Adventure Kid", so he can post them on his website. So just wait a while and you can just download them instead of having them all manually redo them yourself (I don't think I'm allowed to upload them myself)


#23

Some remarks:
* With a one-cycle wavetable, the sample rate of the wave is irrelevant
* I strongly suspect sample rate conversion in audacity (and other similar software) assumes silence before and after the wave, while wavetables should be assumed cyclic.
* The right way change the length of wavetables is going through (unwindowed) fourier transform. A tool to do this is, is with a small script in numpy, gnu octave, or Matlab (or anything similar), but I currently have no time to dedicate to this.
* there are 2 interpretations of a wavetable: bandwidth limited or assuming all of its samples are converted by a pitch-synchronous DAC.
* there are many tricks to improve the properties of wavetable playback: https://www.dafx12.york.ac.uk/papers/dafx12_submission_69.pdf


#24

Cool, thanks @johannes :smile:

I am pretty sure that Serum uses windowed fourier transform. I know the opposite of what you mention. But if you import a file into Serum and export it again, it has got fade in/outs on each wave. This makes sure all indexing is pretty good and make sure that there is a lot less clicks that just importing a wav(.raw) into axoloti. That would create a lot more clicks. I made some wavetable from movie clips, with a lot going on, that works pretty well this way.

I kind of thought I covered most aspects of wavetables by now. But will defiantly look into the suggestions you have :smile:


#25

If you want to extract a single-period wavetable from a wave, window functions are useful.
However when re-processing a single-period wavetable into another single-period wavetable, a window function should not be used.


#27

I'm surprised with all the talk about how much work it is to convert found single cycle waveforms into proper wave tables that nobody has shared their results here.

Lots of talk, but no action? Or maybe people want others to have to do the frustrating work too?

In the mean time I've just found another waveform editor called AudioTerm

Look for the zip file in a link on that page.
If you can't find it - v2.27 is right here


#28

@adnauseam

I think some people in here are all ready sharing A LOT of stuff, like information, objects, subpatches, etc. And some people dont share anything, which is also okay...... But just because this is an open source platform and an open source community doesnt mean that you have to share everything you make.

If you want some wavetables there are many ways to get them;

  1. Make them yourself.
  2. Buy some.
  3. Find free ones.
  4. Ask others(kindly?).

There are many options. But like most things in life, putting an effort into what you want to accomplish does give great satisfaction :wink:

Waveterm... To me no good. I prefer to use Serum for editing and combining waves.


#29

@jaffasplaffa

In no way was I implying that I expect others to share with everyone or give us their finished wavetable, I was simply expressing my surprise.

I hadn't heard of Serum. Given that you own it's great that you can use it for your editing purposes. We can expect most won't want to pay almost $200 for wavetable software given the other free options.

I haven't tried AudioTerm yet but I understand it exports to WAV.

Cheers


#30

No worries :wink:

You dont have to pay anything, you can make them without Serum. It is just a lot more work. Allthough Serum is THET BEST. It is a VSTI which uses wavetables.... BUT the cool thinkg about serum is that you can drop 128 single waveforms into serum and it combines tthe waves into a wavetable of 128 waves. It adapts sizes and everything. Then you export the wavetable from Serum, convert it to raw and you are good to go :wink:

I am just sayin Serum is the easiest way to do it. But there are other ways which yuo can use for free.

That said, I know someone shared a smal bank with some allready converted waves in here somewhere... Did you find it?


#31

audioterm is pretty powerful, does more than the likes of serum, but is not the most obvious to use :wink:

Id actually recommend Tone2 Icarus over Serum for wavetable editing, its absolutely fantastic, allowing you to do things all sorts of crazy things... and can output individual waveforms or wavetables like serum.
(that said, i only used serum for a bit, so it whist i preferred Icarus, it may have some advantages that i didnt spot)


#32

Yeah it might do more....... But not as easy to use as serum. Actually I dont even think it does more. In Serum you can basically just drag in 128 waves and export as wav and you have got a wavetable. PERFECT fit in first shot... Audioterm doesnt do anything like that...

My recommendation goes to Serum.


#33

I came across this little wavetable generator in Python. Maybe someone here uses it already?

I quickly tried only some very basic functions, but it seems pretty okay. I'm more familiar with Python for maths (numpy, scipy), so it'll be nice to use those tools also to create wavetables. The module allows to set the sample size and rate. It can write to a .wav file, which is fine. But it would be nice to have it write to a headerless .raw straight away for use with Axoloti. Anyone who knows a Python function for that to be added?


#34

I am surprised to see no mention of libSox for audio conversion on Linux in this thread - it has utilities that can convert from wave to RAW, do sample rate conversion, etc. from the command line, so it can be scripted for batch processing. Full disclosure: I have not tried it myself for wave tables, although I probably will soon.

To the current point, it has python bindings: https://pypi.org/project/pysox/

Regards,
John


#35

Hi John, thanks. I use sox now to convert the files, which is already much quicker than putting them through Audacity. It would still be nice to write the output directly to .raw within the script. I'll check out pysox for that.

osc_gen is very easy to use. Here's a simple script to generate a wavetable that morphs between sine and triangle waves with 1024 samples per wave. This works fine with Axoloti.

from osc_gen import sig
from osc_gen import wavetable
from osc_gen import dsp

sg = sig.SigGen(num_points=1024)
wt = wavetable.WaveTable(16)
wt.waves = sig.morph((sg.sin(), sg.tri()),16)
wt.to_wav('osc_sin_tri.wav', samplerate=48000)

And then with sox:

sox osc_sin_tri.wav -r 48000 -c 1 osc_sin_tri.raw

#36

Nice find @joagogatao. I've written a Python script using osc_gen, pysoundfile, and pysox, that allows you to choose any two wave files, resizes them to any power of two that you wish, morphs between them over the desired number of wavetable slots (again, any power of two), and outputs a .raw wavetable. Here it is:

#wtgen.py, Jonathan Murphy 2020

from tkinter import Tk
from tkinter.filedialog import askopenfilename
from tkinter.filedialog import askdirectory
import soundfile as sf
import sox
from osc_gen import sig
from osc_gen import wavetable
from osc_gen import dsp

Tk().withdraw()

def is_power_of_two(n):
    return (n != 0) and (n & (n-1) == 0)

setup = input("1024 samples per wave, 64 slots per wavetable. Okay? y/n:")

if setup == "y":
    pts = 1024
    slts = 64
elif setup == "n":
    pts = int(input("How many samples per wave? Enter a power of two:"))
    if is_power_of_two(pts):
        print(pts, "Samples")
    else:
        print(pts, "Is not a power of 2!")
    
    slts = int(input("How many slots per wavetable? Enter a power of two:"))
    if is_power_of_two(slts):
        print(slts, "Slots")
    else:
        print(slts, "Is not a power of 2!")
else:
    print("Please enter y or n")
    
answer1 = input("Are you ready to select your first waveform? Enter y or n:")
if answer1 == "y":
    file1 = askopenfilename(filetypes=[("Wave Files", "*.wav")])
    f1 = sf.SoundFile(file1)
    #print('samples = {}'.format(len(f1)))
    if len(f1) == pts:
        print("File size matches!")
    else: 
        rat1 = len(f1) / pts
        #print('ratio = {}'.format(rat))
        tfm = sox.Transformer()
        tfm.speed(rat1)
        data, samplerate = sf.read(file1)
        new_data = tfm.build_array(input_array=data, sample_rate_in=f1.samplerate)
        #tfm.build_file(input_array=data, sample_rate_in=f1.samplerate, output_filepath=outputfilename)
        #tfm.build_file(file1, outputfilename)      
    #print('sample rate = {}'.format(f1.samplerate))
    #print('seconds = {}'.format(len(f1) / f1.samplerate))
elif answer1 == "n":
    print("That's a shame!")
    exit()
else:
    print("Please enter y or n")
    
answer2 = input("Are you ready to select your second waveform? Enter y or n:")
if answer2 == "y":
    file2 = askopenfilename(filetypes=[("Wave Files", "*.wav")])
    f2 = sf.SoundFile(file2)
    if len(f2) == pts:
        print("File size matches!")
    else: 
        rat2 = len(f2) / pts
        tfm2 = sox.Transformer()
        tfm2.speed(rat2)
        data2, samplerate2 = sf.read(file2)
        new_data_2 = tfm.build_array(input_array=data2, sample_rate_in=f1.samplerate)
elif answer2 == "n":
    print("That's a shame!")
    exit()
else:
    print("Please enter y or n")

answer3 = input("Are you ready to select your output directory? Enter y or n:")
if answer3 == "y":
    output_dir = askdirectory()
    print(output_dir)
    outputfilename = input("Enter a filename for your wavetable:")
    slash = "/"
    filetype = ".raw"
    outputfilename = output_dir + slash + outputfilename + filetype
    print(outputfilename)
    sg = sig.SigGen(num_points=pts)
    wt = wavetable.WaveTable(slts)
    wt.waves = sig.morph((sg.arb(new_data), sg.arb(new_data_2)), slts)
    sf.write(outputfilename, wt.waves, f1.samplerate, 'PCM_16')
elif answer3 == "n":
    print("That's really a shame!")
    exit()
else:
    print("Please enter y or n")