CUGL 2.3
Cornell University Game Library
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Static Public Member Functions | Static Public Attributes | Protected Attributes | List of all members
cugl::AudioWaveform Class Reference

#include <CUAudioWaveform.h>

Inheritance diagram for cugl::AudioWaveform:
cugl::Sound

Public Types

enum class  Type : int {
  NOISE = 0 , SINE = 1 , NAIVE_TRIANG = 2 , NAIVE_SQUARE = 3 ,
  NAIVE_TOOTH = 4 , NAIVE_TRAIN = 5 , POLY_TRIANG = 6 , POLY_SQUARE = 7 ,
  POLY_TOOTH = 8 , BLIT_TRAIN = 9 , UNKNOWN = 10
}
 

Public Member Functions

 AudioWaveform ()
 
 ~AudioWaveform ()
 
bool init ()
 
bool init (Uint8 channels, Uint32 rate)
 
bool init (Uint8 channels, Uint32 rate, Type type, float frequency)
 
virtual void dispose () override
 
Type getType () const
 
void setType (Type type)
 
bool isUpper () const
 
void setUpper (bool upper)
 
float getFrequency () const
 
void setFrequency (float frequency)
 
virtual Sint64 getLength () const override
 
virtual double getDuration () const override
 
void setDuration (double time)
 
Uint32 generate (float *buffer, Uint32 frames, Uint64 offset, float last)
 
virtual std::shared_ptr< audio::AudioNodecreateNode () override
 
- Public Member Functions inherited from cugl::Sound
 Sound ()
 
 ~Sound ()
 
virtual void dispose ()
 
Uint32 getRate () const
 
Uint32 getChannels () const
 
virtual Sint64 getLength () const
 
virtual double getDuration () const
 
const std::string getFile () const
 
const std::string getSuffix () const
 
float getVolume () const
 
void setVolume (float volume)
 
virtual std::shared_ptr< audio::AudioNodecreateNode ()
 

Static Public Member Functions

static std::shared_ptr< AudioWaveformalloc ()
 
static std::shared_ptr< AudioWaveformalloc (Uint8 channels, Uint32 rate)
 
static std::shared_ptr< AudioWaveformalloc (Uint8 channels, Uint32 rate, Type type, float frequency)
 
static std::shared_ptr< AudioWaveformallocWithData (const std::shared_ptr< JsonValue > &data)
 

Static Public Attributes

static const float DEFAULT_FREQUENCY
 

Protected Attributes

std::atomic< int > _type
 
std::atomic< bool > _upper
 
std::atomic< float > _frequency
 
std::atomic< bool > _newfreq
 
std::atomic< double > _duration
 
std::minstd_rand0 _random
 
- Protected Attributes inherited from cugl::Sound
Uint8 _channels
 
Uint32 _rate
 
std::string _file
 
float _volume
 

Detailed Description

This class represents a single-frequency waveform.

Intuitively, this class is used to represent a pure sine wave, which can be read and included in an audio graph. However, this class also supports more traditional computer-music waveforms, like square waves and sawtooth waves. The type of waveform is specified by the getType() attribute.

We support both naive waveforms and bandwidth-limited forms. Bandwidth-limited forms are design to reduce the aliasing that can occur at the discontinuites:

https://ccrma.stanford.edu/~stilti/papers/blit.pdf

For simplicity, we do not use the BLIT integration techniques of Stilson and Smith. Those techniques are subject to error creep over time unless a a backing table is used. Instead, we use the PolyBLEP technique:

https://ieeexplore.ieee.org/document/4117934

This technique is not "music quality." It is known to have audible aliasing near the Nyquist frequency and overly attenuate higher frequencies. However, it is compact and ideal for real-time sound generation. It is also good enough for procedural sound generation in most games.

The audio graph should only be accessed in the main thread. In addition, no methods marked as AUDIO THREAD ONLY should ever be accessed by the user.

This class does not support any actions for the audio::AudioNode#setCallback.

Member Enumeration Documentation

◆ Type

enum class cugl::AudioWaveform::Type : int
strong

The wave generator type.

These types are inspired by STK, the Synthesis Toolkit (even though we chose not to adopt BLIT integration). They are not necessarily complete and additional wave form types may be added at any time. For that reason, you should never refer to a type by its raw number.

Enumerator
NOISE 

Creates random noise using the C rand() function. The quality of the rand() function varies from one OS to another.

SINE 

Creates a sine wave with the given frequency.

NAIVE_TRIANG 

Creates a naive square triangular with the given frequency.

The waveform will have first-order discontinuities at PI and 2PI. This will create a more smoother sound than a square or sawtooth wave of the same frequency.

NAIVE_SQUARE 

Creates a naive square wave with the given frequency.

The waveform will have discontinuities at PI and 2PI. This will create a harsh sound reminiscent of old-school games.

NAIVE_TOOTH 

Creates a naive sawtooth wave with the given frequency.

The waveform will have a discontinuity at 2PI. This will create a harsh sound reminiscent of old-school games.

NAIVE_TRAIN 

Creates an alternating sign impulse train with the given frequency.

The frequence given is the twice the period of the impulse because the signs will alternate when isUpper() is false.

POLY_TRIANG 

Creates a bandwidth-limited triangle wave with the given frequency.

The algorithm uses a PolyBLEP curve to create a bandwidth-limited square wave, as reported in "Antialiasing Oscillators in Subtractive Synthesis" by Valimaki and Huovilainen (2007). This wave is then integrated to produce a triangle wave, using the leaky integration in "Alias-Free Digital Synthesis of Classic Analog Waveforms" by Stilson and Smith (1996). This particular version is adapted from

http://www.martin-finke.de/blog/articles/audio-plugins-018-polyblep-oscillator/
POLY_SQUARE 

Creates a bandwidth-limited square wave with the given frequency.

The algorithm uses a PolyBLEP curve as reported in "Antialiasing Oscillators in Subtractive Synthesis" by Valimaki and Huovilainen (2007). This particular version is adapted from

http://www.martin-finke.de/blog/articles/audio-plugins-018-polyblep-oscillator/
POLY_TOOTH 

Creates a bandwidth-limited sawtooth wave with the given frequency.

The algorithm uses a PolyBLEP curve as reported in "Antialiasing Oscillators in Subtractive Synthesis" by Valimaki and Huovilainen (2007). This particular version is adapted from

http://www.martin-finke.de/blog/articles/audio-plugins-018-polyblep-oscillator/
BLIT_TRAIN 

Creates a band-limited impulse train.

This algorithm uses the closed-form algorithm "Alias-Free Digital Synthesis of Classic Analog Waveforms" by Stilson and Smith (1996). This implementation assumes the maximum number of harmonics.

Based on code by Robin Davies, Gary Scavone, 2005 - 2006.

UNKNOWN 

An unknown type

Constructor & Destructor Documentation

◆ AudioWaveform()

cugl::AudioWaveform::AudioWaveform ( )

Creates a degenerate waveform with no frequency.

The waveform has no channels or frequency, so read options will do nothing. The waveform must be initialized to be used.

◆ ~AudioWaveform()

cugl::AudioWaveform::~AudioWaveform ( )
inline

Deletes this waveform, disposing of all resources.

Member Function Documentation

◆ alloc() [1/3]

static std::shared_ptr< AudioWaveform > cugl::AudioWaveform::alloc ( )
inlinestatic

Returns a newly allocated sine wave of 480 Hz.

When included in an audio graph, the node will support 2 channels at a sampling rate of 48000 Hz.

Returns
a newly allocated sine wave of 480 Hz.

◆ alloc() [2/3]

static std::shared_ptr< AudioWaveform > cugl::AudioWaveform::alloc ( Uint8  channels,
Uint32  rate 
)
inlinestatic

Returns a newly allocated sine wave of 480 Hz.

When included in an audio graph, the node will support the given number of channels at the given sampling rate.

Parameters
channelsThe number of audio channels
rateThe sample rate (frequency) in Hz
Returns
a newly allocated sine wave of 480 Hz.

◆ alloc() [3/3]

static std::shared_ptr< AudioWaveform > cugl::AudioWaveform::alloc ( Uint8  channels,
Uint32  rate,
Type  type,
float  frequency 
)
inlinestatic

Returns a newly allocated wave form of the given type and frequency.

The frequency is specified is the fundamental frequency of the wave form. However, for the Type#NOISE type, it is the seed of the random number generator.

The frequency specified is independent of the sampling rate. The wave form algorithms will create the correct date for both the sampling rate and frequency.

Parameters
channelsThe number of audio channels
rateThe sample rate (frequency) in Hz
typeThe waveform type
frequencyThe waveform fundamental frequency
Returns
a newly allocated wave form of the given type and frequency.

◆ allocWithData()

static std::shared_ptr< AudioWaveform > cugl::AudioWaveform::allocWithData ( const std::shared_ptr< JsonValue > &  data)
static

Returns a newly allocated waveform with the given JSON specificaton.

This initializer is designed to receive the "data" object from the JSON passed to Scene2Loader. This JSON format supports the following attribute values:

 "shape":    The wave shape as a string (e.g. "sine", "triangle")
 "tone":     A float, representing the frequency
 "channels": An int, representing the number of channels
 "rate":     An int, representing the sample rate
 "volume":   A float, representing the volume
 "duration"  A float, representing the duration in seconds

All attributes are optional. There are no required attributes. The recognized shapes are as follows: noise, sine, native triangle, naive square, naive sawtooth, naive impulse, triangle, square, sawtooth, and impulse. The non-naive names are all bandwidth limited.

Parameters
dataThe JSON object specifying the waveform
Returns
a newly allocated waveform with the given JSON specification.

◆ createNode()

virtual std::shared_ptr< audio::AudioNode > cugl::AudioWaveform::createNode ( )
overridevirtual

Returns a playble audio node for this asset.

This audio node may be attached to an audio::AudioOutput for immediate playback. Nodes are distinct. Each call to this method allocates a new audio node.

Returns
a playble audio node for this asset.

Reimplemented from cugl::Sound.

◆ dispose()

virtual void cugl::AudioWaveform::dispose ( )
overridevirtual

Disposes any resources allocated for this waveform

The state of the node is reset to that of an uninitialized constructor. Unlike the destructor, this method allows the node to be reinitialized.

Reimplemented from cugl::Sound.

◆ generate()

Uint32 cugl::AudioWaveform::generate ( float *  buffer,
Uint32  frames,
Uint64  offset,
float  last 
)

Generates the given number of frames for the waveform fom the given offset.

This function is used by audio::AudioNode to generate the correct data for each type. For reasons of precision, the offset is given in frames and not the phase (which is real-valued).

Some waveforms require discrete integration. This is the purpose of last, which was the last sample generated. It is up to the user to remember this value. The method returns the frame position of the last sample generated.

Parameters
bufferThe read buffer to store the results
framesThe maximum number of frames to read
offsetThe phase offset measured in frames
lastThe last value generated (for integration purposes)
Returns
the number of frames generated

◆ getDuration()

virtual double cugl::AudioWaveform::getDuration ( ) const
overridevirtual

Returns the length of this waveform in seconds.

The accuracy of this method depends on the specific implementation. If the asset is infinite (e.g. AudioWaveform), then this method returns a negative value.

Returns
the length of this waveform in seconds.

Reimplemented from cugl::Sound.

◆ getFrequency()

float cugl::AudioWaveform::getFrequency ( ) const

Returns the fundamental frequency of this waveform.

Returns
the fundamental frequency of this waveform.

◆ getLength()

virtual Sint64 cugl::AudioWaveform::getLength ( ) const
overridevirtual

Returns the frame length of this waveform.

The frame length is the number of audio samples in the asset. If the asset is infinite (e.g. AudioWaveform), then this method returns a negative value.

Returns
the frame length of this waveform.

Reimplemented from cugl::Sound.

◆ getType()

Type cugl::AudioWaveform::getType ( ) const

Returns the waveform type.

Returns
the waveform type.

◆ init() [1/3]

bool cugl::AudioWaveform::init ( )

Initializes a stereo sine wave of 480 Hz.

When included in an audio graph, the node will support 2 channels at a sampling rate of 48000 Hz.

Returns
true if initialization was successful

◆ init() [2/3]

bool cugl::AudioWaveform::init ( Uint8  channels,
Uint32  rate 
)

Initializes a sine wave of 480 Hz.

When included in an audio graph, the node will support the given number of channels at the given sampling rate.

Parameters
channelsThe number of audio channels
rateThe sample rate (frequency) in Hz
Returns
true if initialization was successful

◆ init() [3/3]

bool cugl::AudioWaveform::init ( Uint8  channels,
Uint32  rate,
Type  type,
float  frequency 
)

Initializes a wave form of the given type and frequency.

The frequency is specified is the fundamental frequency of the wave form. However, for the Type#NOISE type, it is the seed of the random number generator.

The frequency specified is independent of the sampling rate. The wave form algorithms will create the correct date for both the sampling rate and frequency.

Parameters
channelsThe number of audio channels
rateThe sample rate (frequency) in Hz
typeThe waveform type
frequencyThe waveform fundamental frequency
Returns
true if initialization was successful

◆ isUpper()

bool cugl::AudioWaveform::isUpper ( ) const

Returns true if the waveform has only nonnegative samples.

Mathematically, we sometimes want a waveform to have only non-negative values. For an impulse train, this means a train with only positive poles (as opposed to a bipolar train). For triangle, square, and sawtooth waves, the result is a waveform of the same shape but from 0 to 1 instead of -1 to 1. For a sine wave, the result is the absolute value (or a rectified sine wave). For noise, this has no effect.

Returns
true if the waveform has only nonnegative samples.

◆ setDuration()

void cugl::AudioWaveform::setDuration ( double  time)

Sets the length of this waveform in seconds.

The accuracy of this method depends on the specific implementation. If the asset is infinite (e.g. AudioWaveform), then this value is negative.

Parameters
timethe length of this waveform in seconds.

◆ setFrequency()

void cugl::AudioWaveform::setFrequency ( float  frequency)

Sets the fundamental frequency of this waveform.

Parameters
frequencythe fundamental frequency of this waveform.

◆ setType()

void cugl::AudioWaveform::setType ( Type  type)

Sets the waveform type.

Parameters
typethe waveform type.

◆ setUpper()

void cugl::AudioWaveform::setUpper ( bool  upper)

Sets whether the waveform has only nonnegative samples.

Mathematically, we sometimes want a waveform to have only non-negative values. For an impulse train, this means a train with only positive poles (as opposed to a bipolar train). For triangle, square, and sawtooth waves, the result is a waveform of the same shape but from 0 to 1 instead of -1 to 1. For a sine wave, the result is the absolute value (or a rectified sine wave). For noise, this has no effect.

Parameters
upperWhether the waveform has only nonnegative samples.

Member Data Documentation

◆ _duration

std::atomic<double> cugl::AudioWaveform::_duration
protected

The duration in seconds; -1 if infinite

◆ _frequency

std::atomic<float> cugl::AudioWaveform::_frequency
protected

The (normalized) fundamental frequency

◆ _newfreq

std::atomic<bool> cugl::AudioWaveform::_newfreq
protected

Whether the frequency has changed recently

◆ _random

std::minstd_rand0 cugl::AudioWaveform::_random
protected

The random generator for noise

◆ _type

std::atomic<int> cugl::AudioWaveform::_type
protected

Atomic proxy for the signal type

◆ _upper

std::atomic<bool> cugl::AudioWaveform::_upper
protected

Whether to limit the waveform to the positive y-axis.

◆ DEFAULT_FREQUENCY

const float cugl::AudioWaveform::DEFAULT_FREQUENCY
static

The default fundamental frequency


The documentation for this class was generated from the following file: