Replace direct /dev/dsp output with output via libao.
Makes it easy to configure it to use whatever output device is supported by libao
(default: ALSA).

James 2020
diff -ur SPC-PLAYER-2ab38205d6737b115bd0c02db9a6082bb64747c8/Makefile SPC-PLAYER-new/Makefile
--- SPC-PLAYER-2ab38205d6737b115bd0c02db9a6082bb64747c8/Makefile	2017-04-22 11:52:44.000000000 +1000
+++ SPC-PLAYER-new/Makefile	2020-08-20 00:39:55.721860086 +1000
@@ -2,11 +2,11 @@
 
 NASM = nasm
 MAFLAGS = --prefix _ -f macho 
-NAFLAGS = -f elf
+LAFLAGS = -f elf
 CC = gcc
 #CFLAGS = -W -Wall -pedantic -g
 MCFLAGS = -m32 -W -Wall -pedantic -framework CoreServices -framework AudioToolbox -framework CoreAudio -framework AudioUnit 
-LCFLAGS = -Wall -pedantic 
+LCFLAGS = -m32 -Wall -pedantic 
 SPC_IMPL = SNEeSe
 SPCIMPL_OBJS = SNEeSe/SPC700.o SNEeSe/SPCimpl.o
 LIB_OBJS = main.o dsp.o $(SPCIMPL_OBJS)
@@ -28,7 +28,7 @@
 linux: spcplayer
 
 spcplayer: libopenspc.a $(SPCPLAYERFILE)
-	gcc $(CFLAGS) $(SPCPLAYERFILE) -o spcplayer -lz ./libopenspc.a
+	gcc $(CFLAGS) $(SPCPLAYERFILE) -o spcplayer -lz ./libopenspc.a -lao
 
 
 #install: libopenspc.so openspc.h
diff -ur SPC-PLAYER-2ab38205d6737b115bd0c02db9a6082bb64747c8/spcplayerlinux.c SPC-PLAYER-new/spcplayerlinux.c
--- SPC-PLAYER-2ab38205d6737b115bd0c02db9a6082bb64747c8/spcplayerlinux.c	2017-04-22 11:52:44.000000000 +1000
+++ SPC-PLAYER-new/spcplayerlinux.c	2020-08-20 00:48:53.180828258 +1000
@@ -1,5 +1,6 @@
 /*Stephen B Melvin Jr, <stephenbmelvin@gmail.com>
 Version 0.2
+Version 0.3 - add output via libao.
 */
 
 #ifdef __linux__
@@ -15,99 +16,92 @@
 #include <sys/stat.h>
 #include <ctype.h>
 #include <string.h>
+#include <ao/ao.h>
 #endif
 
 int main(int argc, char *argv[])
 {
-int optionoffset=0,audio_fd,channels=2,rformat,rchannels,format=AFMT_S16_LE,speed=32000,fd;
-char audio_device[]="/dev/dsp";
-char ver[]="0.2";
-char c;
-void *ptr,*buf;
-off_t size;
-
-
-if((argc<2))
-{
-printf("\n[?] Usage: soap [sound device] SPC_FILE_NAME\n[?] Optional parameters are in brackets.\n[?] SOAP Version %s (2003) Steve B Melvin Jr\n\n",ver);
-exit(1);
-}
-
-if((argc>2))
-{
-strcpy(audio_device,argv[1]);
-optionoffset++;
-}
-
-if((audio_fd=open(audio_device, O_WRONLY, 0)) ==-1)
-{
- printf("[-] Could not open, %s.\n", audio_device);
- exit(1);
-}
-printf("[+] Successfully opened, %s.\n",audio_device);
-
-rformat=format;
-if(ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format) == -1)
- {
- printf("[-] Could not set sound format.\n");
- exit(1);
- }
-if(format!=rformat)
-{
- printf("[-] Could not set sound format.\n");
- exit(1);
-}
-printf("[+] Successfully set sound format.\n");
-
-rchannels=channels;
-if(ioctl(audio_fd,SNDCTL_DSP_CHANNELS, &channels) == -1)
-{
-printf("[-] Could not set channels.\n");
-exit(1);
-}
-if(channels!=rchannels)
-{
-printf("[-] Could not set channels.\n");
-exit(1);
-}
-printf("[+] Successfully set channels.\n");
-
-if(ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed)==-1)
-{
-printf("[-] Could not set speed.\n");
-exit(1);
-}
-printf("[+] Using speed, {%iHz}\n",speed);
-
-buf=malloc(32000);
-
-fd=open(argv[1+optionoffset],O_RDONLY);
-if(fd<0)
-{
-printf("[-] Could not open \'%s\'\n.",argv[1]);
-exit(1);
-}
-
-size=lseek(fd,0,SEEK_END);
-lseek(fd,0,SEEK_SET);
-ptr=malloc(size);
-read(fd,ptr,size);
-close(fd);
-
-fd=OSPC_Init(ptr,size);
-
-free(ptr);
-fcntl(STDIN_FILENO,F_SETFL,O_NONBLOCK);
-printf("[+] Playing SPC, press Enter to quit.\n");
-
-while((read(STDIN_FILENO,&c,1))<=0)
-{
-size=OSPC_Run(-1,buf,32000);
-write(audio_fd,buf,size);
-}
-
-printf("\nGoodbye!\n");
-return 0;
+	ao_device *outputdev;
+	int outputdev_id;
+	ao_sample_format output_format = {
+		16,             // 16-bits per sample
+		32000,          // sample rate
+		2,              // channels
+		AO_FMT_LITTLE,  // same as AFMT_S16_LE
+		NULL            // no special mapping
+	};
+	char *audio_device="default";
+	ao_option *output_options = NULL;
+	
+	char ver[]="0.3"; // bump the version
+	void *ptr,*buf;
+	char c;
+	int optionoffset=0,fd;	
+	off_t size;
+
+	// sanity checks
+	if((argc<2))
+	{
+		printf("\n[?] Usage: spcplayer [sound device] SPC_FILE_NAME\n[?] Optional parameters are in brackets.\n[?] SOAP Version %s (2003) Steve B Melvin Jr\n\n",ver);
+		exit(1);
+	}
+
+	if((argc>2))
+	{
+		audio_device = argv[1];
+		optionoffset++;
+	}
+
+	// Configure output
+	ao_initialize();
+	outputdev_id = ao_default_driver_id();
+	if (outputdev_id < 0) {
+		printf("[-] Could not get audio driver id.\n");
+		exit(1);
+	}
+
+	ao_append_option(&output_options, "dev", audio_device);
+	
+	outputdev = ao_open_live(outputdev_id, &output_format, output_options);
+	if (!outputdev) {
+		printf("[-] Could not open audio device: %s\n", audio_device);
+		exit(1);
+	}
+
+	// Open the SPC file
+	buf=malloc(32000);
+
+	fd=open(argv[1+optionoffset],O_RDONLY);
+	if(fd<0)
+	{
+		printf("[-] Could not open \'%s\'\n.",argv[1]);
+		exit(1);
+	}
+
+	size=lseek(fd,0,SEEK_END);
+	lseek(fd,0,SEEK_SET);
+	ptr=malloc(size);
+	read(fd,ptr,size);
+	close(fd);
+
+	fd=OSPC_Init(ptr,size);
+
+	free(ptr);
+	fcntl(STDIN_FILENO,F_SETFL,O_NONBLOCK);
+	printf("[+] Playing SPC, press Enter to quit.\n");
+
+	// Start playing
+	while((read(STDIN_FILENO,&c,1))<=0)
+	{
+		size=OSPC_Run(-1,buf,32000);
+		ao_play(outputdev, buf, size);
+		//write(audio_fd,buf,size);
+	}
+
+	ao_close(outputdev);
+	ao_shutdown();
+	printf("\nGoodbye!\n");
+	return 0;
 }
 
 
