audio: rm paused and stopped states; rm rewind;

- There is now just one "playing" state.
- Instead of rewind, use :seek(0).

Note that now there is no way to resume or rewind all tracked sources.
This can be improved in the future if there's a need for it, probably
using variadic or table-based variants of the audio module functions.
This commit is contained in:
bjorn 2020-02-26 00:25:49 -08:00
parent fa771b04bd
commit 69dd0d4674
5 changed files with 41 additions and 140 deletions

View File

@ -165,16 +165,6 @@ static int l_lovrAudioPause(lua_State* L) {
return 0; return 0;
} }
static int l_lovrAudioResume(lua_State* L) {
lovrAudioResume();
return 0;
}
static int l_lovrAudioRewind(lua_State* L) {
lovrAudioRewind();
return 0;
}
static int l_lovrAudioSetDopplerEffect(lua_State* L) { static int l_lovrAudioSetDopplerEffect(lua_State* L) {
float factor = luax_optfloat(L, 1, 1.f); float factor = luax_optfloat(L, 1, 1.f);
float speedOfSound = luax_optfloat(L, 2, 343.29f); float speedOfSound = luax_optfloat(L, 2, 343.29f);
@ -237,8 +227,6 @@ static const luaL_Reg lovrAudio[] = {
{ "newMicrophone", l_lovrAudioNewMicrophone }, { "newMicrophone", l_lovrAudioNewMicrophone },
{ "newSource", l_lovrAudioNewSource }, { "newSource", l_lovrAudioNewSource },
{ "pause", l_lovrAudioPause }, { "pause", l_lovrAudioPause },
{ "resume", l_lovrAudioResume },
{ "rewind", l_lovrAudioRewind },
{ "setDopplerEffect", l_lovrAudioSetDopplerEffect }, { "setDopplerEffect", l_lovrAudioSetDopplerEffect },
{ "setOrientation", l_lovrAudioSetOrientation }, { "setOrientation", l_lovrAudioSetOrientation },
{ "setPose", l_lovrAudioSetPose }, { "setPose", l_lovrAudioSetPose },

View File

@ -134,11 +134,6 @@ static int l_lovrSourceIsLooping(lua_State* L) {
return 1; return 1;
} }
static int l_lovrSourceIsPaused(lua_State* L) {
lua_pushboolean(L, lovrSourceIsPaused(luax_checktype(L, 1, Source)));
return 1;
}
static int l_lovrSourceIsPlaying(lua_State* L) { static int l_lovrSourceIsPlaying(lua_State* L) {
lua_pushboolean(L, lovrSourceIsPlaying(luax_checktype(L, 1, Source))); lua_pushboolean(L, lovrSourceIsPlaying(luax_checktype(L, 1, Source)));
return 1; return 1;
@ -149,11 +144,6 @@ static int l_lovrSourceIsRelative(lua_State* L) {
return 1; return 1;
} }
static int l_lovrSourceIsStopped(lua_State* L) {
lua_pushboolean(L, lovrSourceIsStopped(luax_checktype(L, 1, Source)));
return 1;
}
static int l_lovrSourcePause(lua_State* L) { static int l_lovrSourcePause(lua_State* L) {
lovrSourcePause(luax_checktype(L, 1, Source)); lovrSourcePause(luax_checktype(L, 1, Source));
return 0; return 0;
@ -166,16 +156,6 @@ static int l_lovrSourcePlay(lua_State* L) {
return 0; return 0;
} }
static int l_lovrSourceResume(lua_State* L) {
lovrSourceResume(luax_checktype(L, 1, Source));
return 0;
}
static int l_lovrSourceRewind(lua_State* L) {
lovrSourceRewind(luax_checktype(L, 1, Source));
return 0;
}
static int l_lovrSourceSeek(lua_State* L) { static int l_lovrSourceSeek(lua_State* L) {
Source* source = luax_checktype(L, 1, Source); Source* source = luax_checktype(L, 1, Source);
TimeUnit unit = luax_checkenum(L, 3, TimeUnits, "seconds", "TimeUnit"); TimeUnit unit = luax_checkenum(L, 3, TimeUnits, "seconds", "TimeUnit");
@ -306,14 +286,10 @@ const luaL_Reg lovrSource[] = {
{ "getVolume", l_lovrSourceGetVolume }, { "getVolume", l_lovrSourceGetVolume },
{ "getVolumeLimits", l_lovrSourceGetVolumeLimits }, { "getVolumeLimits", l_lovrSourceGetVolumeLimits },
{ "isLooping", l_lovrSourceIsLooping }, { "isLooping", l_lovrSourceIsLooping },
{ "isPaused", l_lovrSourceIsPaused },
{ "isPlaying", l_lovrSourceIsPlaying }, { "isPlaying", l_lovrSourceIsPlaying },
{ "isRelative", l_lovrSourceIsRelative }, { "isRelative", l_lovrSourceIsRelative },
{ "isStopped", l_lovrSourceIsStopped },
{ "pause", l_lovrSourcePause }, { "pause", l_lovrSourcePause },
{ "play", l_lovrSourcePlay }, { "play", l_lovrSourcePlay },
{ "resume", l_lovrSourceResume },
{ "rewind", l_lovrSourceRewind },
{ "seek", l_lovrSourceSeek }, { "seek", l_lovrSourceSeek },
{ "setCone", l_lovrSourceSetCone }, { "setCone", l_lovrSourceSetCone },
{ "setFalloff", l_lovrSourceSetFalloff }, { "setFalloff", l_lovrSourceSetFalloff },

View File

@ -64,13 +64,13 @@ bool lovrAudioInit() {
void lovrAudioDestroy() { void lovrAudioDestroy() {
if (!state.initialized) return; if (!state.initialized) return;
alcMakeContextCurrent(NULL);
alcDestroyContext(state.context);
alcCloseDevice(state.device);
for (size_t i = 0; i < state.sources.length; i++) { for (size_t i = 0; i < state.sources.length; i++) {
lovrRelease(Source, state.sources.data[i]); lovrRelease(Source, state.sources.data[i]);
} }
arr_free(&state.sources); arr_free(&state.sources);
alcMakeContextCurrent(NULL);
alcDestroyContext(state.context);
alcCloseDevice(state.device);
memset(&state, 0, sizeof(state)); memset(&state, 0, sizeof(state));
} }
@ -83,7 +83,9 @@ void lovrAudioUpdate() {
} }
uint32_t id = lovrSourceGetId(source); uint32_t id = lovrSourceGetId(source);
bool isStopped = lovrSourceIsStopped(source); ALenum sourceState;
alGetSourcei(id, AL_SOURCE_STATE, &sourceState);
bool isStopped = sourceState == AL_STOPPED;
ALint processed; ALint processed;
alGetSourcei(id, AL_BUFFERS_PROCESSED, &processed); alGetSourcei(id, AL_BUFFERS_PROCESSED, &processed);
@ -163,18 +165,6 @@ void lovrAudioPause() {
} }
} }
void lovrAudioResume() {
for (size_t i = 0; i < state.sources.length; i++) {
lovrSourceResume(state.sources.data[i]);
}
}
void lovrAudioRewind() {
for (size_t i = 0; i < state.sources.length; i++) {
lovrSourceRewind(state.sources.data[i]);
}
}
void lovrAudioSetDopplerEffect(float factor, float speedOfSound) { void lovrAudioSetDopplerEffect(float factor, float speedOfSound) {
alDopplerFactor(factor); alDopplerFactor(factor);
alSpeedOfSound(speedOfSound); alSpeedOfSound(speedOfSound);

View File

@ -22,8 +22,6 @@ float lovrAudioGetVolume(void);
bool lovrAudioHas(struct Source* source); bool lovrAudioHas(struct Source* source);
bool lovrAudioIsSpatialized(void); bool lovrAudioIsSpatialized(void);
void lovrAudioPause(void); void lovrAudioPause(void);
void lovrAudioResume(void);
void lovrAudioRewind(void);
void lovrAudioSetDopplerEffect(float factor, float speedOfSound); void lovrAudioSetDopplerEffect(float factor, float speedOfSound);
void lovrAudioSetOrientation(float* orientation); void lovrAudioSetOrientation(float* orientation);
void lovrAudioSetPosition(float* position); void lovrAudioSetPosition(float* position);

View File

@ -21,7 +21,7 @@ struct Source {
bool isLooping; bool isLooping;
}; };
static ALenum lovrSourceGetState(Source* source) { static ALenum getState(Source* source) {
ALenum state; ALenum state;
alGetSourcei(source->id, AL_SOURCE_STATE, &state); alGetSourcei(source->id, AL_SOURCE_STATE, &state);
return state; return state;
@ -135,12 +135,8 @@ bool lovrSourceIsLooping(Source* source) {
return source->isLooping; return source->isLooping;
} }
bool lovrSourceIsPaused(Source* source) {
return lovrSourceGetState(source) == AL_PAUSED;
}
bool lovrSourceIsPlaying(Source* source) { bool lovrSourceIsPlaying(Source* source) {
return lovrSourceGetState(source) == AL_PLAYING; return getState(source) == AL_PLAYING;
} }
bool lovrSourceIsRelative(Source* source) { bool lovrSourceIsRelative(Source* source) {
@ -149,71 +145,42 @@ bool lovrSourceIsRelative(Source* source) {
return isRelative == AL_TRUE; return isRelative == AL_TRUE;
} }
bool lovrSourceIsStopped(Source* source) {
return lovrSourceGetState(source) == AL_STOPPED;
}
void lovrSourcePause(Source* source) { void lovrSourcePause(Source* source) {
alSourcePause(source->id); alSourcePause(source->id);
} }
void lovrSourcePlay(Source* source) { void lovrSourcePlay(Source* source) {
if (lovrSourceIsPlaying(source)) { if (source->type == SOURCE_STATIC) {
return; if (getState(source) != AL_PLAYING) {
} else if (lovrSourceIsPaused(source)) { alSourcePlay(source->id);
lovrSourceResume(source); }
return; } else {
} switch (getState(source)) {
case AL_INITIAL:
// There is no guarantee that lovrAudioUpdate is called AFTER the state of source becomes STOPPED but case AL_STOPPED:
// BEFORE user code calls source:play(). This means that some buffers may still be queued (but processed alSourcei(source->id, AL_BUFFER, AL_NONE);
// and completely finished playing). These must be unqueued before we can start using the source again. lovrSourceStream(source, source->buffers, SOURCE_BUFFERS);
ALint processed; alSourcePlay(source->id);
ALuint _unused[SOURCE_BUFFERS]; break;
alGetSourcei(lovrSourceGetId(source), AL_BUFFERS_PROCESSED, &processed); case AL_PAUSED:
alSourceUnqueueBuffers(source->id, processed, _unused); alSourcePlay(source->id);
break;
lovrSourceStream(source, source->buffers, SOURCE_BUFFERS); case AL_PLAYING:
alSourcePlay(source->id); break;
} }
void lovrSourceResume(Source* source) {
if (!lovrSourceIsPaused(source)) {
return;
}
alSourcePlay(source->id);
}
void lovrSourceRewind(Source* source) {
if (lovrSourceIsStopped(source)) {
return;
}
bool wasPaused = lovrSourceIsPaused(source);
alSourceRewind(source->id);
lovrSourceStop(source);
lovrSourcePlay(source);
if (wasPaused) {
lovrSourcePause(source);
} }
} }
void lovrSourceSeek(Source* source, size_t sample) { void lovrSourceSeek(Source* source, size_t sample) {
switch (source->type) { if (source->type == SOURCE_STATIC) {
case SOURCE_STATIC: alSourcef(source->id, AL_SAMPLE_OFFSET, sample);
alSourcef(source->id, AL_SAMPLE_OFFSET, sample); } else {
break; bool wasPaused = getState(source) == AL_PAUSED;
alSourceStop(source->id);
case SOURCE_STREAM: { lovrAudioStreamSeek(source->stream, sample);
bool wasPaused = lovrSourceIsPaused(source); lovrSourcePlay(source);
lovrSourceStop(source); if (wasPaused) {
lovrAudioStreamSeek(source->stream, sample); lovrSourcePause(source);
lovrSourcePlay(source);
if (wasPaused) {
lovrSourcePause(source);
}
break;
} }
} }
} }
@ -272,30 +239,12 @@ void lovrSourceSetVolumeLimits(Source* source, float min, float max) {
} }
void lovrSourceStop(Source* source) { void lovrSourceStop(Source* source) {
if (lovrSourceIsStopped(source)) { if (source->type == SOURCE_STATIC) {
return; alSourceStop(source->id);
} } else {
alSourceStop(source->id);
switch (source->type) { alSourcei(source->id, AL_BUFFER, AL_NONE);
case SOURCE_STATIC: lovrAudioStreamRewind(source->stream);
alSourceStop(source->id);
break;
case SOURCE_STREAM: {
// Stop the source
alSourceStop(source->id);
alSourcei(source->id, AL_BUFFER, AL_NONE);
// Empty the buffers
int count = 0;
alGetSourcei(source->id, AL_BUFFERS_QUEUED, &count);
alSourceUnqueueBuffers(source->id, count, NULL);
// Rewind the decoder
lovrAudioStreamRewind(source->stream);
break;
}
} }
} }