Added sound input and recording functionality.

This commit is contained in:
Bill Meltsner
2010-04-11 12:22:40 -04:00
parent 3b841423fa
commit 585e3ec3ee
9 changed files with 278 additions and 123 deletions
+34 -4
View File
@@ -49,14 +49,14 @@ namespace audio
virtual Source * newSource(love::sound::SoundData * soundData) = 0; virtual Source * newSource(love::sound::SoundData * soundData) = 0;
/** /**
* Gets the current number of simulatenous playing sources. * Gets the current number of simultaneous playing sources.
* @return The current number of simulatenous playing sources. * @return The current number of simultaneous playing sources.
**/ **/
virtual int getNumSources() const = 0; virtual int getNumSources() const = 0;
/** /**
* Gets the maximum supported number of simulatenous playing sources. * Gets the maximum supported number of simultaneous playing sources.
* @return The maximum supported number of simulatenous playing sources. * @return The maximum supported number of simultaneous playing sources.
**/ **/
virtual int getMaxSources() const = 0; virtual int getMaxSources() const = 0;
@@ -161,6 +161,36 @@ namespace audio
**/ **/
virtual void setVelocity(float * v) = 0; virtual void setVelocity(float * v) = 0;
/**
* Begins recording audio input from the microphone.
**/
virtual void record() = 0;
/**
* Gets a section of recorded audio.
* Per OpenAL, the measurement begins from the start of the
* audio data in memory, which is after the last time this function
* was called. If this function has not been called yet this recording
* session, it just grabs from the beginning.
* @return All the recorded SoundData thus far.
**/
virtual love::sound::SoundData * getRecordedData() = 0;
/**
* Stops recording and, if passed true, returns all the recorded audio
* not already gotten by getRecordedData.
* @param returnData Whether to return recorded audio.
* @return if returnData, all the recorded audio yet to be gotten,
* otherwise NULL.
**/
virtual love::sound::SoundData * stopRecording(bool returnData) = 0;
/**
* Checks whether LOVE is able to record audio input.
* @return hasMic Whether LOVE has a microphone enabled.
**/
virtual bool canRecord() = 0;
}; // Audio }; // Audio
} // audio } // audio
+19
View File
@@ -133,6 +133,25 @@ namespace null
{ {
} }
void Audio::record()
{
}
love::sound::SoundData * Audio::getRecordedData()
{
return NULL;
}
love::sound::SoundData * Audio::stopRecording(bool)
{
return NULL;
}
bool Audio::canRecord()
{
return false;
}
} // null } // null
} // audio } // audio
} // love } // love
+5
View File
@@ -69,6 +69,11 @@ namespace null
void getVelocity(float * v) const; void getVelocity(float * v) const;
void setVelocity(float * v); void setVelocity(float * v);
void record();
love::sound::SoundData * getRecordedData();
love::sound::SoundData * stopRecording(bool returnData);
bool canRecord();
}; // Audio }; // Audio
} // null } // null
+46
View File
@@ -20,6 +20,8 @@
#include "Audio.h" #include "Audio.h"
#include <sound/Decoder.h>
namespace love namespace love
{ {
namespace audio namespace audio
@@ -45,6 +47,14 @@ namespace openal
if(alcGetError(device) != ALC_NO_ERROR) if(alcGetError(device) != ALC_NO_ERROR)
throw love::Exception("Could not make context current."); throw love::Exception("Could not make context current.");
capture = alcCaptureOpenDevice(alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
love::sound::Decoder::DEFAULT_SAMPLE_RATE, AL_FORMAT_MONO16, 1048576); // about 23 seconds
if (!capture) {
// We're not going to prevent LOVE from running without a microphone, but we should warn, at least
std::cerr << "Warning, couldn't open capture device! No audio input!" << std::endl;
}
// pool must be allocated after AL context. // pool must be allocated after AL context.
pool = new Pool(); pool = new Pool();
@@ -61,6 +71,7 @@ namespace openal
alcMakeContextCurrent(0); alcMakeContextCurrent(0);
alcDestroyContext(context); alcDestroyContext(context);
alcCaptureCloseDevice(capture);
alcCloseDevice(device); alcCloseDevice(device);
} }
@@ -189,6 +200,41 @@ namespace openal
alListenerfv(AL_VELOCITY, v); alListenerfv(AL_VELOCITY, v);
} }
void Audio::record()
{
if (!canRecord()) return;
alcCaptureStart(capture);
}
love::sound::SoundData * Audio::getRecordedData()
{
if (!canRecord()) return NULL;
int samplerate = love::sound::Decoder::DEFAULT_SAMPLE_RATE;
ALCint samples;
alcGetIntegerv(capture, ALC_CAPTURE_SAMPLES, 4, &samples);
void * data = malloc(samples * (2/sizeof(char)));
alcCaptureSamples(capture, data, samples);
love::sound::SoundData * sd = new love::sound::SoundData(data, samples, samplerate, 16, 1);
free(data);
return sd;
}
love::sound::SoundData * Audio::stopRecording(bool returnData)
{
if (!canRecord()) return NULL;
love::sound::SoundData * sd = NULL;
if (returnData) {
sd = getRecordedData();
}
alcCaptureStop(capture);
return sd;
}
bool Audio::canRecord()
{
return (capture != NULL);
}
} // openal } // openal
} // audio } // audio
} // love } // love
+8
View File
@@ -60,6 +60,9 @@ namespace openal
// The OpenAL device. // The OpenAL device.
ALCdevice * device; ALCdevice * device;
// The OpenAL capture device (microphone).
ALCdevice * capture;
// The OpenAL context. // The OpenAL context.
ALCcontext * context; ALCcontext * context;
@@ -108,6 +111,11 @@ namespace openal
void getVelocity(float * v) const; void getVelocity(float * v) const;
void setVelocity(float * v); void setVelocity(float * v);
void record();
love::sound::SoundData * getRecordedData();
love::sound::SoundData * stopRecording(bool returnData);
bool canRecord();
}; // Audio }; // Audio
} // openal } // openal
+35
View File
@@ -26,6 +26,8 @@
#include <scripts/audio.lua.h> #include <scripts/audio.lua.h>
#include <common/runtime.h>
namespace love namespace love
{ {
namespace audio namespace audio
@@ -201,6 +203,36 @@ namespace audio
return 3; return 3;
} }
int w_record(lua_State *)
{
instance->record();
return 0;
}
int w_getRecordedData(lua_State * L)
{
love::sound::SoundData * sd = instance->getRecordedData();
luax_newtype(L, "SoundData", SOUND_SOUND_DATA_T, (void*)sd);
return 1;
}
int w_stopRecording(lua_State * L)
{
if (luax_optboolean(L, 1, true)) {
love::sound::SoundData * sd = instance->stopRecording(true);
luax_newtype(L, "SoundData", SOUND_SOUND_DATA_T, (void*)sd);
return 1;
}
instance->stopRecording(false);
return 0;
}
int w_canRecord(lua_State * L) {
luax_pushboolean(L, instance->canRecord());
return 1;
}
// List of functions to wrap. // List of functions to wrap.
static const luaL_Reg functions[] = { static const luaL_Reg functions[] = {
{ "getNumSources", w_getNumSources }, { "getNumSources", w_getNumSources },
@@ -218,6 +250,9 @@ namespace audio
{ "getOrientation", w_getOrientation }, { "getOrientation", w_getOrientation },
{ "setVelocity", w_setVelocity }, { "setVelocity", w_setVelocity },
{ "getVelocity", w_getVelocity }, { "getVelocity", w_getVelocity },
{ "record", w_record },
{ "getRecordedData", w_getRecordedData },
{ "stopRecording", w_stopRecording },
{ 0, 0 } { 0, 0 }
}; };
+4
View File
@@ -46,6 +46,10 @@ namespace audio
int w_getOrientation(lua_State * L); int w_getOrientation(lua_State * L);
int w_setVelocity(lua_State * L); int w_setVelocity(lua_State * L);
int w_getVelocity(lua_State * L); int w_getVelocity(lua_State * L);
int w_record(lua_State * L);
int w_getRecordedData(lua_State * L);
int w_stopRecording(lua_State * L);
int w_canRecord(lua_State * L);
extern "C" LOVE_EXPORT int luaopen_love_audio(lua_State * L); extern "C" LOVE_EXPORT int luaopen_love_audio(lua_State * L);
} // audio } // audio
+7
View File
@@ -64,6 +64,13 @@ namespace sound
data = (char*)malloc(size); data = (char*)malloc(size);
} }
SoundData::SoundData(void * d, int samples, int sampleRate, int bits, int channels)
: data(0), size(samples*(bits/8)), sampleRate(sampleRate), bits(bits), channels(channels)
{
data = (char*)malloc(size);
memcpy(data, d, size);
}
SoundData::~SoundData() SoundData::~SoundData()
{ {
if(data != 0) if(data != 0)
+1
View File
@@ -45,6 +45,7 @@ namespace sound
SoundData(Decoder * decoder); SoundData(Decoder * decoder);
SoundData(int samples, int sampleRate, int bits, int channels); SoundData(int samples, int sampleRate, int bits, int channels);
SoundData(void * d, int samples, int sampleRate, int bits, int channels);
virtual ~SoundData(); virtual ~SoundData();