21 #include "../../SDL_internal.h"
23 #if SDL_AUDIO_DRIVER_EMSCRIPTEN
26 #include "../SDL_audio_c.h"
29 #include <emscripten/emscripten.h>
32 FeedAudioDevice(
_THIS,
const void *
buf,
const int buflen)
36 var SDL2 = Module[
'SDL2'];
37 var numChannels = SDL2.audio.currentOutputBuffer[
'numberOfChannels'];
38 for (var
c = 0;
c < numChannels; ++
c) {
39 var channelData = SDL2.audio.currentOutputBuffer[
'getChannelData'](
c);
40 if (channelData.length != $1) {
41 throw 'Web Audio output buffer length mismatch! Destination size: ' + channelData.length +
' samples vs expected ' + $1 +
' samples!';
44 for (var
j = 0;
j < $1; ++
j) {
45 channelData[
j] = HEAPF32[$0 + ((
j*numChannels +
c) << 2) >> 2];
48 },
buf, buflen / framelen);
52 HandleAudioProcess(
_THIS)
55 const int stream_len = this->callbackspec.size;
67 callback(this->callbackspec.userdata, this->work_buffer, stream_len);
71 callback(this->callbackspec.userdata, this->work_buffer, stream_len);
86 FeedAudioDevice(
this, this->work_buffer, this->
spec.
size);
90 HandleCaptureProcess(
_THIS)
93 const int stream_len = this->callbackspec.size;
102 var SDL2 = Module[
'SDL2'];
103 var numChannels = SDL2.capture.currentCaptureBuffer.numberOfChannels;
104 for (var
c = 0;
c < numChannels; ++
c) {
105 var channelData = SDL2.capture.currentCaptureBuffer.getChannelData(
c);
106 if (channelData.length != $1) {
107 throw
'Web Audio capture buffer length mismatch! Destination size: ' + channelData.length +
' samples vs expected ' + $1 +
' samples!';
110 if (numChannels == 1) {
111 for (var
j = 0;
j < $1; ++
j) {
112 setValue($0 + (
j * 4), channelData[
j],
'float');
115 for (var
j = 0;
j < $1; ++
j) {
116 setValue($0 + (((
j * numChannels) +
c) * 4), channelData[
j],
'float');
126 callback(this->callbackspec.userdata, this->work_buffer, stream_len);
135 if (got != stream_len) {
136 SDL_memset(this->work_buffer, this->callbackspec.silence, stream_len);
138 callback(this->callbackspec.userdata, this->work_buffer, stream_len);
145 EMSCRIPTENAUDIO_CloseDevice(
_THIS)
148 var SDL2 = Module[
'SDL2'];
150 if (SDL2.capture.silenceTimer !== undefined) {
151 clearTimeout(SDL2.capture.silenceTimer);
153 if (SDL2.capture.stream !== undefined) {
154 var tracks = SDL2.capture.stream.getAudioTracks();
155 for (var i = 0; i < tracks.length; i++) {
156 SDL2.capture.stream.removeTrack(tracks[i]);
158 SDL2.capture.stream = undefined;
160 if (SDL2.capture.scriptProcessorNode !== undefined) {
161 SDL2.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {};
162 SDL2.capture.scriptProcessorNode.disconnect();
163 SDL2.capture.scriptProcessorNode = undefined;
165 if (SDL2.capture.mediaStreamNode !== undefined) {
166 SDL2.capture.mediaStreamNode.disconnect();
167 SDL2.capture.mediaStreamNode = undefined;
169 if (SDL2.capture.silenceBuffer !== undefined) {
170 SDL2.capture.silenceBuffer = undefined
172 SDL2.capture = undefined;
174 if (SDL2.audio.scriptProcessorNode != undefined) {
175 SDL2.audio.scriptProcessorNode.disconnect();
176 SDL2.audio.scriptProcessorNode = undefined;
178 SDL2.audio = undefined;
180 if ((SDL2.audioContext !== undefined) && (SDL2.audio === undefined) && (SDL2.capture === undefined)) {
181 SDL2.audioContext.close();
182 SDL2.audioContext = undefined;
192 EMSCRIPTENAUDIO_OpenDevice(
_THIS,
void *
handle,
const char *devname,
int iscapture)
202 if(typeof(Module[
'SDL2']) ===
'undefined') {
205 var SDL2 = Module[
'SDL2'];
212 if (!SDL2.audioContext) {
213 if (typeof(AudioContext) !==
'undefined') {
214 SDL2.audioContext = new AudioContext();
215 }
else if (typeof(webkitAudioContext) !==
'undefined') {
216 SDL2.audioContext =
new webkitAudioContext();
219 return SDL2.audioContext === undefined ? -1 : 0;
226 while ((!valid_format) && (test_format)) {
227 switch (test_format) {
246 if (this->hidden ==
NULL) {
255 var SDL2 = Module[
'SDL2'];
256 return SDL2.audioContext.sampleRate;
279 var SDL2 = Module[
'SDL2'];
280 var have_microphone =
function(
stream) {
282 if (SDL2.capture.silenceTimer !== undefined) {
283 clearTimeout(SDL2.capture.silenceTimer);
284 SDL2.capture.silenceTimer = undefined;
286 SDL2.capture.mediaStreamNode = SDL2.audioContext.createMediaStreamSource(
stream);
287 SDL2.capture.scriptProcessorNode = SDL2.audioContext.createScriptProcessor($1, $0, 1);
288 SDL2.capture.scriptProcessorNode.onaudioprocess =
function(audioProcessingEvent) {
289 if ((SDL2 === undefined) || (SDL2.capture === undefined)) {
return; }
290 audioProcessingEvent.outputBuffer.getChannelData(0).fill(0.0);
291 SDL2.capture.currentCaptureBuffer = audioProcessingEvent.inputBuffer;
292 dynCall(
'vi', $2, [$3]);
294 SDL2.capture.mediaStreamNode.connect(SDL2.capture.scriptProcessorNode);
295 SDL2.capture.scriptProcessorNode.connect(SDL2.audioContext.destination);
296 SDL2.capture.stream =
stream;
299 var no_microphone =
function(error) {
304 SDL2.capture.silenceBuffer = SDL2.audioContext.createBuffer($0, $1, SDL2.audioContext.sampleRate);
305 SDL2.capture.silenceBuffer.getChannelData(0).fill(0.0);
306 var silence_callback =
function() {
307 SDL2.capture.currentCaptureBuffer = SDL2.capture.silenceBuffer;
308 dynCall(
'vi', $2, [$3]);
311 SDL2.capture.silenceTimer = setTimeout(silence_callback, ($1 / SDL2.audioContext.sampleRate) * 1000);
313 if ((navigator.mediaDevices !== undefined) && (navigator.mediaDevices.getUserMedia !== undefined)) {
314 navigator.mediaDevices.getUserMedia({
audio:
true, video:
false }).then(have_microphone).catch(no_microphone);
315 }
else if (navigator.webkitGetUserMedia !== undefined) {
316 navigator.webkitGetUserMedia({
audio:
true, video:
false }, have_microphone, no_microphone);
322 var SDL2 = Module[
'SDL2'];
323 SDL2.audio.scriptProcessorNode = SDL2.audioContext[
'createScriptProcessor']($1, 0, $0);
324 SDL2.audio.scriptProcessorNode[
'onaudioprocess'] =
function (
e) {
325 if ((SDL2 === undefined) || (SDL2.audio === undefined)) {
return; }
326 SDL2.audio.currentOutputBuffer =
e[
'outputBuffer'];
327 dynCall(
'vi', $2, [$3]);
329 SDL2.audio.scriptProcessorNode[
'connect'](SDL2.audioContext[
'destination']);
340 int capture_available;
343 impl->
OpenDevice = EMSCRIPTENAUDIO_OpenDevice;
353 available = EM_ASM_INT_V({
354 if (typeof(AudioContext) !==
'undefined') {
356 }
else if (typeof(webkitAudioContext) !==
'undefined') {
366 capture_available = available && EM_ASM_INT_V({
367 if ((typeof(navigator.mediaDevices) !==
'undefined') && (typeof(navigator.mediaDevices.getUserMedia) !==
'undefined')) {
369 }
else if (typeof(navigator.webkitGetUserMedia) !==
'undefined') {
382 "emscripten",
"SDL emscripten audio driver", EMSCRIPTENAUDIO_Init, 0
#define SDL_assert(condition)
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
SDL_AudioFormat SDL_NextAudioFormat(void)
Uint16 SDL_AudioFormat
Audio format flags.
#define SDL_AUDIO_BITSIZE(x)
void(* SDL_AudioCallback)(void *userdata, Uint8 *stream, int len)
#define SDL_AudioStreamGet
#define SDL_AudioStreamClear
#define SDL_AudioStreamAvailable
#define SDL_AudioStreamPut
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 SDL_AssertionHandler void SDL_SpinLock SDL_atomic_t int int return SDL_atomic_t return void void void return void return int return SDL_AudioSpec SDL_AudioSpec return int int return return int SDL_RWops int SDL_AudioSpec Uint8 Uint32 * e
#define SDL_OutOfMemory()
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLenum GLuint GLenum GLsizei const GLchar * buf
AudioBootStrap EMSCRIPTENAUDIO_bootstrap
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int int in j)
EGLImageKHR EGLint EGLint * handle
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d ®2 endm macro vzip8 reg2 vzip d d ®2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
void(* CloseDevice)(_THIS)
int OnlyHasDefaultCaptureDevice
int OnlyHasDefaultOutputDevice
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
int ProvidesOwnCallbackThread
static Uint32 callback(Uint32 interval, void *param)