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, int pitch,
float offset) float offset)
{ {
#ifdef __EMSCRIPTEN__
return;
#endif
finiFadeOutInt(); finiFadeOutInt();
lockStream(); lockStream();

View File

@ -30,6 +30,13 @@
#include <SDL_sound.h> #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 #define SE_CACHE_MEM (10*1024*1024) // 10 MB
struct SoundBuffer struct SoundBuffer
@ -119,14 +126,21 @@ SoundEmitter::~SoundEmitter()
SoundBuffer::deref(iter->second); 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 volume,
int pitch) int pitch,
emscripten_fetch_t * fetch)
{ {
float _volume = clamp<int>(volume, 0, 100) / 100.0f; float _volume = clamp<int>(volume, 0, 100) / 100.0f;
float _pitch = clamp<int>(pitch, 50, 150) / 100.0f; float _pitch = clamp<int>(pitch, 50, 150) / 100.0f;
SoundBuffer *buffer = allocateBuffer(filename); SoundBuffer *buffer = allocateBuffer(filename, fetch);
if (!buffer) if (!buffer)
return; return;
@ -178,6 +192,57 @@ void SoundEmitter::play(const std::string &filename,
AL::Source::play(src); 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() void SoundEmitter::stop()
{ {
for (size_t i = 0; i < srcCount; i++) for (size_t i = 0; i < srcCount; i++)
@ -192,16 +257,7 @@ struct SoundOpenHandler : FileSystem::OpenHandler
: buffer(0) : buffer(0)
{} {}
bool tryRead(SDL_RWops &ops, const char *ext) void decode(Sound_Sample *sample) {
{
Sound_Sample *sample = Sound_NewSample(&ops, ext, 0, STREAM_BUF_SIZE);
if (!sample)
{
SDL_RWclose(&ops);
return false;
}
/* Do all of the decoding in the handler so we don't have /* Do all of the decoding in the handler so we don't have
* to keep the source ops around */ * to keep the source ops around */
uint32_t decBytes = Sound_DecodeAll(sample); uint32_t decBytes = Sound_DecodeAll(sample);
@ -217,12 +273,38 @@ struct SoundOpenHandler : FileSystem::OpenHandler
buffer->bytes, sample->actual.rate); buffer->bytes, sample->actual.rate);
Sound_FreeSample(sample); 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; 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); 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 */ /* Buffer not in cache, needs to be loaded */
SoundOpenHandler handler; SoundOpenHandler handler;
shState->fileSystem().openRead(handler, filename.c_str()); handler.emread(fetch);
buffer = handler.buffer; buffer = handler.buffer;
if (!buffer) if (!buffer)

View File

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