The Synthetic Audio Library Software Developer Kit
Copyright (C) 1995, 1996 Carlos Hasan. All Rights Reserved.
If you have questions, problems or comments about the SEAL audio system you can contact the author at the following Internet email address:
Carlos Hasan
chasan@dcc.uchile.cl
The SEAL API allows you, as an application developer, access the audio hardware while insulating you from the specific details of that hardware. The design goal of SEAL is speed. Instead of providing a high-level set of functions, it provides a device-independant interface, allowing applications to take full adventage of the capabilities of the audio hardware.
Under the DOS operating system the following hardware audio devices are natively supported by the audio system:
Your application can also call the routine APingAudio to determine what kind of audio hardware is present on the system. If there is more than one device present on the system, the first detected audio device will be used.
While the audio system is active, your application must call the routine AUpdateAudio to update and send the output audio buffers to the audio hardware. It's not required for Windows 95 and Windows NT applications.
Since the audio system plays music sequences using the virtual audio timer interrupt services, your applications won't be able to play music modules and use the timer services simultaneously. You must use your own timer services if you want to play music in your applications. For applications running in DOS, the hardware timer interrupt vector can be used for such purposes.
Every allocated audio voice must be released by calling ADestroyAudioVoice whenever your application finishes using it. It's important to stop the audio voices before releasing them.
The ACloseVoices routine must be called to release all the available audio voices when your application is going to close the audio system. Your application must stop all the voices and module files before calling it.
To retrieve or set the current playing position in the waveform of an audio voice, call the AGetVoicePosition or ASetVoicePosition routines. The playing position of the voices is specified as an offset from the start of the waveform data measured in samples.
Similarly, by calling the AGetVoiceFrequency and ASetVoiceFrequency routines, you can retrieve and set the sampling frequency at which the audio waveform is being resampled and played by a given audio voice.
To retrieve and set the stereo pan position of an audio voice, your application can call the AGetVoicePanning and ASetVoicePanning routines. These routines have no effect when the system is playing in monophonic format.
Similarly, the AGetModuleVolume and ASetModuleVolume routines can be used by your application to change the global volume at which the audio system is playing the music sequence. These routines can only be called while a music module is active.
Initializes the Synthetic Audio Library.
Returns zero on success.
This routine must be called to initialize the audio system, after initialization your application can use the audio system API routines. It's not required to initialize the audio system for applications running in Windows 95 or Windows NT.
See also AOpenAudio, ACloseAudio
Retrieves the Synthetic Audio Library version.
Returns the audio system major and minor version numbers.
This routine can be used by your application to get the audio system version number, the major version number is encoded in the most significant byte of the returned value and the minor version number in the least significant byte.
Retrieves number of installed audio device drivers.
Returns the number of device drivers installed on the system.
This routine can be used by your application to enumerate the installed audio device drivers on the system. The AGetAudioDevCaps routine can be used to retrieve information from a particular audio device driver.
See also AGetAudioDevCaps
Retrieves information about audio device drivers.
Return zero on success.
VOID PrintAudioDevs(VOID)
{
AUDIOCAPS caps;
UINT nDeviceId;
/* show all the installed device drivers */
for (nDeviceId = 0; nDeviceId < AGetAudioNumDevs(); nDeviceId++) {
AGetAudioDevCaps(nDeviceId, &caps);
printf("nDeviceId=%d wProductId=%d szProductName=%s\n",
nDeviceId, caps.wProductId, caps.szProductName);
}
}
See also AGetAudioNumDevs
Return readable text description for a given error return code.
Return zero on success.
VOID InitializeAudio(VOID)
{
AUDIOINFO info;
CHAR szText[128];
UINT rc;
info.nDeviceId = AUDIO_DEVICE_MAPPER;
info.wFormat = AUDIO_FORMAT_16BITS | AUDIO_FORMAT_STEREO;
info.nSampleRate = 44100;
if ((rc = AOpenAudio(&info)) != AUDIO_ERROR_NONE) {
AGetErrorText(rc, szText, sizeof(szText) - 1);
printf("ERROR: %s\n", szText);
exit(1);
}
}
Automatically detect the installed audio device.
Returns zero on success.
VOID DetectAudioDevice(VOID)
{
AUDIOCAPS caps;
UINT nDeviceId;
if (APingAudio(&nDeviceId) != AUDIO_ERROR_NONE) {
printf("no audio device found.\n");
}
else {
AGetAudioDevCaps(nDeviceId, &caps);
printf("%s device found.\n", caps.szProductName);
}
}
See Also AOpenAudio, AGetAudioDevCaps
Open audio device for playback.
Returns zero on success.
VOID InitializeAudio(VOID)
{
AUDIOINFO info;
info.nDeviceId = AUDIO_DEVICE_MAPPER;
info.wFormat = AUDIO_FORMAT_16BITS | AUDIO_FORMAT_STEREO;
info.nSampleRate = 44100;
if (AOpenAudio(&info) != AUDIO_ERROR_NONE) {
printf("Audio initialization failed.\n");
exit(1);
}
else {
printf("Audio device initialized at %d bits %s %u Hz\n",
info.wFormat & AUDIO_FORMAT_16BITS ? 16 : 8,
info.wFormat & AUDIO_FORMAT_STEREO ?
"stereo": "mono", info.nSampleRate);
}
}
See Also ACloseAudio, AUpdateAudio
Close the audio device.
Returns zero on success.
This routine must be called to close the audio device before leaving from your application. Your application must release all the resources allocated before closing the audio system.
See Also AOpenAudio, AUpdateAudio
Updates the audio system output buffers.
Returns zero on success.
This routine must be called periodically by your application to update the audio buffers which are sent to the hardware for playback. If your application fails to call this routine enough times per second, the audio output will sound like a broken disc. It's not required to call this routine for Windows 95 and Windows NT applications.
See Also AOpenAudio, ACloseAudio
Install audio wave callback routine. Internal use only.
Returns zero on success.
This routine is used internally by the audio system to install the audio wave callback routine used by the software wavetable synthesizer to fill the hardware DMA audio buffer with samples.
Install virtual audio timer callback routine.
Returns zero on success.
volatile UINT nTickCounter = 0;
VOID AIAPI TimerHandler(VOID)
{
nTickCounter++;
}
VOID InitTimerHandler(VOID)
{
/* the handler will be called at 125 BPM (50 times per second) */
ASetAudioTimerProc(TimerHandler);
ASetAudioTimerRate(125);
}
VOID DoneTimerHandler(VOID)
{
ASetAudioTimerProc(NULL);
}
See Also ASetAudioTimerRate
Changes the virtual audio timer rate.
Returns zero on success.
See Also ASetAudioTimerProc
Open audio voices.
Returns zero on success.
See Also ACloseVoices, ACreateAudioVoice, ADestroyAudioVoice
Close all the audio voices.
Returns zero on success.
This routine closes all the active audio voices. Before calling this routine, all the allocated voices, including those allocated indirectly by calling the APlayModule routine, must be released.
See Also AOpenVoices, ACreateAudioVoice, ADestroyAudioVoice
Allocates a single audio voice.
Returns zero on success.
VOID PlayWaveform(LPAUDIOWAVE lpWave)
{
HAC hVoice;
BOOL stopped;
/* allocate an audio voice or channel */
if (ACreateAudioVoice(&hVoice) == AUDIO_ERROR_NONE) {
/* play the waveform through the voice */
APlayVoice(hVoice, lpWave);
ASetVoiceVolume(hVoice, 64);
ASetVoicePanning(hVoice, 128);
/* wait until the wave finishes or a key is pressed */
while (!kbhit()) {
AUpdateAudio();
AGetVoiceStatus(hVoice, &stopped);
if (stopped) break;
}
/* stop the voice (if already playing) */
AStopVoice(hVoice);
/* release the allocated voice */
ADestroyAudioVoice(hVoice);
}
}
See Also AOpenVoices, ACloseVoices, ADestroyAudioVoice
Releases an allocated audio voice.
Returns zero on success.
See Also ACreateAudioVoice
Start playing a waveform through a voice.
Returns zero on success.
See Also APrimeVoice, AStartVoice, AStopVoice
Prepares a waveform on an audio voice.
Returns zero on success.
VOID PlayChord(HAC aVoices[3], LPAUDIOWAVE lpWave, LONG aFreqs[3])
{
UINT n;
/* first prepare the voices to play the waveform */
for (n = 0 ; n < 3 ; n++) {
APrimeVoice(aVoices[n], lpWave);
ASetVoiceFrequency(aVoices[n], aFreqs[n]);
ASetVoiceVolume(aVoices[n], 64);
}
/* now start playing all them simultaneously */
for (n = 0 ; n < 3 ; n++) {
AStartVoice(aVoices[n]);
}
}
See Also APlayVoice, AStartVoice, AStopVoice
Start playing an audio voice.
Returns zero on success.
See Also APrimeVoice, APlayVoice, AStopVoice
Stop playing an audio voice.
Returns zero on success.
See Also APrimeVoice, APlayVoice, AStartVoice
Changes the voice playing position.
Returns zero on success.
VOID PlayEchoVoices(HAC aVoices[2], LPAUDIOWAVE lpWave, LONG dwDelay)
{
/* prepare two voices with the same waveform */
APrimeVoice(aVoices[0], lpWave);
APrimeVoice(aVoices[1], lpWave);
ASetVoiceFrequency(aVoices[0], lpWave->nSampleRate);
ASetVoiceFrequency(aVoices[1], lpWave->nSampleRate);
/* set voice volumes (the "echo" voice has a lower volume) */
ASetVoiceVolume(aVoices[0], 64);
ASetVoiceVolume(aVoices[1], 32);
/* set the delay (measured in samples) for the "echo" voice */
ASetVoicePosition(aVoices[1], dwDelay);
/* start both voices as simultenously as possible */
AStartVoice(aVoices[0]);
AStartVoice(aVoices[1]);
}
See Also AGetVoicePosition
Changes the voice sampling frequency.
Returns zero on success.
VOID PlayVoiceStereo(HAC aVoices[2], LPAUDIOWAVE lpWave, LONG dwPitchShift)
{
/* prepare two voices to play a waveform */
APrimeVoice(aVoices[0], lpWave);
APrimeVoice(aVoices[1], lpWave);
ASetVoiceVolume(aVoices[0], 64);
ASetVoiceVolume(aVoices[1], 64);
/* slightly change the pitch of one of the voices */
ASetVoiceFrequency(aVoices[0], lpWave->nSampleRate);
ASetVoiceFrequency(aVoices[1], lpWave->nSampleRate + dwPitchShift);
/* set the pan position of the voices to left and right */
ASetVoicePanning(aVoices[0], 0);
ASetVoicePanning(aVoices[1], 255);
/* start both voices simultaneously */
AStartVoice(aVoices[0]);
AStartVoice(aVoices[1]);
}
See Also AGetVoiceFrequency
Changes the voice volume level.
Returns zero on success.
See Also AGetVoiceVolume
Changes the voice stereo pan position.
Returns zero on success.
See Also AGetVoicePanning
Retrieves the playing position of a voice.
Returns zero on success.
Retrieves the sampling frequency of a voice.
Returns zero on success.
See Also ASetVoiceFrequency
Retrieves the volume level of a voice.
Returns zero on success.
See Also ASetVoiceVolume
Retrieves the stereo pan position of a voice.
Returns zero on success.
See Also ASetVoicePanning
Retrieves the current status of a voice.
Returns zero on success.
VOID CheckVoice(HAC hVoice)
{
BOOL stopped;
AGetVoiceStatus(hVoice, &stopped);
if (stopped)
printf("voice is stopped.\n");
}
See Also AStartVoice, AStopVoice
Retrieves the amount of available DRAM memory.
Returns amount of available DRAM memory (in bytes).
This routine retrieves the number of free bytes on the hardware audio device when applicable. It can be used to determine if there is enough space to hold a set of samples or waveforms simultaneously. It returns zero when the audio system is using system memory to hold the audio waveforms data.
VOID ShowFreeMemory(VOID)
{
LONG dwMemFree;
dwMemFree = AGetAudioDataAvail();
printf("%ld bytes free.\n", dwMemFree);
}
Creates a waveform object.
Returns zero on success.
LPAUDIOWAVE CreateAudio8BitMono(WORD nSampleRate,
LPBYTE lpData, DWORD dwLength)
{
LPAUDIOWAVE lpWave;
/* first allocate structure to hold the waveform object */
if ((lpWave = (LPAUDIOWAVE) malloc(sizeof(AUDIOWAVE))) != NULL) {
/* create a 8-bit mono one-shot waveform object */
lpWave->wFormat = AUDIO_FORMAT_8BITS | AUDIO_FORMAT_MONO;
lpWave->nSampleRate = nSampleRate;
lpWave->dwLength = dwLength;
lpWave->dwLoopStart = lpWave->dwLoopEnd = 0;
if (ACreateAudioData(lpWave) != AUDIO_ERROR_NONE) {
free(lpWave);
return NULL;
}
/* copy the data into the waveform object */
memcpy(lpWave->lpData, lpData, dwLength);
/* upload the data to the audio DRAM local memory */
AWriteAudioData(lpWave, 0L, dwLength);
}
return lpWave;
}
The waveform structure fields dwLength, dwLoopStart and dwLoopEnd are all measured in bytes, not samples, so your application should be careful to handle 16 bit waveform objects.
See Also ADestroyAudioData, AWriteAudioData
Releases a waveform object.
Returns zero on success.
See Also ACreateAudioData, AWriteAudioData
Upload waveform audio data to DRAM local memory.
Returns zero on success.
VOID StreamData8BitMono(FILE *stream, HAC hVoice, LPAUDIOWAVE lpWave)
{
BYTE aBuffer[1024];
LPBYTE lpChunk;
UINT nLength, nChunkSize;
DWORD dwOffset, dwVoicePosition;
/* check if the waveform is large enough for double buffering */
if (2*sizeof(aBuffer) > lpWave->dwLength) {
printf("the waveform is too small\n");
return;
}
/* first clean up the audio waveform buffer */
memset(lpWave->lpData, 0x80, lpWave->dwLength);
AWriteAudioData(lpWave, 0L, lpWave->dwLength);
/* start playing the waveform with forward looping enabled */
lpWave->wFormat |= AUDIO_FORMAT_LOOP;
lpWave->dwLoopStart = 0L;
lpWave->dwLoopEnd = lpWave->dwLength;
APlayVoice(hVoice, lpWave);
ASetVoiceVolume(hVoice, 64);
/* play the whole 8-bit mono stream of audio through the voice */
dwOffset = 0;
while ((nLength = fread(aBuffer, 1, nLength, stream)) != 0) {
/* write the waveform audio data in chunks */
lpChunk = aBuffer;
while (nLength > 0) {
/* determine size of chunk of data */
nChunkSize = nLength;
if (dwOffset + nChunkSize >= lpWave->dwLength)
nChunkSize = lpWave->dwLength - dwOffset;
/* wait until we can write the chunk of data */
for (;;) {
AUpdateAudio();
AGetVoicePosition(hVoice, &dwVoicePosition);
if (dwOffset + nChunkSize > lpWave->dwLength) {
if (dwVoicePosition < dwOffset &&
dwVoicePosition > dwOffset +
nChunkSize - lpWave->dwLength)
break;
}
else {
if (dwVoicePosition < dwOffset ||
dwVoicePosition > dwOffset + nChunkSize)
break;
}
}
/* upload the chunk of waveform data */
memcpy(lpWave->lpData + dwOffset, lpChunk, nChunkSize);
AWriteAudioData(lpWave, dwOffset, nChunkSize);
if ((dwOffset += nChunkSize) >= lpWave->dwLength)
dwOffset = 0;
lpChunk += nChunkSize;
nLength -= nChunkSize;
}
}
}
See Also ACreateAudioData, ADestroyAudioData
Load a RIFF/WAVE waveform file from disk.
Returns zero on success.
VOID PlayWaveFile(HAC hVoice, LPSTR lpszFileName)
{
LPAUDIOWAVE lpWave;
BOOL stopped;
if (ALoadWaveFile(lpszFileName, &lpWave, 0L) == AUDIO_ERROR_NONE) {
APlayVoice(hVoice, lpWave);
ASetVoiceVolume(hVoice, 64);
while (!kbhit()) {
AUpdateAudio();
AGetVoiceStatus(hVoice, &stopped);
if (stopped) break;
}
AFreeWaveFile(lpWave);
}
}
See Also AFreeWaveFile
Releases a loaded RIFF/WAVE waveform file.
Returns zero on success.
See Also ALoadWaveFile
Start playing a music module file.
Returns zero on success.
See Also AStopModule
Stop playing a music module file.
Returns zero on success.
This routine stop and releases the audio system module player. After calling this routine, your application can select and start another module by calling the APlayModule routine.
See Also APlayModule
Stop playing a music module file.
Returns zero on success.
This routine stop the audio system module player. You can later continue playing the music module by calling the AResumeModule routine. Your application must use AStopModule when the currently select module file is going to be released, or if another music module must be played.
See Also APlayModule, AStopModule, AResumeModule
Restart playing a music module file.
Returns zero on success.
This routine is used to continue playing a music module that was previously paused by the APauseModule routine. Your application can use AGetModuleStatus to retrieve the current state of the audio system module player.
See Also APlayModule, AStopModule, APauseModule, AGetModuleStatus
Changes the music module global volume.
Returns zero on success.
See Also APlayModule, AStopModule, AGetModuleVolume
Changes the music module playing position.
Returns zero on success.
See Also APlayModule, AStopModule, AGetModulePosition
Retrieves the music module global volume.
Returns zero on success.
See Also APlayModule, AStopModule, ASetModuleVolume
Retrieves the music module playing position.
Returns zero on success.
See Also APlayModule, AStopModule, ASetModulePosition
Retrieves the current state of the music module player.
Returns zero on success.
See Also APlayModule, AStopModule, APauseModule, AResumeModule
Changes the music module synchronization callback routine.
Returns zero on success.
#define START_INTRO_SEQUENCE 0x01 /* Z01 */
#define START_VECTOR_GRAPHICS 0x02 /* Z02 */
VOID AIAPI SyncCallback(BYTE nParms, UINT nOrder, UINT nRow)
{
switch (nParms) {
case START_INTRO_SEQUENCE:
StartIntroSequence();
break;
case START_VECTOR_GRAPHICS:
StartVectorGraphics();
break;
default:
/* unknown Znn command found at position (nOrder, nRow) */
break;
}
}
VOID InitSyncCallback(VOID)
{
ASetModuleCallback(SyncCallback);
}
VOID DoneSyncCallback(VOID)
{
ASetModuleCallback(NULL);
}
Load MOD/MTM/S3M/XM module files from disk.
Returns zero on success.
See Also AFreeModuleFile
Releases a music module file from memory.
Returns zero on success.
See Also ALoadModuleFile
} AUDIOCAPS, *LPAUDIOCAPS;
typedef struct {
WORD wProductId;
CHAR szProductName[30];
DWORD dwFormats;
The AUDIOCAPS structure contains the audio capabilities information that can be obtained by calling AGetAudioDevCaps for a given audio device driver.
Members:
Value | Description |
AUDIO_PRODUCT_NONE | Virtual silence device |
AUDIO_PRODUCT_SB | Sound Blaster 1.0 device |
AUDIO_PRODUCT_SB15 | Sound Blaster 1.5 device |
AUDIO_PRODUCT_SB20 | Sound Blaster 2.0 device |
AUDIO_PRODUCT_SBPRO | Sound Blaster Pro I or II device |
AUDIO_PRODUCT_SB16 | Sound Blaster 16/ASP device |
AUDIO_PRODUCT_AWE32 | Sound Blaster AWE32 device |
AUDIO_PRODUCT_WSS | Windows Sound System device |
AUDIO_PRODUCT_ESS | Ensoniq Soundscape (Elite) device |
AUDIO_PRODUCT_GUS | Gravis Ultrasound (GF1) device |
AUDIO_PRODUCT_GUSDB | Gravis Ultrasound Daughterboard device |
AUDIO_PRODUCT_GUSMAX | Gravis Ultrasound Max (CS4231) device |
AUDIO_PRODUCT_IWAVE | AMD Interwave-based device |
AUDIO_PRODUCT_PAS | Pro Audio Spectrum (Plus) device |
AUDIO_PRODUCT_PAS16 | Pro Audio Spectrum 16 device |
AUDIO_PRODUCT_ARIA | Sierra Semiconductors Aria Sound device |
AUDIO_PRODUCT_WINDOWS | Microsoft Windows WAVE device |
AUDIO_PRODUCT_DSOUND | Microsoft Windows DirectSound device |
AUDIO_PRODUCT_LINUX | UNIX Sound System for Linux device |
AUDIO_PRODUCT_SPARC | SPARC workstation 8-bit ulaw or dbri device |
AUDIO_PRODUCT_SGI | Silicon Graphics Indigo Audio Ports device |
AUDIO_PRODUCT_OS2MMPM | OS/2 Multimedia Presentation Manager device |
AUDIO_PRODUCT_BEOSR3 | BeOS Release 3 OLD MediaKit device |
AUDIO_PRODUCT_BEOS | BeOS Release 4 New MediaKit device |
Value | Description |
AUDIO_FORMAT_1M08 | 8-bit mono 11025 Hz |
AUDIO_FORMAT_1S08 | 8-bit stereo 11025 Hz |
AUDIO_FORMAT_1M16 | 16-bit mono 11025 Hz |
AUDIO_FORMAT_1S16 | 16-bit stereo 11025 Hz |
AUDIO_FORMAT_2M08 | 8-bit mono 22050 Hz |
AUDIO_FORMAT_2S08 | 8-bit stereo 22050 Hz |
AUDIO_FORMAT_2M16 | 16-bit mono 22050 Hz |
AUDIO_FORMAT_2S16 | 16-bit stereo 22050 Hz |
AUDIO_FORMAT_4M08 | 8-bit mono 44100 Hz |
AUDIO_FORMAT_4S08 | 8-bit stereo 44100 Hz |
AUDIO_FORMAT_4M16 | 16-bit mono 44100 Hz |
AUDIO_FORMAT_4S16 | 16-bit stereo 44100 Hz |
typedef struct {
UINT nDeviceId;
WORD wFormat;
WORD nSampleRate;
} AUDIOINFO, *LPAUDIOINFO;
Audio information structure used to open the hardware audio device for playback by using the AOpenAudio routine.
Members:
Value | Description |
AUDIO_DEVICE_NONE | Silence device driver |
AUDIO_DEVICE_MAPPER | Audio mapper driver |
Value | Description |
AUDIO_FORMAT_8BITS | 8 bits per sample |
AUDIO_FORMAT_16BITS | 16 bits per sample |
AUDIO_FORMAT_MONO | Monophonic output |
AUDIO_FORMAT_STEREO | Stereo output |
AUDIO_FORMAT_FILTER | Enable filtering |
typedef struct {
LPBYTE lpData;
DWORD dwHandle;
DWORD dwLength;
DWORD dwLoopStart;
DWORD dwLoopEnd;
WORD nSampleRate;
WORD wFormat;
} AUDIOWAVE, *LPAUDIOWAVE;
Audio waveform structure used to hold all the information related to a single waveform.
Members:
Value | Description |
AUDIO_FORMAT_8BITS | 8 bits per sample |
AUDIO_FORMAT_16BITS | 16 bits per sample |
AUDIO_FORMAT_MONO | Monophonic output |
AUDIO_FORMAT_STEREO | Stereo output |
AUDIO_FORMAT_LOOP | Forward looping |
AUDIO_FORMAT_BIDILOOP | Bidirectional looping |
AUDIO_FORMAT_REVERSE | Reverse playing |
WORD nRestart;
WORD nTracks;
WORD nPatterns;
WORD nPatches;
WORD nTempo;
WORD nBPM;
BYTE aOrderTable[AUDIO_MAX_ORDERS];
BYTE aPanningTable[AUDIO_MAX_VOICES];
LPAUDIOPATTERN aPatternTable;
LPAUDIOPATCH aPatchTable;
} AUDIOMODULE, *LPAUDIOMODULE;
typedef struct {
CHAR szModuleName[32];
WORD wFlags;
WORD nOrders;
This structure holds all the information related to a single music module file loaded in system memory.
Members:
Value | Description |
AUDIO_MODULE_LINEAR | The module uses linear frequencies |
AUDIO_MODULE_AMIGA | Use Amiga logarithmic frequencies |
AUDIO_MODULE_PANNING | Use pan position from instruments |
Value | Description |
AUDIO_ERROR_NONE | No error |
AUDIO_ERROR_INVALHANDLE | Invalid voice or waveform handle |
AUDIO_ERROR_INVALPARAM | Invalid parameter passed |
AUDIO_ERROR_NOTSUPPORTED | Invalid audio system call |
AUDIO_ERROR_BADDEVICEID | Invalid device identifier |
AUDIO_ERROR_NODEVICE | No audio device found |
AUDIO_ERROR_DEVICEBUSY | Audio device is busy |
AUDIO_ERROR_BADFORMAT | Bad or unsupported audio playback format |
AUDIO_ERROR_NOMEMORY | Not enough system memory |
AUDIO_ERROR_NODRAMMEMORY | Not enough onboard DRAM memory |
AUDIO_ERROR_FILENOTFOUND | Module or waveform file not found |
AUDIO_ERROR_BADFILEFORMAT | Invalid module or waveform file format |