21 #include "../../SDL_internal.h" 23 #if SDL_AUDIO_DRIVER_EMSCRIPTEN 27 #include "../SDL_audio_c.h" 30 #include <emscripten/emscripten.h> 37 if (this->hidden->write_off + this->convert.len_cvt > this->hidden->mixlen) {
38 if (this->hidden->write_off > this->hidden->read_off) {
40 this->hidden->mixbuf + this->hidden->read_off,
41 this->hidden->mixlen - this->hidden->read_off);
42 this->hidden->write_off = this->hidden->write_off - this->hidden->read_off;
44 this->hidden->write_off = 0;
46 this->hidden->read_off = 0;
49 SDL_memcpy(this->hidden->mixbuf + this->hidden->write_off,
51 this->convert.len_cvt);
52 this->hidden->write_off += this->convert.len_cvt;
53 byte_len = this->hidden->write_off - this->hidden->read_off;
59 HandleAudioProcess(
_THIS)
70 if (this->convert.needed) {
73 if (this->hidden->conv_in_len != 0) {
74 this->convert.len = this->hidden->conv_in_len * bytes_in * this->
spec.
channels;
81 buf = this->convert.buf;
82 byte_len = this->convert.len_cvt;
86 if (!this->hidden->mixbuf) {
87 this->hidden->mixlen = this->
spec.
size > byte_len ? this->
spec.
size * 2 : byte_len * 2;
88 this->hidden->mixbuf =
SDL_malloc(this->hidden->mixlen);
92 byte_len = copyData(
this);
100 byte_len = copyData(
this);
104 buf = this->hidden->mixbuf + this->hidden->read_off;
105 this->hidden->read_off += byte_len;
109 if (!this->hidden->mixbuf) {
110 this->hidden->mixlen = this->
spec.
size;
111 this->hidden->mixbuf =
SDL_malloc(this->hidden->mixlen);
114 this->hidden->mixbuf,
115 this->hidden->mixlen);
116 buf = this->hidden->mixbuf;
117 byte_len = this->hidden->mixlen;
122 var numChannels = SDL2.audio.currentOutputBuffer[
'numberOfChannels'];
123 for (var
c = 0;
c < numChannels; ++
c) {
124 var channelData = SDL2.audio.currentOutputBuffer[
'getChannelData'](
c);
125 if (channelData.length != $1) {
126 throw 'Web Audio output buffer length mismatch! Destination size: ' + channelData.length +
' samples vs expected ' + $1 +
' samples!';
129 for (var
j = 0;
j < $1; ++
j) {
130 channelData[
j] = HEAPF32[$0 + ((
j*numChannels +
c) << 2) >> 2];
138 HandleCaptureProcess(
_THIS)
148 if (this->convert.needed) {
149 buf = this->convert.buf;
150 buflen = this->convert.len_cvt;
152 if (!this->hidden->mixbuf) {
154 if (!this->hidden->mixbuf) {
158 buf = this->hidden->mixbuf;
163 var numChannels = SDL2.capture.currentCaptureBuffer.numberOfChannels;
164 if (numChannels == 1) {
165 var channelData = SDL2.capture.currentCaptureBuffer.getChannelData(0);
166 if (channelData.length != $1) {
167 throw 'Web Audio capture buffer length mismatch! Destination size: ' + channelData.length +
' samples vs expected ' + $1 +
' samples!';
169 for (var
j = 0;
j < $1; ++
j) {
170 setValue($0 + (
j * 4), channelData[
j],
'float');
173 for (var
c = 0;
c < numChannels; ++
c) {
174 var channelData = SDL2.capture.currentCaptureBuffer.getChannelData(
c);
175 if (channelData.length != $1) {
176 throw 'Web Audio capture buffer length mismatch! Destination size: ' + channelData.length +
' samples vs expected ' + $1 +
' samples!';
179 for (var
j = 0;
j < $1; ++
j) {
180 setValue($0 + (((
j * numChannels) +
c) * 4), channelData[
j],
'float');
188 if (this->convert.needed) {
199 EMSCRIPTENAUDIO_CloseDevice(
_THIS)
203 if (SDL2.capture.silenceTimer !== undefined) {
204 clearTimeout(SDL2.capture.silenceTimer);
206 if (SDL2.capture.stream !== undefined) {
207 var tracks = SDL2.capture.stream.getAudioTracks();
208 for (var i = 0; i < tracks.length; i++) {
209 SDL2.capture.stream.removeTrack(tracks[i]);
211 SDL2.capture.stream = undefined;
213 if (SDL2.capture.scriptProcessorNode !== undefined) {
214 SDL2.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {};
215 SDL2.capture.scriptProcessorNode.disconnect();
216 SDL2.capture.scriptProcessorNode = undefined;
218 if (SDL2.capture.mediaStreamNode !== undefined) {
219 SDL2.capture.mediaStreamNode.disconnect();
220 SDL2.capture.mediaStreamNode = undefined;
222 if (SDL2.capture.silenceBuffer !== undefined) {
223 SDL2.capture.silenceBuffer = undefined
225 SDL2.capture = undefined;
227 if (SDL2.audio.scriptProcessorNode != undefined) {
228 SDL2.audio.scriptProcessorNode.disconnect();
229 SDL2.audio.scriptProcessorNode = undefined;
231 SDL2.audio = undefined;
233 if ((SDL2.audioContext !== undefined) && (SDL2.audio === undefined) && (SDL2.capture === undefined)) {
234 SDL2.audioContext.close();
235 SDL2.audioContext = undefined;
244 EMSCRIPTENAUDIO_OpenDevice(
_THIS,
void *handle,
const char *devname,
int iscapture)
255 result = EM_ASM_INT({
256 if(typeof(SDL2) ===
'undefined') {
265 if (!SDL2.audioContext) {
266 if (typeof(AudioContext) !==
'undefined') {
267 SDL2.audioContext = new AudioContext();
268 }
else if (typeof(webkitAudioContext) !==
'undefined') {
269 SDL2.audioContext =
new webkitAudioContext();
272 return SDL2.audioContext === undefined ? -1 : 0;
279 while ((!valid_format) && (test_format)) {
280 switch (test_format) {
298 if (this->hidden ==
NULL) {
304 const int sampleRate = EM_ASM_INT_V({
305 return SDL2.audioContext.sampleRate;
310 f = (float)i / (
float)sampleRate * (float)this->
spec.
freq;
312 this->hidden->conv_in_len =
SDL_floor(f);
340 var have_microphone =
function(
stream) {
342 if (SDL2.capture.silenceTimer !== undefined) {
343 clearTimeout(SDL2.capture.silenceTimer);
344 SDL2.capture.silenceTimer = undefined;
346 SDL2.capture.mediaStreamNode = SDL2.audioContext.createMediaStreamSource(
stream);
347 SDL2.capture.scriptProcessorNode = SDL2.audioContext.createScriptProcessor($1, $0, 1);
348 SDL2.capture.scriptProcessorNode.onaudioprocess =
function(audioProcessingEvent) {
349 if ((SDL2 === undefined) || (SDL2.capture === undefined)) {
return; }
350 audioProcessingEvent.outputBuffer.getChannelData(0).fill(0.0);
351 SDL2.capture.currentCaptureBuffer = audioProcessingEvent.inputBuffer;
352 Runtime.dynCall(
'vi', $2, [$3]);
354 SDL2.capture.mediaStreamNode.connect(SDL2.capture.scriptProcessorNode);
355 SDL2.capture.scriptProcessorNode.connect(SDL2.audioContext.destination);
356 SDL2.capture.stream =
stream;
359 var no_microphone =
function(error) {
364 SDL2.capture.silenceBuffer = SDL2.audioContext.createBuffer($0, $1, SDL2.audioContext.sampleRate);
365 SDL2.capture.silenceBuffer.getChannelData(0).fill(0.0);
366 var silence_callback =
function() {
367 SDL2.capture.currentCaptureBuffer = SDL2.capture.silenceBuffer;
368 Runtime.dynCall(
'vi', $2, [$3]);
371 SDL2.capture.silenceTimer = setTimeout(silence_callback, ($1 / SDL2.audioContext.sampleRate) * 1000);
373 if ((navigator.mediaDevices !== undefined) && (navigator.mediaDevices.getUserMedia !== undefined)) {
374 navigator.mediaDevices.getUserMedia({
audio:
true, video:
false }).then(have_microphone).catch(no_microphone);
375 }
else if (navigator.webkitGetUserMedia !== undefined) {
376 navigator.webkitGetUserMedia({
audio:
true, video:
false }, have_microphone, no_microphone);
382 SDL2.audio.scriptProcessorNode = SDL2.audioContext[
'createScriptProcessor']($1, 0, $0);
383 SDL2.audio.scriptProcessorNode[
'onaudioprocess'] =
function (
e) {
384 if ((SDL2 === undefined) || (SDL2.audio === undefined)) {
return; }
385 SDL2.audio.currentOutputBuffer =
e[
'outputBuffer'];
386 Runtime.dynCall(
'vi', $2, [$3]);
388 SDL2.audio.scriptProcessorNode[
'connect'](SDL2.audioContext[
'destination']);
399 impl->
OpenDevice = EMSCRIPTENAUDIO_OpenDevice;
409 const int available = EM_ASM_INT_V({
410 if (typeof(AudioContext) !==
'undefined') {
412 }
else if (typeof(webkitAudioContext) !==
'undefined') {
422 const int capture_available = available && EM_ASM_INT_V({
423 if ((typeof(navigator.mediaDevices) !==
'undefined') && (typeof(navigator.mediaDevices.getUserMedia) !==
'undefined')) {
425 }
else if (typeof(navigator.webkitGetUserMedia) !==
'undefined') {
438 "emscripten",
"SDL emscripten audio driver", EMSCRIPTENAUDIO_Init, 0
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
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
int ProvidesOwnCallbackThread
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 local skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
Uint16 SDL_AudioFormat
Audio format flags.
int OnlyHasDefaultCaptureDevice
SDL_AudioFormat SDL_NextAudioFormat(void)
int OnlyHasDefaultOutputDevice
uint8_t Uint8
An unsigned 8-bit integer type.
#define SDL_AUDIO_BITSIZE(x)
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)
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
SDL_AudioCallback callback
GLenum GLuint GLenum GLsizei const GLchar * buf
GLenum GLenum GLsizei const GLuint GLboolean enabled
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 in i)
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
#define SDL_OutOfMemory()
void(* CloseDevice)(_THIS)
AudioBootStrap EMSCRIPTENAUDIO_bootstrap