WavetablePrep:
Filter:
ddwWavetableSynth/Classes (extension) | Collections > Ordered

WavetablePrep
ExtensionExtension

Preprocess Serum-style wavetable files for reduced-aliasing wavetable synthesis in SC

Description

This class prepares wavetable data from other software for use in SuperCollider.

It is a companion to the pseudo-UGen MultiWtOsc (multi-wavetable oscillator).

Many notable wavetable synthesizers (Serum, Massive etc.) store multi-wavetables in sequential format. If, for instance, one wavetable consists of 2048 samples (this seems fairly common), then "wavetable position" 0 is found in samples 0 - 2047, position 1 in samples 2048 - 4095, position 2 in samples 4096 - 6143 and so on. I have directly observed this format in Serum and a VCV Rack 1.0 wavetable module (XFXWave from Blamsoft, sadly discontinued); I assume then that this is a standard practice.

These synthesizers use oversampling to reduce the aliasing that is inherent in high-rate wavetable playback. SuperCollider does not have an oversampling wavetable oscillator (and I haven't written one). Instead, MultiWtOsc uses multiple versions of each wavetable position, where each version reduces the number of harmonics that are included. Versions at higher indices are safe to play at higher frequencies (though there is always an upper limit). This technique is similar to mipmapping (except reducing frequency-domain content, instead of reducing resolution).

WavetablePrep reads a Serum-style wavetable file, and writes a "mipmapped" wavetable file for MultiWtOsc.

NOTE: At playback time, indexing resolution may be lost if the resulting size exceeds 24 bits of precision = 16777216 sample frames. A 2048-sample wavetable, with 256 positions and 8 frequency maps, comes to 4194304 samples, well within range. Most original wavetable files are likely to be fine. Exceptionally large ones may need to be reduced.

Class Methods

.new

Create an instance of WavetablePrep, and set properties for future processing.

Arguments:

path

Full path to a Serum-style wavetable file. This should be an audio file in the format noted above: 1/ each waveform should be the same length; 2/ the length should be a power of two; 3/ successive "wavetable position" waveforms should be simply concatenated.

wtSize

The number of samples for each waveform. The default, 2048, seems to be a de facto standard.

numMaps

The number of frequency-mapped versions to create.

ratio

The frequency ratio between subsequent versions. The default maps each octave to a different version.

filter

A symbol, to look up a filtering function from *tables. If omitted, \tenPctSlope will be used.

.read

Create a new instance and read immediately from a disk file.

Arguments:

path

Full path to a Serum-style wavetable file. This should be an audio file in the format noted above: 1/ each waveform should be the same length; 2/ the length should be a power of two; 3/ successive "wavetable position" waveforms should be simply concatenated.

wtSize

The number of samples for each waveform. The default, 2048, seems to be a de facto standard.

numMaps

The number of frequency-mapped versions to create.

ratio

The frequency ratio between subsequent versions. The default maps each octave to a different version.

filter

A symbol, to look up a filtering function from *tables. If omitted, \tenPctSlope will be used.

action

A function to evaluate upon completion. The arguments to this function will be: exception (an Exception or Error, or nil upon success), and the WavetablePrep instance itself.

pause

A number of seconds to wait between processing each wavetable-position.

.readFromProcessedFile

Creates a new WavetablePrep instance and populates it from an expanded wavetable file which WavetablePrep had previously written. This allows you to open a GUI, for instance, without reprocessing from the original wavetable. (It should be faster to read an already-processed wavetable matrix than to re-process it.)

Arguments:

path

A full path to a WavetablePrep output file.

wtSize

The number of samples for each waveform. The default, 2048, seems to be a de facto standard.

numMaps

The number of frequency-mapped versions to create.

ratio

The frequency ratio between subsequent versions. The default maps each octave to a different version.

startFrame

The starting position in the file. In normal usage, you would read from the beginning. However, this option allows you to read arbitrary audio as if it were a wavetable matrix, from any position in an audio file.

numFrames

The number of frames to read. Again, normal usage is to read an entire wavetable matrix file. When reading arbitrary audio, this argument can force a smaller result matrix.

.readImage

Convert an image file on disk into a wavetable matrix.

Arguments:

path

Full path to an image file on disk. The format should be one of those supported by Image.

wtSize

The number of samples for each waveform.

numPos

The number of "wavetable positions" to create.

numMaps

The frequency ratio between subsequent versions. The default maps each octave to a different version.

ratio

The frequency ratio between subsequent versions. The default maps each octave to a different version.

valueFunc

A function which accepts a Color object representing one pixel. This function should return a floating point value between 0.0 and 1.0. You can convert the color into the value any way you like. The default uses a standard luminance formula.

filter

A symbol, to look up a filtering function from *tables. If omitted, \tenPctSlope will be used.

.fromImage

Convert an Image object in memory into a wavetable matrix.

NOTE: This method will resize the input Image object, in place. If you need the original Image to be unaffected, make sure to copy it first.

Arguments:

image

An Image object.

wtSize

The number of samples for each waveform.

numPos

The number of "wavetable positions" to create.

numMaps

The frequency ratio between subsequent versions. The default maps each octave to a different version.

ratio

The frequency ratio between subsequent versions. The default maps each octave to a different version.

valueFunc

A function which accepts a Color object representing one pixel. This function should return a floating point value between 0.0 and 1.0. You can convert the color into the value any way you like. The default uses a standard luminance formula.

filter

A symbol, to look up a filtering function from *tables. If omitted, \tenPctSlope will be used.

.filters

A dictionary of functions for frequency-domain filtering the wavetables. Currently two are provided:

You may add to this collection. Follow the models in the class source.

Instance Methods

Input

.read

Read from the previously-set file path.

Note that this operation may take several seconds. It is not suitable to run on stage. If you must run it on stage, you may give a positive value for pause. The entire operation will take longer to complete, but will be less likely to interrupt ongoing scheduled processes.

Arguments:

action

A function to evaluate upon completion. The arguments to this function will be: exception (an Exception or Error, or nil upon success), and the WavetablePrep instance itself.

pause

A number of seconds to wait between processing each wavetable-position.

Returns:

The WavetablePrep instance is returned. Upon completion, the wavetable versions will be available in -tables.

.readFromProcessedFile

Creates a new WavetablePrep instance and populates it from an expanded wavetable file which WavetablePrep had previously written. This allows you to open a GUI, for instance, without reprocessing from the original wavetable. (It should be faster to read an already-processed wavetable matrix than to re-process it.)

This method assumes that the wavetable matrix properties -wtSize, -numMaps and -ratio have already been set within the instance.

Arguments:

path

A full path to a WavetablePrep output file.

startFrame

The starting position in the file. In normal usage, you would read from the beginning. However, this option allows you to read arbitrary audio as if it were a wavetable matrix, from any position in an audio file.

numFrames

The number of frames to read. Again, normal usage is to read an entire wavetable matrix file. When reading arbitrary audio, this argument can force a smaller result matrix.

.readStream

Reads source wave tables from a SoundFile or compatible object. This is useful for calculating source wave tables in memory (using SoundFileStream), and populating a WavetablePrep directly from memory without using a disk file.

Arguments:

file

The SoundFile (you are responsible for opening it, SoundFile: -seek-ing and closing it) or SoundFileStream object.

action

An action function to evaluate upon completion.

pause

The number of seconds to pause after processing one "wavetable position."

.readProcessedStream

Reads a wavetable matrix from a SoundFile or compatible object. This is useful for calculating source wave tables in memory (using SoundFileStream), and populating a WavetablePrep directly from memory without using a disk file.

Arguments:

file

The SoundFile (you are responsible for opening it and SoundFile: -seek-ing) or SoundFileStream object.

numFrames

The number of frames to read. Again, normal usage is to read an entire wavetable matrix file.

.fromImage

Populates this WavetablePrep instance with data from an Image object.

This method assumes that the wavetable matrix properties -wtSize, -numMaps and -ratio have already been set within the instance.

NOTE: This method will resize the input Image object, in place. If you need the original Image to be unaffected, make sure to copy it first.

Arguments:

image

An Image object.

numPos

The number of "wavetable positions" to create.

valueFunc

A function which accepts a Color object representing one pixel. This function should return a floating point value between 0.0 and 1.0. You can convert the color into the value any way you like. The default uses a standard luminance formula.

Output

.write

Write the processed contents into a new file, ready for MultiWtOsc. It will be a floating-point WAV file (because the bandlimiting function may cause the waveform to exceed +/- 1).

Arguments:

outPath

Full path to the file to be written.

.writeStream

Write the processed wavetables to a SoundFile or compatible object. With SoundFileStream, this is useful for in-memory scenarios where you might want to avoid writing a disk file.

Arguments:

file

The SoundFile (you are responsible for opening and closing it) or SoundFileStream object.

Properties

.wtSize

Get or set the wavetable size.

.numMaps

Get or set the number of frequency maps to create.

.path

Get or set the path to the wavetable source file.

.ratio

Get or set the frequency ratio between mapped versions.

.fudgeFactor

Get or set an offset for the frequency boundaries. In general, 0 <= fudgeFactor < 2. A higher value will lose less high-frequency content, but allow more aliasing.

.tables

After a successful -read, this is a two-dimensional array. tables[0] contains the frequency-mapped versions for wavetable position 0, and so on.

.filter

A symbol, to look up a filtering function from *tables. If the symbol does not locate a function, \tenPctSlope will be used.

Other methods

.blendAt

Return a wavetable, interpolated linearly at the intersection of a wavetable position and a frequency map.

Arguments:

wtPos

The wavetable position, clipped to 0 .. (tables.size - 1.001).

freq

The frequency to map.

sr

The sample rate to use for frequency mapping. A higher sample rate will allow a less-filtered wavetable to be used.

Returns:

A Signal containing the interpolated waveform.

.gui

Opens a WavetablePrepGui to display interpolated waveforms.

Arguments:

parent

Optional. Supply a Window or View if you wish to put the interface into an existing GUI context. This can be nil if you either a/ supply bounds (in which case the view will create its own window) or b/ you will put the WavetablePrepGui into a Layout later.

bounds

Optional, if you are using Qt layouts. If not, a Rect should be provided.

.decimate

Produces the mapped versions for an input Signal object containing one waveform.

Arguments:

timeDomainTable

A Signal.

cos

Optional: The Signal: -fftCosTable for FFT processing.

Returns:

An Array of numMaps Signals.

Examples