Yet another sound patch

Ah, a day where I haven’t mass-mailed a large patch is like a day without
sunshine. :slight_smile:

For my own debugging purposes, I’ve written an SDL audio driver that
writes raw audio to disk in whatever format is requested when opening the
audio “device”. I figured this might be generally handy to have around, so
I’ve cleaned it up for everyone to enjoy.

To use:
When building SDL, ./configure --enable-diskaudio (disabled by default).

Then at runtime, export SDL_AUDIODEVICE=disk

It will write its output to sdlaudio.raw in the current directory. This
can be changed by exporting SDL_DISKAUDIOFILE=myfilename.ext …

Also, if you want it to write out as fast as possible (like the XMMS
diskwriter plugin does), export SDL_DISKAUDIODELAY=0. If you want it to
write at something more normal (for trying to sync to a video, or to get
the correct effect from that SDL_mixer panning test code I sent earlier),
try higher values. It is specified in milliseconds it should pretend to be
waiting for the “sound card” to finish writing its buffer, and defaults to
150 milliseconds.

You can use sox to convert the raw data to another format, or play it to
the soundcard as such:

# Assume the raw data is 44100Hz, 2 channels, 16-bit signed data.
sox -t .raw -c 2 -r 44100 -s -w sdlaudio.raw -t .wav output.wav
sox -t .raw -c 2 -r 44100 -s -w sdlaudio.raw -t .ossdsp /dev/dsp

That’s about it. There’s some interesting applications for this, I
think. Sure as heck would’ve made ripping the sound out of those Descent3
movies easier. :slight_smile:

–ryan.

-------------- next part --------------
diff -urBbN --exclude=CVS --exclude=.m4 --exclude=Makefile.in --exclude=configure --exclude=Makefile --exclude=.l --exclude=directfb SDL12-virgin/configure.in SDL12/configure.in
— SDL12-virgin/configure.in Sun Jun 10 11:20:23 2001
+++ SDL12/configure.in Thu Jun 14 21:49:56 2001
@@ -368,6 +368,21 @@
fi
}+
+dnl rcg07142001 See if the user wants the disk writer audio driver…
+CheckDiskAudio()
+{

  • AC_ARG_ENABLE(diskaudio,
    +[ --enable-diskaudio support the disk writer audio driver [default=no]],
  •              , enable_diskaudio=no)
    
  • if test x$enable_audio = xyes -a x$enable_diskaudio = xyes; then
  •    CFLAGS="$CFLAGS -DDISKAUD_SUPPORT"
    
  •    AUDIO_SUBDIRS="$AUDIO_SUBDIRS disk"
    
  •    AUDIO_DRIVERS="$AUDIO_DRIVERS disk/libaudio_disk.la"
    
  • fi
    +}

dnl See if we can use x86 assembly blitters
CheckNASM()
{
@@ -1085,6 +1100,7 @@
--linux*)
ARCH=linux
CheckDummyVideo

  •    CheckDiskAudio
       CheckNASM
       CheckOSS
       CheckALSA
    

@@ -1151,6 +1167,7 @@
--bsdi*)
ARCH=bsdi
CheckDummyVideo

  •    CheckDiskAudio
       CheckNASM
       CheckOSS
       CheckARTSC
    

@@ -1194,6 +1211,7 @@
--freebsd*)
ARCH=freebsd
CheckDummyVideo

  •    CheckDiskAudio
       CheckNASM
       CheckOSS
       CheckARTSC
    

@@ -1246,6 +1264,7 @@
--netbsd*)
ARCH=netbsd
CheckDummyVideo

  •    CheckDiskAudio
       CheckNASM
       CheckOSS
       CheckARTSC
    

@@ -1297,6 +1316,7 @@
--openbsd*)
ARCH=openbsd
CheckDummyVideo

  •    CheckDiskAudio
       CheckNASM
       CheckOSS
       CheckARTSC
    

@@ -1345,6 +1365,7 @@
--sysv5*)
ARCH=sysv5
CheckDummyVideo

  •    CheckDiskAudio
       CheckNASM
       CheckOSS
       CheckARTSC
    

@@ -1392,6 +1413,7 @@
ARCH=solaris
CFLAGS="$CFLAGS -D__ELF__" # Fix for nasm on Solaris x86
CheckDummyVideo

  •    CheckDiskAudio
       CheckNASM
       CheckOSS
       CheckARTSC
    

@@ -1438,6 +1460,7 @@
--irix*)
ARCH=irix
CheckDummyVideo

  •    CheckDiskAudio
       CheckNAS
       CheckX11
       CheckAAlib
    

@@ -1496,6 +1519,7 @@
--hpux*)
ARCH=hpux
CheckDummyVideo

  •    CheckDiskAudio
       CheckOSS
       CheckNAS
       CheckX11
    

@@ -1540,6 +1564,7 @@
--aix*)
ARCH=aix
CheckDummyVideo

  •    CheckDiskAudio
       CheckOSS
       CheckNAS
       CheckX11
    

@@ -1583,6 +1608,7 @@
--osf*)
ARCH=osf
CheckDummyVideo

  •    CheckDiskAudio
       CheckNAS
       CheckX11
       CheckGGI
    

@@ -1626,6 +1652,7 @@
--qnx*)
ARCH=qnx
CheckDummyVideo

  •    CheckDiskAudio
       CheckNAS
       CheckPHOTON
       CheckX11
    

@@ -1680,6 +1707,7 @@
fi
fi
CheckDummyVideo

  •    CheckDiskAudio
       CheckWIN32
       CheckDIRECTX
       CheckNASM
    

@@ -1736,6 +1764,7 @@
ARCH=beos
ac_default_prefix=/boot/develop/tools/gnupro
CheckDummyVideo

  •    CheckDiskAudio
       CheckNASM
       CheckBWINDOW
       CheckBeGL
    

@@ -1781,6 +1810,7 @@
# for which this case would be handy.
ARCH=macos
CheckDummyVideo

  •    CheckDiskAudio
       CheckTOOLBOX
       CheckMacGL
       # Set up files for the main() stub
    

@@ -1824,6 +1854,7 @@
# config.guess comes back with “darwin”, so go with the flow.
ARCH=macos
CheckDummyVideo

  •    CheckDiskAudio
       CheckCARBON
       CheckMacGL
       CheckPTHREAD
    

@@ -1973,6 +2004,7 @@
src/audio/ums/Makefile
src/audio/windib/Makefile
src/audio/windx5/Makefile
+src/audio/disk/Makefile
src/video/Makefile
src/video/cybergfx/Makefile
src/video/x11/Makefile
diff -urBbN --exclude=CVS --exclude=.m4 --exclude=Makefile.in --exclude=configure --exclude=Makefile --exclude=.l --exclude=directfb SDL12-virgin/src/audio/Makefile.am SDL12/src/audio/Makefile.am
— SDL12-virgin/src/audio/Makefile.am Sat May 26 09:58:37 2001
+++ SDL12/src/audio/Makefile.am Thu Jun 14 21:42:11 2001
@@ -5,8 +5,7 @@

Define which subdirectories need to be built

SUBDIRS = @AUDIO_SUBDIRS@
-DIST_SUBDIRS = alsa arts baudio dma dmedia dsp esd macrom nas nto \

  •           openbsd paudio sun ums windib windx5
    

+DIST_SUBDIRS = alsa arts baudio dma dmedia dsp esd macrom nas nto openbsd paudio sun ums windib windx5 disk

DRIVERS = @AUDIO_DRIVERS@

diff -urBbN --exclude=CVS --exclude=.m4 --exclude=Makefile.in --exclude=configure --exclude=Makefile --exclude=.l --exclude=directfb SDL12-virgin/src/audio/SDL_audio.c SDL12/src/audio/SDL_audio.c
— SDL12-virgin/src/audio/SDL_audio.c Sat May 26 14:39:01 2001
+++ SDL12/src/audio/SDL_audio.c Thu Jun 14 22:01:45 2001
@@ -81,7 +81,9 @@
#ifdef ENABLE_AHI
&AHI_bootstrap,
#endif

+#ifdef DISKAUD_SUPPORT

  • &DISKAUD_bootstrap,
    +#endif
    NULL
    };
    SDL_AudioDevice current_audio = NULL;
    diff -urBbN --exclude=CVS --exclude=
    .m4* --exclude=Makefile.in --exclude=configure --exclude=Makefile --exclude=.l --exclude=directfb SDL12-virgin/src/audio/SDL_sysaudio.h SDL12/src/audio/SDL_sysaudio.h
    — SDL12-virgin/src/audio/SDL_sysaudio.h Sat May 26 09:58:37 2001
    +++ SDL12/src/audio/SDL_sysaudio.h Thu Jun 14 20:06:28 2001
    @@ -140,6 +140,9 @@
    #ifdef ENABLE_AHI
    extern AudioBootStrap AHI_bootstrap;
    #endif
    +#ifdef DISKAUD_SUPPORT
    +extern AudioBootStrap DISKAUD_bootstrap;
    +#endif

/* This is the current audio device /
extern SDL_AudioDevice current_audio;
diff -urBbN --exclude=CVS --exclude=
.m4
--exclude=Makefile.in --exclude=configure --exclude=Makefile --exclude=.l --exclude=directfb SDL12-virgin/src/audio/disk/.cvsignore SDL12/src/audio/disk/.cvsignore
— SDL12-virgin/src/audio/disk/.cvsignore Wed Dec 31 16:00:00 1969
+++ SDL12/src/audio/disk/.cvsignore Fri Jun 15 02:50:19 2001
@@ -0,0 +1,6 @@
+Makefile.in
+Makefile
+.libs
+.o
+
.lo
+.la
diff -urBbN --exclude=CVS --exclude=
.m4* --exclude=Makefile.in --exclude=configure --exclude=Makefile --exclude=.l --exclude=directfb SDL12-virgin/src/audio/disk/Makefile.am SDL12/src/audio/disk/Makefile.am
— SDL12-virgin/src/audio/disk/Makefile.am Wed Dec 31 16:00:00 1969
+++ SDL12/src/audio/disk/Makefile.am Thu Jun 14 18:03:48 2001
@@ -0,0 +1,9 @@
+
+## Makefile.am for SDL audio “driver” that writes to a file.
+
+noinst_LTLIBRARIES = libaudio_disk.la
+libaudio_disk_la_SOURCES = $(SRCS)
+
+# The SDL audio driver sources
+SRCS = SDL_diskaudio.c \

  • SDL_diskaudio.h
    diff -urBbN --exclude=CVS --exclude=.m4 --exclude=Makefile.in --exclude=configure --exclude=Makefile --exclude=.l --exclude=directfb SDL12-virgin/src/audio/disk/SDL_diskaudio.c SDL12/src/audio/disk/SDL_diskaudio.c
    — SDL12-virgin/src/audio/disk/SDL_diskaudio.c Wed Dec 31 16:00:00 1969
    +++ SDL12/src/audio/disk/SDL_diskaudio.c Fri Jun 15 02:52:16 2001
    @@ -0,0 +1,222 @@
    +/*
  • SDL - Simple DirectMedia Layer
  • Copyright © 1997, 1998, 1999, 2000, 2001 Sam Lantinga
  • This library is free software; you can redistribute it and/or
  • modify it under the terms of the GNU Library General Public
  • License as published by the Free Software Foundation; either
  • version 2 of the License, or (at your option) any later version.
  • This library is distributed in the hope that it will be useful,
  • but WITHOUT ANY WARRANTY; without even the implied warranty of
  • MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  • Library General Public License for more details.
  • You should have received a copy of the GNU Library General Public
  • License along with this library; if not, write to the Free
  • Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  • Sam Lantinga
  • slouken at devolution.com
  • This file hacked^H^H^H^H^H^Hwritten by Ryan C. Gordon
  •    (@icculus1)
    

+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =

  • “@(#) $Id: SDL_diskaudio.c,v 1.0 2001/05/23 00:36:17 icculus Exp $”;
    +#endif

+/* Output raw audio data to a file. /
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+
+#include “SDL_audio.h”
+#include “SDL_error.h”
+#include “SDL_audiomem.h”
+#include “SDL_audio_c.h”
+#include “SDL_timer.h”
+#include “SDL_audiodev_c.h”
+#include “SDL_diskaudio.h”
+
+/
The tag name used by DISK audio /
+#define DISKAUD_DRIVER_NAME “disk”
+
+/
environment variables and defaults. /
+#define DISKENVR_OUTFILE “SDL_DISKAUDIOFILE”
+#define DISKDEFAULT_OUTFILE “sdlaudio.raw”
+#define DISKENVR_WRITEDELAY “SDL_DISKAUDIODELAY”
+#define DISKDEFAULT_WRITEDELAY 150
+
+/
Audio driver functions */
+static int DISKAUD_OpenAudio(_THIS, SDL_AudioSpec *spec);
+static void DISKAUD_WaitAudio(_THIS);
+static void DISKAUD_PlayAudio(_THIS);
+static Uint8 *DISKAUD_GetAudioBuf(_THIS);
+static void DISKAUD_CloseAudio(_THIS);
+
+static const char *DISKAUD_GetOutputFilename(void)
+{

  • const char *envr = getenv(DISKENVR_OUTFILE);
  • return((envr != NULL) ? envr : DISKDEFAULT_OUTFILE);
    +}

+/* Audio driver bootstrap functions */
+static int DISKAUD_Available(void)
+{
+#if 0

  • int fd;
  • int available;
  • int exists = 0;
  • struct stat statbuf;
  • const char *fname = DISKAUD_GetOutputFilename();
  • available = 0;
  • if (stat(fname, &statbuf) == 0)
  •    exists = 1;
    
  • fd = open(fname, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
  • if ( fd != -1 ) {
  •   available = 1;
    
  •   close(fd);
    
  •    if (!exists) {
    
  •        unlink(fname);
    
  •    }
    
  • }
  • return(available);
    +#else
  • return(1);
    +#endif
    +}

+static void DISKAUD_DeleteDevice(SDL_AudioDevice *device)
+{

  • free(device->hidden);
  • free(device);
    +}

+static SDL_AudioDevice *DISKAUD_CreateDevice(int devindex)
+{

  • SDL_AudioDevice *this;
  • const char *envr;
  • /* Initialize all variables that we clean on shutdown */
  • this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
  • if ( this ) {
  •   memset(this, 0, (sizeof *this));
    
  •   this->hidden = (struct SDL_PrivateAudioData *)
    
  •   		malloc((sizeof *this->hidden));
    
  • }
  • if ( (this == NULL) || (this->hidden == NULL) ) {
  •   SDL_OutOfMemory();
    
  •   if ( this ) {
    
  •   	free(this);
    
  •   }
    
  •   return(0);
    
  • }
  • memset(this->hidden, 0, (sizeof *this->hidden));
  • envr = getenv(DISKENVR_WRITEDELAY);
  • this->hidden->write_delay = (envr) ? atoi(envr) : DISKDEFAULT_WRITEDELAY;
  • /* Set the function pointers */
  • this->OpenAudio = DISKAUD_OpenAudio;
  • this->WaitAudio = DISKAUD_WaitAudio;
  • this->PlayAudio = DISKAUD_PlayAudio;
  • this->GetAudioBuf = DISKAUD_GetAudioBuf;
  • this->CloseAudio = DISKAUD_CloseAudio;
  • this->free = DISKAUD_DeleteDevice;
  • return this;
    +}

+AudioBootStrap DISKAUD_bootstrap = {

  • DISKAUD_DRIVER_NAME, “direct-to-disk audio”,
  • DISKAUD_Available, DISKAUD_CreateDevice
    +};

+/* This function waits until it is possible to write a full sound buffer */
+static void DISKAUD_WaitAudio(_THIS)
+{

  • SDL_Delay(this->hidden->write_delay);
    +}

+static void DISKAUD_PlayAudio(_THIS)
+{

  • int written;
  • /* Write the audio data, checking for EAGAIN on broken audio drivers */
  • do {
  •   written = write(this->hidden->audio_fd,
    
  •                    this->hidden->mixbuf,
    
  •                    this->hidden->mixlen);
    
  •   if ( (written < 0) && ((errno == 0) || (errno == EAGAIN)) ) {
    
  •   	SDL_Delay(1);	/* Let a little CPU time go by */
    
  •   }
    
  • } while ( (written < 0) &&
  •         ((errno == 0) || (errno == EAGAIN) || (errno == EINTR)) );
    
  • /* If we couldn’t write, assume fatal error for now */
  • if ( written < 0 ) {
  •   this->enabled = 0;
    
  • }
    +#ifdef DEBUG_AUDIO
  • fprintf(stderr, “Wrote %d bytes of audio data\n”, written);
    +#endif
    +}

+static Uint8 *DISKAUD_GetAudioBuf(_THIS)
+{

  • return(this->hidden->mixbuf);
    +}

+static void DISKAUD_CloseAudio(_THIS)
+{

  • if ( this->hidden->mixbuf != NULL ) {
  •   SDL_FreeAudioMem(this->hidden->mixbuf);
    
  •   this->hidden->mixbuf = NULL;
    
  • }
  • if ( this->hidden->audio_fd >= 0 ) {
  •   close(this->hidden->audio_fd);
    
  •   this->hidden->audio_fd = -1;
    
  • }
    +}

+static int DISKAUD_OpenAudio(_THIS, SDL_AudioSpec *spec)
+{

  • const char *fname = DISKAUD_GetOutputFilename();
  • /* Open the audio device */
  • this->hidden->audio_fd = open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
  • if ( this->hidden->audio_fd < 0 ) {
  •   SDL_SetError("Couldn't open %s: %s", fname, strerror(errno));
    
  •   return(-1);
    
  • }
  • fprintf(stderr, “WARNING: You are using the SDL disk writer”
  •                " audio driver!\n Writing to file [%s].\n", fname);
    
  • /* Allocate mixing buffer */
  • this->hidden->mixlen = spec->size;
  • this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
  • if ( this->hidden->mixbuf == NULL ) {
  •   return(-1);
    
  • }
  • memset(this->hidden->mixbuf, spec->silence, spec->size);
  • /* We’re ready to rock and roll. :slight_smile: */
  • return(0);
    +}

diff -urBbN --exclude=CVS --exclude=.m4 --exclude=Makefile.in --exclude=configure --exclude=Makefile --exclude=.l --exclude=directfb SDL12-virgin/src/audio/disk/SDL_diskaudio.h SDL12/src/audio/disk/SDL_diskaudio.h
— SDL12-virgin/src/audio/disk/SDL_diskaudio.h Wed Dec 31 16:00:00 1969
+++ SDL12/src/audio/disk/SDL_diskaudio.h Thu Jun 14 21:53:21 2001
@@ -0,0 +1,44 @@
+/*

  • SDL - Simple DirectMedia Layer
  • Copyright © 1997, 1998, 1999, 2000, 2001 Sam Lantinga
  • This library is free software; you can redistribute it and/or
  • modify it under the terms of the GNU Library General Public
  • License as published by the Free Software Foundation; either
  • version 2 of the License, or (at your option) any later version.
  • This library is distributed in the hope that it will be useful,
  • but WITHOUT ANY WARRANTY; without even the implied warranty of
  • MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  • Library General Public License for more details.
  • You should have received a copy of the GNU Library General Public
  • License along with this library; if not, write to the Free
  • Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  • Sam Lantinga
  • slouken at devolution.com
    +*/

+#ifdef SAVE_RCSID
+static char rcsid =

  • “@(#) $Id: SDL_diskaudio.h,v 1.0 2001/04/26 16:50:17 icculus Exp $”;
    +#endif

+#ifndef _SDL_diskaudio_h
+#define _SDL_diskaudio_h
+
+#include “SDL_sysaudio.h”
+
+/* Hidden “this” pointer for the video functions */
+#define _THIS SDL_AudioDevice *this
+
+struct SDL_PrivateAudioData {

  • /* The file descriptor for the audio device */
  • int audio_fd;
  • Uint8 *mixbuf;
  • Uint32 mixlen;
  • Uint32 write_delay;
    +};

+#endif /* _SDL_diskaudio_h */

This sounds like a great idea for debugging audio effects! I’d also
like to see something equivalent to the “null” video driver, so that I
can test SDL apps that have audio without turning off my background
music on every run!–

Olivier A. Dagenais - Software Architect and Developer

“Ryan C. Gordon” wrote in message
news:Pine.LNX.4.21.0106150302370.20254-200000 at gemini.verizon.net

Ah, a day where I haven’t mass-mailed a large patch is like a day
without
sunshine. :slight_smile:

For my own debugging purposes, I’ve written an SDL audio driver that
writes raw audio to disk in whatever format is requested when
opening the
audio “device”. I figured this might be generally handy to have
around, so
I’ve cleaned it up for everyone to enjoy.

To use:
When building SDL, ./configure --enable-diskaudio (disabled by
default).

Then at runtime, export SDL_AUDIODEVICE=disk

It will write its output to sdlaudio.raw in the current directory.
This
can be changed by exporting SDL_DISKAUDIOFILE=myfilename.ext …

Also, if you want it to write out as fast as possible (like the XMMS
diskwriter plugin does), export SDL_DISKAUDIODELAY=0. If you want it
to
write at something more normal (for trying to sync to a video, or to
get
the correct effect from that SDL_mixer panning test code I sent
earlier),
try higher values. It is specified in milliseconds it should pretend
to be
waiting for the “sound card” to finish writing its buffer, and
defaults to
150 milliseconds.

You can use sox to convert the raw data to another format, or play
it to
the soundcard as such:

Assume the raw data is 44100Hz, 2 channels, 16-bit signed data.

sox -t .raw -c 2 -r 44100 -s -w sdlaudio.raw -t .wav output.wav
sox -t .raw -c 2 -r 44100 -s -w sdlaudio.raw -t .ossdsp /dev/dsp

That’s about it. There’s some interesting applications for this, I
think. Sure as heck would’ve made ripping the sound out of those
Descent3
movies easier. :slight_smile:

–ryan.

Ah, a day where I haven’t mass-mailed a large patch is like a day without
sunshine. :slight_smile:

To use:
When building SDL, ./configure --enable-diskaudio (disabled by default).

Then at runtime, export SDL_AUDIODEVICE=disk

It will write its output to sdlaudio.raw in the current directory. This
can be changed by exporting SDL_DISKAUDIOFILE=myfilename.ext …

Also, if you want it to write out as fast as possible (like the XMMS
diskwriter plugin does), export SDL_DISKAUDIODELAY=0. If you want it to
write at something more normal (for trying to sync to a video, or to get
the correct effect from that SDL_mixer panning test code I sent earlier),
try higher values. It is specified in milliseconds it should pretend to be
waiting for the “sound card” to finish writing its buffer, and defaults to
150 milliseconds.

You can use sox to convert the raw data to another format, or play it to
the soundcard as such:

Assume the raw data is 44100Hz, 2 channels, 16-bit signed data.

sox -t .raw -c 2 -r 44100 -s -w sdlaudio.raw -t .wav output.wav
sox -t .raw -c 2 -r 44100 -s -w sdlaudio.raw -t .ossdsp /dev/dsp

That’s about it. There’s some interesting applications for this, I
think. Sure as heck would’ve made ripping the sound out of those Descent3
movies easier. :slight_smile:

Thanks Ryan, I’ve added it to CVS! :slight_smile:

See ya,
-Sam Lantinga, Lead Programmer, Loki Software, Inc.