mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 17:29:47 +02:00
Minor changes: added an additional audio buffer (captures audio input), with a corresponding read method. This buffer is optional, and toggleable via a preprocessor macro. Also added const-correctness for Audio write methods.
This commit is contained in:
parent
094faf3617
commit
908a853223
4 changed files with 128 additions and 18 deletions
92
audio.cpp
92
audio.cpp
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file audio.cpp
|
* @file audio.cpp
|
||||||
* Low level audio i/o wrapper around portaudio.
|
* Low level audio i/o portaudio wrapper.
|
||||||
*
|
*
|
||||||
* @author Seiji Emery
|
* @author Seiji Emery
|
||||||
*
|
*
|
||||||
|
@ -56,25 +56,56 @@ int audioCallback (const void *inputBuffer,
|
||||||
float *input = (float*)inputBuffer;
|
float *input = (float*)inputBuffer;
|
||||||
float *output = (float*)outputBuffer;
|
float *output = (float*)outputBuffer;
|
||||||
|
|
||||||
if (input != NULL) {
|
#if WRITE_AUDIO_INPUT_TO_OUTPUT
|
||||||
|
if (input != NULL) {// && Audio::writeAudioInputToOutput) {
|
||||||
// combine input into data buffer
|
// combine input into data buffer
|
||||||
|
|
||||||
// temp variables (frames and bufferPos need to remain untouched so they can be used in the second block of code)
|
// temp variables (frames and bufferPos need to remain untouched so they can be used in the second block of code)
|
||||||
unsigned int f = (unsigned int)frames,
|
unsigned int f = (unsigned int)frames,
|
||||||
p = data->bufferPos;
|
p = data->bufferPos;
|
||||||
for (; p < data->bufferLength && f > 0; --f, ++p) {
|
for (; p < data->bufferLength && f > 0; --f, ++p) {
|
||||||
|
#if WRITE_AUDIO_INPUT_TO_BUFFER
|
||||||
|
data->buffer[p].l +=
|
||||||
|
data->inputBuffer[p].l = (*input++) * data->inputGain;
|
||||||
|
data->buffer[p].r +=
|
||||||
|
data->inputBuffer[p].r = (*input++) * data->inputGain;
|
||||||
|
#else
|
||||||
data->buffer[p].l += (*input++) * data->inputGain;
|
data->buffer[p].l += (*input++) * data->inputGain;
|
||||||
data->buffer[p].r += (*input++) * data->inputGain;
|
data->buffer[p].r += (*input++) * data->inputGain;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (f > 0) {
|
if (f > 0) {
|
||||||
// handle data->buffer wraparound
|
// handle data->buffer wraparound
|
||||||
for (p = 0; f > 0; --f, ++p) {
|
for (p = 0; f > 0; --f, ++p) {
|
||||||
|
#if WRITE_AUDIO_INPUT_TO_BUFFER
|
||||||
|
data->buffer[p].l +=
|
||||||
|
data->inputBuffer[p].l = (*input++) * data->inputGain;
|
||||||
|
data->buffer[p].r +=
|
||||||
|
data->inputBuffer[p].r = (*input++) * data->inputGain;
|
||||||
|
#else
|
||||||
data->buffer[p].l += (*input++) * data->inputGain;
|
data->buffer[p].l += (*input++) * data->inputGain;
|
||||||
data->buffer[p].r += (*input++) * data->inputGain;
|
data->buffer[p].r += (*input++) * data->inputGain;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#elif WRITE_AUDIO_INPUT_TO_BUFFER
|
||||||
|
if (input != NULL) {// && Audio::writeAudioInputToBuffer) {
|
||||||
|
unsigned int f = (unsigned int)frames,
|
||||||
|
p = data->bufferPos;
|
||||||
|
for (; p < data->bufferLength && f > 0; --f, ++p) {
|
||||||
|
data->inputBuffer[p].l = (*input++) * data->inputGain;
|
||||||
|
data->inputBuffer[p].r = (*input++) * data->inputGain;
|
||||||
|
}
|
||||||
|
if (f > 0) {
|
||||||
|
// handle data->buffer wraparound
|
||||||
|
for (p = 0; f > 0; --f, ++p) {
|
||||||
|
data->inputBuffer[p].l = (*input++) * data->inputGain;
|
||||||
|
data->inputBuffer[p].r = (*input++) * data->inputGain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
// Write data->buffer into outputBuffer
|
// Write data->buffer into outputBuffer
|
||||||
if (data->bufferPos + frames >= data->bufferLength) {
|
if (data->bufferPos + frames >= data->bufferLength) {
|
||||||
// wraparound: write first section (end of buffer) first
|
// wraparound: write first section (end of buffer) first
|
||||||
|
@ -143,7 +174,8 @@ error:
|
||||||
*/
|
*/
|
||||||
bool Audio::terminate ()
|
bool Audio::terminate ()
|
||||||
{
|
{
|
||||||
if (!initialized) return;
|
if (!initialized)
|
||||||
|
return true;
|
||||||
initialized = false;
|
initialized = false;
|
||||||
// err = Pa_StopStream(stream);
|
// err = Pa_StopStream(stream);
|
||||||
// if (err != paNoError) goto error;
|
// if (err != paNoError) goto error;
|
||||||
|
@ -171,7 +203,9 @@ error:
|
||||||
* @param[in] left Left channel of the audio stream.
|
* @param[in] left Left channel of the audio stream.
|
||||||
* @param[in] right Right channel of the audio stream.
|
* @param[in] right Right channel of the audio stream.
|
||||||
*/
|
*/
|
||||||
void Audio::writeAudio (unsigned int offset, unsigned int length, float *left, float *right) {
|
void Audio::writeAudio (unsigned int offset, unsigned int length, float const *left, float const *right) {
|
||||||
|
if (data->buffer == NULL)
|
||||||
|
return;
|
||||||
if (length > data->bufferLength) {
|
if (length > data->bufferLength) {
|
||||||
fprintf(stderr, "Audio::writeAudio length exceeded (%d). Truncating to %d.\n", length, data->bufferLength);
|
fprintf(stderr, "Audio::writeAudio length exceeded (%d). Truncating to %d.\n", length, data->bufferLength);
|
||||||
length = data->bufferLength;
|
length = data->bufferLength;
|
||||||
|
@ -200,7 +234,9 @@ void Audio::writeAudio (unsigned int offset, unsigned int length, float *left, f
|
||||||
* @param[in] left Left component.
|
* @param[in] left Left component.
|
||||||
* @param[in] right Right component.
|
* @param[in] right Right component.
|
||||||
*/
|
*/
|
||||||
void Audio::writeTone (unsigned int offset, unsigned int length, float left, float right) {
|
void Audio::writeTone (unsigned int offset, unsigned int length, float const left, float const right) {
|
||||||
|
if (data->buffer == NULL)
|
||||||
|
return;
|
||||||
if (length > data->bufferLength) {
|
if (length > data->bufferLength) {
|
||||||
fprintf(stderr, "Audio::writeTone length exceeded (%d). Truncating to %d.\n", length, data->bufferLength);
|
fprintf(stderr, "Audio::writeTone length exceeded (%d). Truncating to %d.\n", length, data->bufferLength);
|
||||||
length = data->bufferLength;
|
length = data->bufferLength;
|
||||||
|
@ -230,7 +266,9 @@ void Audio::writeTone (unsigned int offset, unsigned int length, float left, flo
|
||||||
* @param[in] left Left channel of the audio stream.
|
* @param[in] left Left channel of the audio stream.
|
||||||
* @param[in] right Right channel of the audio stream.
|
* @param[in] right Right channel of the audio stream.
|
||||||
*/
|
*/
|
||||||
void Audio::addAudio (unsigned int offset, unsigned int length, float *left, float *right) {
|
void Audio::addAudio (unsigned int offset, unsigned int length, float const *left, float const *right) {
|
||||||
|
if (data->buffer == NULL)
|
||||||
|
return;
|
||||||
if (length > data->bufferLength) {
|
if (length > data->bufferLength) {
|
||||||
fprintf(stderr, "Audio::addAudio length exceeded (%d). Truncating to %d.\n", length, data->bufferLength);
|
fprintf(stderr, "Audio::addAudio length exceeded (%d). Truncating to %d.\n", length, data->bufferLength);
|
||||||
length = data->bufferLength;
|
length = data->bufferLength;
|
||||||
|
@ -260,7 +298,9 @@ void Audio::addAudio (unsigned int offset, unsigned int length, float *left, flo
|
||||||
* @param[in] left Left component.
|
* @param[in] left Left component.
|
||||||
* @param[in] right Right component.
|
* @param[in] right Right component.
|
||||||
*/
|
*/
|
||||||
void Audio::addTone (unsigned int offset, unsigned int length, float left, float right) {
|
void Audio::addTone (unsigned int offset, unsigned int length, float const left, float const right) {
|
||||||
|
if (data->buffer == NULL)
|
||||||
|
return;
|
||||||
if (length > data->bufferLength) {
|
if (length > data->bufferLength) {
|
||||||
fprintf(stderr, "Audio::writeTone length exceeded (%d). Truncating to %d.\n", length, data->bufferLength);
|
fprintf(stderr, "Audio::writeTone length exceeded (%d). Truncating to %d.\n", length, data->bufferLength);
|
||||||
length = data->bufferLength;
|
length = data->bufferLength;
|
||||||
|
@ -286,6 +326,8 @@ void Audio::addTone (unsigned int offset, unsigned int length, float left, float
|
||||||
* @param[in] length Length of section to clear.
|
* @param[in] length Length of section to clear.
|
||||||
*/
|
*/
|
||||||
void Audio::clearAudio(unsigned int offset, unsigned int length) {
|
void Audio::clearAudio(unsigned int offset, unsigned int length) {
|
||||||
|
if (data->buffer == NULL)
|
||||||
|
return;
|
||||||
if (length > data->bufferLength) {
|
if (length > data->bufferLength) {
|
||||||
fprintf(stderr, "Audio::clearAudio length exceeded (%d). Truncating to %d.\n", length, data->bufferLength);
|
fprintf(stderr, "Audio::clearAudio length exceeded (%d). Truncating to %d.\n", length, data->bufferLength);
|
||||||
length = data->bufferLength;
|
length = data->bufferLength;
|
||||||
|
@ -304,7 +346,39 @@ void Audio::clearAudio(unsigned int offset, unsigned int length) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read audio input into the target buffer.
|
||||||
|
* @param[in] offset Offset from the start of the input audio buffer to read from.
|
||||||
|
* @param[in] length Length of the target buffer.
|
||||||
|
* @param[out] left Left channel of the target buffer.
|
||||||
|
* @param[out] right Right channel of the target buffer.
|
||||||
|
*/
|
||||||
|
void Audio::readAudioInput (unsigned int offset, unsigned int length, float *left, float *right) {
|
||||||
|
#if WRITE_AUDIO_INPUT_TO_BUFFER
|
||||||
|
if (data->inputBuffer == NULL)
|
||||||
|
return;
|
||||||
|
if (length + offset > data->bufferLength) {
|
||||||
|
fprintf(stderr, "Audio::readAudioInput length exceeded (%d + %d). Truncating to %d + %d.\n", offset, length, offset, data->bufferLength - offset);
|
||||||
|
length = data->bufferLength - offset;
|
||||||
|
}
|
||||||
|
unsigned int p = data->bufferPos + offset;
|
||||||
|
if (p > data->bufferLength)
|
||||||
|
p -= data->bufferLength;
|
||||||
|
for (; p < data->bufferLength && length > 0; --length, ++p) {
|
||||||
|
*left++ = data->inputBuffer[p].l;
|
||||||
|
*right++ = data->inputBuffer[p].r;
|
||||||
|
}
|
||||||
|
if (length > 0) {
|
||||||
|
p = 0;
|
||||||
|
for (; length > 0; --length, ++p) {
|
||||||
|
*left++ = data->inputBuffer[p].l;
|
||||||
|
*right++ = data->inputBuffer[p].r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
46
audio.h
46
audio.h
|
@ -13,6 +13,24 @@
|
||||||
|
|
||||||
// Note: main documentation in audio.cpp
|
// 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.
|
* Low level audio interface.
|
||||||
*
|
*
|
||||||
|
@ -30,12 +48,16 @@ public:
|
||||||
static bool terminate ();
|
static bool terminate ();
|
||||||
|
|
||||||
// Write methods: write to internal audio buffer.
|
// Write methods: write to internal audio buffer.
|
||||||
static void writeAudio (unsigned int offset, unsigned int length, float *left, float *right);
|
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 *left, float *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 left, float 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 left, float 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);
|
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)
|
* Set the audio input gain. (multiplier applied to mic input)
|
||||||
*/
|
*/
|
||||||
|
@ -69,7 +91,7 @@ private:
|
||||||
*/
|
*/
|
||||||
struct BufferFrame{
|
struct BufferFrame{
|
||||||
float l, r;
|
float l, r;
|
||||||
} *buffer;
|
} *buffer, *inputBuffer;
|
||||||
/**
|
/**
|
||||||
* Length of the audio buffer.
|
* Length of the audio buffer.
|
||||||
*/
|
*/
|
||||||
|
@ -88,14 +110,20 @@ private:
|
||||||
AudioData () : bufferPos(0) {
|
AudioData () : bufferPos(0) {
|
||||||
inputGain = 1.0f;
|
inputGain = 1.0f;
|
||||||
buffer = new BufferFrame[bufferLength];
|
buffer = new BufferFrame[bufferLength];
|
||||||
for (unsigned int i = 0; i < bufferLength; ++i) {
|
memset((float*)buffer, 0, sizeof(float) * bufferLength * 2);
|
||||||
buffer[i].l = buffer[i].r = 0;
|
#if WRITE_AUDIO_INPUT_TO_BUFFER
|
||||||
}
|
inputBuffer = new BufferFrame[bufferLength];
|
||||||
|
memset((float*)inputBuffer, 0, sizeof(float) * bufferLength * 2);
|
||||||
|
#else
|
||||||
|
inputBuffer = NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
~AudioData () {
|
~AudioData () {
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
|
#if WRITE_AUDIO_INPUT_TO_BUFFER
|
||||||
|
delete[] inputBuffer;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}*data;
|
}*data;
|
||||||
/**
|
/**
|
||||||
* Internal audio stream handle.
|
* Internal audio stream handle.
|
||||||
|
|
|
@ -216,6 +216,10 @@
|
||||||
"\"$(SRCROOT)\"",
|
"\"$(SRCROOT)\"",
|
||||||
/usr/local/lib,
|
/usr/local/lib,
|
||||||
);
|
);
|
||||||
|
OTHER_CPLUSPLUSFLAGS = (
|
||||||
|
"-O3",
|
||||||
|
"$(OTHER_CFLAGS)",
|
||||||
|
);
|
||||||
PRODUCT_NAME = interface;
|
PRODUCT_NAME = interface;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
|
@ -233,6 +237,10 @@
|
||||||
"\"$(SRCROOT)\"",
|
"\"$(SRCROOT)\"",
|
||||||
/usr/local/lib,
|
/usr/local/lib,
|
||||||
);
|
);
|
||||||
|
OTHER_CPLUSPLUSFLAGS = (
|
||||||
|
"-O3",
|
||||||
|
"$(OTHER_CFLAGS)",
|
||||||
|
);
|
||||||
PRODUCT_NAME = interface;
|
PRODUCT_NAME = interface;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
|
|
Binary file not shown.
Loading…
Reference in a new issue