disk audio: Implemented "capture" support, cleaned up some things.

Ryan C. Gordon 2016-08-06 03:39:15 -04:00
parent a15b974044
commit 978df1ad74
4 changed files with 82 additions and 46 deletions

View File

@ -33,11 +33,6 @@
static SDL_AudioDriver current_audio; static SDL_AudioDriver current_audio;
static SDL_AudioDevice *open_devices[16]; static SDL_AudioDevice *open_devices[16];
/* !!! FIXME: These are wordy and unlocalized... */
#define DEFAULT_OUTPUT_DEVNAME "System audio output device"
#define DEFAULT_INPUT_DEVNAME "System audio capture device"
/* /*
* Not all of these will be compiled and linked in, but it's convenient * Not all of these will be compiled and linked in, but it's convenient
* to have a complete list here and saves yet-another block of #ifdefs... * to have a complete list here and saves yet-another block of #ifdefs...

View File

@ -26,6 +26,10 @@
#include "SDL_mutex.h" #include "SDL_mutex.h"
#include "SDL_thread.h" #include "SDL_thread.h"
/* !!! FIXME: These are wordy and unlocalized... */
#define DEFAULT_OUTPUT_DEVNAME "System audio output device"
#define DEFAULT_INPUT_DEVNAME "System audio capture device"
/* The SDL audio driver */ /* The SDL audio driver */
typedef struct SDL_AudioDevice SDL_AudioDevice; typedef struct SDL_AudioDevice SDL_AudioDevice;
#define _THIS SDL_AudioDevice *_this #define _THIS SDL_AudioDevice *_this

View File

@ -34,42 +34,31 @@
#include "../SDL_audio_c.h" #include "../SDL_audio_c.h"
#include "SDL_diskaudio.h" #include "SDL_diskaudio.h"
/* !!! FIXME: these should be SDL hints, not environment variables. */
/* environment variables and defaults. */ /* environment variables and defaults. */
#define DISKENVR_OUTFILE "SDL_DISKAUDIOFILE" #define DISKENVR_OUTFILE "SDL_DISKAUDIOFILE"
#define DISKDEFAULT_OUTFILE "sdlaudio.raw" #define DISKDEFAULT_OUTFILE "sdlaudio.raw"
#define DISKENVR_WRITEDELAY "SDL_DISKAUDIODELAY" #define DISKENVR_INFILE "SDL_DISKAUDIOFILEIN"
#define DISKDEFAULT_WRITEDELAY 150 #define DISKDEFAULT_INFILE "sdlaudio-in.raw"
#define DISKENVR_IODELAY "SDL_DISKAUDIODELAY"
static const char * #define DISKDEFAULT_IODELAY 150
DISKAUD_GetOutputFilename(const char *devname)
{
if (devname == NULL) {
devname = SDL_getenv(DISKENVR_OUTFILE);
if (devname == NULL) {
devname = DISKDEFAULT_OUTFILE;
}
}
return devname;
}
/* This function waits until it is possible to write a full sound buffer */ /* This function waits until it is possible to write a full sound buffer */
static void static void
DISKAUD_WaitDevice(_THIS) DISKAUD_WaitDevice(_THIS)
{ {
SDL_Delay(this->hidden->write_delay); SDL_Delay(this->hidden->io_delay);
} }
static void static void
DISKAUD_PlayDevice(_THIS) DISKAUD_PlayDevice(_THIS)
{ {
size_t written; const size_t written = SDL_RWwrite(this->hidden->io,
this->hidden->mixbuf,
/* Write the audio data */ 1, this->spec.size);
written = SDL_RWwrite(this->hidden->output,
this->hidden->mixbuf, 1, this->hidden->mixlen);
/* If we couldn't write, assume fatal error for now */ /* If we couldn't write, assume fatal error for now */
if (written != this->hidden->mixlen) { if (written != this->spec.size) {
SDL_OpenedAudioDeviceDisconnected(this); SDL_OpenedAudioDeviceDisconnected(this);
} }
#ifdef DEBUG_AUDIO #ifdef DEBUG_AUDIO
@ -83,22 +72,66 @@ DISKAUD_GetDeviceBuf(_THIS)
return (this->hidden->mixbuf); return (this->hidden->mixbuf);
} }
static int
DISKAUD_CaptureFromDevice(_THIS, void *buffer, int buflen)
{
struct SDL_PrivateAudioData *h = this->hidden;
const int origbuflen = buflen;
SDL_Delay(h->io_delay);
if (h->io) {
const size_t br = SDL_RWread(h->io, buffer, 1, buflen);
buflen -= (int) br;
buffer = ((Uint8 *) buffer) + br;
if (buflen > 0) { /* EOF (or error, but whatever). */
SDL_RWclose(h->io);
h->io = NULL;
}
}
/* if we ran out of file, just write silence. */
SDL_memset(buffer, this->spec.silence, buflen);
return origbuflen;
}
static void
DISKAUD_FlushCapture(_THIS)
{
/* no op...we don't advance the file pointer or anything. */
}
static void static void
DISKAUD_CloseDevice(_THIS) DISKAUD_CloseDevice(_THIS)
{ {
if (this->hidden->output != NULL) { if (this->hidden->io != NULL) {
SDL_RWclose(this->hidden->output); SDL_RWclose(this->hidden->io);
} }
SDL_free(this->hidden->mixbuf); SDL_free(this->hidden->mixbuf);
SDL_free(this->hidden); SDL_free(this->hidden);
} }
static const char *
get_filename(const int iscapture, const char *devname)
{
if (devname == NULL) {
devname = SDL_getenv(iscapture ? DISKENVR_INFILE : DISKENVR_OUTFILE);
if (devname == NULL) {
devname = iscapture ? DISKDEFAULT_INFILE : DISKDEFAULT_OUTFILE;
}
}
return devname;
}
static int static int
DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{ {
/* handle != NULL means "user specified the placeholder name on the fake detected device list" */ /* handle != NULL means "user specified the placeholder name on the fake detected device list" */
const char *fname = DISKAUD_GetOutputFilename(handle ? NULL : devname); const char *fname = get_filename(iscapture, handle ? NULL : devname);
const char *envr = SDL_getenv(DISKENVR_WRITEDELAY); const char *envr = SDL_getenv(DISKENVR_IODELAY);
this->hidden = (struct SDL_PrivateAudioData *) this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc(sizeof(*this->hidden)); SDL_malloc(sizeof(*this->hidden));
@ -107,27 +140,28 @@ DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
} }
SDL_zerop(this->hidden); SDL_zerop(this->hidden);
this->hidden->mixlen = this->spec.size; this->hidden->io_delay = (envr) ? SDL_atoi(envr) : DISKDEFAULT_IODELAY;
this->hidden->write_delay =
(envr) ? SDL_atoi(envr) : DISKDEFAULT_WRITEDELAY;
/* Open the audio device */ /* Open the audio device */
this->hidden->output = SDL_RWFromFile(fname, "wb"); this->hidden->io = SDL_RWFromFile(fname, iscapture ? "rb" : "wb");
if (this->hidden->output == NULL) { if (this->hidden->io == NULL) {
return -1; return -1;
} }
/* Allocate mixing buffer */ /* Allocate mixing buffer */
this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen); if (!iscapture) {
if (this->hidden->mixbuf == NULL) { this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->spec.size);
return -1; if (this->hidden->mixbuf == NULL) {
return SDL_OutOfMemory();
}
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
} }
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
#if HAVE_STDIO_H #if HAVE_STDIO_H
fprintf(stderr, fprintf(stderr,
"WARNING: You are using the SDL disk writer audio driver!\n" "WARNING: You are using the SDL disk i/o audio driver!\n"
" Writing to file [%s].\n", fname); " %s file [%s].\n", iscapture ? "Reading from" : "Writing to",
fname);
#endif #endif
/* We're ready to rock and roll. :-) */ /* We're ready to rock and roll. :-) */
@ -137,8 +171,8 @@ DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
static void static void
DISKAUD_DetectDevices(void) DISKAUD_DetectDevices(void)
{ {
/* !!! FIXME: stole this literal string from DEFAULT_OUTPUT_DEVNAME in SDL_audio.c */ SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) 0x1);
SDL_AddAudioDevice(SDL_FALSE, "System audio output device", (void *) 0x1); SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, (void *) 0x2);
} }
static int static int
@ -149,10 +183,14 @@ DISKAUD_Init(SDL_AudioDriverImpl * impl)
impl->WaitDevice = DISKAUD_WaitDevice; impl->WaitDevice = DISKAUD_WaitDevice;
impl->PlayDevice = DISKAUD_PlayDevice; impl->PlayDevice = DISKAUD_PlayDevice;
impl->GetDeviceBuf = DISKAUD_GetDeviceBuf; impl->GetDeviceBuf = DISKAUD_GetDeviceBuf;
impl->CaptureFromDevice = DISKAUD_CaptureFromDevice;
impl->FlushCapture = DISKAUD_FlushCapture;
impl->CloseDevice = DISKAUD_CloseDevice; impl->CloseDevice = DISKAUD_CloseDevice;
impl->DetectDevices = DISKAUD_DetectDevices; impl->DetectDevices = DISKAUD_DetectDevices;
impl->AllowsArbitraryDeviceNames = 1; impl->AllowsArbitraryDeviceNames = 1;
impl->HasCaptureSupport = SDL_TRUE;
return 1; /* this audio target is available. */ return 1; /* this audio target is available. */
} }

View File

@ -32,10 +32,9 @@
struct SDL_PrivateAudioData struct SDL_PrivateAudioData
{ {
/* The file descriptor for the audio device */ /* The file descriptor for the audio device */
SDL_RWops *output; SDL_RWops *io;
Uint32 io_delay;
Uint8 *mixbuf; Uint8 *mixbuf;
Uint32 mixlen;
Uint32 write_delay;
}; };
#endif /* _SDL_diskaudio_h */ #endif /* _SDL_diskaudio_h */