Replace the amiga ahi driver with a working one.

Based on a MikMod driver written by Szilard Biro, which was loosely
based on an old AmigaOS4 version by Fredrik Wikstrom.
master
sezero 9 years ago committed by Claudio Matsuoka
parent 3056bfd713
commit 5e5ba53799
  1. 156
      src/sound_ahi.c

@ -1,59 +1,128 @@
/* Amiga AHI driver for Extended Module Player
* Copyright (C) 2007 Lorence Lombardo
* Based on a MikMod driver written by Szilard Biro, which was loosely
* based on an old AmigaOS4 version by Fredrik Wikstrom.
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See the COPYING
* file for more information.
*/
#ifdef __amigaos4__
#define __USE_INLINE__
#endif
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "sound.h"
static int fd;
#include <proto/exec.h>
#include <proto/dos.h>
#include <devices/ahi.h>
static int init(struct options *options)
{
char **parm = options->driver_parm;
char outfile[256];
int nch = options->format & XMP_FORMAT_MONO ? 1 : 2;
int res = options->format & XMP_FORMAT_8BIT ? 8 : 16;
int bsize = options->rate * nch * res / 4;
parm_init(parm);
chkparm1("buffer", bsize = strtoul(token, NULL, 0));
parm_end();
sprintf(outfile, "AUDIO:B/%d/F/%d/C/%d/BUFFER/%d",
res, options->rate, nch, bsize);
fd = open(outfile, O_WRONLY);
if (fd < 0)
return -1;
return 0;
#define BUFFERSIZE (4 << 10)
static struct MsgPort *AHImp = NULL;
static struct AHIRequest *AHIReq[2] = { NULL, NULL };
static int active = 0;
static signed char *AHIBuf[2] = { NULL, NULL };
static void closeLibs(void) {
if (AHIReq[1]) {
AHIReq[0]->ahir_Link = NULL; /* in case we are linked to req[0] */
if (!CheckIO((struct IORequest *) AHIReq[1])) {
AbortIO((struct IORequest *) AHIReq[1]);
WaitIO((struct IORequest *) AHIReq[1]);
}
FreeVec(AHIReq[1]);
AHIReq[1] = NULL;
}
if (AHIReq[0]) {
if (!CheckIO((struct IORequest *) AHIReq[0])) {
AbortIO((struct IORequest *) AHIReq[0]);
WaitIO((struct IORequest *) AHIReq[0]);
}
if (AHIReq[0]->ahir_Std.io_Device) {
CloseDevice((struct IORequest *) AHIReq[0]);
AHIReq[0]->ahir_Std.io_Device = NULL;
}
DeleteIORequest((struct IORequest *) AHIReq[0]);
AHIReq[0] = NULL;
}
if (AHImp) {
DeleteMsgPort(AHImp);
AHImp = NULL;
}
if (AHIBuf[0]) {
FreeVec(AHIBuf[0]);
AHIBuf[0] = NULL;
}
if (AHIBuf[1]) {
FreeVec(AHIBuf[1]);
AHIBuf[1] = NULL;
}
}
static void play(void *b, int i)
{
int j;
while (i) {
if ((j = write(fd, b, i)) > 0) {
i -= j;
b = (char *)b + j;
} else
break;
}
static int init(struct options *options) {
AHImp = CreateMsgPort();
if (AHImp) {
AHIReq[0] = (struct AHIRequest *)CreateIORequest(AHImp, sizeof(struct AHIRequest));
if (AHIReq[0]) {
AHIReq[0]->ahir_Version = 4;
AHIReq[1] = AllocVec(sizeof(struct AHIRequest), MEMF_PUBLIC);
if (AHIReq[1]) {
if (!OpenDevice(AHINAME, AHI_DEFAULT_UNIT, (struct IORequest *)AHIReq[0], 0)) {
AHIReq[0]->ahir_Std.io_Command = CMD_WRITE;
AHIReq[0]->ahir_Std.io_Data = NULL;
AHIReq[0]->ahir_Std.io_Offset = 0;
AHIReq[0]->ahir_Frequency = options->rate;
AHIReq[0]->ahir_Type = (options->format & XMP_FORMAT_8BIT)?
((options->format & XMP_FORMAT_MONO)? AHIST_M8S : AHIST_S8S ) :
((options->format & XMP_FORMAT_MONO)? AHIST_M16S : AHIST_S16S);
AHIReq[0]->ahir_Volume = 0x10000;
AHIReq[0]->ahir_Position = 0x8000;
CopyMem(AHIReq[0], AHIReq[1], sizeof(struct AHIRequest));
AHIBuf[0] = AllocVec(BUFFERSIZE, MEMF_PUBLIC | MEMF_CLEAR);
if (AHIBuf[0]) {
AHIBuf[1] = AllocVec(BUFFERSIZE, MEMF_PUBLIC | MEMF_CLEAR);
if (AHIBuf[1]) {
/* driver is initialized before calling libxmp, so this is OK : */
options->format &= ~XMP_FORMAT_UNSIGNED;/* no unsigned with AHI */
return 0;
}
}
}
}
}
}
closeLibs();
return -1;
}
static void deinit(void)
{
close(fd);
static void deinit(void) {
closeLibs();
}
static void play(void *b, int len) {
signed char *in = (signed char *)b;
int chunk;
while (len > 0) {
if (AHIReq[active]->ahir_Std.io_Data) {
WaitIO((struct IORequest *) AHIReq[active]);
}
chunk = (len < BUFFERSIZE)? len : BUFFERSIZE;
memcpy(AHIBuf[active], in, chunk);
len -= chunk;
in += chunk;
AHIReq[active]->ahir_Std.io_Data = AHIBuf[active];
AHIReq[active]->ahir_Std.io_Length = chunk;
AHIReq[active]->ahir_Link = !CheckIO((struct IORequest *) AHIReq[active ^ 1]) ? AHIReq[active ^ 1] : NULL;
SendIO((struct IORequest *)AHIReq[active]);
active ^= 1;
}
}
static void flush(void)
@ -68,15 +137,10 @@ static void onresume(void)
{
}
static const char *const help[] = {
"buffer=val", "Audio buffer size",
NULL
};
struct sound_driver sound_ahi = {
"ahi",
"Amiga AHI audio",
help,
NULL,
init,
deinit,
play,

Loading…
Cancel
Save