7d27fc8e57
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2066 fc73d0e0-1445-4013-8a0c-d673dee63da5
248 lines
5.8 KiB
C
248 lines
5.8 KiB
C
#include <exec/exec.h>
|
|
#include <devices/ahi.h>
|
|
#include <proto/exec.h>
|
|
#define USE_INLINE_STDARG
|
|
#include <proto/ahi.h>
|
|
|
|
#include "quakedef.h"
|
|
|
|
#warning Remove this once Spike fixes the sound input code.
|
|
void S_UpdateCapture(void)
|
|
{
|
|
}
|
|
|
|
struct AHIChannelInfo
|
|
{
|
|
struct AHIEffChannelInfo aeci;
|
|
ULONG offset;
|
|
};
|
|
|
|
struct AHIdata
|
|
{
|
|
struct MsgPort *msgport;
|
|
struct AHIRequest *ahireq;
|
|
int ahiopen;
|
|
struct AHIAudioCtrl *audioctrl;
|
|
void *samplebuffer;
|
|
struct Hook EffectHook;
|
|
struct AHIChannelInfo aci;
|
|
unsigned int readpos;
|
|
};
|
|
|
|
ULONG EffectFunc()
|
|
{
|
|
struct Hook *hook = (struct Hook *)REG_A0;
|
|
struct AHIEffChannelInfo *aeci = (struct AHIEffChannelInfo *)REG_A1;
|
|
|
|
struct AHIdata *ad;
|
|
|
|
ad = hook->h_Data;
|
|
|
|
ad->readpos = aeci->ahieci_Offset[0];
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct EmulLibEntry EffectFunc_Gate =
|
|
{
|
|
TRAP_LIB, 0, (void (*)(void))EffectFunc
|
|
};
|
|
|
|
static void AHI_Shutdown(soundcardinfo_t *sc)
|
|
{
|
|
struct AHIdata *ad;
|
|
|
|
struct Library *AHIBase;
|
|
|
|
ad = sc->handle;
|
|
|
|
AHIBase = (struct Library *)ad->ahireq->ahir_Std.io_Device;
|
|
|
|
ad->aci.aeci.ahie_Effect = AHIET_CHANNELINFO|AHIET_CANCEL;
|
|
AHI_SetEffect(&ad->aci.aeci, ad->audioctrl);
|
|
AHI_ControlAudio(ad->audioctrl,
|
|
AHIC_Play, FALSE,
|
|
TAG_END);
|
|
|
|
AHI_FreeAudio(ad->audioctrl);
|
|
FreeVec(ad->samplebuffer);
|
|
CloseDevice((struct IORequest *)ad->ahireq);
|
|
DeleteIORequest((struct IORequest *)ad->ahireq);
|
|
DeleteMsgPort(ad->msgport);
|
|
FreeVec(ad);
|
|
}
|
|
|
|
static unsigned int AHI_GetDMAPos(soundcardinfo_t *sc)
|
|
{
|
|
struct AHIdata *ad;
|
|
|
|
ad = sc->handle;
|
|
|
|
sc->sn.samplepos = ad->readpos*sc->sn.numchannels;
|
|
|
|
return sc->sn.samplepos;
|
|
}
|
|
|
|
static void AHI_UnlockBuffer(soundcardinfo_t *sc, void *buffer)
|
|
{
|
|
}
|
|
|
|
static void *AHI_LockBuffer(soundcardinfo_t *sc)
|
|
{
|
|
return sc->sn.buffer;
|
|
}
|
|
|
|
static void AHI_SetUnderWater(soundcardinfo_t *sc, qboolean uw)
|
|
{
|
|
}
|
|
|
|
static void AHI_Submit(soundcardinfo_t *sc)
|
|
{
|
|
}
|
|
|
|
static int AHI_InitCard(soundcardinfo_t *sc, int cardnum)
|
|
{
|
|
struct AHIdata *ad;
|
|
|
|
ULONG channels;
|
|
ULONG speed;
|
|
ULONG bits;
|
|
|
|
ULONG r;
|
|
|
|
struct Library *AHIBase;
|
|
|
|
struct AHISampleInfo sample;
|
|
|
|
if (cardnum)
|
|
return 2; /* Which means "no more cards" */
|
|
|
|
ad = AllocVec(sizeof(*ad), MEMF_ANY);
|
|
if (ad)
|
|
{
|
|
ad->msgport = CreateMsgPort();
|
|
if (ad->msgport)
|
|
{
|
|
ad->ahireq = (struct AHIRequest *)CreateIORequest(ad->msgport, sizeof(struct AHIRequest));
|
|
if (ad->ahireq)
|
|
{
|
|
ad->ahiopen = !OpenDevice("ahi.device", AHI_NO_UNIT, (struct IORequest *)ad->ahireq, 0);
|
|
if (ad->ahiopen)
|
|
{
|
|
AHIBase = (struct Library *)ad->ahireq->ahir_Std.io_Device;
|
|
|
|
ad->audioctrl = AHI_AllocAudio(AHIA_AudioID, AHI_DEFAULT_ID,
|
|
AHIA_MixFreq, sc->sn.speed,
|
|
AHIA_Channels, 1,
|
|
AHIA_Sounds, 1,
|
|
TAG_END);
|
|
|
|
if (ad->audioctrl)
|
|
{
|
|
AHI_GetAudioAttrs(AHI_INVALID_ID, ad->audioctrl,
|
|
AHIDB_BufferLen, sizeof(sc->name),
|
|
AHIDB_Name, (ULONG)sc->name,
|
|
AHIDB_MaxChannels, (ULONG)&channels,
|
|
AHIDB_Bits, (ULONG)&bits,
|
|
TAG_END);
|
|
|
|
AHI_ControlAudio(ad->audioctrl,
|
|
AHIC_MixFreq_Query, (ULONG)&speed,
|
|
TAG_END);
|
|
|
|
if (bits == 8 || bits == 16)
|
|
{
|
|
if (channels > 2)
|
|
channels = 2;
|
|
|
|
sc->sn.speed = speed;
|
|
sc->sn.samplebits = bits;
|
|
sc->sn.numchannels = channels;
|
|
sc->sn.samples = speed*channels;
|
|
|
|
ad->samplebuffer = AllocVec(speed*(bits/8)*channels, MEMF_ANY);
|
|
if (ad->samplebuffer)
|
|
{
|
|
sc->sn.buffer = ad->samplebuffer;
|
|
|
|
if (channels == 1)
|
|
{
|
|
if (bits == 8)
|
|
sample.ahisi_Type = AHIST_M8S;
|
|
else
|
|
sample.ahisi_Type = AHIST_M16S;
|
|
}
|
|
else
|
|
{
|
|
if (bits == 8)
|
|
sample.ahisi_Type = AHIST_S8S;
|
|
else
|
|
sample.ahisi_Type = AHIST_S16S;
|
|
}
|
|
|
|
sample.ahisi_Address = ad->samplebuffer;
|
|
sample.ahisi_Length = (speed*(bits/8)*channels)/AHI_SampleFrameSize(sample.ahisi_Type);
|
|
|
|
r = AHI_LoadSound(0, AHIST_DYNAMICSAMPLE, &sample, ad->audioctrl);
|
|
if (r == 0)
|
|
{
|
|
r = AHI_ControlAudio(ad->audioctrl,
|
|
AHIC_Play, TRUE,
|
|
TAG_END);
|
|
|
|
if (r == 0)
|
|
{
|
|
AHI_Play(ad->audioctrl,
|
|
AHIP_BeginChannel, 0,
|
|
AHIP_Freq, speed,
|
|
AHIP_Vol, 0x10000,
|
|
AHIP_Pan, 0x8000,
|
|
AHIP_Sound, 0,
|
|
AHIP_EndChannel, NULL,
|
|
TAG_END);
|
|
|
|
ad->aci.aeci.ahie_Effect = AHIET_CHANNELINFO;
|
|
ad->aci.aeci.ahieci_Func = &ad->EffectHook;
|
|
ad->aci.aeci.ahieci_Channels = 1;
|
|
|
|
ad->EffectHook.h_Entry = (void *)&EffectFunc_Gate;
|
|
ad->EffectHook.h_Data = ad;
|
|
|
|
AHI_SetEffect(&ad->aci, ad->audioctrl);
|
|
|
|
sc->handle = ad;
|
|
|
|
sc->Lock = AHI_LockBuffer;
|
|
sc->Unlock = AHI_UnlockBuffer;
|
|
sc->SetWaterDistortion = AHI_SetUnderWater;
|
|
sc->Submit = AHI_Submit;
|
|
sc->Shutdown = AHI_Shutdown;
|
|
sc->GetDMAPos = AHI_GetDMAPos;
|
|
|
|
Con_Printf("Using AHI mode \"%s\" for audio output\n", sc->name);
|
|
Con_Printf("Channels: %d bits: %d frequency: %d\n", channels, bits, speed);
|
|
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
FreeVec(ad->samplebuffer);
|
|
}
|
|
AHI_FreeAudio(ad->audioctrl);
|
|
}
|
|
else
|
|
Con_Printf("Failed to allocate AHI audio\n");
|
|
|
|
CloseDevice((struct IORequest *)ad->ahireq);
|
|
}
|
|
DeleteIORequest((struct IORequest *)ad->ahireq);
|
|
}
|
|
DeleteMsgPort(ad->msgport);
|
|
}
|
|
FreeVec(ad);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
sounddriver pAHI_InitCard = &AHI_InitCard;
|