Go to the first, previous, next, last section, table of contents.


Making Noise

After you have allocated the sound hardware and declared all your sounds, you're ready to start playback. This is done with a call to AHI_ControlAudioA(), with the AHIC_Play tag set to TRUE. When this function returns the PlayerFunc (see AHI_AllocAudioA()) is active, and the audio driver is feeding silence to the sound hardware.

Playing A Sound

All you have to do now is to set the desired sound, it's frequency and volume. This is done with AHI_SetSound(), AHI_SetFreq() and AHI_SetVol(). Make sure the AHISF_IMM flag is set for all these function's flag argument. And don't try to modify a channel that is out of range! If you have allocated 4 channels you may only modify channels 0-3.

The sound will not start until both AHI_SetSound() and AHI_SetFreq() has been called. The sound will play even if AHI_SetVol() was not called, but it will play completely silent. If you wish to temporary stop a sound, set its frequency to 0. When you change the frequency again, the sound will continue where it were.

When the sound has been started it will play to the end and then repeat. In order to play a one-shot sound you have use the AHI_PlayA() function, or install a sound interrupt using the AHIA_SoundFunc tag with AHI_AllocAudioA(). For more information about using sound interrupts, see below.

A little note regarding AHI_SetSound(): Offset is the first sample that will be played, both when playing backwards and forwards. This means that if you call AHI_SetSound() with offset 0 and length 4, sample 0,1,2 and 3 will be played. If you call AHI_SetSound() with offset 3 and length -4, sample 3,2,1 and 0 will be played.

Also note that playing very short sounds will be very CPU intensive, since there are many tasks that must be done each time a sound has reached its end (like starting the next one, calling the SoundFunc, etc.). Therefore, it is recommended that you "unroll" short sounds a couple of times before you play them. How many times you should unroll? Well, it depends on the situation, of course, but try making the sound a thousand samples long if you can. Naturally, if you need your SoundFunc to be called, you cannot unroll.

Playing One-shot Sounds And Advanced Loops

Some changes has been made since earlier releases. One-shot sounds and sounds with only one loop segment can now be played without using sample interrupts. This is possible because one of the restrictions regarding the AHISF_IMM flag has been removed.

The AHISF_IMM flag determines if AHI_SetSound(), AHI_SetFreq() and AHI_SetVol() should take effect immediately or when the current sound has reached its end. The rules for this flags are:

What does this mean? It means that if all you want to do is to play a one-shot sound from inside a PlayerFunc, you can do that by first calling AHI_SetSound(), AHI_SetFreq() and AHI_SetVol() with AHISF_IMM set, and then use AHI_SetSound(ch, AHI_NOSOUND, 0, 0, actrl, 0L) to stop the sound when it has reached the end. You can also set one loop segment this way.

AHI_PlayA() was added in AHI version 4, and combines AHI_SetSound(), AHI_SetFreq() and AHI_SetVol() into one tag-based function. It also allows you to set one loop and play one-shot sounds.

To play a sound with more than one loop segment or ping-pong looping, a sample interrupt needs to be used. AHI's SoundFunc works like Paula's interrupts and is very easy to use.

The SoundFunc hook will be called with an AHIAudioCtrl structure as object and an AHISoundMessage structure as message. ahism_Channel indicates which channel caused the hook to be called.

An example SoundFunc which handles the repeat part of an instrument can look like this (SAS/C code):

__asm __saveds ULONG SoundFunc(register __a0 struct Hook *hook,
    register __a2 struct AHIAudioCtrl *actrl,
    register __a1 struct AHISoundMessage *chan)
{
  if(ChannelDatas[chan->ahism_Channel].Length)
    AHI_SetSound(chan->ahism_Channel, 0,
        (ULONG) ChannelDatas[chan->ahism_Channel].Address,
        ChannelDatas[chan->ahism_Channel].Length,
        actrl, NULL);
  else
    AHI_SetSound(chan->ahism_Channel, AHI_NOSOUND,
        NULL, NULL, actrl, NULL);
  return NULL;
}

This example is from an old version of the AHI NotePlayer for DeliTracker 2. ChannelDatas is an array where the start and length of the repeat part is stored. Here, a repeat length of zero indicates a one-shot sound. Note that this particular example only uses one sound (0). For applications using multiple sounds, the sound number would have to be stored in the array as well.

Once again, note that the AHISF_IMM flag should never be set in a SoundFunc hook!

Tricks With The Volume

Starting with V4, AHI_SetVol() can take both negative volume and pan parameters. If you set the volume to a negative value, the sample will, if the audio mode supports it, invert each sample before playing. If pan is negative, the sample will be encoded to go to the surround speakers.


Go to the first, previous, next, last section, table of contents.