Skip to content

Commit

Permalink
Sound support for Javascript (untested).
Browse files Browse the repository at this point in the history
  • Loading branch information
reduz committed Oct 27, 2017
1 parent b1b11ea commit b8ac700
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 3 deletions.
79 changes: 76 additions & 3 deletions platform/javascript/audio_driver_javascript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
/*************************************************************************/
#include "audio_driver_javascript.h"

#include <emscripten.h>
#include <string.h>

#define MAX_NUMBER_INTERFACES 3
Expand All @@ -38,22 +39,91 @@

//AudioDriverJavaScript* AudioDriverJavaScript::s_ad=NULL;

AudioDriverJavaScript *AudioDriverJavaScript::singleton_js = NULL;
const char *AudioDriverJavaScript::get_name() const {

return "JavaScript";
}

extern "C" {

void js_audio_driver_mix_function(int p_frames) {

//print_line("MIXI! "+itos(p_frames));
AudioDriverJavaScript::singleton_js->mix_to_js(p_frames);
}
}

void AudioDriverJavaScript::mix_to_js(int p_frames) {

int todo = p_frames;
int offset = 0;

while (todo) {

int tomix = MIN(todo, INTERNAL_BUFFER_SIZE);

audio_server_process(p_frames, stream_buffer);
for (int i = 0; i < tomix * internal_buffer_channels; i++) {
internal_buffer[i] = float(stream_buffer[i] >> 16) * 32768.0;
}

/* clang-format off */
EM_ASM_({
var data = HEAPF32.subarray($0 / 4, $0 / 4 + $2 * 2);

for (var channel = 0; channel < _as_output_buffer.numberOfChannels; channel++) {
var outputData = _as_output_buffer.getChannelData(channel);
// Loop through samples
for (var sample = 0; sample < $2; sample++) {
// make output equal to the same as the input
outputData[sample + $1] = data[sample * 2 + channel];
}
}
}, internal_buffer, offset, tomix);
/* clang-format on */

todo -= tomix;
offset += tomix;
}
}

Error AudioDriverJavaScript::init() {

return OK;
}

void AudioDriverJavaScript::start() {

internal_buffer_channels = 2;
internal_buffer = memnew_arr(float, INTERNAL_BUFFER_SIZE *internal_buffer_channels);
stream_buffer = memnew_arr(int32_t, INTERNAL_BUFFER_SIZE * 4); //max 4 channels

/* clang-format off */
EM_ASM(
_as_audioctx = new (window.AudioContext || window.webkitAudioContext)();

audio_server_mix_function = Module.cwrap('js_audio_driver_mix_function', 'void', ['number']);
);

int buffer_latency = 16384;
EM_ASM_( {
_as_script_node = _as_audioctx.createScriptProcessor($0, 0, 2);
_as_script_node.connect(_as_audioctx.destination);
console.log(_as_script_node.bufferSize);

_as_script_node.onaudioprocess = function(audioProcessingEvent) {
// The output buffer contains the samples that will be modified and played
_as_output_buffer = audioProcessingEvent.outputBuffer;
audio_server_mix_function(_as_output_buffer.getChannelData(0).length);
}
}, buffer_latency);
/* clang-format on */
}

int AudioDriverJavaScript::get_mix_rate() const {

return 44100;
return mix_rate;
}

AudioDriver::SpeakerMode AudioDriverJavaScript::get_speaker_mode() const {
Expand All @@ -63,15 +133,15 @@ AudioDriver::SpeakerMode AudioDriverJavaScript::get_speaker_mode() const {

void AudioDriverJavaScript::lock() {

/*
/*no locking, as threads are not supported
if (active && mutex)
mutex->lock();
*/
}

void AudioDriverJavaScript::unlock() {

/*
/*no locking, as threads are not supported
if (active && mutex)
mutex->unlock();
*/
Expand All @@ -81,4 +151,7 @@ void AudioDriverJavaScript::finish() {
}

AudioDriverJavaScript::AudioDriverJavaScript() {

mix_rate = 44100;
singleton_js = this;
}
16 changes: 16 additions & 0 deletions platform/javascript/audio_driver_javascript.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,23 @@
#include "os/mutex.h"

class AudioDriverJavaScript : public AudioDriver {

enum {
INTERNAL_BUFFER_SIZE = 4096,
STREAM_SCALE_BITS = 12

};

int mix_rate;
float *internal_buffer;
int internal_buffer_channels;
int internal_buffer_size;
int32_t *stream_buffer;

public:
void mix_to_js(int p_frames);
static AudioDriverJavaScript *singleton_js;

virtual const char *get_name() const;

virtual Error init();
Expand Down

0 comments on commit b8ac700

Please sign in to comment.