SDL 2.0
SDL_diskaudio.c
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "../../SDL_internal.h"
22
23#if SDL_AUDIO_DRIVER_DISK
24
25/* Output raw audio data to a file. */
26
27#if HAVE_STDIO_H
28#include <stdio.h>
29#endif
30
31#include "SDL_rwops.h"
32#include "SDL_timer.h"
33#include "SDL_audio.h"
34#include "../SDL_audio_c.h"
35#include "SDL_diskaudio.h"
36#include "SDL_log.h"
37
38/* !!! FIXME: these should be SDL hints, not environment variables. */
39/* environment variables and defaults. */
40#define DISKENVR_OUTFILE "SDL_DISKAUDIOFILE"
41#define DISKDEFAULT_OUTFILE "sdlaudio.raw"
42#define DISKENVR_INFILE "SDL_DISKAUDIOFILEIN"
43#define DISKDEFAULT_INFILE "sdlaudio-in.raw"
44#define DISKENVR_IODELAY "SDL_DISKAUDIODELAY"
45
46/* This function waits until it is possible to write a full sound buffer */
47static void
48DISKAUDIO_WaitDevice(_THIS)
49{
50 SDL_Delay(this->hidden->io_delay);
51}
52
53static void
54DISKAUDIO_PlayDevice(_THIS)
55{
56 const size_t written = SDL_RWwrite(this->hidden->io,
57 this->hidden->mixbuf,
58 1, this->spec.size);
59
60 /* If we couldn't write, assume fatal error for now */
61 if (written != this->spec.size) {
63 }
64#ifdef DEBUG_AUDIO
65 fprintf(stderr, "Wrote %d bytes of audio data\n", written);
66#endif
67}
68
69static Uint8 *
70DISKAUDIO_GetDeviceBuf(_THIS)
71{
72 return (this->hidden->mixbuf);
73}
74
75static int
76DISKAUDIO_CaptureFromDevice(_THIS, void *buffer, int buflen)
77{
78 struct SDL_PrivateAudioData *h = this->hidden;
79 const int origbuflen = buflen;
80
81 SDL_Delay(h->io_delay);
82
83 if (h->io) {
84 const size_t br = SDL_RWread(h->io, buffer, 1, buflen);
85 buflen -= (int) br;
86 buffer = ((Uint8 *) buffer) + br;
87 if (buflen > 0) { /* EOF (or error, but whatever). */
88 SDL_RWclose(h->io);
89 h->io = NULL;
90 }
91 }
92
93 /* if we ran out of file, just write silence. */
94 SDL_memset(buffer, this->spec.silence, buflen);
95
96 return origbuflen;
97}
98
99static void
100DISKAUDIO_FlushCapture(_THIS)
101{
102 /* no op...we don't advance the file pointer or anything. */
103}
104
105
106static void
107DISKAUDIO_CloseDevice(_THIS)
108{
109 if (this->hidden->io != NULL) {
110 SDL_RWclose(this->hidden->io);
111 }
112 SDL_free(this->hidden->mixbuf);
113 SDL_free(this->hidden);
114}
115
116
117static const char *
118get_filename(const int iscapture, const char *devname)
119{
120 if (devname == NULL) {
121 devname = SDL_getenv(iscapture ? DISKENVR_INFILE : DISKENVR_OUTFILE);
122 if (devname == NULL) {
123 devname = iscapture ? DISKDEFAULT_INFILE : DISKDEFAULT_OUTFILE;
124 }
125 }
126 return devname;
127}
128
129static int
130DISKAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
131{
132 /* handle != NULL means "user specified the placeholder name on the fake detected device list" */
133 const char *fname = get_filename(iscapture, handle ? NULL : devname);
134 const char *envr = SDL_getenv(DISKENVR_IODELAY);
135
136 this->hidden = (struct SDL_PrivateAudioData *)
137 SDL_malloc(sizeof(*this->hidden));
138 if (this->hidden == NULL) {
139 return SDL_OutOfMemory();
140 }
141 SDL_zerop(this->hidden);
142
143 if (envr != NULL) {
144 this->hidden->io_delay = SDL_atoi(envr);
145 } else {
146 this->hidden->io_delay = ((this->spec.samples * 1000) / this->spec.freq);
147 }
148
149 /* Open the audio device */
150 this->hidden->io = SDL_RWFromFile(fname, iscapture ? "rb" : "wb");
151 if (this->hidden->io == NULL) {
152 return -1;
153 }
154
155 /* Allocate mixing buffer */
156 if (!iscapture) {
157 this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->spec.size);
158 if (this->hidden->mixbuf == NULL) {
159 return SDL_OutOfMemory();
160 }
161 SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
162 }
163
165 "You are using the SDL disk i/o audio driver!\n");
167 " %s file [%s].\n", iscapture ? "Reading from" : "Writing to",
168 fname);
169
170 /* We're ready to rock and roll. :-) */
171 return 0;
172}
173
174static void
175DISKAUDIO_DetectDevices(void)
176{
179}
180
181static int
182DISKAUDIO_Init(SDL_AudioDriverImpl * impl)
183{
184 /* Set the function pointers */
185 impl->OpenDevice = DISKAUDIO_OpenDevice;
186 impl->WaitDevice = DISKAUDIO_WaitDevice;
187 impl->PlayDevice = DISKAUDIO_PlayDevice;
188 impl->GetDeviceBuf = DISKAUDIO_GetDeviceBuf;
189 impl->CaptureFromDevice = DISKAUDIO_CaptureFromDevice;
190 impl->FlushCapture = DISKAUDIO_FlushCapture;
191
192 impl->CloseDevice = DISKAUDIO_CloseDevice;
193 impl->DetectDevices = DISKAUDIO_DetectDevices;
194
197
198 return 1; /* this audio target is available. */
199}
200
202 "disk", "direct-to-disk audio", DISKAUDIO_Init, 1
203};
204
205#endif /* SDL_AUDIO_DRIVER_DISK */
206
207/* vi: set ts=4 sw=4 expandtab: */
#define _THIS
void SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)
Definition: SDL_audio.c:469
void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
Definition: SDL_audio.c:486
#define SDL_memset
#define SDL_LogCritical
#define SDL_RWwrite
#define SDL_RWread
#define SDL_getenv
#define SDL_malloc
#define SDL_free
#define SDL_RWFromFile
#define SDL_Delay
#define SDL_atoi
#define SDL_RWclose
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
@ SDL_LOG_CATEGORY_AUDIO
Definition: SDL_log.h:70
GLuint buffer
GLfloat GLfloat GLfloat GLfloat h
@ SDL_TRUE
Definition: SDL_stdinc.h:164
@ SDL_FALSE
Definition: SDL_stdinc.h:163
#define SDL_zerop(x)
Definition: SDL_stdinc.h:417
uint8_t Uint8
Definition: SDL_stdinc.h:179
#define DEFAULT_OUTPUT_DEVNAME
Definition: SDL_sysaudio.h:32
#define DEFAULT_INPUT_DEVNAME
Definition: SDL_sysaudio.h:33
AudioBootStrap DISKAUDIO_bootstrap
#define NULL
Definition: begin_code.h:167
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
SDL_AudioSpec spec
Definition: loopwave.c:31
void(* PlayDevice)(_THIS)
Definition: SDL_sysaudio.h:73
void(* WaitDevice)(_THIS)
Definition: SDL_sysaudio.h:72
void(* CloseDevice)(_THIS)
Definition: SDL_sysaudio.h:78
void(* FlushCapture)(_THIS)
Definition: SDL_sysaudio.h:76
void(* DetectDevices)(void)
Definition: SDL_sysaudio.h:67
int(* CaptureFromDevice)(_THIS, void *buffer, int buflen)
Definition: SDL_sysaudio.h:75
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
Definition: SDL_sysaudio.h:68
Uint8 *(* GetDeviceBuf)(_THIS)
Definition: SDL_sysaudio.h:74
Uint32 size
Definition: SDL_audio.h:186
Uint16 samples
Definition: SDL_audio.h:184
Uint8 silence
Definition: SDL_audio.h:183