I'm not sure I will use XAct or OpenAL. To maintain compatibility I may simply use the multimedia API within the Windows API. I will have to do some old school mixing and loading but it's not too hard.
The basic scheme seems to be:
1. Open audio device and specify callback
2. Load data into audio blocks (buffers)
3. Mix set portion of all audio blocks into one primary audio block
4. Write (play) data of first half of primary audio block, load into second block
4. Callback function is called when driver is done with audio block.
5. At this point, send the second block, load first, mix, etc.
This is very similar to old school DOS when you did this:
1. Retrieve port and interrupt values from BLASTER environment variable.
2. Program DMA for the transfer size (usually auto-init DMA)
3. Program the PIC using the correct interrupt mask
4. Program the DSP for the HALF of the transfer
5. Write an interrupt handler for interrupt specified in BLASTER variable
6. Load data into audio buffers
7. Mix set portion of all audio blocks into one primary audio block and send to DSP
8. When DSP is done it will fire a hardware interrupt on the interrupt specified in BLASTER
9. Inside interrupt handler play block that was just loaded and load into block that just played.
10. Continue ad nauseum.
Essentially this is the mixing:
Code:
...
struct Sample16
{
unsigned int *buffer;
unsigned int sample_length;
unsigned int fade_out_start;
unsigned int fade_out_length;
};
...
...
float fade = 0.0f;
for (int i = 0;i < mix_buffer_size; ++i)
{
unsigned int play_offset = play_cursor + i;
unsigned int sample_value = samples[num_sample].buffer[play_offset];
unsigned int fade_out_start = sample[num_sample].fade_out_start;
if (play_offset > fade_out_start)
{
fade = ((float)play_offset - (float)fade_out_start) / (float)(sample[num_sample].fade_out_length);
}
float final_value = (float)sample_value * fade;
primary_buffer[current_block_start + i] = static_cast<unsigned int>(value);
++num_sample;
}
...
...
If my memory serves me right this will fade out a sound as it nears the end so it will not pop or click. The primary buffer is then what is sent to Windows to be played or in DOS would have been the pointer to the memory area that the DMA was programmed for. Since the DMA scanned this memory it then transferred any changes directly to the sound card DSP all without the CPU touching any of the data.
I'm fairly sure I can code this using pure Win32 multimedia calls.