CUGL 2.1
Cornell University Game Library
|
#include <CUAudioInput.h>
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< AudioSample > | save () |
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 |
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.
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.
cugl::audio::AudioInput::~AudioInput | ( | ) |
Deletes the audio input node, disposing of all resources
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.
|
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.
Reimplemented from cugl::audio::AudioNode.
|
inline |
Returns the audio device identifier associated with this audio input.
|
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.
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.
const std::string& cugl::audio::AudioInput::getDevice | ( | ) | const |
Returns the device associated with this input node.
|
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.
Reimplemented from cugl::audio::AudioNode.
|
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.
Reimplemented from cugl::audio::AudioNode.
|
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.
Reimplemented from cugl::audio::AudioNode.
|
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.
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.
|
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.
Reimplemented from cugl::audio::AudioNode.
|
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.
Reimplemented from cugl::audio::AudioNode.
|
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.
buffer | The read buffer to store the results |
frames | The maximum number of frames to read |
Reimplemented from cugl::audio::AudioNode.
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.
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.
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.
|
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.
Reimplemented from cugl::audio::AudioNode.
|
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.
Reimplemented from cugl::audio::AudioNode.
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.
|
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.
time | The elapsed time in seconds. |
Reimplemented from cugl::audio::AudioNode.
|
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.
position | the current frame position of this audio node. |
Reimplemented from cugl::audio::AudioNode.
|
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.
time | The remaining time in seconds. |
Reimplemented from cugl::audio::AudioNode.
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.
|
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.
Reimplemented from cugl::audio::AudioNode.
|
friend |
Allow AudioManager to access intializers
|
static |
The default delay (in frames) for an input device