# 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:

- WATCOM C/C++32 10.0 Compiler for DOS4GW and Win32
- DJGPP 2.0 Compiler port of GNU CC for DOS/DPMI32
- GNU CC 2.7.0 Compiler for Linux (a.out and ELF) operating system
- Visual C++ 4.1 Compiler for Windows 95 and Windows NT
- Borland Delphi 2.0 Compiler for Windows 95 and Windows NT
- Metrowerks CodeWarrior C++ for BeOS Intel Release 3
- GNU CC Compiler for BeOS Intel Release 4
- EMX port of GNU CC 2.7.x Compiler for OS/2 operating 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:

- Sound Blaster 1.0
- Sound Blaster 1.5
- Sound Blaster 2.0
- Sound Blaster Pro I and II
- Sound Blaster 16 / ASP
- Sound Blaster 32
- Sound Blaster AWE32
- Creative PCI64 and PCI128 cards
- Windows Sound System
- Ensoniq Soundscape
- Ensoniq Soundscape Elite
- Ensoniq AudioPCI cards
- Gravis Ultrasound
- Gravis Ultrasound Daughterboard
- Gravis Ultrasound MAX
- AMD InterWave-based boards
- Pro Audio Spectrum
- Pro Audio Spectrum Plus
- Pro Audio Spectrum 16
- Aria sound cards

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

- Mixing The most used feature of the audio system is the low-latency mixing of digital audio channels. Your application can create up to 32 voices to play concurrently audio data through your sound device. The audio system mixes all the active voices and writes the result to the audio hardware.
Low-latency mixing allows the user to experience no perceptible delay between the time that the application start playing a waveform through the audio hardware and the time that the speakers reproduct the sound.

- Hardware Acceleration The SEAL audio system automatically takes advantage of accelerated sound hardware, including hardware mixing and hardware local memory. Your application does not need to query the hardware to specifically use hardware acceleration.

## 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.

- nDeviceId Audio device driver identifier.
- lpCaps Address of an AUDIOCAPS structure that will hold the capabitilies information of the audio device driver referenced by the nDeviceId device driver identifier.

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.

- nErrorCode Numeric error return code to be translated.
- lpText Address of the null-terminated text description buffer.
- nSize Number of bytes of the text description buffer.

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.

- lpnDeviceId Address of an unsigned integer that will hold the detect device identifier.

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.

- lpInfo Address of an AUDIOINFO structure that holds the playback configuration.

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.

- nFrames The maximum amount of sample frames to update in the output buffer.

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.

- nChannel The mixer channel identifier.
- nValue The new mixer channel's value (0-256).

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.

- lpfnAudioTimer Address of the timer handler routine.

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.

- nTimerRate The timer rate given in beats per minute (32-255).

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.

- nVoices Maximum number of allocatable audio voices (1-32).

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.

- lphVoice Address of a voice handle that will hold the allocated voice.

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.

- hVoice Handle of the audio voice which will be released.

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.

- hVoice Handle of the audio voice that will play the waveform.
- lpWave Address of the waveform structure to be played.

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.

- hVoice Handle of the audio voice that will be prepared.
- lpWave Address of the waveform structure that will be played.

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.

- hVoice Handle of the audio voice to be started.

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.

- hVoice Handle of the audio voice to be stopped.

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.

- hVoice Handle of an audio voice.
- dwPosition Playing position measured in samples.

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.

- hVoice Handle of the audio voice to be changed.
- dwFrequency Sampling frequency measured in Hertz (cycles per second).

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.

- hVoice Handle of the audio voice to be changed.
- nVolume Linear volume level (0-64).

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.

- hVoice Handle of the audio voice to be changed.
- nPanning Stereo pan position value (0-255).

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.

- hVoice Handle of the audio voice to be queried.
- lpdwPosition Address of a long variable which will hold the playing position.

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.

- hVoice Handle of the audio voice to be queried.
- lpdwFrequency Address of a long variable that will hold the frequency.

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.

- hVoice Handle of the audio voice to be queried.
- lpnVolume Address of an unsigned integer variable that will hold the volume.

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.

- hVoice Handle of the audio voice which will be queried.
- lpnPanning Address of an unsigned integer variable that will hold the pan position.

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.

- hVoice Handle of the audio voice that will be queried.
- lpbStatus Address of a boolean variable that will hold the voice status.

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.

- lpWave Address of the waveform structure.

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.

- lpWave Address of the waveform object to be released.

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.

- lpWave Address of the waveform object.
- dwOffset Starting offset of the block of samples to be uploaded.
- nCount Number of bytes in the block of samples to be transferred.

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.

- lpszFileName Filename of the .WAV waveform file on disk.
- lplpWave Address of a pointer to a waveform structure.
- dwOffset Starting file offset of the waveform file.

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.

- lpWave Address of the waveform structure to be released.

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.

- lpModule Address of the module to be played.

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.

- nVolume The new volume level for the music module (0-64).

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.

- nOrder The new order position.
- nRow The new pattern row number.

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.

- lpnVolume Address of an unsigned integer that will hold the module volume.

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.

- lpnOrder Address of an unsigned integer that will hold the order position.
- lpnRow Address of an unsigned integer that will hold the pattern row number.

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.

- lpbStatus Address of an unsigned integer that will hold the status.

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.

- lpfnAudioCallback Address of the synchronization callback routine.

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.

- lpszFileName File name of the music module file.
- lplpModule Address of a music module reference variable.
- dwOffset Starting file offset of the music module file.

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.

- lpModule Address of a music module file in memory.

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:

- wProductId Specifies the hardware audio device product identifier. This member can hold any of the following values:

  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_OS2DART | OS/2 DART Real Time Audio device
  AUDIO_PRODUCT_BEOSR3 | BeOS Release 3 OLD MediaKit device
  AUDIO_PRODUCT_BEOS | BeOS Release 4 New MediaKit device

- szProductName Null terminated readable text string describing the hardware audio device product.
- dwFormats Specifies the playback formats supported by the hardware audio device product. This member can be built using any combination of the following values:

  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

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:

- nDeviceId Specifies the audio device we want to use for playback. The following virtual audio device identifiers are always defined:

  Value | Description
  AUDIO_DEVICE_NONE | Silence device driver
  AUDIO_DEVICE_MAPPER | Audio mapper driver

- wFormat Specifies the audio output format for playback. This member can be built using the following values:

  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

- nSampleRate Specifies the sampling frequency used for playback. It's recommended to use the standard frequencies 11025, 22050 or 44100 Hz for better compatibility.

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:

- lpData Read Only. Address of the a buffer in system memory used to hold the waveform data.
- dwHandle Read Only. Handle used internally by the audio device drivers to reference the waveform data.
- dwLength Specifies the length in bytes of the waveform data.
- dwLoopStart Specifies the loop start point measured in bytes, only used for looped samples.
- dwLoopEnd Specifies the loop end point measured in bytes, only used for looped samples.
- nSampleEate The default sampling frequency of the waveform data.
- wFormat Specifies the format and the looping type of the waveform data. This member can be built using the following defines:

  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

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:

- szModuleName Specifies the music module name as a null-terminated text string.
- wFlags Specifies some intial flags for the music module. This member can be built using the following values:

  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

- nOrders Number of entries in the sequence order table.
- nRestart Specifies the restart order position for looped modules.
- nTracks Number of tracks used in the music module.
- nPatterns Number of patterns used in the music module.
- nPatches Number of patches or instruments used in the music module.
- nTempo Initial speed or tempo value.
- nBPM Initial BPM or beats per minute value.
- aOrderTable Specifies the sequence order in which the patterns are played.
- aPanningTable Initial stereo pan position for all the music module tracks.
- aPatternTable Array of pattern structures.
- aPatchTable Array of patches structures.

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.