Source:setPitch;

Co-authored-by: Nevyn Bengtsson <nevyn@alloverse.com>
This commit is contained in:
bjorn 2022-09-11 20:41:58 -07:00
parent 1c9adea2e2
commit d8c23bacec
4 changed files with 51 additions and 4 deletions

View File

@ -229,6 +229,7 @@ static int l_lovrAudioNewSource(lua_State* L) {
Sound* sound = luax_totype(L, 1, Sound);
bool decode = false;
bool pitchable = false;
bool spatial = true;
uint32_t effects = ~0u;
if (lua_gettop(L) >= 2) {
@ -238,6 +239,10 @@ static int l_lovrAudioNewSource(lua_State* L) {
decode = lua_toboolean(L, -1);
lua_pop(L, 1);
lua_getfield(L, 2, "pitchable");
pitchable = lua_toboolean(L, -1);
lua_pop(L, 1);
lua_getfield(L, 2, "effects");
if (!lua_isnil(L, -1)) {
effects = 0;
@ -270,7 +275,7 @@ static int l_lovrAudioNewSource(lua_State* L) {
lovrRetain(sound);
}
Source* source = lovrSourceCreate(sound, spatial, effects);
Source* source = lovrSourceCreate(sound, pitchable, spatial, effects);
luax_pushtype(L, Source, source);
lovrRelease(sound, lovrSoundDestroy);
lovrRelease(source, lovrSourceDestroy);

View File

@ -57,6 +57,18 @@ static int l_lovrSourceSetLooping(lua_State* L) {
return 0;
}
static int l_lovrSourceGetPitch(lua_State* L) {
Source* source = luax_checktype(L, 1, Source);
lua_pushnumber(L, lovrSourceGetPitch(source));
return 1;
}
static int l_lovrSourceSetPitch(lua_State* L) {
Source* source = luax_checktype(L, 1, Source);
lovrSourceSetPitch(source, luax_checkfloat(L, 2));
return 0;
}
static int l_lovrSourceGetVolume(lua_State* L) {
Source* source = luax_checktype(L, 1, Source);
VolumeUnit units = luax_checkenum(L, 2, VolumeUnit, "linear");
@ -224,6 +236,8 @@ const luaL_Reg lovrSource[] = {
{ "isPlaying", l_lovrSourceIsPlaying },
{ "isLooping", l_lovrSourceIsLooping },
{ "setLooping", l_lovrSourceSetLooping },
{ "getPitch", l_lovrSourceGetPitch },
{ "setPitch", l_lovrSourceSetPitch },
{ "getVolume", l_lovrSourceGetVolume },
{ "setVolume", l_lovrSourceSetVolume },
{ "seek", l_lovrSourceSeek },

View File

@ -25,6 +25,7 @@ struct Source {
ma_data_converter* converter;
intptr_t spatializerMemo;
uint32_t offset;
float pitch;
float volume;
float position[4];
float orientation[4];
@ -34,6 +35,7 @@ struct Source {
uint8_t effects;
bool playing;
bool looping;
bool pitchable;
bool spatial;
};
@ -379,7 +381,7 @@ void lovrAudioSetAbsorption(float absorption[3]) {
// Source
Source* lovrSourceCreate(Sound* sound, bool spatial, uint32_t effects) {
Source* lovrSourceCreate(Sound* sound, bool pitchable, bool spatial, uint32_t effects) {
lovrAssert(lovrSoundGetChannelLayout(sound) != CHANNEL_AMBISONIC, "Ambisonic Sources are not currently supported");
Source* source = calloc(1, sizeof(Source));
lovrAssert(source, "Out of memory");
@ -388,7 +390,9 @@ Source* lovrSourceCreate(Sound* sound, bool spatial, uint32_t effects) {
source->sound = sound;
lovrRetain(source->sound);
source->pitch = 1.f;
source->volume = 1.f;
source->pitchable = pitchable;
source->spatial = spatial;
source->effects = spatial ? effects : 0;
quat_identity(source->orientation);
@ -400,8 +404,9 @@ Source* lovrSourceCreate(Sound* sound, bool spatial, uint32_t effects) {
config.channelsOut = spatial ? 1 : 2;
config.sampleRateIn = lovrSoundGetSampleRate(sound);
config.sampleRateOut = state.sampleRate;
config.allowDynamicSampleRate = pitchable;
if (config.formatIn != config.formatOut || config.channelsIn != config.channelsOut || config.sampleRateIn != config.sampleRateOut) {
if (pitchable || config.formatIn != config.formatOut || config.channelsIn != config.channelsOut || config.sampleRateIn != config.sampleRateOut) {
source->converter = malloc(sizeof(ma_data_converter));
lovrAssert(source->converter, "Out of memory");
ma_result status = ma_data_converter_init(&config, NULL, source->converter);
@ -418,6 +423,7 @@ Source* lovrSourceClone(Source* source) {
clone->index = ~0u;
clone->sound = source->sound;
lovrRetain(clone->sound);
clone->pitch = source->pitch;
clone->volume = source->volume;
memcpy(clone->position, source->position, 4 * sizeof(float));
memcpy(clone->orientation, source->orientation, 4 * sizeof(float));
@ -426,6 +432,7 @@ Source* lovrSourceClone(Source* source) {
clone->dipolePower = source->dipolePower;
clone->effects = source->effects;
clone->looping = source->looping;
clone->pitchable = source->pitchable;
clone->spatial = source->spatial;
if (source->converter) {
clone->converter = malloc(sizeof(ma_data_converter));
@ -437,6 +444,7 @@ Source* lovrSourceClone(Source* source) {
config.channelsOut = source->converter->channelsOut;
config.sampleRateIn = source->converter->sampleRateIn;
config.sampleRateOut = source->converter->sampleRateOut;
config.allowDynamicSampleRate = clone->pitchable;
ma_result status = ma_data_converter_init(&config, NULL, clone->converter);
lovrAssert(status == MA_SUCCESS, "Problem creating Source data converter: %s (%d)", ma_result_description(status), status);
}
@ -500,6 +508,23 @@ void lovrSourceSetLooping(Source* source, bool loop) {
source->looping = loop;
}
float lovrSourceGetPitch(Source* source) {
return source->pitch;
}
void lovrSourceSetPitch(Source* source, float pitch) {
lovrCheck(pitch > 0.f, "Source pitch must be positive");
lovrCheck(source->pitchable, "Source must be created with the 'pitchable' flag to change its pitch");
if (source->pitch != pitch) {
source->pitch = pitch;
ma_mutex_lock(&state.lock);
float ratio = (float) lovrSoundGetSampleRate(source->sound) / state.sampleRate;
ma_data_converter_set_rate_ratio(source->converter, pitch * ratio);
ma_mutex_unlock(&state.lock);
}
}
float lovrSourceGetVolume(Source* source, VolumeUnit units) {
return units == UNIT_LINEAR ? source->volume : linearToDb(source->volume);
}

View File

@ -75,7 +75,7 @@ void lovrAudioSetAbsorption(float absorption[3]);
// Source
Source* lovrSourceCreate(struct Sound* sound, bool spatial, uint32_t effects);
Source* lovrSourceCreate(struct Sound* sound, bool pitch, bool spatial, uint32_t effects);
Source* lovrSourceClone(Source* source);
void lovrSourceDestroy(void* ref);
struct Sound* lovrSourceGetSound(Source* source);
@ -85,11 +85,14 @@ void lovrSourceStop(Source* source);
bool lovrSourceIsPlaying(Source* source);
bool lovrSourceIsLooping(Source* source);
void lovrSourceSetLooping(Source* source, bool loop);
float lovrSourceGetPitch(Source* source);
void lovrSourceSetPitch(Source* source, float pitch);
float lovrSourceGetVolume(Source* source, VolumeUnit units);
void lovrSourceSetVolume(Source* source, float volume, VolumeUnit units);
void lovrSourceSeek(Source* source, double time, TimeUnit units);
double lovrSourceTell(Source* source, TimeUnit units);
double lovrSourceGetDuration(Source* source, TimeUnit units);
bool lovrSourceIsPitchable(Source* source);
bool lovrSourceIsSpatial(Source* source);
void lovrSourceGetPose(Source* source, float position[4], float orientation[4]);
void lovrSourceSetPose(Source* source, float position[4], float orientation[4]);