/* =============== SNDDMA_Init =============== */ qboolean SNDDMA_Init(void) { SDL_AudioSpec desired; SDL_AudioSpec obtained; int tmp; if (snd_inited) return qtrue; if (!s_sdlBits) { s_sdlBits = Cvar_Get("s_sdlBits", "16", CVAR_ARCHIVE); s_sdlSpeed = Cvar_Get("s_sdlSpeed", "44100", CVAR_ARCHIVE); s_sdlChannels = Cvar_Get("s_sdlChannels", "2", CVAR_ARCHIVE); s_sdlDevSamps = Cvar_Get("s_sdlDevSamps", "0", CVAR_ARCHIVE); s_sdlMixSamps = Cvar_Get("s_sdlMixSamps", "0", CVAR_ARCHIVE); } Com_Printf( "SDL_Init( SDL_INIT_AUDIO )... " ); if (!SDL_WasInit(SDL_INIT_AUDIO)) { if (SDL_Init(SDL_INIT_AUDIO) == -1) { Com_Printf( "FAILED (%s)\n", SDL_GetError( ) ); return qfalse; } } Com_Printf( "OK\n" ); Com_Printf( "SDL audio driver is \"%s\".\n", SDL_GetCurrentAudioDriver( ) ); memset(&desired, '\0', sizeof (desired)); memset(&obtained, '\0', sizeof (obtained)); tmp = ((int) s_sdlBits->value); if ((tmp != 16) && (tmp != 8)) tmp = 16; desired.freq = (int) s_sdlSpeed->value; if(!desired.freq) desired.freq = 44100; desired.format = ((tmp == 16) ? AUDIO_S16SYS : AUDIO_U8); // I dunno if this is the best idea, but I'll give it a try... // should probably check a cvar for this... if (s_sdlDevSamps->value) desired.samples = s_sdlDevSamps->value; else { // just pick a sane default. if (desired.freq <= 11025) desired.samples = 256; else if (desired.freq <= 22050) desired.samples = 512; else if (desired.freq <= 44100) desired.samples = 1024; else desired.samples = 2048; // (*shrug*) } desired.channels = (int) s_sdlChannels->value; desired.callback = SNDDMA_AudioCallback; if (SDL_OpenAudio(&desired, &obtained) == -1) { Com_Printf("SDL_OpenAudio() failed: %s\n", SDL_GetError()); SDL_QuitSubSystem(SDL_INIT_AUDIO); return qfalse; } SNDDMA_PrintAudiospec("SDL_AudioSpec", &obtained); // dma.samples needs to be big, or id's mixer will just refuse to // work at all; we need to keep it significantly bigger than the // amount of SDL callback samples, and just copy a little each time // the callback runs. // 32768 is what the OSS driver filled in here on my system. I don't // know if it's a good value overall, but at least we know it's // reasonable...this is why I let the user override. tmp = s_sdlMixSamps->value; if (!tmp) tmp = (obtained.samples * obtained.channels) * 10; if (tmp & (tmp - 1)) // not a power of two? Seems to confuse something. { int val = 1; while (val < tmp) val <<= 1; tmp = val; } dmapos = 0; dma.samplebits = obtained.format & 0xFF; // first byte of format is bits. dma.channels = obtained.channels; dma.samples = tmp; dma.submission_chunk = 1; dma.speed = obtained.freq; dmasize = (dma.samples * (dma.samplebits/8)); dma.buffer = (byte *)calloc(1, dmasize); Com_Printf("Starting SDL audio callback...\n"); SDL_PauseAudio(0); // start callback. Com_Printf("SDL audio initialized.\n"); snd_inited = qtrue; return qtrue; }
/* =============== SNDDMA_Init =============== */ qboolean SNDDMA_Init(void) { SDL_AudioSpec desired; SDL_AudioSpec obtained; const char *driver_name; int tmp; if (snd_inited) { return qtrue; } // before rc 2 we have had own s_sdl_ cvars to set this // changed back to use genuine cvar names // - it's more compatible when existing profiles are used // - we don't have to touch menu & ui to make speed/khz work (uses s_khz!) s_bits = Cvar_Get("s_bits", "16", CVAR_LATCH | CVAR_ARCHIVE); s_khz = Cvar_Get("s_khz", "44", CVAR_LATCH | CVAR_ARCHIVE); s_sdlChannels = Cvar_Get("s_channels", "2", CVAR_LATCH | CVAR_ARCHIVE); s_sdlDevSamps = Cvar_Get("s_sdlDevSamps", "0", CVAR_LATCH | CVAR_ARCHIVE); s_sdlMixSamps = Cvar_Get("s_sdlMixSamps", "0", CVAR_LATCH | CVAR_ARCHIVE); Com_Printf("SDL_Init( SDL_INIT_AUDIO )... "); if (!SDL_WasInit(SDL_INIT_AUDIO)) { if (LegacySDL_Init(SDL_INIT_AUDIO) == -1) { Com_Printf("FAILED (%s)\n", SDL_GetError()); return qfalse; } } Com_Printf("OK\n"); driver_name = SDL_GetCurrentAudioDriver(); if (driver_name) { Com_Printf("SDL audio driver is \"%s\".\n", driver_name); } else { Com_Printf("SDL audio driver isn't initialized.\n"); } memset(&desired, '\0', sizeof(desired)); memset(&obtained, '\0', sizeof(obtained)); tmp = ((int) s_bits->value); if ((tmp != 16) && (tmp != 8)) { tmp = 16; } desired.freq = (int) s_khz->value * 1000; // desired freq expects Hz not kHz if (!desired.freq) { desired.freq = 22050; } // dirty correction for profile values if (desired.freq == 11000) { desired.freq = 11025; } else if (desired.freq == 22000) { desired.freq = 22050; } else if (desired.freq == 44000) { desired.freq = 44100; } else { desired.freq = 22050; } desired.format = ((tmp == 16) ? AUDIO_S16SYS : AUDIO_U8); // I dunno if this is the best idea, but I'll give it a try... // should probably check a cvar for this... if (s_sdlDevSamps->value) { desired.samples = s_sdlDevSamps->value; } else { // just pick a sane default. if (desired.freq <= 11025) { desired.samples = 256; } else if (desired.freq <= 22050) { desired.samples = 512; } else if (desired.freq <= 44100) { desired.samples = 1024; } else { desired.samples = 2048; // (*shrug*) } } desired.channels = (int) s_sdlChannels->value; desired.callback = SNDDMA_AudioCallback; if (SDL_OpenAudio(&desired, &obtained) == -1) { Com_Printf("SDL_OpenAudio() failed: %s\n", SDL_GetError()); SDL_QuitSubSystem(SDL_INIT_AUDIO); return qfalse; } SNDDMA_PrintAudiospec("SDL_AudioSpec", &obtained); // dma.samples needs to be big, or id's mixer will just refuse to // work at all; we need to keep it significantly bigger than the // amount of SDL callback samples, and just copy a little each time // the callback runs. // 32768 is what the OSS driver filled in here on my system. I don't // know if it's a good value overall, but at least we know it's // reasonable...this is why I let the user override. tmp = s_sdlMixSamps->value; if (!tmp) { tmp = (obtained.samples * obtained.channels) * 10; } if (tmp & (tmp - 1)) // not a power of two? Seems to confuse something. { int val = 1; while (val < tmp) val <<= 1; tmp = val; } dmapos = 0; dma.samplebits = obtained.format & 0xFF; // first byte of format is bits. dma.channels = obtained.channels; dma.samples = tmp; dma.submission_chunk = 1; dma.speed = obtained.freq; dmasize = (dma.samples * (dma.samplebits / 8)); dma.buffer = calloc(1, dmasize); if (!dma.buffer) { Com_Printf("Unable to allocate dma buffer\n"); SDL_QuitSubSystem(SDL_INIT_AUDIO); return qfalse; } Com_Printf("Starting SDL audio callback...\n"); SDL_PauseAudio(0); // start callback. Com_Printf("SDL audio initialized.\n"); snd_inited = qtrue; return qtrue; }
/* =============== SNDDMA_Init =============== */ qboolean SNDDMA_Init(void) { SDL_AudioSpec desired; SDL_AudioSpec obtained; int tmp; #ifdef USE_SDL_AUDIO_CAPTURE SDL_version sdlVersion; #endif if (snd_inited) return qtrue; if (!s_sdlBits) { s_sdlBits = Cvar_Get("s_sdlBits", "16", CVAR_ARCHIVE); s_sdlSpeed = Cvar_Get("s_sdlSpeed", "0", CVAR_ARCHIVE); s_sdlChannels = Cvar_Get("s_sdlChannels", "2", CVAR_ARCHIVE); s_sdlDevSamps = Cvar_Get("s_sdlDevSamps", "0", CVAR_ARCHIVE); s_sdlMixSamps = Cvar_Get("s_sdlMixSamps", "0", CVAR_ARCHIVE); } Com_Printf( "SDL_Init( SDL_INIT_AUDIO )... " ); if (SDL_Init(SDL_INIT_AUDIO) != 0) { Com_Printf( "FAILED (%s)\n", SDL_GetError( ) ); return qfalse; } Com_Printf( "OK\n" ); Com_Printf( "SDL audio driver is \"%s\".\n", SDL_GetCurrentAudioDriver( ) ); memset(&desired, '\0', sizeof (desired)); memset(&obtained, '\0', sizeof (obtained)); tmp = ((int) s_sdlBits->value); if ((tmp != 16) && (tmp != 8)) tmp = 16; desired.freq = (int) s_sdlSpeed->value; if(!desired.freq) desired.freq = 22050; desired.format = ((tmp == 16) ? AUDIO_S16SYS : AUDIO_U8); // I dunno if this is the best idea, but I'll give it a try... // should probably check a cvar for this... if (s_sdlDevSamps->value) desired.samples = s_sdlDevSamps->value; else { // just pick a sane default. if (desired.freq <= 11025) desired.samples = 256; else if (desired.freq <= 22050) desired.samples = 512; else if (desired.freq <= 44100) desired.samples = 1024; else desired.samples = 2048; // (*shrug*) } desired.channels = (int) s_sdlChannels->value; desired.callback = SNDDMA_AudioCallback; sdlPlaybackDevice = SDL_OpenAudioDevice(NULL, SDL_FALSE, &desired, &obtained, SDL_AUDIO_ALLOW_ANY_CHANGE); if (sdlPlaybackDevice == 0) { Com_Printf("SDL_OpenAudioDevice() failed: %s\n", SDL_GetError()); SDL_QuitSubSystem(SDL_INIT_AUDIO); return qfalse; } SNDDMA_PrintAudiospec("SDL_AudioSpec", &obtained); // dma.samples needs to be big, or id's mixer will just refuse to // work at all; we need to keep it significantly bigger than the // amount of SDL callback samples, and just copy a little each time // the callback runs. // 32768 is what the OSS driver filled in here on my system. I don't // know if it's a good value overall, but at least we know it's // reasonable...this is why I let the user override. tmp = s_sdlMixSamps->value; if (!tmp) tmp = (obtained.samples * obtained.channels) * 10; if (tmp & (tmp - 1)) // not a power of two? Seems to confuse something. { int val = 1; while (val < tmp) val <<= 1; tmp = val; } dmapos = 0; dma.samplebits = SDL_AUDIO_BITSIZE(obtained.format); dma.isfloat = SDL_AUDIO_ISFLOAT(obtained.format); dma.channels = obtained.channels; dma.samples = tmp; dma.submission_chunk = 1; dma.speed = obtained.freq; dmasize = (dma.samples * (dma.samplebits/8)); dma.buffer = calloc(1, dmasize); #ifdef USE_SDL_AUDIO_CAPTURE // !!! FIXME: some of these SDL_OpenAudioDevice() values should be cvars. s_sdlCapture = Cvar_Get( "s_sdlCapture", "1", CVAR_ARCHIVE | CVAR_LATCH ); // !!! FIXME: hopefully pulseaudio capture will be fixed in SDL 2.0.9... https://bugzilla.libsdl.org/show_bug.cgi?id=4087 SDL_GetVersion(&sdlVersion); if (sdlVersion.major == 2 && sdlVersion.minor == 0 && sdlVersion.patch < 9 && Q_stricmp(SDL_GetCurrentAudioDriver(), "pulseaudio") == 0) { Com_Printf("SDL audio capture support disabled (pulseaudio capture does not work correctly with SDL %d.%d.%d)\n", sdlVersion.major, sdlVersion.minor, sdlVersion.patch); } else if (!s_sdlCapture->integer) { Com_Printf("SDL audio capture support disabled by user ('+set s_sdlCapture 1' to enable)\n"); } #if USE_MUMBLE else if (cl_useMumble->integer) { Com_Printf("SDL audio capture support disabled for Mumble support\n"); } #endif else { /* !!! FIXME: list available devices and let cvar specify one, like OpenAL does */ SDL_AudioSpec spec; SDL_zero(spec); spec.freq = 48000; spec.format = AUDIO_S16SYS; spec.channels = 1; spec.samples = VOIP_MAX_PACKET_SAMPLES * 4; sdlCaptureDevice = SDL_OpenAudioDevice(NULL, SDL_TRUE, &spec, NULL, 0); Com_Printf( "SDL capture device %s.\n", (sdlCaptureDevice == 0) ? "failed to open" : "opened"); } sdlMasterGain = 1.0f; #endif Com_Printf("Starting SDL audio callback...\n"); SDL_PauseAudioDevice(sdlPlaybackDevice, 0); // start callback. // don't unpause the capture device; we'll do that in StartCapture. Com_Printf("SDL audio initialized.\n"); snd_inited = qtrue; return qtrue; }