mirror of https://github.com/bjornbytes/lovr.git
Add Microphone objects for audio capture;
This commit is contained in:
parent
889144cc45
commit
b650f2b770
|
@ -255,6 +255,7 @@ set(LOVR_SRC
|
|||
src/api/types/joints.c
|
||||
src/api/types/material.c
|
||||
src/api/types/mesh.c
|
||||
src/api/types/microphone.c
|
||||
src/api/types/model.c
|
||||
src/api/types/modelData.c
|
||||
src/api/types/randomGenerator.c
|
||||
|
@ -269,6 +270,7 @@ set(LOVR_SRC
|
|||
src/api/types/vertexData.c
|
||||
src/api/types/world.c
|
||||
src/audio/audio.c
|
||||
src/audio/microphone.c
|
||||
src/audio/source.c
|
||||
src/data/audioStream.c
|
||||
src/data/blob.c
|
||||
|
|
|
@ -49,6 +49,7 @@ extern const luaL_Reg lovrHingeJoint[];
|
|||
extern const luaL_Reg lovrJoint[];
|
||||
extern const luaL_Reg lovrMaterial[];
|
||||
extern const luaL_Reg lovrMesh[];
|
||||
extern const luaL_Reg lovrMicrophone[];
|
||||
extern const luaL_Reg lovrModel[];
|
||||
extern const luaL_Reg lovrModelData[];
|
||||
extern const luaL_Reg lovrRandomGenerator[];
|
||||
|
|
|
@ -18,6 +18,7 @@ const char* TimeUnits[] = {
|
|||
int l_lovrAudioInit(lua_State* L) {
|
||||
lua_newtable(L);
|
||||
luaL_register(L, NULL, lovrAudio);
|
||||
luax_registertype(L, "Microphone", lovrMicrophone);
|
||||
luax_registertype(L, "Source", lovrSource);
|
||||
lovrAudioInit();
|
||||
return 1;
|
||||
|
@ -36,6 +37,26 @@ int l_lovrAudioGetDopplerEffect(lua_State* L) {
|
|||
return 2;
|
||||
}
|
||||
|
||||
int l_lovrAudioGetMicrophoneNames(lua_State* L) {
|
||||
const char* names[MAX_MICROPHONES];
|
||||
uint8_t count;
|
||||
lovrAudioGetMicrophoneNames(names, &count);
|
||||
|
||||
if (lua_istable(L, 1)) {
|
||||
lua_settop(L, 1);
|
||||
} else {
|
||||
lua_settop(L, 0);
|
||||
lua_createtable(L, count, 0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
lua_pushstring(L, names[i]);
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrAudioGetOrientation(lua_State* L) {
|
||||
float angle, ax, ay, az;
|
||||
lovrAudioGetOrientation(&angle, &ax, &ay, &az);
|
||||
|
@ -74,6 +95,18 @@ int l_lovrAudioIsSpatialized(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrAudioNewMicrophone(lua_State* L) {
|
||||
const char* name = luaL_optstring(L, 1, NULL);
|
||||
int samples = luaL_optinteger(L, 2, 1024);
|
||||
int sampleRate = luaL_optinteger(L, 3, 8000);
|
||||
int bitDepth = luaL_optinteger(L, 4, 16);
|
||||
int channelCount = luaL_optinteger(L, 5, 1);
|
||||
Microphone* microphone = lovrMicrophoneCreate(name, samples, sampleRate, bitDepth, channelCount);
|
||||
luax_pushtype(L, Microphone, microphone);
|
||||
lovrRelease(microphone);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrAudioNewSource(lua_State* L) {
|
||||
Source* source = NULL;
|
||||
SoundData** soundDataRef = luax_totype(L, 1, SoundData);
|
||||
|
@ -177,11 +210,13 @@ int l_lovrAudioStop(lua_State* L) {
|
|||
const luaL_Reg lovrAudio[] = {
|
||||
{ "update", l_lovrAudioUpdate },
|
||||
{ "getDopplerEffect", l_lovrAudioGetDopplerEffect },
|
||||
{ "getMicrophoneNames", l_lovrAudioGetMicrophoneNames },
|
||||
{ "getOrientation", l_lovrAudioGetOrientation },
|
||||
{ "getPosition", l_lovrAudioGetPosition },
|
||||
{ "getVelocity", l_lovrAudioGetVelocity },
|
||||
{ "getVolume", l_lovrAudioGetVolume },
|
||||
{ "isSpatialized", l_lovrAudioIsSpatialized },
|
||||
{ "newMicrophone", l_lovrAudioNewMicrophone },
|
||||
{ "newSource", l_lovrAudioNewSource },
|
||||
{ "pause", l_lovrAudioPause },
|
||||
{ "resume", l_lovrAudioResume },
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
#include "api.h"
|
||||
#include "audio/microphone.h"
|
||||
|
||||
int l_lovrMicrophoneGetBitDepth(lua_State* L) {
|
||||
Microphone* microphone = luax_checktype(L, 1, Microphone);
|
||||
lua_pushinteger(L, lovrMicrophoneGetBitDepth(microphone));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrMicrophoneGetChannelCount(lua_State* L) {
|
||||
Microphone* microphone = luax_checktype(L, 1, Microphone);
|
||||
lua_pushinteger(L, lovrMicrophoneGetChannelCount(microphone));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrMicrophoneGetData(lua_State* L) {
|
||||
Microphone* microphone = luax_checktype(L, 1, Microphone);
|
||||
SoundData* soundData = lovrMicrophoneGetData(microphone);
|
||||
luax_pushtype(L, SoundData, soundData);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrMicrophoneGetName(lua_State* L) {
|
||||
Microphone* microphone = luax_checktype(L, 1, Microphone);
|
||||
lua_pushstring(L, lovrMicrophoneGetName(microphone));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrMicrophoneGetSampleCount(lua_State* L) {
|
||||
Microphone* microphone = luax_checktype(L, 1, Microphone);
|
||||
lua_pushinteger(L, lovrMicrophoneGetSampleCount(microphone));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrMicrophoneGetSampleRate(lua_State* L) {
|
||||
Microphone* microphone = luax_checktype(L, 1, Microphone);
|
||||
lua_pushinteger(L, lovrMicrophoneGetSampleRate(microphone));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrMicrophoneIsRecording(lua_State* L) {
|
||||
Microphone* microphone = luax_checktype(L, 1, Microphone);
|
||||
lua_pushboolean(L, lovrMicrophoneIsRecording(microphone));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrMicrophoneStartRecording(lua_State* L) {
|
||||
Microphone* microphone = luax_checktype(L, 1, Microphone);
|
||||
lovrMicrophoneStartRecording(microphone);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrMicrophoneStopRecording(lua_State* L) {
|
||||
Microphone* microphone = luax_checktype(L, 1, Microphone);
|
||||
lovrMicrophoneStopRecording(microphone);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg lovrMicrophone[] = {
|
||||
{ "getBitDepth", l_lovrMicrophoneGetBitDepth },
|
||||
{ "getChannelCount", l_lovrMicrophoneGetChannelCount },
|
||||
{ "getData", l_lovrMicrophoneGetData },
|
||||
{ "getName", l_lovrMicrophoneGetName },
|
||||
{ "getSampleCount", l_lovrMicrophoneGetSampleCount },
|
||||
{ "getSampleRate", l_lovrMicrophoneGetSampleRate },
|
||||
{ "isRecording", l_lovrMicrophoneIsRecording },
|
||||
{ "startRecording", l_lovrMicrophoneStartRecording },
|
||||
{ "stopRecording", l_lovrMicrophoneStopRecording },
|
||||
{ NULL, NULL }
|
||||
};
|
|
@ -6,6 +6,20 @@
|
|||
|
||||
static AudioState state;
|
||||
|
||||
ALenum lovrAudioConvertFormat(int bitDepth, int channelCount) {
|
||||
if (bitDepth == 8 && channelCount == 1) {
|
||||
return AL_FORMAT_MONO8;
|
||||
} else if (bitDepth == 8 && channelCount == 2) {
|
||||
return AL_FORMAT_STEREO8;
|
||||
} else if (bitDepth == 16 && channelCount == 1) {
|
||||
return AL_FORMAT_MONO16;
|
||||
} else if (bitDepth == 16 && channelCount == 2) {
|
||||
return AL_FORMAT_STEREO16;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lovrAudioInit() {
|
||||
if (state.initialized) return;
|
||||
|
||||
|
@ -84,6 +98,15 @@ void lovrAudioGetDopplerEffect(float* factor, float* speedOfSound) {
|
|||
alGetFloatv(AL_SPEED_OF_SOUND, speedOfSound);
|
||||
}
|
||||
|
||||
void lovrAudioGetMicrophoneNames(const char* names[MAX_MICROPHONES], uint8_t* count) {
|
||||
const char* name = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
|
||||
*count = 0;
|
||||
while (*name) {
|
||||
names[(*count)++] = name;
|
||||
name += strlen(name);
|
||||
}
|
||||
}
|
||||
|
||||
void lovrAudioGetOrientation(float* angle, float* ax, float* ay, float* az) {
|
||||
quat_getAngleAxis(state.orientation, angle, ax, ay, az);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "audio/source.h"
|
||||
#include "audio/microphone.h"
|
||||
#include "lib/vec/vec.h"
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
|
@ -7,6 +8,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#define MAX_MICROPHONES 8
|
||||
|
||||
typedef struct {
|
||||
bool initialized;
|
||||
ALCdevice* device;
|
||||
|
@ -18,11 +21,14 @@ typedef struct {
|
|||
float velocity[3];
|
||||
} AudioState;
|
||||
|
||||
ALenum lovrAudioConvertFormat(int bitDepth, int channelCount);
|
||||
|
||||
void lovrAudioInit();
|
||||
void lovrAudioDestroy();
|
||||
void lovrAudioUpdate();
|
||||
void lovrAudioAdd(Source* source);
|
||||
void lovrAudioGetDopplerEffect(float* factor, float* speedOfSound);
|
||||
void lovrAudioGetMicrophoneNames(const char* names[MAX_MICROPHONES], uint8_t* count);
|
||||
void lovrAudioGetOrientation(float* angle, float* ax, float* ay, float* az);
|
||||
void lovrAudioGetPosition(float* x, float* y, float* z);
|
||||
void lovrAudioGetVelocity(float* x, float* y, float* z);
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
#include "audio/microphone.h"
|
||||
#include "audio/audio.h"
|
||||
|
||||
Microphone* lovrMicrophoneCreate(const char* name, int samples, int sampleRate, int bitDepth, int channelCount) {
|
||||
Microphone* microphone = lovrAlloc(sizeof(Microphone), lovrMicrophoneDestroy);
|
||||
if (!microphone) return NULL;
|
||||
|
||||
ALCdevice* device = alcCaptureOpenDevice(name, sampleRate, lovrAudioConvertFormat(bitDepth, channelCount), samples);
|
||||
|
||||
if (!device) {
|
||||
free(microphone);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
microphone->device = device;
|
||||
microphone->name = name ? name : alcGetString(device, ALC_CAPTURE_DEVICE_SPECIFIER);
|
||||
microphone->sampleRate = sampleRate;
|
||||
microphone->bitDepth = bitDepth;
|
||||
microphone->channelCount = channelCount;
|
||||
|
||||
return microphone;
|
||||
}
|
||||
|
||||
void lovrMicrophoneDestroy(void* ref) {
|
||||
Microphone* microphone = ref;
|
||||
alcCaptureCloseDevice(microphone->device);
|
||||
free(microphone);
|
||||
}
|
||||
|
||||
int lovrMicrophoneGetBitDepth(Microphone* microphone) {
|
||||
return microphone->bitDepth;
|
||||
}
|
||||
|
||||
int lovrMicrophoneGetChannelCount(Microphone* microphone) {
|
||||
return microphone->channelCount;
|
||||
}
|
||||
|
||||
SoundData* lovrMicrophoneGetData(Microphone* microphone) {
|
||||
if (!microphone->isRecording) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int samples = lovrMicrophoneGetSampleCount(microphone);
|
||||
if (samples == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SoundData* soundData = lovrSoundDataCreate(samples, microphone->sampleRate, microphone->bitDepth, microphone->channelCount);
|
||||
alcCaptureSamples(microphone->device, soundData->blob.data, samples);
|
||||
return soundData;
|
||||
}
|
||||
|
||||
const char* lovrMicrophoneGetName(Microphone* microphone) {
|
||||
return microphone->name;
|
||||
}
|
||||
|
||||
int lovrMicrophoneGetSampleCount(Microphone* microphone) {
|
||||
if (!microphone->isRecording) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ALCint samples;
|
||||
alcGetIntegerv(microphone->device, ALC_CAPTURE_SAMPLES, sizeof(ALCint), &samples);
|
||||
return (int) samples;
|
||||
}
|
||||
|
||||
int lovrMicrophoneGetSampleRate(Microphone* microphone) {
|
||||
return microphone->sampleRate;
|
||||
}
|
||||
|
||||
bool lovrMicrophoneIsRecording(Microphone* microphone) {
|
||||
return microphone->isRecording;
|
||||
}
|
||||
|
||||
void lovrMicrophoneStartRecording(Microphone* microphone) {
|
||||
if (microphone->isRecording) {
|
||||
return;
|
||||
}
|
||||
|
||||
alcCaptureStart(microphone->device);
|
||||
microphone->isRecording = true;
|
||||
}
|
||||
|
||||
void lovrMicrophoneStopRecording(Microphone* microphone) {
|
||||
if (!microphone->isRecording) {
|
||||
return;
|
||||
}
|
||||
|
||||
microphone->isRecording = false;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#include "util.h"
|
||||
#include "data/soundData.h"
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef struct {
|
||||
Ref ref;
|
||||
ALCdevice* device;
|
||||
bool isRecording;
|
||||
const char* name;
|
||||
int sampleRate;
|
||||
int bitDepth;
|
||||
int channelCount;
|
||||
} Microphone;
|
||||
|
||||
Microphone* lovrMicrophoneCreate(const char* name, int samples, int sampleRate, int bitDepth, int channelCount);
|
||||
void lovrMicrophoneDestroy(void* ref);
|
||||
int lovrMicrophoneGetBitDepth(Microphone* microphone);
|
||||
int lovrMicrophoneGetChannelCount(Microphone* microphone);
|
||||
SoundData* lovrMicrophoneGetData(Microphone* microphone);
|
||||
const char* lovrMicrophoneGetName(Microphone* microphone);
|
||||
int lovrMicrophoneGetSampleCount(Microphone* microphone);
|
||||
int lovrMicrophoneGetSampleRate(Microphone* microphone);
|
||||
bool lovrMicrophoneIsRecording(Microphone* microphone);
|
||||
void lovrMicrophoneStartRecording(Microphone* microphone);
|
||||
void lovrMicrophoneStopRecording(Microphone* microphone);
|
|
@ -1,26 +1,10 @@
|
|||
#include "audio/source.h"
|
||||
#include "audio/audio.h"
|
||||
#include "data/audioStream.h"
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static ALenum lovrSourceGetFormat(Source* source) {
|
||||
int channelCount = source->type == SOURCE_STATIC ? source->soundData->channelCount : source->stream->channelCount;
|
||||
int bitDepth = source->type == SOURCE_STATIC ? source->soundData->bitDepth : source->stream->bitDepth;
|
||||
|
||||
if (bitDepth == 8 && channelCount == 1) {
|
||||
return AL_FORMAT_MONO8;
|
||||
} else if (bitDepth == 8 && channelCount == 2) {
|
||||
return AL_FORMAT_STEREO8;
|
||||
} else if (bitDepth == 16 && channelCount == 1) {
|
||||
return AL_FORMAT_MONO16;
|
||||
} else if (bitDepth == 16 && channelCount == 2) {
|
||||
return AL_FORMAT_STEREO16;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ALenum lovrSourceGetState(Source* source) {
|
||||
ALenum state;
|
||||
alGetSourcei(source->id, AL_SOURCE_STATE, &state);
|
||||
|
@ -31,11 +15,12 @@ Source* lovrSourceCreateStatic(SoundData* soundData) {
|
|||
Source* source = lovrAlloc(sizeof(Source), lovrSourceDestroy);
|
||||
if (!source) return NULL;
|
||||
|
||||
ALenum format = lovrAudioConvertFormat(soundData->bitDepth, soundData->channelCount);
|
||||
source->type = SOURCE_STATIC;
|
||||
source->soundData = soundData;
|
||||
alGenSources(1, &source->id);
|
||||
alGenBuffers(1, source->buffers);
|
||||
alBufferData(source->buffers[0], lovrSourceGetFormat(source), soundData->blob.data, soundData->blob.size, soundData->sampleRate);
|
||||
alBufferData(source->buffers[0], format, soundData->blob.data, soundData->blob.size, soundData->sampleRate);
|
||||
alSourcei(source->id, AL_BUFFER, source->buffers[0]);
|
||||
lovrRetain(soundData);
|
||||
|
||||
|
@ -299,7 +284,7 @@ void lovrSourceStream(Source* source, ALuint* buffers, int count) {
|
|||
}
|
||||
|
||||
AudioStream* stream = source->stream;
|
||||
ALenum format = lovrSourceGetFormat(source);
|
||||
ALenum format = lovrAudioConvertFormat(stream->bitDepth, stream->channelCount);
|
||||
int frequency = stream->sampleRate;
|
||||
int samples = 0;
|
||||
int n = 0;
|
||||
|
|
Loading…
Reference in New Issue