SEAL Synthetic Audio Library 1.07

Programmer's Guide


Copyright Information

Information in this document is subject to change without notice. No part of this document may be reproduced or transmitted in any form or by any means, electronic or mechanical, for any purpose, without the express written permission of the author.

The Synthetic Audio Library Software Developer Kit
Copyright (C) 1995-1999 Carlos Hasan

This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

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


About the Synthetic Audio Library

The Synthetic Audio Library application programming interface allows your applications to play digital audio waveforms and multichannel music sequences in your applications, provides low-latency mixing, hardware acceleration and dynamic digital filtering for improved sound quality.

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.

Supported Platforms and Hardware

The Synthetic Audio Library SEAL SDK is available for DOS, Extended DOS, Windows 95, Windows NT and Linux operating systems. The following compilers are supported in the current version of the audio system:

Any other language for Windows 95 or Windows NT with 32-bit dynamic link libraries support, such as Visual Basic or Borland C++ 5.0, should also be able to use the audio system AUDIOW32.DLL dynamic link library.

Under the DOS operating system the following hardware audio devices are natively supported by the audio system:

Other sound devices compatible with any of the above sound boards are also supported.

Data Types

The most fundamental data types used in the audio system are waveforms, modules and voices. The waveform data type represent digital audio data of individual sources of sound, modules represent multichannel music sequences, and voices represent monophonic audio channels used to play waveforms. Each voice can control the sound characteristics of the waveform that is being played through it, such as frequency and volume levels.

Features


Audio Device Interface

Initialization

The audio device interface allows your application to communicate and control the audio hardware on the system. Your application must initialize the audio system to be able to start using it by calling the AInitialize routine. It's not required for Windows 95 and Windows NT applications.

Device Capabilities

Before initializing the audio device for playback, your application can enumerate and retrieve information of the registered audio device drivers. The device drivers are enumerated starting from zero, and the AGetAudioNumDevs routine returns the number of audio device drivers installed on the system. The application can retrieve the capabilities information of any of the installed audio device drivers by calling the routine AGetAudioDevCaps.

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.

Opening the Audio Device

After investigating the capabilities of the sound device, your application can open the audio hardware for playback calling AOpenAudio and specifying what audio device, output format, and sampling frequency should be used. Since the specified audio device might not support the desired parameters, the audio system will use the closest configuration supported by the audio hardware.

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.

Closing the Audio Device

Applications can release the audio hardware by calling the ACloseAudio routine. It's very important to release all the allocated waveforms, modules and voice resources before closing the audio system.

Timer Interrupt Services

Your application can install a virtual audio timer interrupt callback routine by calling the ASetAudioTimerProc routine. The rate or speed at which the virtual audio timer routine is called can be changed by calling the routine ASetAudioTimerRate. Since the installed timer callback routine can be called from within a hardware interrupt handler, for applications running under the DOS operating system, your timer routine has the same constrains than hardware interrupt handler routines.

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.

Audio Voice Interface

Creating Audio Voices

Your application can allocate audio voices to play digital audio waveforms concurrently. After calling the routine AOpenVoices to specify the amount of available audio voices, your application can call the ACreateAudioVoice routine to allocate audio voices.

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.

Play Management

Your application can start playing a waveform through a voice by calling the APlayVoice or APrimeVoice routines. The real-time playback of the audio voices is controlled by calling the AStartVoice and AStopVoice routines. The voice stops automatically when the end of the waveform is reached. However, if looping is specified, the voice repeats until AStopVoice is called.

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.

Environment Management

To retrieve or set the volume at which a waveform is being played by a particular audio voice your application can call the AGetVoiceVolume and ASetVoiceVolume routines, respectively.

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.

Retrieving State Information

The AGetVoiceStatus routine can be used by your application to determine the current state of an audio voice. The returned boolean value is true when the voice is stopped. Notice that a voice will never stop playing a looped waveform unless the AStopVoice is called.

Audio Waveform Interface

Creating Waveforms

Your application can load waveform files directly from disk by calling ALoadWaveFile. The routine AFreeWaveFile is called to release the waveform from memory. It's also possible to create and destroy custom waveforms calling the ACreateAudioData and ADestroyAudioData routines, respectively. Your application can't release a waveform while it's being played by one or more audio voices.

Playing Waveforms

The waveform objects, that represent audio data of individual sound sources such as musical instruments or sound effects, can be played through audio voices calling the APlayVoice or APrimeVoice routines. See the Audio Voices Interface section for more information.

Audio Music Module Interface

Creating Modules

Your application can load music module files directly from disk by calling ALoadModuleFile. The routine AFreeModuleFile is used to release modules from system memory. If the module file is being played by the audio system, your application must stop it to be able to release it from memory.

Play Management

The APlayModule routine is used to select and start playing a music module. The audio system can't play music modules concurrently, but there is no limit in the amount of modules loaded in system memory. The AStopModule routine is called to stop playing the current music module, and to be able to select another module for playback or whenever the module is going to be released from memory. While a music module is being played by the audio system, your application can control the real-time playback of the module by calling the APauseModule and AResumeModule routines to pause or resume playing the music sequence.

Environment Management

Your application can retrieve or set the current module position by calling the AGetModulePosition and ASetModulePosition routines. These positions are measured in orders and pattern rows.

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.

Reference Guide

Functions


UINT AIAPI Ainitialize(VOID)

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


UINT AIAPI AGetVersion(VOID)

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.


UINT AIAPI AGetAudioNumDevs(VOID)

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


UINT AIAPI AGetAudioDevCaps(UINT nDeviceId, LPAUDIOCAPS lpCaps)

Retrieves information about audio device drivers.

Return zero on success.

This routine retrieves the audio capabilities information from an audio device driver identified by the nDevideId parameter. The AGetAudioNumDevs returns the number of installed audio devices on the system.

    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
UINT AIAPI AGetErrorText(UINT nErrorCode, LPSTR lpText, UINT nSize)

Return readable text description for a given error return code.

Return zero on success.

Most of the routines in the Synthetic Audio Library return numeric error codes which can be translated to a readable text description using this routine. The returned text description is a null-terminated string of ASCII characters.

    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);
       }
    }

UINT AIAPI APingAudio(LPUINT lpnDeviceId)

Automatically detect the installed audio device.

Returns zero on success.

This routine can be used to determine which audio device is present on the system. Alternatively, your application can detect and use an audio device by using the virtual audio device identifer AUDIO_DEVICE_MAPPER to open the audio system with the AOpenAudio routine.

    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
UINT AIAPI AOpenAudio(LPAUDIOINFO lpInfo)

Open audio device for playback.

Returns zero on success.

This routine open a given audio device for playback at the specified format and sampling frequency. Since the hardware device might not support the desired configuration, the audio system will use the closest parameters which are then returned in the AUDIOINFO structure.

    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
UINT AIAPI ACloseAudio(VOID)

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


UINT AIAPI AUpdateAudio(VOID)

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, AUpdateAudioEx


UINT AIAPI AUpdateAudioEx(UINT nFrames)

Updates the audio system output buffers.

Returns zero on success.

This routine is similar to AUpdateAudio but lets you have more control on the latency of the audio system. It must be called to update up to nFrames sample frames in the output buffer. For example, every time you call AUpdateAudioEx(nSampleRate/100) the audio system will fill up to 10 ms of sound in the output buffer.

See Also AOpenAudio, ACloseAudio, AUpdateAudio


UINT AIAPI ASetAudioMixerValue(UINT nChannel, UINT nValue)

Changes the audio mixer settings.

Returns zero on success.

This routine changes the mixer level settings of the audio engine. Currently the only channel supported is the AUDIO_MIXER_MASTER_VOLUME channel which sets the overall mixing volume level for all the audio voices.
UINT AIAPI ASetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave)

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.


UINT AIAPI ASetAudioTimerProc(LPFNAUDIOTIMER lpfnAudioTimer)

Install virtual audio timer callback routine.

Returns zero on success.

This routine set the virtual audio timer callback routine. Since the audio system uses this timer to play module files in background, your application should not use this routine while the system is playing a music sequence. The virtual timer callback can be called from a hardware interrupt handler for applications running in DOS.

    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
UINT AIAPI ASetAudioTimerRate(UINT nTimerRate)

Changes the virtual audio timer rate.

Returns zero on success.

This routine changes the rate at which the virtual audio timer callback will be called by the audio system. Since the virtual audio timer is used by the system to play music sequences, your application can change the tempo or speed of the music by calling this routine while the module is being played.

See Also ASetAudioTimerProc


UINT AIAPI AOpenVoices(UINT nVoices)

Open audio voices.

Returns zero on success.

This routine is used to open audio voices for playback. The number of opened voices may affect both the performance and sound quality for some audio devices, so your application should allocate the minimum amount of voices. Your application must call the routine ACloseVoices to close all the audio voices before exiting or when the number of opened voices need to be changed.

See Also ACloseVoices, ACreateAudioVoice, ADestroyAudioVoice


UINT AIAPI ACloseVoices(VOID)

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


UINT AIAPI ACreateAudioVoice(LPHAC lphVoice)

Allocates a single audio voice.

Returns zero on success.

This routine allocates an audio voice which can be used by your application to play waveforms through it. The routine will fail if no more voices are availables or if the application has not yet called AOpenVoices to open audio voices.

    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
UINT AIAPI ADestroyAudioVoice(HAC hVoice)

Releases an allocated audio voice.

Returns zero on success.

This routine releases an audio voice that was previously allocated by calling the ACreateAudioVoice routine. Your application should not release voices which are currently being used to play a waveform.

See Also ACreateAudioVoice


UINT AIAPI APlayVoice(HAC hVoice, LPAUDIOWAVE lpWave)

Start playing a waveform through a voice.

Returns zero on success.

This routine start playing a waveform through an audio voice at the default sampling frequency. The volume and panning settings of the audio voice are not changed, so your application may need to change these parameters manually.

See Also APrimeVoice, AStartVoice, AStopVoice


UINT AIAPI APrimeVoice(HAC hVoice, LPAUDIOWAVE lpWave)

Prepares a waveform on an audio voice.

Returns zero on success.

This routine is similar to APlayVoice but will only prepare a waveform to be played through a voice. The routine AStartVoice must be called to actually start playing the waveform. The frequency, volume and panning settings of the voice are not changed by this routine.

    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
UINT AIAPI AStartVoice(HAC hVoice)

Start playing an audio voice.

Returns zero on success.

This routines starts or continues playing a waveform through an audio voice that was prepared or stopped by the APrimeVoice or AStopVoice routines.

See Also APrimeVoice, APlayVoice, AStopVoice


UINT AIAPI AStopVoice(HAC hVoice)

Stop playing an audio voice.

Returns zero on success.

This routine stop an audio voice. Your application can restart the audio voice by calling the AStartVoice routine, the voice will continue playing the waveform starting at the position where it was previously stopped.

See Also APrimeVoice, APlayVoice, AStartVoice


UINT AIAPI ASetVoicePosition(HAC hVoice, LONG dwPosition)

Changes the voice playing position.

Returns zero on success.

This routine changes the playing position of an audio voice. The position will be changed in real-time, so your application can program echo effects using a pair of allocated voices, for example.

    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
UINT AIAPI ASetVoiceFrequency(HAC hVoice, LONG dwFrequency)

Changes the voice sampling frequency.

Returns zero on success.

This routine changes the sampling frequency of an audio voice. Your application can use this routine to do things like pitch slides or simple stereo enhancement effects by changing the frequency of the audio voices in real-time.

    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
UINT AIAPI ASetVoiceVolume(HAC hVoice, UINT nVolume)

Changes the voice volume level.

Returns zero on success.

This routine changes the volume level of an audio voice. The voices can be faded in and out smoothly in real-time using this routine and the virtual audio timer services, for example.

See Also AGetVoiceVolume


UINT AIAPI ASetVoicePanning(HAC hVoice, UINT nPanning)

Changes the voice stereo pan position.

Returns zero on success.

This routine changes the stereo pan position of an audio voice. It has no effect when the audio system is playing in monophonic mode.

See Also AGetVoicePanning


UINT AIAPI AGetVoicePosition(HAC hVoice, LPLONG lpdwPosition)

Retrieves the playing position of a voice.

Returns zero on success.

This routine retrieves the current playing position of an audio voice measured in samples. Your application can use this routine to implement a double buffering algorithm to play streams of audio data from disk using a single audio voice.

See Also ASetVoicePosition
UINT AIAPI AGetVoiceFrequency(HAC hVoice, LPLONG lpdwFrequency)

Retrieves the sampling frequency of a voice.

Returns zero on success.

This routine retrieves the current sampling frequency of an audio voice. Your application should not expect to get back the same frequency used in the last call to the ASetVoiceFrequency routine, due to possible rounding errors that occur when the audio system translates frequencies in Hertz to the device dependant format used by the hardware audio device.

See Also ASetVoiceFrequency


UINT AIAPI AGetVoiceVolume(HAC hVoice, LPUINT lpnVolume)

Retrieves the volume level of a voice.

Returns zero on success.

This routine retrieves the current volume level of an audio voice. Your application should not expect to get back the same volume level used in the last call to the ASetVoiceVolume routine, due to possible rounding errors that occur when the audio system translates linear volumes to the device dependant format used by the hardware audio device.

See Also ASetVoiceVolume


UINT AIAPI AGetVoicePanning(HAC hVoice, LPUINT lpnPanning)

Retrieves the stereo pan position of a voice.

Returns zero on success.

This routine retrieves the current stereo pan position of an audio voice. Your application should not expect to get back the same pan position used in the last call to the ASetVoicePanning routine, due to possible rounding errors that occur when the audio system translates pan positions to the device dependant format used by the hardware audio device.

See Also ASetVoicePanning


UINT AIAPI AGetVoiceStatus(HAC hVoice, LPBOOL lpbStatus)

Retrieves the current status of a voice.

Returns zero on success.

This routine retrieves the current status of an audio voice. Your application can use this routine to determine if a voice is stopped or if it's playing a waveform.

    VOID CheckVoice(HAC hVoice)
    {
        BOOL stopped;
        AGetVoiceStatus(hVoice, &stopped);
        if (stopped)
            printf("voice is stopped.\n");
    }
See Also AStartVoice, AStopVoice
LONG AIAPI AGetAudioDataAvail(VOID)

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);
    }

UINT AIAPI ACreateAudioData(LPAUDIOWAVE lpWave)

Creates a waveform object.

Returns zero on success.

This routine is used to create custom waveform objects. Your application can also use ALoadWaveFile to load RIFF/WAVE waveform files from disk. The current version of the audio system only support 8 and 16 bit mono one-shot or looped waveforms (reverse and bidirectional looping modes are not supported by AWE32 audio devices).

    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


UINT AIAPI ADestroyAudioData(LPAUDIOWAVE lpWave)

Releases a waveform object.

Returns zero on success.

This routine releases a waveform object previously allocated by calling the ACreateAudioData routine. Before releasing any waveform, your application must be sure that no voices are currently playing the waveform.

See Also ACreateAudioData, AWriteAudioData


UINT AIAPI AWriteAudioData(LPAUDIOWAVE lpWave, DWORD dwOffset, UINT nCount)

Upload waveform audio data to DRAM local memory.

Returns zero on success.

This routine uploads a block of samples from system memory to the hardware DRAM local memory when applicable. Your application must call this routine everytime it writes to the waveform audio data. The chunk of samples to be uploaded is specified by the offset and count parameters measured in bytes.

    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
UINT AIAPI ALoadWaveFile(LPSTR lpszFileName, LPAUDIOWAVE* lplpWave, DWORD dwOffset)

Load a RIFF/WAVE waveform file from disk.

Returns zero on success.

This routine load a RIFF/WAVE waveform from disk. The loaded waveform must be released with the AFreeWaveFile routine.

    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
UINT AIAPI AFreeWaveFile(LPAUDIOWAVE lpWave)

Releases a loaded RIFF/WAVE waveform file.

Returns zero on success.

This routine releases waveform files loaded from disk. Your application can't use ADestroyAudioData to release waveforms loaded from disk. You must stop any voice that is playing the waveform before releasing it.

See Also ALoadWaveFile


UINT AIAPI APlayModule(LPAUDIOMODULE lpModule)

Start playing a music module file.

Returns zero on success.

This routine start playing a module file in background using the audio system module player. Your application can stop a module by calling the AStopModule routine. The application must have enough available audio voices to play the music module.

See Also AStopModule


UINT AIAPI AStopModule(VOID)

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


UINT AIAPI APauseModule(VOID)

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


UINT AIAPI AResumeModule(VOID)

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


UINT AIAPI ASetModuleVolume(UINT nVolume)

Changes the music module global volume.

Returns zero on success.

This routine changes the global volume at which the audio system is playing a music module sequence.

See Also APlayModule, AStopModule, AGetModuleVolume


UINT AIAPI ASetModulePosition(UINT nOrder, UINT nRow)

Changes the music module playing position.

Returns zero on success.

This routine changes the playing position of the audio system module player. Your application can use this routine to play small music sequences or patterns of sound effects, intro music, etc. all of them stored in the same music module file.

See Also APlayModule, AStopModule, AGetModulePosition


UINT AIAPI AGetModuleVolume(LPUINT lpnVolume)

Retrieves the music module global volume.

Returns zero on success.

This routine retrieves the global volume used by the audio system to play a music module sequence.

See Also APlayModule, AStopModule, ASetModuleVolume


UINT AIAPI AGetModulePosition(LPUINT lpnOrder, LPUINT lpnRow)

Retrieves the music module playing position.

Returns zero on success.

This routine retrieves the playing position of the audio system module player. Your application can use this routine to synchronize graphics or video with the music.

See Also APlayModule, AStopModule, ASetModulePosition


UINT AIAPI AGetModuleStatus(LPBOOL lpbStatus)

Retrieves the current state of the music module player.

Returns zero on success.

This routine retrieves the current status of the audio system module player. The routine returns true if the module player is paused or false otherwise. The audio system pauses the module file when the APauseModule routine is called or when the end of a non-looped music sequence is reached.

See Also APlayModule, AStopModule, APauseModule, AResumeModule


UINT AIAPI ASetModuleCallback(LPFNAUDIOCALLBACK lpfnAudioCallback)

Changes the music module synchronization callback routine.

Returns zero on success.

This routine changes the synchronization routine that is called by the audio system module player whenever it encounters a synchronization mark in the pattern effects column, the argument of the effect is passed to the callback routine. For ScreamTracker 3.0 and FastTracker 2.0 modules, the command effect Znn is used for synchronization (where nn is an hexadecimal number passed to the synchronization callback routine). For applications running under DOS, the synchronization callback can be called from within a hardware interrupt handler routine.

    #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);
    }

UINT AIAPI ALoadModuleFile(LPSTR lpszFileName, LPAUDIOMODULE* lplpModule, DWORD dwOffset)

Load MOD/MTM/S3M/XM module files from disk.

Returns zero on success.

This routine loads MOD/MTM/S3M/XM music module files from disk. The music module can be played and stopped by calling the APlayModule and AStopModule routines, respectively.

See Also AFreeModuleFile


UINT AIAPI AFreeModuleFile(LPAUDIOMODULE lpModule)

Releases a music module file from memory.

Returns zero on success.

This routine releases music module files from memory previously loaded by the ALoadModuleFile routine. Your application can't release modules currently being played by the audio system.

See Also ALoadModuleFile

Structures


AUDIOCAPS

    typedef struct {
        WORD    wProductId;
        CHAR    szProductName[30];
        DWORD   dwFormats;
    } AUDIOCAPS, *LPAUDIOCAPS;
The AUDIOCAPS structure contains the audio capabilities information that can be obtained by calling AGetAudioDevCaps for a given audio device driver.

Members:


AUDIOINFO

    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:


AUDIOWAVE

    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:


AUDIOMODULE

    typedef struct {
        CHAR    szModuleName[32];
        WORD    wFlags;
        WORD    nOrders;
        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;
This structure holds all the information related to a single music module file loaded in system memory.

Members:


RETURN CODES

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


November 30th, 1998.