mirror of
				https://github.com/Ryujinx/SDL.git
				synced 2025-11-04 09:24:57 +00:00 
			
		
		
		
	disk audio: Implemented "capture" support, cleaned up some things.
This commit is contained in:
		
							parent
							
								
									a15b974044
								
							
						
					
					
						commit
						978df1ad74
					
				| 
						 | 
				
			
			@ -33,11 +33,6 @@
 | 
			
		|||
static SDL_AudioDriver current_audio;
 | 
			
		||||
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
 | 
			
		||||
 *  to have a complete list here and saves yet-another block of #ifdefs...
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,6 +26,10 @@
 | 
			
		|||
#include "SDL_mutex.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 */
 | 
			
		||||
typedef struct SDL_AudioDevice SDL_AudioDevice;
 | 
			
		||||
#define _THIS   SDL_AudioDevice *_this
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,42 +34,31 @@
 | 
			
		|||
#include "../SDL_audio_c.h"
 | 
			
		||||
#include "SDL_diskaudio.h"
 | 
			
		||||
 | 
			
		||||
/* !!! FIXME: these should be SDL hints, not environment variables. */
 | 
			
		||||
/* environment variables and defaults. */
 | 
			
		||||
#define DISKENVR_OUTFILE         "SDL_DISKAUDIOFILE"
 | 
			
		||||
#define DISKDEFAULT_OUTFILE      "sdlaudio.raw"
 | 
			
		||||
#define DISKENVR_WRITEDELAY      "SDL_DISKAUDIODELAY"
 | 
			
		||||
#define DISKDEFAULT_WRITEDELAY   150
 | 
			
		||||
 | 
			
		||||
static const char *
 | 
			
		||||
DISKAUD_GetOutputFilename(const char *devname)
 | 
			
		||||
{
 | 
			
		||||
    if (devname == NULL) {
 | 
			
		||||
        devname = SDL_getenv(DISKENVR_OUTFILE);
 | 
			
		||||
        if (devname == NULL) {
 | 
			
		||||
            devname = DISKDEFAULT_OUTFILE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return devname;
 | 
			
		||||
}
 | 
			
		||||
#define DISKENVR_INFILE         "SDL_DISKAUDIOFILEIN"
 | 
			
		||||
#define DISKDEFAULT_INFILE      "sdlaudio-in.raw"
 | 
			
		||||
#define DISKENVR_IODELAY      "SDL_DISKAUDIODELAY"
 | 
			
		||||
#define DISKDEFAULT_IODELAY   150
 | 
			
		||||
 | 
			
		||||
/* This function waits until it is possible to write a full sound buffer */
 | 
			
		||||
static void
 | 
			
		||||
DISKAUD_WaitDevice(_THIS)
 | 
			
		||||
{
 | 
			
		||||
    SDL_Delay(this->hidden->write_delay);
 | 
			
		||||
    SDL_Delay(this->hidden->io_delay);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
DISKAUD_PlayDevice(_THIS)
 | 
			
		||||
{
 | 
			
		||||
    size_t written;
 | 
			
		||||
 | 
			
		||||
    /* Write the audio data */
 | 
			
		||||
    written = SDL_RWwrite(this->hidden->output,
 | 
			
		||||
                          this->hidden->mixbuf, 1, this->hidden->mixlen);
 | 
			
		||||
    const size_t written = SDL_RWwrite(this->hidden->io,
 | 
			
		||||
                                       this->hidden->mixbuf,
 | 
			
		||||
                                       1, this->spec.size);
 | 
			
		||||
 | 
			
		||||
    /* If we couldn't write, assume fatal error for now */
 | 
			
		||||
    if (written != this->hidden->mixlen) {
 | 
			
		||||
    if (written != this->spec.size) {
 | 
			
		||||
        SDL_OpenedAudioDeviceDisconnected(this);
 | 
			
		||||
    }
 | 
			
		||||
#ifdef DEBUG_AUDIO
 | 
			
		||||
| 
						 | 
				
			
			@ -83,22 +72,66 @@ DISKAUD_GetDeviceBuf(_THIS)
 | 
			
		|||
    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
 | 
			
		||||
DISKAUD_CloseDevice(_THIS)
 | 
			
		||||
{
 | 
			
		||||
    if (this->hidden->output != NULL) {
 | 
			
		||||
        SDL_RWclose(this->hidden->output);
 | 
			
		||||
    if (this->hidden->io != NULL) {
 | 
			
		||||
        SDL_RWclose(this->hidden->io);
 | 
			
		||||
    }
 | 
			
		||||
    SDL_free(this->hidden->mixbuf);
 | 
			
		||||
    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
 | 
			
		||||
DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 | 
			
		||||
{
 | 
			
		||||
    /* handle != NULL means "user specified the placeholder name on the fake detected device list" */
 | 
			
		||||
    const char *fname = DISKAUD_GetOutputFilename(handle ? NULL : devname);
 | 
			
		||||
    const char *envr = SDL_getenv(DISKENVR_WRITEDELAY);
 | 
			
		||||
    const char *fname = get_filename(iscapture, handle ? NULL : devname);
 | 
			
		||||
    const char *envr = SDL_getenv(DISKENVR_IODELAY);
 | 
			
		||||
 | 
			
		||||
    this->hidden = (struct SDL_PrivateAudioData *)
 | 
			
		||||
        SDL_malloc(sizeof(*this->hidden));
 | 
			
		||||
| 
						 | 
				
			
			@ -107,27 +140,28 @@ DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 | 
			
		|||
    }
 | 
			
		||||
    SDL_zerop(this->hidden);
 | 
			
		||||
 | 
			
		||||
    this->hidden->mixlen = this->spec.size;
 | 
			
		||||
    this->hidden->write_delay =
 | 
			
		||||
        (envr) ? SDL_atoi(envr) : DISKDEFAULT_WRITEDELAY;
 | 
			
		||||
    this->hidden->io_delay = (envr) ? SDL_atoi(envr) : DISKDEFAULT_IODELAY;
 | 
			
		||||
 | 
			
		||||
    /* Open the audio device */
 | 
			
		||||
    this->hidden->output = SDL_RWFromFile(fname, "wb");
 | 
			
		||||
    if (this->hidden->output == NULL) {
 | 
			
		||||
    this->hidden->io = SDL_RWFromFile(fname, iscapture ? "rb" : "wb");
 | 
			
		||||
    if (this->hidden->io == NULL) {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Allocate mixing buffer */
 | 
			
		||||
    this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
 | 
			
		||||
    if (this->hidden->mixbuf == NULL) {
 | 
			
		||||
        return -1;
 | 
			
		||||
    if (!iscapture) {
 | 
			
		||||
        this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->spec.size);
 | 
			
		||||
        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
 | 
			
		||||
    fprintf(stderr,
 | 
			
		||||
            "WARNING: You are using the SDL disk writer audio driver!\n"
 | 
			
		||||
            " Writing to file [%s].\n", fname);
 | 
			
		||||
            "WARNING: You are using the SDL disk i/o audio driver!\n"
 | 
			
		||||
            " %s file [%s].\n", iscapture ? "Reading from" : "Writing to",
 | 
			
		||||
            fname);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* We're ready to rock and roll. :-) */
 | 
			
		||||
| 
						 | 
				
			
			@ -137,8 +171,8 @@ DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 | 
			
		|||
static void
 | 
			
		||||
DISKAUD_DetectDevices(void)
 | 
			
		||||
{
 | 
			
		||||
    /* !!! FIXME: stole this literal string from DEFAULT_OUTPUT_DEVNAME in SDL_audio.c */
 | 
			
		||||
    SDL_AddAudioDevice(SDL_FALSE, "System audio output device", (void *) 0x1);
 | 
			
		||||
    SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) 0x1);
 | 
			
		||||
    SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, (void *) 0x2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
| 
						 | 
				
			
			@ -149,10 +183,14 @@ DISKAUD_Init(SDL_AudioDriverImpl * impl)
 | 
			
		|||
    impl->WaitDevice = DISKAUD_WaitDevice;
 | 
			
		||||
    impl->PlayDevice = DISKAUD_PlayDevice;
 | 
			
		||||
    impl->GetDeviceBuf = DISKAUD_GetDeviceBuf;
 | 
			
		||||
    impl->CaptureFromDevice = DISKAUD_CaptureFromDevice;
 | 
			
		||||
    impl->FlushCapture = DISKAUD_FlushCapture;
 | 
			
		||||
 | 
			
		||||
    impl->CloseDevice = DISKAUD_CloseDevice;
 | 
			
		||||
    impl->DetectDevices = DISKAUD_DetectDevices;
 | 
			
		||||
 | 
			
		||||
    impl->AllowsArbitraryDeviceNames = 1;
 | 
			
		||||
    impl->HasCaptureSupport = SDL_TRUE;
 | 
			
		||||
 | 
			
		||||
    return 1;   /* this audio target is available. */
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,10 +32,9 @@
 | 
			
		|||
struct SDL_PrivateAudioData
 | 
			
		||||
{
 | 
			
		||||
    /* The file descriptor for the audio device */
 | 
			
		||||
    SDL_RWops *output;
 | 
			
		||||
    SDL_RWops *io;
 | 
			
		||||
    Uint32 io_delay;
 | 
			
		||||
    Uint8 *mixbuf;
 | 
			
		||||
    Uint32 mixlen;
 | 
			
		||||
    Uint32 write_delay;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif /* _SDL_diskaudio_h */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue