CUGL 2.0
Cornell University Game Library
Public Member Functions | Static Public Attributes | Friends | List of all members
cugl::audio::AudioInput Class Reference

#include <CUAudioInput.h>

Inheritance diagram for cugl::audio::AudioInput:
cugl::audio::AudioNode

Public Member Functions

 AudioInput ()
 
 ~AudioInput ()
 
const SDL_AudioDeviceID getAUID () const
 
const std::string & getDevice () const
 
bool isDefault () const
 
Uint16 getCapacity () const
 
Uint32 getDelay () const
 
virtual bool pause () override
 
virtual bool resume () override
 
bool isRecording () const
 
bool release ()
 
bool acquire ()
 
void stop ()
 
std::shared_ptr< AudioSamplesave ()
 
virtual bool completed () override
 
virtual Uint32 read (float *buffer, Uint32 frames) override
 
Uint32 record (float *buffer, Uint32 frames)
 
void reboot ()
 
virtual bool mark () override
 
virtual bool unmark () override
 
virtual bool reset () override
 
virtual Sint64 getPosition () const override
 
virtual Sint64 setPosition (Uint32 position) override
 
virtual double getElapsed () const override
 
virtual double setElapsed (double time) override
 
virtual double getRemaining () const override
 
virtual double setRemaining (double time) override
 
- Public Member Functions inherited from cugl::audio::AudioNode
 AudioNode ()
 
virtual ~AudioNode ()
 
Uint8 getChannels () const
 
Uint32 getRate () const
 
float getGain ()
 
virtual void setGain (float gain)
 
const std::string & getClassName () const
 
const std::string & getName () const
 
void setName (const std::string name)
 
Sint32 getTag () const
 
void setTag (Sint32 tag)
 
virtual std::string toString (bool verbose=false) const
 
 operator std::string () const
 
Callback getCallback ()
 
void setCallback (Callback callback)
 
virtual bool isPaused ()
 
virtual Sint64 advance (Uint32 frames)
 

Static Public Attributes

const static Uint32 DEFAULT_DELAY
 
- Static Public Attributes inherited from cugl::audio::AudioNode
const static Uint32 DEFAULT_CHANNELS
 
const static Uint32 DEFAULT_SAMPLING
 

Friends

class cugl::AudioDevices
 

Additional Inherited Members

- Public Types inherited from cugl::audio::AudioNode
enum  Action : int {
  COMPLETE = 0, INTERRUPT = 1, FADE_OUT = 2, FADE_IN = 3,
  FADE_DIP = 4, LOOPBACK = 5
}
 
typedef std::function< void(const std::shared_ptr< AudioNode > &node, Action type)> Callback
 
- Protected Member Functions inherited from cugl::audio::AudioNode
void notify (const std::shared_ptr< AudioNode > &node, Action action)
 
- Protected Attributes inherited from cugl::audio::AudioNode
Uint8 _channels
 
Uint32 _sampling
 
bool _booted
 
std::atomic< float > _ndgain
 
std::atomic< bool > _paused
 
std::atomic< bool > _polling
 
Callback _callback
 
std::atomic< bool > _calling
 
Sint32 _tag
 
std::string _localname
 
std::string _classname
 
size_t _hashOfName
 

Detailed Description

This class provides a graph node interface for an audio recording device.

This audio node provides a modern, graph-based approach to sound design. This input can be plugged into the audio graph and piped to the output device with a small (but significant) amount of latency. This node is intended to be the root of an audio DAG, much like AudioPlayer.

One of the important issues to understand about this class is that there are actually two different latency values: the recording latency and the playback latency. The recording latency is time from when the data is captured at the hardware device and is recorded at this node. It is entirely determined by the buffer size of this device, much like the buffer determines the playback latency for AudioOutput. However, unlike AudioOutput, there is no guarantee that recording happens at uniform time intervals. For example, on MacOS at 48000 Hz, a buffer size of 512 will record twice (in immediate sucession) every 21 ms instead of once every 11 ms (a buffer size of 1024 appers to record once every 21 ms as expected).

The playback latency is the time from when data is passed to record() and made available to read(); it does not include the latency of any output device. It is determined by the additional delay value, which is the number of frames that must be recorded before any can be read. So a delay of 0 means that data is instantly available, while a delay of the buffer size means that no data can be read until more than a single buffer has been recorded (which means that at least two buffers worth of data must have been recorded). Because output and input devices run in different threads and have no coordination at all, a delay of at least one buffer is recommended for real-time playback.

This method has no public initializers or non-degenerate constructors. That is because all input nodes should be created by the factory methods in AudioDevices. That way, the AudioDevices can properly handle device conflicts as they may arise.

Audio devices in SDL are identified by name. If you have two devices with the same name, SDL will add a distinguishing index to the name. You can see the list of all available devices with the AudioDevices#devices() method. In addition, the empty string may be used to refer to the default devices. Instances of AudioOutput attached to a default device will roll over (if possible) whenever the default device changes.

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 AudioNode#setCallback.

Constructor & Destructor Documentation

◆ AudioInput()

cugl::audio::AudioInput::AudioInput ( )

Creates a degenerate audio input node.

The node has not been initialized, so it is not active. The node must be initialized to be used.

NEVER USE A CONSTRUCTOR WITH NEW. If you want to allocate a node on the heap, use the factory in AudioDevices.

◆ ~AudioInput()

cugl::audio::AudioInput::~AudioInput ( )

Deletes the audio input node, disposing of all resources

Member Function Documentation

◆ acquire()

bool cugl::audio::AudioInput::acquire ( )

Resumes recording for a previously released node.

This method does not effect playback. If playback is paused, then recording will be buffered if mark() is set, or else it will overwrite itself in the circular buffer.

If the node is already recording, this method has no effect.

Returns
true if the node was successfully acquired

◆ completed()

virtual bool cugl::audio::AudioInput::completed ( )
overridevirtual

Returns true if this audio node has no more data.

An audio node is typically completed if it return 0 (no frames read) on subsequent calls to read(). However, input nodes may run infinitely. Therefore this method only returns true when either of the methods stop() or setRemaining() are called.

Returns
true if this audio node has no more data.

Reimplemented from cugl::audio::AudioNode.

◆ getAUID()

const SDL_AudioDeviceID cugl::audio::AudioInput::getAUID ( ) const
inline

Returns the audio device identifier associated with this audio input.

Returns
the audio device identifier associated with this audio input.

◆ getCapacity()

Uint16 cugl::audio::AudioInput::getCapacity ( ) const
inline

Returns the buffer size of this input node.

The buffer value is the number of samples recorded at each poll. Smaller buffers clearly tax the CPU, as the device is collecting data at a higher rate. Furthermore, if the value is too small, the recording device may not be able to keep up with the output device. For example, we find on MacOS that the input device at a sample rate of 48000 Hz can only record data every 21 milliseconds. Hence so it can only (at best) keep up with a 1024 playback buffer.

Returns
the buffer size of this output node.

◆ getDelay()

Uint32 cugl::audio::AudioInput::getDelay ( ) const

Returns the current playback delay (in frames) of this audio node

The playback delay is the number of frames between when an audio frame is recorded by record() to when it can be accessed by read(). Typically, this is the delay value set by the initialzer (commonly 1024 frames). However, if the read position has been changed by setPosition() or setElapsed(), then this method will reflect the new delay.

Because of the real-time nature of this node, this value is only an approximation.

Returns
the current playback delay (in frames) of this audio node

◆ getDevice()

const std::string& cugl::audio::AudioInput::getDevice ( ) const

Returns the device associated with this input node.

Returns
the device associated with this input node.

◆ getElapsed()

virtual double cugl::audio::AudioInput::getElapsed ( ) const
overridevirtual

Returns the elapsed time in seconds.

This method returns -1 (indicating it is not supported) if mark() is not set. Otherwise, the position will be the number of seconds since the mark.

Returns
the elapsed time in seconds.

Reimplemented from cugl::audio::AudioNode.

◆ getPosition()

virtual Sint64 cugl::audio::AudioInput::getPosition ( ) const
overridevirtual

Returns the current frame position of this audio node

This method returns -1 (indicating it is not supported) if mark() is not set. Otherwise, the position will be the number of frames since the mark.

Returns
the current frame position of this audio node.

Reimplemented from cugl::audio::AudioNode.

◆ getRemaining()

virtual double cugl::audio::AudioInput::getRemaining ( ) const
overridevirtual

Returns the remaining time in seconds.

This method returns -1 (indicating it is not supported) if the method setRemaining() has not been called or has been interrupted. Otherwise, it returns the amount of time left in the countdown timer until this node completes.

Returns
the remaining time in seconds.

Reimplemented from cugl::audio::AudioNode.

◆ isDefault()

bool cugl::audio::AudioInput::isDefault ( ) const
inline

Returns true if this output node is associated with the default device

A graph on the default device will switch devices whenever the default device changes.

Returns
true if this audio graph is associated with the default device

◆ isRecording()

bool cugl::audio::AudioInput::isRecording ( ) const

Returns true if this node is currently recording audio.

Recording is completely independent of playback. An input node can be recording, but have its played paused, and vice versa.

Returns
true if this node is currently recording audio.

◆ mark()

virtual bool cugl::audio::AudioInput::mark ( )
overridevirtual

Marks the current read position in the audio steam.

This methods creates an internal buffer for recording audio data. This buffer may be returned to at any time with reset() command. Doing so introduces an inherent delay going forward, as the playback comes from the recorded buffer.

Returns
true if the read position was marked.

Reimplemented from cugl::audio::AudioNode.

◆ pause()

virtual bool cugl::audio::AudioInput::pause ( )
overridevirtual

Pauses this node, preventing any data from being played back.

As with all other audio nodes, pausing effects the playback. However, it does not affect recording. Recording will still happen in the background and may be recovered if mark() is set. To stop recording (but not playback) call release() instead.

If the node is already paused, this method has no effect. Pausing will not go into effect until the next render call in the audio thread.

Returns
true if the node was successfully paused

Reimplemented from cugl::audio::AudioNode.

◆ read()

virtual Uint32 cugl::audio::AudioInput::read ( float *  buffer,
Uint32  frames 
)
overridevirtual

Reads up to the specified number of frames into the given buffer

AUDIO THREAD ONLY: Users should never access this method directly. The only exception is when the user needs to create a custom subclass of this AudioOutput.

The buffer should have enough room to store frames * channels elements. The channels are interleaved into the output buffer. The number of frames read is determined by the audio graph, not the buffer of this device.

This method will always forward the read position.

Parameters
bufferThe read buffer to store the results
framesThe maximum number of frames to read
Returns
the actual number of frames read

Reimplemented from cugl::audio::AudioNode.

◆ reboot()

void cugl::audio::AudioInput::reboot ( )

Reboots the audio input node without interrupting any active polling.

AUDIO THREAD ONLY: Users should never access this method directly. The only exception is when the user needs to create a custom subclass of this AudioNode.

This method will close and reopen the associated audio device. It is primarily used when an node on the default device needs to migrate between devices.

◆ record()

Uint32 cugl::audio::AudioInput::record ( float *  buffer,
Uint32  frames 
)

Records the specified number of frames to this audio node

AUDIO THREAD ONLY: Users should never access this method directly. The only exception is when the user needs to create a custom subclass of this AudioOutput.

If mark() is not set, this method records to a circular buffer that has the given getDelay(). Data that is not read in a timely manner is lost from the buffer.

However, if mark is set, then this method writes to an ever-increasing queue. This queue can be accessed at any time with reset() or setPosition(). This can potentially take a lot of memory and so it should be used carefully. Use release() to stop recording to the buffer while still having access to it.

◆ release()

bool cugl::audio::AudioInput::release ( )

Stops this input node from recording.

This method does not effect playback. Unpaused playback will continue until the delay has caught up. After that point, it will only play silence.

If the node is not recording, this method has no effect.

Returns
true if the node was successfully released

◆ reset()

virtual bool cugl::audio::AudioInput::reset ( )
overridevirtual

Resets the read position to the marked position of the audio stream.

This method does nothing (and returns false) if no mark() is set. Otherwise, it resets to the start of the buffer created by the call to mark. This introduces an inherent delay going forward, as the playback comes from the recorded buffer.

Returns
true if the read position was moved.

Reimplemented from cugl::audio::AudioNode.

◆ resume()

virtual bool cugl::audio::AudioInput::resume ( )
overridevirtual

Resumes this previously paused node, allowing data to be played back.

As with all other audio nodes, pausing effects the playback. However, does not affect recording. When play is resumed, the playback will either return with immediate playback or the recording buffer, depending on whether mark() is set.

If the node is not paused, this method has no effect.

Returns
true if the node was successfully resumed

Reimplemented from cugl::audio::AudioNode.

◆ save()

std::shared_ptr<AudioSample> cugl::audio::AudioInput::save ( )

Returns any cached data as an in-memory audio sample.

This method is potentially expensive and should only be called when the audio node has stopped recording (via the release() method, and when the node is not part of an audio graph giving real-time playback.

If mark() is not set, this will return null rather than return an empty audio sample.

Returns
any cached data as an in-memory audio sample.

◆ setElapsed()

virtual double cugl::audio::AudioInput::setElapsed ( double  time)
overridevirtual

Sets the read position to the elapsed time in seconds.

This method returns -1 (indicating it is not supported) if mark() is not set. Otherwise, it will set the position to the number of seconds since the mark. If the position is in the future (a time not already buffered) then this method will fail and return -1.

Parameters
timeThe elapsed time in seconds.
Returns
the new elapsed time in seconds.

Reimplemented from cugl::audio::AudioNode.

◆ setPosition()

virtual Sint64 cugl::audio::AudioInput::setPosition ( Uint32  position)
overridevirtual

Sets the current frame position of this audio node.

This method returns -1 (indicating it is not supported) if mark() is not set. Otherwise, it will set the position to the number of frames since the mark. If the position is in the future (a frame not already buffered) then this method will fail and return -1.

Parameters
positionthe current frame position of this audio node.
Returns
the new frame position of this audio node.

Reimplemented from cugl::audio::AudioNode.

◆ setRemaining()

virtual double cugl::audio::AudioInput::setRemaining ( double  time)
overridevirtual

Sets the remaining time in seconds.

This method sets a countdown timer on the input node, forcing it to complete in the given number of seconds. If the audio has been reading from the buffer (because of a call to setPosition(), this method immediately skips ahead to real-time recording. Any call to setPosition() or setElapsed() before this time is up will cancel the countdown.

Parameters
timeThe remaining time in seconds.
Returns
the new remaining time in seconds.

Reimplemented from cugl::audio::AudioNode.

◆ stop()

void cugl::audio::AudioInput::stop ( )

Instantly stops this node from both recording and playback.

This method is the same as calling both the methods pause() and release(). In addition, the input node will be marked as completed() for the purpose of the audio graph.

◆ unmark()

virtual bool cugl::audio::AudioInput::unmark ( )
overridevirtual

Clears the current marked position.

If the method mark() has started recording to a buffer, then this method will stop recording and release the buffer. When the mark is cleared the method reset() will no longer work.

Returns
true if the read position was marked.

Reimplemented from cugl::audio::AudioNode.

Friends And Related Function Documentation

◆ cugl::AudioDevices

friend class cugl::AudioDevices
friend

Allow AudioManager to access intializers

Member Data Documentation

◆ DEFAULT_DELAY

const static Uint32 cugl::audio::AudioInput::DEFAULT_DELAY
static

The default delay (in frames) for an input device


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