Add audio async for SE, disable AudioStream

This commit is contained in:
Varun Patil 2019-05-08 20:45:00 +05:30
parent bbe9976740
commit 55e83078de
3 changed files with 108 additions and 16 deletions

View File

@ -82,6 +82,9 @@ void AudioStream::play(const std::string &filename,
int pitch,
float offset)
{
#ifdef __EMSCRIPTEN__
return;
#endif
finiFadeOutInt();
lockStream();

View File

@ -30,6 +30,13 @@
#include <SDL_sound.h>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#include <emscripten/fetch.h>
#include <string>
#include <fstream>
#endif
#define SE_CACHE_MEM (10*1024*1024) // 10 MB
struct SoundBuffer
@ -119,14 +126,21 @@ SoundEmitter::~SoundEmitter()
SoundBuffer::deref(iter->second);
}
void SoundEmitter::play(const std::string &filename,
struct PlayInternalCallbackData {
SoundEmitter * se;
int volume;
int pitch;
};
void SoundEmitter::play_internal(const std::string &filename,
int volume,
int pitch)
int pitch,
emscripten_fetch_t * fetch)
{
float _volume = clamp<int>(volume, 0, 100) / 100.0f;
float _pitch = clamp<int>(pitch, 50, 150) / 100.0f;
SoundBuffer *buffer = allocateBuffer(filename);
SoundBuffer *buffer = allocateBuffer(filename, fetch);
if (!buffer)
return;
@ -178,6 +192,57 @@ void SoundEmitter::play(const std::string &filename,
AL::Source::play(src);
}
void saveAudioFile(void * arg) {
emscripten_fetch_t * fetch = (emscripten_fetch_t *) arg;
/*std::string fname(fetch->url);
for (size_t i = 0; i < fname.size(); i++) {
if (fname[i] == '/') fname[i] = '_';
}
fname = fname + ".ogg";*/
try {
PlayInternalCallbackData * data = ((PlayInternalCallbackData *) fetch->userData);
data->se->play_internal(fetch->url, data->volume, data->pitch, fetch);
} catch (const Exception &e) {}
delete ((PlayInternalCallbackData *) fetch->userData);
emscripten_fetch_close(fetch);
}
void audioDownloadSucceeded(emscripten_fetch_t *fetch) {
emscripten_push_main_loop_blocker(saveAudioFile, (void *) fetch);
}
void audioDownloadFailed(emscripten_fetch_t *fetch) {
printf("Downloading %s failed, HTTP failure status code: %d.\n", fetch->url, fetch->status);
delete ((PlayInternalCallbackData *) fetch->userData);
emscripten_fetch_close(fetch);
}
void addAudioDownload(const char * filename, PlayInternalCallbackData * se) {
const char *pfx = "async/";
char result[512];
strcpy(result, pfx);
strcat(result, filename);
emscripten_fetch_attr_t attr;
emscripten_fetch_attr_init(&attr);
strcpy(attr.requestMethod, "GET");
attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY;
attr.onsuccess = audioDownloadSucceeded;
attr.onerror = audioDownloadFailed;
attr.userData = se;
emscripten_fetch(&attr, result);
}
void SoundEmitter::play(const std::string &filename,
int volume,
int pitch) {
PlayInternalCallbackData * data = new PlayInternalCallbackData();
data->se = this;
data->volume = volume;
data->pitch = pitch;
addAudioDownload(filename.c_str(), data);
}
void SoundEmitter::stop()
{
for (size_t i = 0; i < srcCount; i++)
@ -192,16 +257,7 @@ struct SoundOpenHandler : FileSystem::OpenHandler
: buffer(0)
{}
bool tryRead(SDL_RWops &ops, const char *ext)
{
Sound_Sample *sample = Sound_NewSample(&ops, ext, 0, STREAM_BUF_SIZE);
if (!sample)
{
SDL_RWclose(&ops);
return false;
}
void decode(Sound_Sample *sample) {
/* Do all of the decoding in the handler so we don't have
* to keep the source ops around */
uint32_t decBytes = Sound_DecodeAll(sample);
@ -217,12 +273,38 @@ struct SoundOpenHandler : FileSystem::OpenHandler
buffer->bytes, sample->actual.rate);
Sound_FreeSample(sample);
}
bool tryRead(SDL_RWops &ops, const char *ext)
{
Sound_Sample *sample = Sound_NewSample(&ops, ext, 0, STREAM_BUF_SIZE);
if (!sample)
{
SDL_RWclose(&ops);
return false;
}
decode(sample);
return true;
}
bool emread(emscripten_fetch_t *fetch) {
Sound_Sample *sample = Sound_NewSample(SDL_RWFromConstMem(fetch->data, fetch->numBytes), "ogg", 0, STREAM_BUF_SIZE);
if (!sample)
{
return false;
}
decode(sample);
return true;
}
};
SoundBuffer *SoundEmitter::allocateBuffer(const std::string &filename)
SoundBuffer *SoundEmitter::allocateBuffer(const std::string &filename, emscripten_fetch_t *fetch)
{
SoundBuffer *buffer = bufferHash.value(filename, 0);
@ -239,7 +321,7 @@ SoundBuffer *SoundEmitter::allocateBuffer(const std::string &filename)
{
/* Buffer not in cache, needs to be loaded */
SoundOpenHandler handler;
shState->fileSystem().openRead(handler, filename.c_str());
handler.emread(fetch);
buffer = handler.buffer;
if (!buffer)

View File

@ -29,6 +29,10 @@
#include <string>
#include <vector>
#ifdef __EMSCRIPTEN__
#include <emscripten/fetch.h>
#endif
struct SoundBuffer;
struct Config;
@ -55,11 +59,14 @@ struct SoundEmitter
void play(const std::string &filename,
int volume,
int pitch);
void play_internal(const std::string &filename,
int volume,
int pitch, emscripten_fetch_t *fetch);
void stop();
private:
SoundBuffer *allocateBuffer(const std::string &filename);
SoundBuffer *allocateBuffer(const std::string &filename, emscripten_fetch_t *fetch);
};
#endif // SOUNDEMITTER_H