@mateusz_s, post #62
// 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.
// --- Memory ---
#define sys_audio__MUS_CHUNK_SIZE 768
#define sys_audio__MUS_CHUNKS 16
#define sys_audio__MUS_CHIP_BUFFER_SIZE (sys_audio__MUS_CHUNK_SIZE * sys_audio__MUS_CHUNKS)
#define sys_audio__MUS_CHIP_TOTAL_SIZE (sys_audio__MUS_CHIP_BUFFER_SIZE * 2)
#define sys_audio__SFX_BUFFER_SIZE 768
#define sys_audio__SFX_CHIP_TOTAL_SIZE (sys_audio__SFX_BUFFER_SIZE * 2)
#define sys_audio__SFX_FAST_TOTAL_SIZE (sys_audio__SFX_BUFFER_SIZE * 60)
static BYTE* sys_audio__chip_buffer__mus[2];
static BYTE* sys_audio__chip_buffer__sfx[2];
static BYTE* sys_audio__fast_buffer__sfx_mixed;
// --- Audio structures ---
// 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
// Audio channels to allocate.
static UBYTE sys_audio__channels[] = { sys_audio__CHANNEL_LEFT_1 | sys_audio__CHANNEL_RIGHT_1 | sys_audio__CHANNEL_LEFT_2 | sys_audio__CHANNEL_RIGHT_2 };
// Enumerating all IO Audio request blocks we need.
enum { sys_audio__MUS_LEFT,
sys_audio__MUS_RIGHT,
sys_audio__SFX_LEFT,
sys_audio__SFX_RIGHT,
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];
static ULONG sys_audio__audio_device_result;
// --- Tasks ---
// We need additional task (thread) that won't be interefered with WaitTOF() in the main game loop
// because it could create lags when playing short buffers. This task will cycle and play next mus and sfx requests.
static struct Task* sys_audio__main_task;
static struct Task* sys_audio__audio_task;
static volatile BYTE sys_audio__audio_task__result;
static BYTE sys_audio__audio_task__signal;
static ULONG sys_audio__audio_task__signal_mask;
static LONG sys_audio__audio_task__loop;
// --- Buffering and mixing routines ---
static BYTE* sys_audio__mus_data;
static LONG sys_audio__mus_size;
static LONG sys_audio__mus_offset;
static LONG sys_audio__mus_chip_buffer_to_fill__index;
static BYTE* sys_audio__mus_chip_buffer_to_fill__ptr;
static volatile LONG sys_audio__mus_chunks_to_copy;
static volatile LONG sys_audio__sfx_fast_buffer_offset_to_copy;
// ------------------------------------
// --- Private function definitions ---
// ------------------------------------
int sys_audio__audio_task__create(void)
{
// Get clock value, PAL or NTSC.
LONG gfxbase_clock = 3546895L; // PAL clock;
if (((struct ExecBase*)SysBase)->VBlankFrequency == 60)
gfxbase_clock = 3579545L; // NTSC clock
// 01.
// Allocate one continous buffer in CHIP mem for MUS and split it into two buffers.
// Sound samples to be played, must be in CHIP mem.
sys_audio__chip_buffer__mus[0] = (BYTE*)AllocVec( sys_audio__MUS_CHIP_TOTAL_SIZE, MEMF_CHIP | MEMF_CLEAR );
if (sys_audio__chip_buffer__mus[0] == NULL)
return 0;
sys_audio__chip_buffer__mus[1] = sys_audio__chip_buffer__mus[0] + sys_audio__MUS_CHIP_BUFFER_SIZE;
// 02.
// Allocate chip buffer for SFX and assign correct pointers to all SFX buffers.
// Sound samples to be played, must be in CHIP mem.
sys_audio__chip_buffer__sfx[0] = (BYTE*)AllocVec( sys_audio__SFX_CHIP_TOTAL_SIZE, MEMF_CHIP | MEMF_CLEAR );
if (sys_audio__chip_buffer__sfx[0] == NULL)
return 0;
sys_audio__chip_buffer__sfx[1] = sys_audio__chip_buffer__sfx[0] + sys_audio__SFX_BUFFER_SIZE;
// 03.
// Alloc fast ram buffer that will be used for mixing and holding mixed samples.
sys_audio__fast_buffer__sfx_mixed = (BYTE*)AllocVec( sys_audio__SFX_FAST_TOTAL_SIZE, MEMF_PUBLIC | MEMF_CLEAR );
if (sys_audio__fast_buffer__sfx_mixed == 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__MUS_LEFT] = (struct IOAudio *)AllocVec( sizeof(struct IOAudio) * sys_audio__COUNT, MEMF_PUBLIC | MEMF_CLEAR );
if (sys_audio__io[sys_audio__MUS_LEFT] == NULL)
return 0;
// 06.
// Assign correct pointers for rest of io audio blocks.
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;
// 07.
// Lets open audio device using MUS_LEFT.
sys_audio__io[sys_audio__MUS_LEFT]->ioa_Request.io_Message.mn_Node.ln_Type = 127;
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_Message.mn_Length = sizeof(struct IOAudio);
sys_audio__io[sys_audio__MUS_LEFT]->ioa_Request.io_Command = ADCMD_ALLOCATE;
sys_audio__io[sys_audio__MUS_LEFT]->ioa_Request.io_Flags = ADIOF_NOWAIT;
sys_audio__io[sys_audio__MUS_LEFT]->ioa_Length = sizeof(sys_audio__channels);
sys_audio__io[sys_audio__MUS_LEFT]->ioa_Data = sys_audio__channels;
sys_audio__audio_device_result = OpenDevice("audio.device", 0, (struct IORequest*)sys_audio__io[sys_audio__MUS_LEFT], 0);
if (sys_audio__audio_device_result != 0)
return 0;
// Check if all desired channels were allocated.
if ( (((LONG)sys_audio__io[sys_audio__MUS_LEFT]->ioa_Request.io_Unit) & 0x0F) != sys_audio__channels[0] ) return 0;
// Setup rest of io audio blocks.
// Copy all structure to the remaining structures to keep the generated allocation key.
*sys_audio__io[sys_audio__MUS_RIGHT] = *sys_audio__io[sys_audio__MUS_LEFT];
*sys_audio__io[sys_audio__SFX_LEFT] = *sys_audio__io[sys_audio__MUS_LEFT];
*sys_audio__io[sys_audio__SFX_RIGHT] = *sys_audio__io[sys_audio__MUS_LEFT];
// Setup MUS_LEFT.
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 = 32;
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;
// Setup MUS_RIGHT.
*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.
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 = 32;
sys_audio__io[sys_audio__SFX_LEFT]->ioa_Cycles = 1;
sys_audio__io[sys_audio__SFX_LEFT]->ioa_Length = sys_audio__SFX_BUFFER_SIZE;
// Setup SFX_RIGHT.
*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)
{
// 07.
for (int i = 0; i < sys_audio__COUNT; i ++)
while (GetMsg(sys_audio__mp[i])) {};
if (sys_audio__audio_device_result == 0)
CloseDevice( (struct IORequest*)sys_audio__io[sys_audio__MUS_LEFT] );
// 06.
for (int i = 1; i < sys_audio__COUNT; i ++)
sys_audio__io[i] = NULL;
// 05.
if (sys_audio__io[sys_audio__MUS_LEFT])
{
FreeVec( sys_audio__io[sys_audio__MUS_LEFT] );
sys_audio__io[sys_audio__MUS_LEFT] = 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.
if (sys_audio__fast_buffer__sfx_mixed)
{
FreeVec( sys_audio__fast_buffer__sfx_mixed );
sys_audio__fast_buffer__sfx_mixed = NULL;
}
// 02.
sys_audio__chip_buffer__sfx[1] = NULL;
if (sys_audio__chip_buffer__sfx[0])
{
FreeVec( sys_audio__chip_buffer__sfx[0] );
sys_audio__chip_buffer__sfx[0] = NULL;
}
// 01.
sys_audio__chip_buffer__mus[1] = NULL;
if (sys_audio__chip_buffer__mus[0])
{
FreeVec( sys_audio__chip_buffer__mus[0] );
sys_audio__chip_buffer__mus[0] = NULL;
}
}
void sys_audio__audio_task__run(void)
{
// ----------------------------------------
// --- Init all elements for audio task ---
// ----------------------------------------
sys_audio__audio_task__result = sys_audio__audio_task__create();
if (sys_audio__audio_task__result == 0)
{
// Send the signal to main task, that initialization is finished and the result can be checked.
sys_audio__audio_task__destroy();
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);
}
// 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);
// -------------------------------------------
// --- Before entering the audio task loop ---
// -------------------------------------------
// Get all signal masks.
ULONG all_signal_masks = sys_audio__audio_task__signal_mask |
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];
// Prepare sfx swapping.
LONG sfx_chip_buffer_next = 0;
sys_audio__sfx_fast_buffer_offset_to_copy = 0;
// Trigger the first pair to playback with buffer 0.
// This is the first request that will trigger SFX swapping routine.
sys_audio__io[sys_audio__SFX_LEFT]->ioa_Data = sys_audio__chip_buffer__sfx[0];
sys_audio__io[sys_audio__SFX_RIGHT]->ioa_Data = sys_audio__chip_buffer__sfx[0];
BeginIO((struct IORequest*)sys_audio__io[sys_audio__SFX_LEFT]);
BeginIO((struct IORequest*)sys_audio__io[sys_audio__SFX_RIGHT]);
// Right away trigger next pair to playback buffer 1.
// This request will be queued and will start play right away after previous pair stops.
sys_audio__io[sys_audio__SFX_LEFT]->ioa_Data = sys_audio__chip_buffer__sfx[1];
sys_audio__io[sys_audio__SFX_RIGHT]->ioa_Data = sys_audio__chip_buffer__sfx[1];
BeginIO((struct IORequest*)sys_audio__io[sys_audio__SFX_LEFT]);
BeginIO((struct IORequest*)sys_audio__io[sys_audio__SFX_RIGHT]);
// Set the loop to active.
sys_audio__audio_task__loop = 1;
// ----------------------------
// --- Audio task main loop ---
// ----------------------------
while(sys_audio__audio_task__loop)
{
// ---------------------------------------------
// --- Wait until someone will send a signal ---
// --------------------------------------------
ULONG signals = Wait( all_signal_masks );
// ---------------------------------
// --- Getting a signal from MUS ---
// ---------------------------------
if ( (signals & sys_audio__mp_signal_mask[sys_audio__MUS_LEFT]) || (signals & sys_audio__mp_signal_mask[sys_audio__MUS_RIGHT]) )
{
if ( CheckIO( (struct IORequest*)sys_audio__io[sys_audio__MUS_LEFT] ) && CheckIO( (struct IORequest*)sys_audio__io[sys_audio__MUS_RIGHT] ) )
{
WaitIO( (struct IORequest*)sys_audio__io[sys_audio__MUS_LEFT] );
WaitIO( (struct IORequest*)sys_audio__io[sys_audio__MUS_RIGHT] );
GetMsg(sys_audio__mp[sys_audio__MUS_LEFT]);
GetMsg(sys_audio__mp[sys_audio__MUS_RIGHT]);
sys_audio__mus_chunks_to_copy = sys_audio__MUS_CHUNKS;
}
}
// ---------------------------------
// --- Getting a signal from SFX ---
// ---------------------------------
if ( (signals & sys_audio__mp_signal_mask[sys_audio__SFX_LEFT]) || (signals & sys_audio__mp_signal_mask[sys_audio__SFX_RIGHT]) )
{
if ( CheckIO( (struct IORequest*)sys_audio__io[sys_audio__SFX_LEFT] ) && CheckIO( (struct IORequest*)sys_audio__io[sys_audio__SFX_RIGHT] ) )
{
GetMsg(sys_audio__mp[sys_audio__SFX_LEFT]);
GetMsg(sys_audio__mp[sys_audio__SFX_RIGHT]);
WaitIO( (struct IORequest*)sys_audio__io[sys_audio__SFX_LEFT] );
WaitIO( (struct IORequest*)sys_audio__io[sys_audio__SFX_RIGHT] );
memcpy( sys_audio__chip_buffer__sfx[sfx_chip_buffer_next],
sys_audio__fast_buffer__sfx_mixed + sys_audio__sfx_fast_buffer_offset_to_copy,
sys_audio__SFX_BUFFER_SIZE);
LONG sfx_fast_buffer_offset_to_erase;
if (sys_audio__sfx_fast_buffer_offset_to_copy + sys_audio__SFX_BUFFER_SIZE < sys_audio__SFX_FAST_TOTAL_SIZE)
{
sfx_fast_buffer_offset_to_erase = sys_audio__sfx_fast_buffer_offset_to_copy;
sys_audio__sfx_fast_buffer_offset_to_copy += sys_audio__SFX_BUFFER_SIZE;
}
else
{
sys_audio__sfx_fast_buffer_offset_to_copy = 0;
sfx_fast_buffer_offset_to_erase = sys_audio__SFX_FAST_TOTAL_SIZE - sys_audio__SFX_BUFFER_SIZE;
}
// Already trigger next pair to play. It will be queued and will start right away as current stops.
sys_audio__io[sys_audio__SFX_LEFT]->ioa_Data = sys_audio__chip_buffer__sfx[sfx_chip_buffer_next];
sys_audio__io[sys_audio__SFX_RIGHT]->ioa_Data = sys_audio__chip_buffer__sfx[sfx_chip_buffer_next];
BeginIO((struct IORequest*)sys_audio__io[sys_audio__SFX_LEFT]);
BeginIO((struct IORequest*)sys_audio__io[sys_audio__SFX_RIGHT]);
// Swap buffer index.
sfx_chip_buffer_next ^= 1;
// Chunk that already has been copied to chip buffer should be erased,
// so we keep the mixing buffer clean for future mixing.
memset(sys_audio__fast_buffer__sfx_mixed + sfx_fast_buffer_offset_to_erase, 0, sys_audio__SFX_BUFFER_SIZE);
}
}
}
// ----------------
// --- Clean up ---
// ----------------
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);
}
// -----------------------------------
// --- Public function definitions ---
// -----------------------------------
int SYSTEM_audio__create(void)
{
// Prepare MUS swapping.
sys_audio__mus_chunks_to_copy = 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", 21, (APTR)sys_audio__audio_task__run, 4096*4);
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)
{
if (sys_audio__audio_task__result)
{
// Send signal to audio task to finish its audio main loop.
sys_audio__audio_task__loop = 0;
Signal(sys_audio__audio_task, sys_audio__audio_task__signal_mask);
// Now wait for signal from audio task.
// It will send signal when it finish cleaning up.
Wait(sys_audio__audio_task__signal_mask);
}
if (sys_audio__audio_task)
{
Forbid();
DeleteTask(sys_audio__audio_task);
Permit();
sys_audio__audio_task = NULL;
}
FreeSignal(sys_audio__audio_task__signal);
sys_audio__main_task = NULL;
}
void SYSTEM_audio__run(void)
{
if (sys_audio__mus_chunks_to_copy > 0)
{
LONG new_offset = sys_audio__mus_offset + sys_audio__MUS_CHUNK_SIZE;
// Test against the music end. The new offset cant exceed the music size.
if (new_offset < sys_audio__mus_size)
{
// Its safe to copy another chunk from the current music offset.
memcpy(sys_audio__mus_chip_buffer_to_fill__ptr, (sys_audio__mus_data + sys_audio__mus_offset), sys_audio__MUS_CHUNK_SIZE);
sys_audio__mus_offset += sys_audio__MUS_CHUNK_SIZE;
}
else
{
// We can't copy one whole chunk. We must split it into two parts.
// First part - from the current offset to the end of music data buffer.
LONG first_part_size = sys_audio__mus_size - sys_audio__mus_offset;
memcpy( sys_audio__mus_chip_buffer_to_fill__ptr, (sys_audio__mus_data + sys_audio__mus_offset), first_part_size );
// Second part - from the start of music data buffer.
LONG second_part_size = sys_audio__MUS_CHUNK_SIZE - first_part_size;
memcpy( (sys_audio__mus_chip_buffer_to_fill__ptr + first_part_size), sys_audio__mus_data, second_part_size );
sys_audio__mus_offset = second_part_size;
}
sys_audio__mus_chip_buffer_to_fill__ptr += sys_audio__MUS_CHUNK_SIZE;
sys_audio__mus_chunks_to_copy--;
if (sys_audio__mus_chunks_to_copy == 0)
{
sys_audio__io[sys_audio__MUS_LEFT]->ioa_Data = sys_audio__chip_buffer__mus[sys_audio__mus_chip_buffer_to_fill__index];
sys_audio__io[sys_audio__MUS_RIGHT]->ioa_Data = sys_audio__chip_buffer__mus[sys_audio__mus_chip_buffer_to_fill__index];
BeginIO((struct IORequest*)sys_audio__io[sys_audio__MUS_LEFT]);
BeginIO((struct IORequest*)sys_audio__io[sys_audio__MUS_RIGHT]);
sys_audio__mus_chip_buffer_to_fill__index ^= 1;
sys_audio__mus_chip_buffer_to_fill__ptr = sys_audio__chip_buffer__mus[sys_audio__mus_chip_buffer_to_fill__index];
}
}
}
void SYSTEM_audio__mus_start(char* _data, int _size)
{
sys_audio__mus_data = _data;
sys_audio__mus_size = _size;
sys_audio__mus_chip_buffer_to_fill__index = 0;
sys_audio__mus_chip_buffer_to_fill__ptr = sys_audio__chip_buffer__mus[sys_audio__mus_chip_buffer_to_fill__index];
sys_audio__mus_chunks_to_copy = 0;
// Fill up two chip buffers with initial data.
memcpy(sys_audio__chip_buffer__mus[0], sys_audio__mus_data, sys_audio__MUS_CHIP_TOTAL_SIZE);
sys_audio__mus_offset = sys_audio__MUS_CHIP_TOTAL_SIZE;
// Trigger music audio request.
sys_audio__io[sys_audio__MUS_LEFT]->ioa_Data = sys_audio__chip_buffer__mus[0];
sys_audio__io[sys_audio__MUS_RIGHT]->ioa_Data = sys_audio__chip_buffer__mus[0];
BeginIO((struct IORequest*)sys_audio__io[sys_audio__MUS_LEFT]);
BeginIO((struct IORequest*)sys_audio__io[sys_audio__MUS_RIGHT]);
sys_audio__io[sys_audio__MUS_LEFT]->ioa_Data = sys_audio__chip_buffer__mus[1];
sys_audio__io[sys_audio__MUS_RIGHT]->ioa_Data = sys_audio__chip_buffer__mus[1];
BeginIO((struct IORequest*)sys_audio__io[sys_audio__MUS_LEFT]);
BeginIO((struct IORequest*)sys_audio__io[sys_audio__MUS_RIGHT]);
}
void SYSTEM_audio__sfx_start(char* _data, int _size)
{
volatile LONG chunk_offset = sys_audio__sfx_fast_buffer_offset_to_copy;
LONG size_remain = (sys_audio__SFX_FAST_TOTAL_SIZE - chunk_offset);
LONG difference = size_remain - _size;
if (difference > 0)
{
// Will fit.
BYTE *ptr = sys_audio__fast_buffer__sfx_mixed + chunk_offset;
// Mix to the end of sample. We wont exceed the fast buffer.
for (int i = 0; i < _size; i++)
ptr[i] += _data[i];
}
else
{
// Won't fit, lets split.
BYTE *ptr = sys_audio__fast_buffer__sfx_mixed + chunk_offset;
// Mix to the end of fast buffer.
for (int i = 0; i < size_remain; i++)
ptr[i] += _data[i];
// Mix the rest from the start of fast buffer.
for (int i = 0; i < -difference; i++)
sys_audio__fast_buffer__sfx_mixed[i] += _data[size_remain + i];
}
}@mateusz_s, post #62
@mateusz_s, post #64
@mateusz_s, post #64
@Don_Adan, post #67
Na C sie nie znam, ale zdaje sie ze przesuwasz zsumowane 2 probki w prawo o 1 bit, czyli lsr.l
a powinno byc raczej rorx.l uzyte, choc moze kompilator tak to robi.
@Krashan, post #68
Teoretycznie to, co co wstawia kompilator od lewej przy przesuwaniu liczby ze znakiem w prawo jest... niezdefiniowane.
@Krashan, post #68
@Don_Adan, post #70
MOVE.B (a0)+,d0 ADD.B (a1)+,d0 ROXR.B #1,d0
@Don_Adan, post #70
Mixer4V movem.l D0-D2/A0-A6,-(SP) movem.l MixPtr,A0-A4 move.w MixCtr,D2 MixIt move.l (A1)+,D0 ; pierwszy SFX dane add.l (A2)+,D0 ; drugi SFX dane roxr.l #1,D0 ; zmiksowany 1 i 2 move.l (A3)+,D1 ; trzeci SFX dane add.l (A4)+,D1 ; czwarty SFX dane roxr.l #1,D1; zmiksowany 3 i 4 add.l D1,D0 roxr.l #1,D0 zmiksowany 1,2,3 i 4 move.l D0,(A0)+ ; zapis do bufora, ktory ma byc odgrywany jako nastepny dbf D2,MixIt lea EmptyBuffy,A5 cmp.l A0,A5 bne.b BuffyOk lea MixBuffy1,A0 ; ustawienie pierwszego bufora jako nastepnego targetu BuffyOk moveq #1,D0 lea SFXCtr1,A6 subq.w #1,(A6)+ bne.b NoEnd1 move.w D0,-2(A6) move.l A5,A1 NoEnd1 subq.w #1,(A6)+ bne.b NoEnd2 move.w D0,-2(A6) move.l A5,A2 NoEnd2 subq.w #1,(A6)+ bne.b NoEnd3 move.w D0,-2(A6) move.l A5,A3 NoEnd3 subq.w #1,(A6)+ bne.b NoEnd4 move.w D0,-2(A6) move.l A5,A4 NoEnd4 movem.l A0-A4,MixPtr ; ustawienie wszystkich ptr movem.l (SP)+,D0-D2/A0-A6 rts MixPtr MixBuffy1 SFXPtr1 EmptyBuffy SFXPtr2 EmptyBuffy SFXPtr3 EmptyBuffy SFXPtr4 EmptyBuffy SFXCtr1 dc.w 1 ; licznik SFX1, czyli ile razy w samplu1 miesci sie sys_audio__SFX_BUFFER_SIZE plus 1 SFXCtr2 dc.w 1 ; licznik SFX2, czyli ile razy w samplu2 miesci sie sys_audio__SFX_BUFFER_SIZE plus 1 SFXCtr3 dc.w 1 ; licznik SFX3, czyli ile razy w samplu3 miesci sie sys_audio__SFX_BUFFER_SIZE plus 1 SFXCtr4 dc.w 1 ; licznik SFX4, czyli ile razy w samplu4 miesci sie sys_audio__SFX_BUFFER_SIZE plus 1 MixCtr dc.w sys_audio__SFX_BUFFER_SIZE/4-1 ; licznik dla petli mixera MixBuffy1 ds.b sys_audio__SFX_BUFFER_SIZE MixBuffy2 ds.b sys_audio__SFX_BUFFER_SIZE EmptyBuffy ds.b sys_audio__SFX_BUFFER_SIZE