mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
151 lines
5.3 KiB
C++
151 lines
5.3 KiB
C++
//
|
||
// audio.h
|
||
// interface
|
||
//
|
||
// Created by Seiji Emery on 9/2/12.
|
||
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
|
||
//
|
||
|
||
#ifndef interface_audio_h
|
||
#define interface_audio_h
|
||
|
||
#include "portaudio.h"
|
||
|
||
// Note: main documentation in audio.cpp
|
||
|
||
/**
|
||
* If enabled, direct the audio callback to write the audio input buffer
|
||
* directly into the audio output buffer.
|
||
*/
|
||
#define WRITE_AUDIO_INPUT_TO_OUTPUT 1
|
||
/**
|
||
* If enabled, create an additional buffer to store audio input
|
||
* and direct the audio callback to write the audio input to this buffer.
|
||
*/
|
||
#define WRITE_AUDIO_INPUT_TO_BUFFER 0
|
||
|
||
// Note: I initially used static const bools within the Audio class and normal
|
||
// 'if' blocks instead of preprocessor - under the assumption that the compiler
|
||
// would optimize out the redundant code.
|
||
// However, as that apparently did not work (for some reason or another - even
|
||
// with full compiler optimization turned on), I've switched to using preprocessor
|
||
// macros instead (which is probably faster anyways (at compile-time)).
|
||
|
||
/**
|
||
* Low level audio interface.
|
||
*
|
||
* Contains static methods that write to an internal audio buffer, which
|
||
is read from by a portaudio callback.
|
||
* Responsible for initializing and terminating portaudio. Audio::init()
|
||
and Audio::terminate() should be called at the beginning and end of
|
||
program execution.
|
||
*/
|
||
class Audio {
|
||
public:
|
||
// Initializes portaudio. Should be called at the beginning of program execution.
|
||
static bool init ();
|
||
// Deinitializes portaudio. Should be called at the end of program execution.
|
||
static bool terminate ();
|
||
|
||
// Write methods: write to internal audio buffer.
|
||
static void writeAudio (unsigned int offset, unsigned int length, float const *left, float const *right);
|
||
static void addAudio (unsigned int offset, unsigned int length, float const *left, float const *right);
|
||
static void writeTone (unsigned int offset, unsigned int length, float const left, float const right);
|
||
static void addTone (unsigned int offset, unsigned int length, float const left, float const right);
|
||
static void clearAudio (unsigned int offset, unsigned int length);
|
||
|
||
// Read data from internal 'input' audio buffer to an external audio buffer.
|
||
// (*only* works if WRITE_AUDIO_INPUT_TO_BUFFER is enabled).
|
||
static void readAudioInput (unsigned int offset, unsigned int length, float *left, float *right);
|
||
|
||
/**
|
||
* Set the audio input gain. (multiplier applied to mic input)
|
||
*/
|
||
static void setInputGain (float gain) {
|
||
data->inputGain = gain;
|
||
}
|
||
/**
|
||
* Get the internal portaudio error code (paNoError if none).
|
||
* Use in conjunction with Audio::init() or Audio::terminate(), as it is not
|
||
impacted by any other methods.
|
||
*/
|
||
const PaError getError () { return err; }
|
||
|
||
private:
|
||
/**
|
||
* Set to true by Audio::init() and false by Audio::terminate().
|
||
* Used to prevent Audio::terminate() from deleting uninitialized memory.
|
||
*/
|
||
static bool initialized;
|
||
|
||
/**
|
||
* Internal audio data.
|
||
* Used to communicate with the audio callback code via a shared pointer.
|
||
*/
|
||
static struct AudioData {
|
||
/**
|
||
* Internal (stereo) audio buffer.
|
||
* Written to by Audio I/O methods and the audio callback.
|
||
* As this is a ring buffer, it should not be written to directly – thus methods
|
||
like Audio::writeAudio are provided.
|
||
*/
|
||
struct BufferFrame{
|
||
float l, r;
|
||
} *buffer, *inputBuffer;
|
||
/**
|
||
* Length of the audio buffer.
|
||
*/
|
||
const static unsigned int bufferLength = 1000;
|
||
/**
|
||
* Current position (start) within the ring buffer.
|
||
* Updated by the audio callback.
|
||
*/
|
||
unsigned int bufferPos;
|
||
/**
|
||
* Audio input gain (multiplier applied to the incoming audio stream).
|
||
* Use Audio::setInputGain() to modify this.
|
||
*/
|
||
static float inputGain;// = 1.f;
|
||
|
||
AudioData () : bufferPos(0) {
|
||
inputGain = 1.0f;
|
||
buffer = new BufferFrame[bufferLength];
|
||
memset((float*)buffer, 0, sizeof(float) * bufferLength * 2);
|
||
#if WRITE_AUDIO_INPUT_TO_BUFFER
|
||
inputBuffer = new BufferFrame[bufferLength];
|
||
memset((float*)inputBuffer, 0, sizeof(float) * bufferLength * 2);
|
||
#else
|
||
inputBuffer = NULL;
|
||
#endif
|
||
}
|
||
~AudioData () {
|
||
delete[] buffer;
|
||
#if WRITE_AUDIO_INPUT_TO_BUFFER
|
||
delete[] inputBuffer;
|
||
#endif
|
||
}
|
||
}*data;
|
||
/**
|
||
* Internal audio stream handle.
|
||
*/
|
||
static PaStream *stream;
|
||
/**
|
||
* Internal error code (used only by Audio::init() and Audio::terminate()).
|
||
*/
|
||
static PaError err;
|
||
|
||
Audio (); // prevent instantiation (private constructor)
|
||
|
||
friend int audioCallback (const void*, void*, unsigned long, const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags, void*);
|
||
};
|
||
|
||
// Audio callback called by portaudio.
|
||
int audioCallback (const void *inputBuffer,
|
||
void *outputBuffer,
|
||
unsigned long framesPerBuffer,
|
||
const PaStreamCallbackTimeInfo *timeInfo,
|
||
PaStreamCallbackFlags statusFlags,
|
||
void *userData);
|
||
|
||
|
||
#endif
|