Class WaveSynth
waveDataList.
WaveSynth is organized around properties, such as gain (i.e. loudness or brightness)
and gamma (a sort of contrast setting), and data objects. The data objects include a
a bitmap, mapImage, that is a Processing PImage instance for the image representation
of the WaveSynth, a PixelAudioMapper that allows the WaveSynth to mediate between audio
data and image data, arrays for the WaveSynth's audio signal and the image data ordered
by the PixelAudioMapper signal path, and an array of WaveData objects, waveDataList,
that holds the individual sine wave components of the WaveSynth with their frequency,
amplitude, phase, and other properties. There are also a series of properties concerned
with animation and video output.
When a WaveSynth is used to produce color patterns, each WaveData object in the waveDataList
controls a color. The colors of the various WaveData objects are added together, much
as the audio sine waves are to produce audio, with the brightness of each color determined
by the amplitude of the controlling sine wave.
The WaveSynthEditor example code
provides a graphical user interface for editing the WaveSynth properties and the individual
WaveData objects. Experiment with it to get an idea of what WaveSynth can do to
produce patterns and additive audio synth waveforms.
Gamma and histogram scaling are intended primarily for still-image grading and offline rendering. For realtime animation, prefer adjusting operator amplitudes and DC offsets to control brightness/contrast, and leave gamma = 1.0 and isScaleHisto = false for best performance.
-
Field Summary
FieldsModifier and TypeFieldDescriptionprivate float[]Pre-split color channel B for active waves (first activeCount entries valid).private float[]Pre-split color channel G for active waves (first activeCount entries valid).private float[]Pre-split color channel R for active waves (first activeCount entries valid).private intNumber of active waves in the current frame (length of valid entries in activeWaves).private WaveData[]Active (unmuted, non-suspended) waves for current frame.private float[]Weights just for active waves (first activeCount entries valid).intDefault number of animation stepsfloat[]Array of audio signal values corresponding to colorSignalint[]Array of color values for the audio signalcomments for JSON fileintThe length of the audio and image pixeldata, w * hfloatGain factor for audio and color signalfloatGamma correction factorint[]Precomputed gamma tableprivate intThe height of the imageintThe high value for histogram scalingintThe low value for histogram scaling(package private) booleanWhether to render the audio signalbooleanWhether to scale the histogramprocessing.core.PImageThe image generated by the WaveSynthfloatthe increment in phase over the image pixels, typically TWO_PI / image sizeThe PixelAudioMapper instance used to map audio signals to pixel valuesintThe size of the imageint[]array of color values for mask, especially useful when it is constantfloatNoisiness factor for frequency modulation, left for future developmentfloat[]Array of rendered signal valuesfloatThe sampling frequency, the number of samples read in one second of sound.intCurrent animation stepintStop animation at this stepbooleanWhether to use the gamma table for correction, or compute on the fly.Video filename as stored in JSON data, used for outputintVideo frame rate as stored in JSON data, often set externallyprivate intThe width of the imageint[]array of colors associated with the WaveData operatorsList of WaveData objectsfloat[]array of amplitudes associated with the WaveData operatorsfloatoffset for normailzing signal, see renderFrame methodfloatscaling factor for normalizing signal, see renderFrame method -
Constructor Summary
ConstructorsConstructorDescriptionWaveSynth(PixelAudioMapper mapper) Convenience constructor for WaveSynth that initializes with a default list of WaveData objects.WaveSynth(PixelAudioMapper mapper, ArrayList<WaveData> wdList) Preferred constructor for WaveSynth. -
Method Summary
Modifier and TypeMethodDescriptionclone()Creates a deep copy of this WaveSynth instance.intfloatgetGain()floatgetGamma()intstatic int[]getHistoBounds(int[] source) Calculate the histogram bounds (minimum and maximum pixel values) for a given array of pixel values.intintfloatfloatintgetStep()intgetStop()intintgetWidth()booleanChecks if audio rendering is enabled.booleanfloatnoiseAt(int x, int y) Experimental method, for future use.static float[]normalize(float[] sig) Normalize an array of float values to a limit of 1.0f.static float[]normalize(float[] sig, float limit) Normalize an array of float values to a specified limit.voidLegacy code: set up mapImage for editing, load colorSignal, set mapInc.Initializes a list of WaveData for use by a WaveSynth.private voidRebuilds the list of active (unmuted, non-suspended) waves and pre-splits their colors into RGB channels.float[]renderAudio(int frame) Render the audio signal for a given frame, returning an array of float values representing the audio signal.float[]renderAudio(int frame, float limit) Render the audio signal for a given frame, returning an array of float values representing the normalized audio signal.float[]renderAudioRaw(int frame) Render the raw audio signal for a given frame, returning an array of float values representing the audio signal.processing.core.PImagerenderFrame(int frame) Loop to render all the pixels in a frame.intrenderPixel(int frame, int pos, ArrayList<WaveData> wdList) Render one pixel, return its RGB value.voidsetAnimSteps(int animSteps) voidsetComments(String comments) voidsetGain(float gain) voidsetGamma(float gamma) voidsetHistoHigh(int histoHigh) voidsetHistoLow(int histoLow) voidsetMapper(PixelAudioMapper mapper) Sets the PixelAudioMapper for this WaveSynth and initializes associated properties and data structures.voidsetNoiseiness(float noiseiness) voidsetRenderAudio(boolean isRenderAudio) Sets the audio rendering flag.voidsetSampleRate(float newSampleRate) voidsetScaleHisto(boolean isScaleHisto) voidsetStep(int step) voidsetStop(int stop) voidsetVideoFilename(String videoFilename) voidsetVideoFrameRate(int videoFrameRate) voidsetWaveData(ArrayList<WaveData> wdList) Sets the list of WaveData objects for this WaveSynth.voidsetWaveDataList(ArrayList<WaveData> waveDataList) static int[]stretch(int[] source, int low, int high) Apply a linear stretch to an array of pixel values based on specified low and high bounds.toString()Returns a string representation of this WaveSynth instance.voidUpdates the wave colors based on the current list of WaveData objects.intweightedColor(int[] colors, float[] weights) Calculate the weighted color for a pixel based on the colors and weights of the active waves.private intweightedColorActive(float[] weights, int count) Optimized weighted color for the current active waves.
-
Field Details
-
mapper
The PixelAudioMapper instance used to map audio signals to pixel values -
mapImage
public processing.core.PImage mapImageThe image generated by the WaveSynth -
colorSignal
public int[] colorSignalArray of color values for the audio signal -
audioSignal
public float[] audioSignalArray of audio signal values corresponding to colorSignal -
renderSignal
public float[] renderSignalArray of rendered signal values -
waveDataList
List of WaveData objects -
isRenderAudio
boolean isRenderAudioWhether to render the audio signal -
w
private int wThe width of the image -
h
private int hThe height of the image -
mapSize
public int mapSizeThe size of the image -
dataLength
public int dataLengthThe length of the audio and image pixeldata, w * h -
gain
public float gainGain factor for audio and color signal -
gamma
public float gammaGamma correction factor -
gammaTable
public int[] gammaTablePrecomputed gamma table -
useGammaTable
public boolean useGammaTableWhether to use the gamma table for correction, or compute on the fly. -
isScaleHisto
public boolean isScaleHistoWhether to scale the histogram -
histoLow
public int histoLowThe low value for histogram scaling -
histoHigh
public int histoHighThe high value for histogram scaling -
animSteps
public int animStepsDefault number of animation steps -
step
public int stepCurrent animation step -
stop
public int stopStop animation at this step -
noisiness
public float noisinessNoisiness factor for frequency modulation, left for future development -
comments
comments for JSON file -
sampleRate
public float sampleRateThe sampling frequency, the number of samples read in one second of sound. By default, for WaveSynth instances that are intended to be primarily visual, mapSize is the sampling frequency. This makes one period of a 1.0 Hz wave fill the entire signal curve. OTOH, if we want the image to represent an audio signal that is also produced by additive synthesis, we should set samplingFrequency to a standard such as 44100 or 48000. -
mapInc
public float mapIncthe increment in phase over the image pixels, typically TWO_PI / image size -
weights
public float[] weightsarray of amplitudes associated with the WaveData operators -
waveColors
public int[] waveColorsarray of colors associated with the WaveData operators -
maskScan
public int[] maskScanarray of color values for mask, especially useful when it is constant -
woff
public float woffoffset for normailzing signal, see renderFrame method -
wscale
public float wscalescaling factor for normalizing signal, see renderFrame method -
videoFrameRate
public int videoFrameRateVideo frame rate as stored in JSON data, often set externally -
videoFilename
Video filename as stored in JSON data, used for output -
activeWaves
Active (unmuted, non-suspended) waves for current frame. -
activeCount
private int activeCountNumber of active waves in the current frame (length of valid entries in activeWaves). -
activeWeights
private float[] activeWeightsWeights just for active waves (first activeCount entries valid). -
activeColorR
private float[] activeColorRPre-split color channel R for active waves (first activeCount entries valid). -
activeColorG
private float[] activeColorGPre-split color channel G for active waves (first activeCount entries valid). -
activeColorB
private float[] activeColorBPre-split color channel B for active waves (first activeCount entries valid).
-
-
Constructor Details
-
WaveSynth
Preferred constructor for WaveSynth. InitializesPixelAudioMapper mapperandwaveDataListand sets up the associated properties and data structures. Themapperargument is essential for the WaveSynth to function, as it defines the mapping between audio signals and pixel values. ThewaveDataListcontains the individual sine wave components that will be used for synthesis. The constructor also initializes themapImage,colorSignal, andaudioSignalarrays based on the dimensions of the mapper.
Note that the constructor does not prepare the animation or render any frames; it simply sets up the initial state of the WaveSynth.- Parameters:
mapper- the PixelAudioMapper instance that defines the mapping between audio signals and pixel valueswdList- the list of WaveData objects to initialize with
-
WaveSynth
Convenience constructor for WaveSynth that initializes with a default list of WaveData objects.- Parameters:
mapper- the PixelAudioMapper instance that defines the mapping between audio signals and pixel values
-
-
Method Details
-
setMapper
Sets the PixelAudioMapper for this WaveSynth and initializes associated properties and data structures.- Parameters:
mapper-
-
setWaveData
Sets the list of WaveData objects for this WaveSynth.- Parameters:
wdList- list of WaveData objects to initialize local waveDataList with
-
updateWaveColors
public void updateWaveColors()Updates the wave colors based on the current list of WaveData objects. -
rebuildActiveWaves
private void rebuildActiveWaves()Rebuilds the list of active (unmuted, non-suspended) waves and pre-splits their colors into RGB channels. -
quickWaveDataList
Initializes a list of WaveData for use by a WaveSynth.- Returns:
- an ArrayList of WaveData objects
-
getWaveDataList
-
setWaveDataList
-
getGain
public float getGain() -
setGain
public void setGain(float gain) -
getGamma
public float getGamma() -
setGamma
public void setGamma(float gamma) -
isScaleHisto
public boolean isScaleHisto() -
setScaleHisto
public void setScaleHisto(boolean isScaleHisto) -
getHistoLow
public int getHistoLow() -
setHistoLow
public void setHistoLow(int histoLow) -
getHistoHigh
public int getHistoHigh() -
setHistoHigh
public void setHistoHigh(int histoHigh) -
getNoiseiness
public float getNoiseiness() -
setNoiseiness
public void setNoiseiness(float noiseiness) -
getAnimSteps
public int getAnimSteps() -
setAnimSteps
public void setAnimSteps(int animSteps) -
getStop
public int getStop() -
setStop
public void setStop(int stop) -
getStep
public int getStep() -
setStep
public void setStep(int step) -
getComments
-
setComments
-
getVideoFrameRate
public int getVideoFrameRate() -
setVideoFrameRate
public void setVideoFrameRate(int videoFrameRate) -
getVideoFilename
-
setVideoFilename
-
getMapper
-
getWidth
public int getWidth() -
getHeight
public int getHeight() -
getSampleRate
public float getSampleRate() -
setSampleRate
public void setSampleRate(float newSampleRate) -
clone
Creates a deep copy of this WaveSynth instance. -
toString
Returns a string representation of this WaveSynth instance. -
isRenderAudio
public boolean isRenderAudio()Checks if audio rendering is enabled.- Returns:
- true if audio rendering is enabled, false otherwise
-
setRenderAudio
public void setRenderAudio(boolean isRenderAudio) Sets the audio rendering flag.- Parameters:
isRenderAudio- true to enable audio rendering, false to disable
-
prepareAnimation
public void prepareAnimation()Legacy code: set up mapImage for editing, load colorSignal, set mapInc. colorSignal = mapper.pluckPixels(...) is no longer essential, because renderFrame() overwrites every colorSignal[pos] before planting it back into mapImage.pixels. -
renderFrame
public processing.core.PImage renderFrame(int frame) Loop to render all the pixels in a frame. We want it to complete a frame before any changes to the WaveSynth, so it's synchronized.- Parameters:
frame- the number of the frame we are rendering in an animation sequence- Returns:
- a PImage derived from additive audio synthesis.
-
weightedColorActive
private int weightedColorActive(float[] weights, int count) Optimized weighted color for the current active waves. Uses pre-split RGB and only the first activeCount entries. Gamma and Histogram settings are primarily intended for still frame rendering. You can probably tweak operator amplitudes and perhaps DC offset to obtain the brightness and contrast you want for animation. Leave gamma = 1.0 and isScaleHisto = false for best performance.- Parameters:
weights- the array of weights for scaling the active wavescount- the number of active waves (length of valid entries in weights and activeColor arrays)
-
renderPixel
Render one pixel, return its RGB value.
NOTES
Our basic equation:
Restated, in two parts:sample amplitude = sin(initial phase + phase shift + frequency * i * (TWO_PI/n))wd.phaseInc = (wd.cycles * TWO_PI)/animSteps; mapInc = TWO_PI / mapSize;
Instead of incrementing phase at each step, we subtract (frame * phase increment) from the initial phase: instead of adding, we subtract so that animation data files give the same result in previous implementations. And yes, I have forgotten the original reasons for subtracting.float val = (float) (Math.sin(wd.phaseTwoPi - frame * wd.phaseInc + wd.freq * freqShift * pos * mapInc) + woff) * wscale + wd.dc;We now let the WaveData object calculate the signal: this is much more flexible and barely affects the time. For the latest version (2026-06), the WaveData class has been refactored to have a prepareFrame() method that calculates the current phase for the frame, and a nextValue() method that uses recurrence relations to calculate the next sample value without trig functions. This should be much more efficient, especially for large numbers of waves.:
- Parameters:
frame- number of the frame to renderpos- index position of the pixelswdList- list of WaveData objects that calculate output value- Returns:
- the color of the pixel in RGBA format
-
weightedColor
public int weightedColor(int[] colors, float[] weights) Calculate the weighted color for a pixel based on the colors and weights of the active waves. This method applies optional gamma correction and optional histogram scaling to the resulting color, but you should avoid using those for animation, as they are primarily intended for still frame rendering.- Parameters:
colors- an array of colorsweights- an array of weights for scaling the colors- Returns:
- weighted color value
-
renderAudio
public float[] renderAudio(int frame) Render the audio signal for a given frame, returning an array of float values representing the audio signal. This method builds the active wave list, prepares the oscillators for the current frame, and sums the contributions of the active waves to produce the audio signal. The resulting audio signal is normalized to a specified limit.- Parameters:
frame- the frame to render- Returns:
- audio signal as an array of float, scaled by 0.95f normalization
-
renderAudioRaw
public float[] renderAudioRaw(int frame) Render the raw audio signal for a given frame, returning an array of float values representing the audio signal. This method builds the active wave list, prepares the oscillators for the current frame, and sums the contributions of the active waves to produce the audio signal. It is a little more efficient than renderAudio() because it does not normalize the signal.- Parameters:
frame- the frame to render- Returns:
- the raw audio signal, rendered but not normalized
-
renderAudio
public float[] renderAudio(int frame, float limit) Render the audio signal for a given frame, returning an array of float values representing the normalized audio signal. This method calls renderAudioRaw() to get the raw audio signal, and then normalizes it to a specified limit using the normalize() method. The resulting audio signal is suitable for output to an audio file or audio output device.- Parameters:
frame- the frame to renderlimit- the normalization limit- Returns:
- audio signal, rendered and normalized
-
noiseAt
public float noiseAt(int x, int y) Experimental method, for future use.- Parameters:
x-y-- Returns:
-
normalize
public static float[] normalize(float[] sig, float limit) Normalize an array of float values to a specified limit. This method finds the minimum and maximum values in the input array, and then maps all values to a new range defined by -limit to limit.- Parameters:
sig- the array of float values representing the audio signal to be normalizedlimit- the maximum absolute value for the normalized signal- Returns:
- an array of float values representing the normalized audio signal
-
normalize
public static float[] normalize(float[] sig) Normalize an array of float values to a limit of 1.0f.- Parameters:
sig- the array of float values representing the audio signal to be normalized- Returns:
- an array of float values representing the normalized audio signal
-
getHistoBounds
public static int[] getHistoBounds(int[] source) Calculate the histogram bounds (minimum and maximum pixel values) for a given array of pixel values. This method iterates through the input array, extracts the RGB components of each pixel, and updates the minimum and maximum values found. The resulting minimum and maximum values can be used for histogram scaling or other image processing tasks. May not produce the desired contrast enhancement if the histogram is heavily skewed.- Parameters:
source- array of pixel values to analyze for min and max- Returns:
- int[] array with min and max values
-
stretch
public static int[] stretch(int[] source, int low, int high) Apply a linear stretch to an array of pixel values based on specified low and high bounds. This method iterates through the input array, extracts the RGB components of each pixel, and applies a linear mapping to stretch the values from the range defined by low and high to the full range of 0 to 255. The resulting array contains the stretched pixel values, which can be used for image enhancement or other processing tasks. You can run getHistoBounds to determine low and high values for the stretch. Not recommended for animation.- Parameters:
source- an array of pixel values to stretchlow- desired lower boundhigh- desired upper bound- Returns:
- scaled array of pixel values
-