Unverified Commit e751294b authored by Jake Stine's avatar Jake Stine Committed by GitHub
Browse files

audio: temporary workaround for audio crashing (#172)

* audio: temporary workaround for audio crashing - nullify samples on unexpected __gc

* audio: Fixed compile error

* sound: don't cleanup sndta, only sources in mixer need cleanup on __gc for now.
parent 4d332d8e
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <file/file_path.h> #include <file/file_path.h>
#include <audio/conversion/float_to_s16.h> #include <audio/conversion/float_to_s16.h>
#include <math.h> #include <math.h>
#include <assert.h>
/* TODO/FIXME - no sound on big-endian */ /* TODO/FIXME - no sound on big-endian */
...@@ -23,6 +24,29 @@ static int16_t saturate(mixer_presaturate_t in) { ...@@ -23,6 +24,29 @@ static int16_t saturate(mixer_presaturate_t in) {
return cvt_presaturate_to_int16(in); return cvt_presaturate_to_int16(in);
} }
int audio_sources_nullify_refs(const audio_Source* source)
{
int counted = 0;
if (!source) return 0;
// rather than crash, let's nullify any known references here,
// even if they're currently playing (they'll be cut to silence)
for(int i=0; i<num_sources; ++i)
{
if (sources[i] == source)
{
if (sources[i]->state != AUDIO_STOPPED)
++counted;
// do not free - the pointers in sources are lua user data
sources[i] = NULL;
}
}
return counted;
}
void mixer_render(int16_t *buffer) void mixer_render(int16_t *buffer)
{ {
static mixer_presaturate_t presaturateBuffer[AUDIO_FRAMES * CHANNELS]; static mixer_presaturate_t presaturateBuffer[AUDIO_FRAMES * CHANNELS];
...@@ -32,6 +56,9 @@ void mixer_render(int16_t *buffer) ...@@ -32,6 +56,9 @@ void mixer_render(int16_t *buffer)
// Loop over audio sources // Loop over audio sources
for (int i = 0; i < num_sources; i++) for (int i = 0; i < num_sources; i++)
{ {
if (!sources[i])
continue;
if (sources[i]->state == AUDIO_STOPPED) if (sources[i]->state == AUDIO_STOPPED)
continue; continue;
...@@ -154,7 +181,7 @@ void lutro_audio_deinit() ...@@ -154,7 +181,7 @@ void lutro_audio_deinit()
{ {
for (unsigned i = 0; i < num_sources; i++) for (unsigned i = 0; i < num_sources; i++)
{ {
if (sources[i]->oggData) if (sources[i] && sources[i]->oggData)
{ {
ov_clear(&sources[i]->oggData->vf); ov_clear(&sources[i]->oggData->vf);
free(sources[i]->oggData); free(sources[i]->oggData);
...@@ -167,6 +194,19 @@ void lutro_audio_deinit() ...@@ -167,6 +194,19 @@ void lutro_audio_deinit()
} }
} }
static int assign_to_existing_source_slot(audio_Source* self)
{
for(int i=0; i<num_sources; ++i)
{
if (!sources[i])
{
sources[i] = self;
return 1;
}
}
return 0;
}
int audio_newSource(lua_State *L) int audio_newSource(lua_State *L)
{ {
int n = lua_gettop(L); int n = lua_gettop(L);
...@@ -178,6 +218,11 @@ int audio_newSource(lua_State *L) ...@@ -178,6 +218,11 @@ int audio_newSource(lua_State *L)
self->oggData = NULL; self->oggData = NULL;
self->sndta.fp = NULL; self->sndta.fp = NULL;
//if (lua_isstring(L,1)) // (lua_type(L, 1) == LUA_TSTRING)
//{
//
//}
void *p = lua_touserdata(L, 1); void *p = lua_touserdata(L, 1);
if (p == NULL) if (p == NULL)
{ {
...@@ -227,9 +272,13 @@ int audio_newSource(lua_State *L) ...@@ -227,9 +272,13 @@ int audio_newSource(lua_State *L)
self->bps = self->sndta.head.NumChannels * self->sndta.head.BitsPerSample / 8; self->bps = self->sndta.head.NumChannels * self->sndta.head.BitsPerSample / 8;
fseek(self->sndta.fp, 0, SEEK_END); fseek(self->sndta.fp, 0, SEEK_END);
} }
num_sources++;
sources = (audio_Source**)realloc(sources, num_sources * sizeof(audio_Source)); if (!assign_to_existing_source_slot(self))
sources[num_sources-1] = self; {
num_sources++;
sources = (audio_Source**)realloc(sources, num_sources * sizeof(audio_Source));
sources[num_sources-1] = self;
}
if (luaL_newmetatable(L, "Source") != 0) if (luaL_newmetatable(L, "Source") != 0)
{ {
...@@ -418,6 +467,18 @@ int source_getPitch(lua_State *L) ...@@ -418,6 +467,18 @@ int source_getPitch(lua_State *L)
int source_gc(lua_State *L) int source_gc(lua_State *L)
{ {
audio_Source* self = (audio_Source*)luaL_checkudata(L, 1, "Source"); audio_Source* self = (audio_Source*)luaL_checkudata(L, 1, "Source");
// todo - add some info to help identify the offending leaker.
// (don't get carried away tho - this message is only really useful to lutro core devs since
// it indiciates a failure of our internal Lua/C glue)
int leaks = audio_sources_nullify_refs(self);
if (leaks)
{
fprintf(stderr, "source_gc: playing audio references were nullified.\n");
//assert(false);
}
(void)self; (void)self;
return 0; return 0;
} }
......
...@@ -77,4 +77,5 @@ int source_setPitch(lua_State *L); ...@@ -77,4 +77,5 @@ int source_setPitch(lua_State *L);
int source_gc(lua_State *L); int source_gc(lua_State *L);
#endif // AUDIO_H #endif // AUDIO_H
#include "sound.h" #include "sound.h"
#include "lutro.h" #include "lutro.h"
#include "audio.h"
#include "compat/strl.h" #include "compat/strl.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h>
int lutro_sound_preload(lua_State *L) int lutro_sound_preload(lua_State *L)
{ {
...@@ -25,6 +27,11 @@ void lutro_sound_init() ...@@ -25,6 +27,11 @@ void lutro_sound_init()
{ {
} }
void newSoundData_internal(lua_State *L, const char* path)
{
snd_SoundData* self = (snd_SoundData*)lua_newuserdata(L, sizeof(snd_SoundData));
}
int snd_newSoundData(lua_State *L) int snd_newSoundData(lua_State *L)
{ {
int n = lua_gettop(L); int n = lua_gettop(L);
...@@ -72,7 +79,7 @@ int snd_newSoundData(lua_State *L) ...@@ -72,7 +79,7 @@ int snd_newSoundData(lua_State *L)
int sndta_type(lua_State *L) int sndta_type(lua_State *L)
{ {
wavhead_t* self = (wavhead_t*)luaL_checkudata(L, 1, "SoundData"); snd_SoundData* self = (snd_SoundData*)luaL_checkudata(L, 1, "SoundData");
(void) self; (void) self;
lua_pushstring(L, "SoundData"); lua_pushstring(L, "SoundData");
return 1; return 1;
...@@ -80,7 +87,10 @@ int sndta_type(lua_State *L) ...@@ -80,7 +87,10 @@ int sndta_type(lua_State *L)
int sndta_gc(lua_State *L) int sndta_gc(lua_State *L)
{ {
wavhead_t* self = (wavhead_t*)luaL_checkudata(L, 1, "SoundData"); snd_SoundData* self = (snd_SoundData*)luaL_checkudata(L, 1, "SoundData");
//audio makes deep copies of this object when it preps it as a mixer source, so no cleanup needed here.
(void)self; (void)self;
return 0; return 0;
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment