21 #include "../../SDL_internal.h" 23 #if SDL_AUDIO_DRIVER_EMSCRIPTEN 27 #include "../SDL_audio_c.h" 31 #include <emscripten/emscripten.h> 34 FeedAudioDevice(
_THIS,
const void *
buf,
const int buflen)
38 var numChannels = SDL2.audio.currentOutputBuffer[
'numberOfChannels'];
39 for (var
c = 0;
c < numChannels; ++
c) {
40 var channelData = SDL2.audio.currentOutputBuffer[
'getChannelData'](
c);
41 if (channelData.length != $1) {
42 throw 'Web Audio output buffer length mismatch! Destination size: ' + channelData.length +
' samples vs expected ' + $1 +
' samples!';
45 for (var
j = 0;
j < $1; ++
j) {
46 channelData[
j] = HEAPF32[$0 + ((
j*numChannels +
c) << 2) >> 2];
49 },
buf, buflen / framelen);
53 HandleAudioProcess(
_THIS)
56 const int stream_len = this->callbackspec.size;
68 callback(this->callbackspec.userdata, this->work_buffer, stream_len);
72 callback(this->callbackspec.userdata, this->work_buffer, stream_len);
87 FeedAudioDevice(
this, this->work_buffer, this->
spec.
size);
91 HandleCaptureProcess(
_THIS)
94 const int stream_len = this->callbackspec.size;
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)
149 if (SDL2.capture.silenceTimer !== undefined) {
150 clearTimeout(SDL2.capture.silenceTimer);
152 if (SDL2.capture.stream !== undefined) {
153 var tracks = SDL2.capture.stream.getAudioTracks();
154 for (var i = 0; i < tracks.length; i++) {
155 SDL2.capture.stream.removeTrack(tracks[i]);
157 SDL2.capture.stream = undefined;
159 if (SDL2.capture.scriptProcessorNode !== undefined) {
160 SDL2.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {};
161 SDL2.capture.scriptProcessorNode.disconnect();
162 SDL2.capture.scriptProcessorNode = undefined;
164 if (SDL2.capture.mediaStreamNode !== undefined) {
165 SDL2.capture.mediaStreamNode.disconnect();
166 SDL2.capture.mediaStreamNode = undefined;
168 if (SDL2.capture.silenceBuffer !== undefined) {
169 SDL2.capture.silenceBuffer = undefined
171 SDL2.capture = undefined;
173 if (SDL2.audio.scriptProcessorNode != undefined) {
174 SDL2.audio.scriptProcessorNode.disconnect();
175 SDL2.audio.scriptProcessorNode = undefined;
177 SDL2.audio = undefined;
179 if ((SDL2.audioContext !== undefined) && (SDL2.audio === undefined) && (SDL2.capture === undefined)) {
180 SDL2.audioContext.close();
181 SDL2.audioContext = undefined;
191 EMSCRIPTENAUDIO_OpenDevice(
_THIS,
void *
handle,
const char *devname,
int iscapture)
200 result = EM_ASM_INT({
201 if(typeof(SDL2) ===
'undefined') {
210 if (!SDL2.audioContext) {
211 if (typeof(AudioContext) !==
'undefined') {
212 SDL2.audioContext = new AudioContext();
213 }
else if (typeof(webkitAudioContext) !==
'undefined') {
214 SDL2.audioContext =
new webkitAudioContext();
217 return SDL2.audioContext === undefined ? -1 : 0;
224 while ((!valid_format) && (test_format)) {
225 switch (test_format) {
244 if (this->hidden ==
NULL) {
251 this->
spec.
freq = EM_ASM_INT_V({
return SDL2.audioContext.sampleRate; });
273 var have_microphone =
function(
stream) {
275 if (SDL2.capture.silenceTimer !== undefined) {
276 clearTimeout(SDL2.capture.silenceTimer);
277 SDL2.capture.silenceTimer = undefined;
279 SDL2.capture.mediaStreamNode = SDL2.audioContext.createMediaStreamSource(
stream);
280 SDL2.capture.scriptProcessorNode = SDL2.audioContext.createScriptProcessor($1, $0, 1);
281 SDL2.capture.scriptProcessorNode.onaudioprocess =
function(audioProcessingEvent) {
282 if ((SDL2 === undefined) || (SDL2.capture === undefined)) {
return; }
283 audioProcessingEvent.outputBuffer.getChannelData(0).fill(0.0);
284 SDL2.capture.currentCaptureBuffer = audioProcessingEvent.inputBuffer;
285 Runtime.dynCall(
'vi', $2, [$3]);
287 SDL2.capture.mediaStreamNode.connect(SDL2.capture.scriptProcessorNode);
288 SDL2.capture.scriptProcessorNode.connect(SDL2.audioContext.destination);
289 SDL2.capture.stream =
stream;
292 var no_microphone =
function(error) {
297 SDL2.capture.silenceBuffer = SDL2.audioContext.createBuffer($0, $1, SDL2.audioContext.sampleRate);
298 SDL2.capture.silenceBuffer.getChannelData(0).fill(0.0);
299 var silence_callback =
function() {
300 SDL2.capture.currentCaptureBuffer = SDL2.capture.silenceBuffer;
301 Runtime.dynCall(
'vi', $2, [$3]);
304 SDL2.capture.silenceTimer = setTimeout(silence_callback, ($1 / SDL2.audioContext.sampleRate) * 1000);
306 if ((navigator.mediaDevices !== undefined) && (navigator.mediaDevices.getUserMedia !== undefined)) {
307 navigator.mediaDevices.getUserMedia({
audio:
true, video:
false }).then(have_microphone).catch(no_microphone);
308 }
else if (navigator.webkitGetUserMedia !== undefined) {
309 navigator.webkitGetUserMedia({
audio:
true, video:
false }, have_microphone, no_microphone);
315 SDL2.audio.scriptProcessorNode = SDL2.audioContext[
'createScriptProcessor']($1, 0, $0);
316 SDL2.audio.scriptProcessorNode[
'onaudioprocess'] =
function (
e) {
317 if ((SDL2 === undefined) || (SDL2.audio === undefined)) {
return; }
318 SDL2.audio.currentOutputBuffer =
e[
'outputBuffer'];
319 Runtime.dynCall(
'vi', $2, [$3]);
321 SDL2.audio.scriptProcessorNode[
'connect'](SDL2.audioContext[
'destination']);
332 int capture_available;
335 impl->
OpenDevice = EMSCRIPTENAUDIO_OpenDevice;
345 available = EM_ASM_INT_V({
346 if (typeof(AudioContext) !==
'undefined') {
348 }
else if (typeof(webkitAudioContext) !==
'undefined') {
358 capture_available = available && EM_ASM_INT_V({
359 if ((typeof(navigator.mediaDevices) !==
'undefined') && (typeof(navigator.mediaDevices.getUserMedia) !==
'undefined')) {
361 }
else if (typeof(navigator.webkitGetUserMedia) !==
'undefined') {
374 "emscripten",
"SDL emscripten audio driver", EMSCRIPTENAUDIO_Init, 0
AudioBootStrap EMSCRIPTENAUDIO_bootstrap
#define SDL_AudioStreamAvailable
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
#define SDL_AudioStreamGet
int ProvidesOwnCallbackThread
Uint16 SDL_AudioFormat
Audio format flags.
int OnlyHasDefaultCaptureDevice
SDL_AudioFormat SDL_NextAudioFormat(void)
int OnlyHasDefaultOutputDevice
EGLImageKHR EGLint EGLint * handle
void(* SDL_AudioCallback)(void *userdata, Uint8 *stream, int len)
#define SDL_AUDIO_BITSIZE(x)
#define SDL_AudioStreamPut
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)
static Uint32 callback(Uint32 interval, void *param)
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
GLenum GLuint GLenum GLsizei const GLchar * buf
GLenum GLenum GLsizei const GLuint GLboolean enabled
#define SDL_assert(condition)
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
#define SDL_OutOfMemory()
void(* CloseDevice)(_THIS)
#define SDL_AudioStreamClear