@mateusz_s, post #31
@mateusz_s, post #30
Użycie Wait() nie działa w tym tasku z jakiegoś powoduGdy system umieszcza przychodzącą wiadomość w message porcie, a ten ma ustawioną flagę PA_SIGNAL (typowy przypadek), to wysyła sygnał ustawiony w mp_SigBit do tasku w mp_SigTask. Jeżeli port został stworzony przez CreateMsgPort(), to mp_SigTask jest ustawiany na task, który wywołał CreateMsgPort() i sygnał jest alokowany dla tego właśnie tasku.
@Don_Adan, post #32
@Don_Adan, post #38
@mateusz_s, post #40
@mateusz_s, post #41
@mateusz_s, post #42
@mateusz_s, post #42
@Krashan, post #43
@Krashan, post #43
channels = {
LEFT_1 | RIGHT_1,
LEFT_1 | RIGHT_2,
LEFT_2 | RIGHT_1,
LEFT_2 | RIGHT_2 }@mateusz_s, post #46
@mateusz_s, post #47
@Krashan, post #49
@mateusz_s, post #51
jeśli dam CMD_WRITE i prześlę to BeginIO() to dzwiek zaczyna grać od razu.Zgadza się.
Chyba że jak dałeś wczesniej CMD_STOP to wtedy nie? I trzeba dać CMD_START, tak?Dokładnie tak. Taka sekwencja komend: STOP na kilku kanałach, zestaw WRITE do tych kanałów, START na tych kanałach, służy do synchronicznego wystartowania kilku kanałów (z dokładnością do 1 sampla). Jest to opisane w dokumentacji systemu.
@Krashan, post #54
@Don_Adan, post #55
A to mozesz (jak chcesz) sprawdzic pierwsza wersje tego customa,Nie mam czasu na debugowanie błędów w czyimś kodzie...
Tutaj zdaje sie pomyslodawca polegl na niemoznosci (?) synchronizacji lewego i prawego kanalu audio AmigiTo jest stałe przesunięcie między parą 0-3 i parą 1-2 wynoszące około 6 mikrosekund. Czyli przykładowo dla próbkowania 44,1 kHz to jest opóźnienie o mniej niż 1/3 sampla. To może mieć znaczenie przy tym pracowitym składaniu bitów, żeby mieć pseudo 14-bit, ale nie ma żadnego znaczenia przy odtwarzaniu normalnych danych 8-bitowych.
@Krashan, post #56
@Krashan, post #56
@Don_Adan, post #58
// Amiga includes.
#include <proto/exec.h>
#include <proto/dos.h>
#include <devices/audio.h>
#include <clib/alib_protos.h>
#include <graphics/gfxbase.h>
// Standard includes.
#include <stdlib.h>
// ---------------
// --- Globals ---
// ---------------
#define sys_audio__FREQUENCY 22050 // Fixed frequency for all sounds.
#define sys_audio__CHUNK_SIZE 512 // Operational chunk size in bytes for music. This amount will be copied each frame to one of the buffers.
#define sys_audio__MUS_CHIP_BUFFER_SIZE (sys_audio__CHUNK_SIZE * 2)
#define sys_audio__SFX_CHIP_BUFFER_SIZE (sys_audio__CHUNK_SIZE * 2) // Continuous buffer in CHIP mem. made of two chunks.
#define sys_audio__SFX_FAST_BUFFER_SIZE (sys_audio__CHUNK_SIZE * 50 * 3) // Size in bytes. Chunks multiplied by 50*3, that gives ~2 secs. of space. This determines the maximum sample lenght.
// Amiga audio channel allocation bits.
#define sys_audio__CHANNEL_LEFT_1 1
#define sys_audio__CHANNEL_RIGHT_1 2
#define sys_audio__CHANNEL_RIGHT_2 4
#define sys_audio__CHANNEL_LEFT_2 8
static UBYTE sys_audio__channels[] = { 15 }; // 15 for allocating all channels.
// Enumerating all IO Audio request blocks we need.
enum { sys_audio__CONTROL, // For volume control.
sys_audio__MUS_LEFT, // For switching music buffers.
sys_audio__MUS_RIGHT, // For switching music buffers.
sys_audio__SFX_LEFT, // For switching sfx buffers.
sys_audio__SFX_RIGHT, // For switching sfx buffers.
sys_audio__COUNT };
// Message ports and signal masks.
// One message port for each io audio request block.
static struct MsgPort* sys_audio__mp[sys_audio__COUNT];
static ULONG sys_audio__mp_signal_mask[sys_audio__COUNT];
// IO Audio request blocks.
static struct IOAudio* sys_audio__io[sys_audio__COUNT];
// Buffer in fast ram that will be used for mixing sfx samples
// and hold them until they are copied to chip ram.
static BYTE *sys_audio__fast_buf;
// One continuous buffer in CHIP mem. that will be splitted
// into two equal buffers for music and two equal for sfx.
static BYTE *sys_audio__chip_buf__mus[2];
static BYTE *sys_audio__chip_buf__sfx[2];
struct Task* sys_audio__main_task;
struct Task* sys_audio__audio_task;
static ULONG sys_audio__audio_task__result;
BYTE sys_audio__audio_task__signal;
ULONG sys_audio__audio_task__signal_mask;
LONG sys_audio__audio_task__loop;
static ULONG sys_audio__audio_device_result;
volatile LONG sys_audio__chunk_offset;
static char* sys_audio__mus_source;
static LONG sys_audio__mus_size;
static LONG sys_audio__mus_started;
static LONG sys_audio__mus_chunk_offset;
int test = -1;
// ------------------------------------
// --- Private function definitions ---
// ------------------------------------
int sys_audio__audio_task__create(void)
{
// Get clock value, PAL or NTSC.
LONG gfxbase_clock;
struct GfxBase *GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L);
if (GfxBase == 0L)
return 0;
if (GfxBase->DisplayFlags & PAL) gfxbase_clock = 3546895L; // PAL clock
else gfxbase_clock = 3579545L; // NTSC clock
if (GfxBase)
CloseLibrary( (struct Library *) GfxBase);
// 01.
// Alloc fast ram buffer that will be used for mixing and holding mixed samples.
sys_audio__fast_buf = (BYTE*)AllocMem( sys_audio__SFX_FAST_BUFFER_SIZE, MEMF_PUBLIC | MEMF_CLEAR );
if (sys_audio__fast_buf == NULL)
return 0;
// 02.
// Allocate one continuous buffer and assign correct pointers.
// Sound samples to be played, must be in CHIP mem.
sys_audio__chip_buf__mus[0] = (BYTE*)AllocMem( sys_audio__MUS_CHIP_BUFFER_SIZE + sys_audio__SFX_CHIP_BUFFER_SIZE, MEMF_CHIP | MEMF_CLEAR );
if (sys_audio__chip_buf__mus[0] == NULL)
return 0;
// 03.
// Assign correct pointers.
sys_audio__chip_buf__mus[1] = sys_audio__chip_buf__mus[0] + (sys_audio__MUS_CHIP_BUFFER_SIZE / 2);
sys_audio__chip_buf__sfx[0] = sys_audio__chip_buf__mus[1] + (sys_audio__SFX_CHIP_BUFFER_SIZE / 2);
sys_audio__chip_buf__sfx[1] = sys_audio__chip_buf__sfx[0] + (sys_audio__SFX_CHIP_BUFFER_SIZE / 2);
if (sys_audio__chip_buf__mus[1] == NULL || sys_audio__chip_buf__sfx[0] == NULL || sys_audio__chip_buf__sfx[1] == NULL)
return 0;
// 04.
// Create message ports.
for (int i = 0; i < sys_audio__COUNT; i++)
{
sys_audio__mp[i] = CreateMsgPort();
if (sys_audio__mp[i] == NULL)
return 0;
}
// Save the signal masks.
for (int i = 0; i < sys_audio__COUNT; i++)
sys_audio__mp_signal_mask[i] = 1L << sys_audio__mp[i]->mp_SigBit;
// 05.
// Alloc memory for IO Audio Request Blocks.
// One continuous block that will be splitted.
sys_audio__io[sys_audio__CONTROL] = (struct IOAudio *)AllocMem( sizeof(struct IOAudio) * sys_audio__COUNT, MEMF_PUBLIC | MEMF_CLEAR );
if (sys_audio__io[sys_audio__CONTROL] == NULL)
return 0;
// 06.
// Assign correct pointers.
sys_audio__io[sys_audio__MUS_LEFT] = sys_audio__io[sys_audio__CONTROL] + 1;
sys_audio__io[sys_audio__MUS_RIGHT] = sys_audio__io[sys_audio__MUS_LEFT] + 1;
sys_audio__io[sys_audio__SFX_LEFT] = sys_audio__io[sys_audio__MUS_RIGHT] + 1;
sys_audio__io[sys_audio__SFX_RIGHT] = sys_audio__io[sys_audio__SFX_LEFT] + 1;
if ( sys_audio__io[sys_audio__MUS_LEFT] == NULL || sys_audio__io[sys_audio__MUS_RIGHT] == NULL ||
sys_audio__io[sys_audio__SFX_LEFT] == NULL || sys_audio__io[sys_audio__SFX_RIGHT] == NULL )
return 0;
// Lets open audio device using MUS_CONTROL.
sys_audio__io[sys_audio__CONTROL]->ioa_Request.io_Message.mn_Node.ln_Type = 127;
sys_audio__io[sys_audio__CONTROL]->ioa_Request.io_Message.mn_ReplyPort = sys_audio__mp[sys_audio__CONTROL];
sys_audio__io[sys_audio__CONTROL]->ioa_Request.io_Message.mn_Length = sizeof(struct IOAudio);
sys_audio__io[sys_audio__CONTROL]->ioa_Request.io_Command = ADCMD_ALLOCATE;
sys_audio__io[sys_audio__CONTROL]->ioa_Request.io_Flags = ADIOF_NOWAIT;
sys_audio__io[sys_audio__CONTROL]->ioa_Length = sizeof(sys_audio__channels);
sys_audio__io[sys_audio__CONTROL]->ioa_Data = sys_audio__channels;
// 07.
sys_audio__audio_device_result = OpenDevice("audio.device", 0, (struct IORequest*)sys_audio__io[sys_audio__CONTROL], 0);
if (sys_audio__audio_device_result != 0)
return 0;
// Copy all sttucture to the remaining structures. Keeping the generated allocation key.
*sys_audio__io[sys_audio__MUS_LEFT] = *sys_audio__io[sys_audio__CONTROL];
*sys_audio__io[sys_audio__MUS_RIGHT] = *sys_audio__io[sys_audio__CONTROL];
*sys_audio__io[sys_audio__SFX_LEFT] = *sys_audio__io[sys_audio__CONTROL];
*sys_audio__io[sys_audio__SFX_RIGHT] = *sys_audio__io[sys_audio__CONTROL];
// Setup MUS_CONTROL.
sys_audio__io[sys_audio__CONTROL]->ioa_Request.io_Message.mn_ReplyPort = sys_audio__mp[sys_audio__CONTROL];
sys_audio__io[sys_audio__CONTROL]->ioa_Request.io_Unit = (APTR)(sys_audio__CHANNEL_LEFT_1 | sys_audio__CHANNEL_RIGHT_1 | sys_audio__CHANNEL_LEFT_2 | sys_audio__CHANNEL_RIGHT_2);
// Setup MUS_LEFT.
// Using LEFT 1 audio channel.
sys_audio__io[sys_audio__MUS_LEFT]->ioa_Request.io_Message.mn_ReplyPort = sys_audio__mp[sys_audio__MUS_LEFT];
sys_audio__io[sys_audio__MUS_LEFT]->ioa_Request.io_Command = CMD_WRITE;
sys_audio__io[sys_audio__MUS_LEFT]->ioa_Request.io_Flags = ADIOF_PERVOL;
sys_audio__io[sys_audio__MUS_LEFT]->ioa_Request.io_Unit = (APTR)(sys_audio__CHANNEL_LEFT_1);
sys_audio__io[sys_audio__MUS_LEFT]->ioa_Period = (UWORD)( gfxbase_clock / sys_audio__FREQUENCY );
sys_audio__io[sys_audio__MUS_LEFT]->ioa_Volume = 48;
sys_audio__io[sys_audio__MUS_LEFT]->ioa_Cycles = 1;
sys_audio__io[sys_audio__MUS_LEFT]->ioa_Length = (sys_audio__MUS_CHIP_BUFFER_SIZE / 2);
sys_audio__io[sys_audio__MUS_LEFT]->ioa_Data = sys_audio__chip_buf__mus[0];
// Setup MUS_RIGHT.
// Same as MUS_LEFT, but using RIGHT 1 sudio channel
// and separate message port.
*sys_audio__io[sys_audio__MUS_RIGHT] = *sys_audio__io[sys_audio__MUS_LEFT];
sys_audio__io[sys_audio__MUS_RIGHT]->ioa_Request.io_Message.mn_ReplyPort = sys_audio__mp[sys_audio__MUS_RIGHT];
sys_audio__io[sys_audio__MUS_RIGHT]->ioa_Request.io_Unit = (APTR)(sys_audio__CHANNEL_RIGHT_1);
// Setup SFX_LEFT.
// Using LEFT 2 audio channel.
sys_audio__io[sys_audio__SFX_LEFT]->ioa_Request.io_Message.mn_ReplyPort = sys_audio__mp[sys_audio__SFX_LEFT];
sys_audio__io[sys_audio__SFX_LEFT]->ioa_Request.io_Command = CMD_WRITE;
sys_audio__io[sys_audio__SFX_LEFT]->ioa_Request.io_Flags = ADIOF_PERVOL;
sys_audio__io[sys_audio__SFX_LEFT]->ioa_Request.io_Unit = (APTR)(sys_audio__CHANNEL_LEFT_2);
sys_audio__io[sys_audio__SFX_LEFT]->ioa_Period = (UWORD)( gfxbase_clock / sys_audio__FREQUENCY );
sys_audio__io[sys_audio__SFX_LEFT]->ioa_Volume = 48;
sys_audio__io[sys_audio__SFX_LEFT]->ioa_Cycles = 1;
sys_audio__io[sys_audio__SFX_LEFT]->ioa_Length = sys_audio__CHUNK_SIZE;
sys_audio__io[sys_audio__SFX_LEFT]->ioa_Data = sys_audio__chip_buf__sfx[0];
// Setup SFX_RIGHT.
// Same as SFX_LEFT, but using RIGHT 2 sudio channel
// and separate message port.
*sys_audio__io[sys_audio__SFX_RIGHT] = *sys_audio__io[sys_audio__SFX_LEFT];
sys_audio__io[sys_audio__SFX_RIGHT]->ioa_Request.io_Message.mn_ReplyPort = sys_audio__mp[sys_audio__SFX_RIGHT];
sys_audio__io[sys_audio__SFX_RIGHT]->ioa_Request.io_Unit = (APTR)(sys_audio__CHANNEL_RIGHT_2);
return 1;
}
void sys_audio__audio_task__destroy(void)
{
for (int i = 0; i < sys_audio__COUNT; i ++)
AbortIO((struct IORequest*)sys_audio__io[i]);
// Unqueqe message ports.
for (int i = 0; i < sys_audio__COUNT; i ++)
while (GetMsg(sys_audio__mp[i])) {};
// 07.
if (sys_audio__audio_device_result == 0)
CloseDevice( (struct IORequest*)sys_audio__io[sys_audio__CONTROL] );
// 06.
sys_audio__io[sys_audio__MUS_LEFT] = NULL;
sys_audio__io[sys_audio__MUS_RIGHT] = NULL;
sys_audio__io[sys_audio__SFX_LEFT] = NULL;
sys_audio__io[sys_audio__SFX_RIGHT] = NULL;
// 05.
if (sys_audio__io[sys_audio__CONTROL])
{
FreeMem( sys_audio__io[sys_audio__CONTROL], sizeof(struct IOAudio) * sys_audio__COUNT );
sys_audio__io[sys_audio__CONTROL] = NULL;
}
// 04.
for (int i = 0; i < sys_audio__COUNT; i ++)
if (sys_audio__mp[i])
{
DeleteMsgPort(sys_audio__mp[i]);
sys_audio__mp[i] = NULL;
}
// 03.
sys_audio__chip_buf__sfx[1] = NULL;
sys_audio__chip_buf__sfx[0] = NULL;
sys_audio__chip_buf__mus[1] = NULL;
// 02.
if (sys_audio__chip_buf__mus[0])
{
FreeMem( sys_audio__chip_buf__mus[0], sys_audio__MUS_CHIP_BUFFER_SIZE + sys_audio__SFX_CHIP_BUFFER_SIZE );
sys_audio__chip_buf__mus[0] = NULL;
}
// 01.
if (sys_audio__fast_buf)
{
FreeMem( sys_audio__fast_buf, sys_audio__SFX_FAST_BUFFER_SIZE );
sys_audio__fast_buf = NULL;
}
}
void sys_audio__audio_task__func(void)
{
sys_audio__audio_task__result = sys_audio__audio_task__create();
if (sys_audio__audio_task__result == 0)
{
sys_audio__audio_task__destroy();
return;
}
// Send the signal to main task, that initialization is finished
// and the result can be checked.
Signal(sys_audio__main_task, sys_audio__audio_task__signal_mask);
// ----------------------------
// --- Audio task main loop ---
// ----------------------------
LONG swap_sfx = 0;
LONG chunk_offset_to_erase = 0;
sys_audio__chunk_offset = 0;
// Trigger SFX_BUFFERS to start the routine.
sys_audio__io[sys_audio__CONTROL]->ioa_Request.io_Command = CMD_STOP;
DoIO((struct IORequest*)sys_audio__io[sys_audio__CONTROL]);
BeginIO((struct IORequest*)sys_audio__io[sys_audio__SFX_LEFT]);
BeginIO((struct IORequest*)sys_audio__io[sys_audio__SFX_RIGHT]);
sys_audio__io[sys_audio__CONTROL]->ioa_Request.io_Command = CMD_START;
DoIO((struct IORequest*)sys_audio__io[sys_audio__CONTROL]);
// To break the loop before closing up everything,
// the main program will set sys_audio__audio_task__loop to 0
// and send a simple IO request to sys_audio__MUS_CONTROL to move out from Wait()
// and check the while condition.
sys_audio__audio_task__loop = 1;
while(sys_audio__audio_task__loop)
{
ULONG signals = Wait( sys_audio__mp_signal_mask[sys_audio__CONTROL] |
sys_audio__mp_signal_mask[sys_audio__MUS_LEFT] |
sys_audio__mp_signal_mask[sys_audio__MUS_RIGHT] |
sys_audio__mp_signal_mask[sys_audio__SFX_LEFT] |
sys_audio__mp_signal_mask[sys_audio__SFX_RIGHT] );
// -----------------------------------------
// --- Getting a signal from MUS_CONTROL ---
// -----------------------------------------
if ( signals & sys_audio__mp_signal_mask[sys_audio__CONTROL] )
while(GetMsg(sys_audio__mp[sys_audio__CONTROL]));
// ---------------------------------------
// --- Getting a signal from SFX_RIGHT ---
// ---------------------------------------
// Only dispatching the message port.
if ( signals & sys_audio__mp_signal_mask[sys_audio__MUS_RIGHT] )
while(GetMsg(sys_audio__mp[sys_audio__MUS_RIGHT]));
if ( signals & sys_audio__mp_signal_mask[sys_audio__MUS_LEFT] )
while(GetMsg(sys_audio__mp[sys_audio__MUS_LEFT]));
// ---------------------------------------
// --- Getting a signal from SFX_RIGHT ---
// ---------------------------------------
// Only dispatching the message port.
if ( signals & sys_audio__mp_signal_mask[sys_audio__SFX_RIGHT] )
while(GetMsg(sys_audio__mp[sys_audio__SFX_RIGHT]));
// --------------------------------------
// --- Getting a signal from SFX_LEFT ---
// --------------------------------------
// When signal is recieved, SFX_LEFT (and most probably also SFX_RIGHT) request has finished playing.
// To keep both channels synchronized first we send CMD_STOP to SFX_CONTROL - it works on both channels,
// so both channels will stop play but also the CMD_WRITE from BeginIO() wont trigger them.
// We can swap the buffers and set CMD_WRITE thru BeginIO() for both.
// Now sending CMD_START will play both channels the same time.
// Also its time to copy new chunk from fast to not used chip buffer
// and erase previous chunk from fast buffer.
if ( signals & sys_audio__mp_signal_mask[sys_audio__SFX_LEFT] )
{
// Dispatching the message port.
while(GetMsg(sys_audio__mp[sys_audio__SFX_LEFT]));
// Stop playing both SFX channels.
sys_audio__io[sys_audio__CONTROL]->ioa_Request.io_Command = CMD_STOP;
DoIO((struct IORequest*)sys_audio__io[sys_audio__CONTROL]);
// Swap buffers and send request.
// Now the info is written but the channels wont play.
sys_audio__io[sys_audio__SFX_LEFT]->ioa_Data = sys_audio__chip_buf__sfx[swap_sfx^1];
sys_audio__io[sys_audio__SFX_RIGHT]->ioa_Data = sys_audio__chip_buf__sfx[swap_sfx^1];
sys_audio__io[sys_audio__MUS_LEFT]->ioa_Data = sys_audio__chip_buf__mus[swap_sfx^1];
sys_audio__io[sys_audio__MUS_RIGHT]->ioa_Data = sys_audio__chip_buf__mus[swap_sfx^1];
BeginIO((struct IORequest*)sys_audio__io[sys_audio__SFX_LEFT]);
BeginIO((struct IORequest*)sys_audio__io[sys_audio__SFX_RIGHT]);
BeginIO((struct IORequest*)sys_audio__io[sys_audio__MUS_LEFT]);
BeginIO((struct IORequest*)sys_audio__io[sys_audio__MUS_RIGHT]);
// Now start playing both channels at the same time.
sys_audio__io[sys_audio__CONTROL]->ioa_Request.io_Command = CMD_START;
DoIO((struct IORequest*)sys_audio__io[sys_audio__CONTROL]);
// Copy chunk of mixed data from fast to not using chip buffer.
memcpy(sys_audio__chip_buf__sfx[swap_sfx], sys_audio__fast_buf + sys_audio__chunk_offset, sys_audio__CHUNK_SIZE);
// Is it safe to increase the offset?
// This value is used in main program - dont optimize it. Never exceed the max offset.
if (sys_audio__chunk_offset < sys_audio__SFX_FAST_BUFFER_SIZE - sys_audio__CHUNK_SIZE)
{
sys_audio__chunk_offset += sys_audio__CHUNK_SIZE;
if (sys_audio__chunk_offset > 0) chunk_offset_to_erase = sys_audio__chunk_offset - sys_audio__CHUNK_SIZE;
else chunk_offset_to_erase = sys_audio__SFX_FAST_BUFFER_SIZE - sys_audio__CHUNK_SIZE;
}
else
{
sys_audio__chunk_offset = 0;
chunk_offset_to_erase = sys_audio__SFX_FAST_BUFFER_SIZE - sys_audio__CHUNK_SIZE;
}
// Clear previous chunk in fast mem. So we won't mix in future with some trash.
memset(sys_audio__fast_buf + chunk_offset_to_erase, 0, sys_audio__CHUNK_SIZE);
if (sys_audio__mus_started)
{
sys_audio__mus_chunk_offset += sys_audio__CHUNK_SIZE;
memcpy(sys_audio__chip_buf__mus[swap_sfx], sys_audio__mus_source + sys_audio__mus_chunk_offset, sys_audio__CHUNK_SIZE);
}
swap_sfx ^= 1;
}
}
// Cleanup.
sys_audio__audio_task__destroy();
// After everything is cleaned up send the signal to the main task.
Signal(sys_audio__main_task, sys_audio__audio_task__signal_mask);
// Dont finish the task.
// It will be deleted in the main task.
Wait(0);
return;
}
// -----------------------------------
// --- Public function definitions ---
// -----------------------------------
int SYSTEM_audio__create(void)
{
sys_audio__mus_started = 0;
// Create separate thread/task for switching audio buffers and double buffer routines.
// It's because this can't be affected by WaitTOF() in the main game loop.
// Find main task.
sys_audio__main_task = FindTask(NULL);
// Create a signal to communicate with audio task.
sys_audio__audio_task__signal = AllocSignal(-1);
sys_audio__audio_task__signal_mask = 1L << sys_audio__audio_task__signal;
// Create separate audio task.
sys_audio__audio_task = (struct Task*)CreateTask("audio_task", 10, (APTR)sys_audio__audio_task__func, 4096);
if (sys_audio__audio_task == NULL) return 0;
// Wait for a signal from the audio task, while it is initializing.
Wait(sys_audio__audio_task__signal_mask);
// The result of initialisation.
if (sys_audio__audio_task__result == 0)
return 0;
return 1;
}
void SYSTEM_audio__destroy(void)
{
// Send signal to audio task to finish its audio main loop.
sys_audio__audio_task__loop = 0;
Signal(sys_audio__audio_task, sys_audio__mp_signal_mask[sys_audio__CONTROL]);
// Now wait for signal fro audio task.
// It will send signal when it finish cleaning up.
Wait(sys_audio__audio_task__signal_mask);
// Finish audio task manually.
if (sys_audio__audio_task)
{
Forbid();
DeleteTask(sys_audio__audio_task);
Permit();
sys_audio__audio_task = NULL;
}
FreeSignal(sys_audio__audio_task__signal);
}
void SYSTEM_audio__mus_play(char* _sample, int _size)
{
sys_audio__mus_source = _sample;
sys_audio__mus_size = _size;
sys_audio__mus_started = 1;
}
void SYSTEM_audio__sfx_play(char* _sample, int _size)
{
// Copy desired sample from source fast buffer to mixing fast buffer
// and perform the mixing.
// Checking if the desired sample will fit into fast buffer.
// Current position in fast buffer is: sys_audio__chunk_offset.
volatile LONG chunk_offset = sys_audio__chunk_offset;
LONG size_remain = (sys_audio__SFX_FAST_BUFFER_SIZE - chunk_offset);
LONG difference = size_remain - _size;
if (difference > 0)
{
// Will fit.
BYTE *ptr = sys_audio__fast_buf + chunk_offset;
// Mix to the end of sample. We wont exceed the fast buffer.
for (int i = 0; i < _size; i++)
ptr[i] += _sample[i];
}
else
{
// Won't fit, lets split.
BYTE *ptr = sys_audio__fast_buf + chunk_offset;
// Mix to the end of fast buffer.
for (int i = 0; i < size_remain; i++)
ptr[i] += _sample[i];
// Mix the rest from the start of fast buffer.
for (int i = 0; i < -difference; i++)
sys_audio__fast_buf[i] += _sample[size_remain + i];
}
} @mateusz_s, post #59