kategoria: ANSI C
[#61] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@mateusz_s, post #59

Możesz sobie zaoszczędzić otwierania graphics.library w tym tasku.
gfxbase_clock = CLK_PAL;
if (((struct ExecBase*)SysBase)->VBlankFrequency == 60) gfxbase_clock = CLK_NTSC;
2
[#62] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@Krashan, post #61

O ciekawe, dzięki..
[#63] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@mateusz_s, post #62

Ufff.. cały tydzień jeszcze nad tym siedziałem.. ale zrobiłem OKOKOK


Zajebiscie działa bez 'pypnięć' i mini-trzasków pomiędzy zmianą buforów.
Długo testowałem i nie zauważyłem żadnych asynchronów, nie łapie zwiechy po zamknięciu
ani nie widac wycieków pamieci. Monitor CPU IDLE może ledwo drgnie. Więc jest chyba git.


Jedyna rzecz która się pokazała podczas testowania w grze to trzaski przy mixowaniu większej ilości głosów na raz.
Bo na ten moment tylko sumuje próbki. Więc byc może trzeba będzie wprowadzić jakieś przytłumienie.
Nie jestem pewien, ale sama próbka tez ma znacznie. Tzn. jak jest przygotowana. Bo jedna ładnie się miksowała
a druga totalnie skrzeczała. Więc przy dobrym przygotowaniu sampli powinno trochę pomóc.
Możliwe że trzeba będzie też zwiększyć bufory sfx z 2 do 3, żeby więcej zapasu było. ale tez lag się zwiększy.


Ale z grubsza tak to chyba zostawię.
Żeby mixer nie zamulał gry musi miec krótkie próbki,
i może jakiś limit max. dziweków naraz np. 4.







A teraz, co było źle w poprzednim kodzie:

Poprzedni kod który tu wkleiłem działał sobie OK pod WinUAE.
Przy czym pod 020 było OK a pod 040 słychać było 'pypcie' zarówno przy muzyce jak i przy mixerze sfx.
No ale nic odpalam to na A1200.. i totalna kaszana nic nie działało wszystko się rozlazło.

Sam juz nie wiem co było źle, być może nawet coś z buforami w chip.
No ale niby to połatałem i było git. Ale zarówno przy muzyce jak i przy sfx słyszałem 'pypcie'
taki mini-trzaski.

Dziwna sprawa bo pierwszy streaming muzyki z fast do chip który robiłem już jakiś czas temu był OK.

No i się okazało, że po prostu trzeba wysłać kolejny BeginIO jeszcze jak aktualny gra tak żeby się skolejkował
i była zachowana ciągłość. OK Jeśli wyślę kolejny BeginIO w momencie jak skończy się aktualny to będą trzaski.
Zrezygnowałem też zupełnie z CMD_START i STOP.

W przypadku strimowania muzyki z fast, kolejny BeginIO wysyłam juz w momencie gdy kolejny bufor jest
załadowany nowym kawałkiem. BeginIO sie kolejkuje i odpala gdy skończy. No i podobnie zrobiłem przy sfx mixerze.
Czyli zawsze musi czekac w kolejce kolejny BeginIO z kolejnym buforem.

Wklejam cały kod, może się komuś przyda
jakby walczył z konfiguracją IO bo chyba nad tym najwiecej zeszło xDD
zeby to zainicjowac a potem zwolnic zeby sie nic nie zawieszało i zwolniło całą pamięć.


// 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];
    }
}


Ostatnia aktualizacja: 26.10.2025 19:38:03 przez mateusz_s
7
[#64] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@mateusz_s, post #62

Yes.. OK

Udało się poprawić sposób mixowania, dzięki temu nawet przy dużej liczbie nakładających się
dźwięków lub po prostu głośniejszych, nie ma żadnych trzasków przesterowych.

Na prostej zasadzie: ((int)sample1 + (int)sample2) >> 1.
Tu kluczowe było sumować to w 32bitach. Nie w 8bit jak same próbki.

Myślałem, że będzie gorzej ale w maksymalnym peaku zżera góra 3 fps-y ;p
wiec nie jest tak źle. Zależy od długości trwania dźwięku i ilości tych dzwięków.
Wiec wystarczy trzymać sie krotkich próbek i nie za dużo ich naraz puszczać.

Dorzuciłem tez limit, że na 1 klatkę max jeden sfx może być odpalony.

Ostatni problem jaki się pojawił, to jakiś distortion/skrzek, który pojawia się gdzieś
w buforze roboczym w fast. Dziwne bo po przekopiowaniu probki do chip, jest ona czyszczona
z fast od razu. A zachowuje ise jakby nie była. Na sucho (w osobym programie) nie ma takiego problemu.
Tylko gdy podepne ten mixer pod grę.

Słychać to w kilku momentach. Nie wiem skąd się to bierze. Jeszcez bede szukał potem.

Ale generalnie jestem zadowolony z efektu końcowego OKOKOK

2
[#65] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@mateusz_s, post #64

edit:
jakims cudem renderowanie playera odpowiada za ten trzask, ktory pozostaje w buforze xDD
tego sie nie spodziewałem, moze jakiś wyciek jest.. ale ciesze sie ze to namierzyłem OK

edit:
tak.. renderowanie pocisków, pewnie wyłażą za bufor pomysł






Ostatnia aktualizacja: 27.10.2025 21:14:04 przez mateusz_s
[#66] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@mateusz_s, post #65

Ta giera to mój typ nr 1 !
[#67] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@mateusz_s, post #64

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.
A co do dziwnych dzwiekow, to dodaj na koncu kazdego sampla 2 puste buffory czyli 768x2 bajty.
Ewentualnie allokuj na sampel w fast clearedmem, buffer = sampel size + 768 bajty.
Nie powinno byc wtedy dziwnych dzwiekow.
Przynajmniej tak mi sie wydaje
[#68] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

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

To jedna z zawiłości języka C. Teoretycznie to, co co wstawia kompilator od lewej przy przesuwaniu liczby ze znakiem w prawo jest... niezdefiniowane. Pochodzi to jeszcze z zamierzchłych czasów, gdy korzystanie z kodowania U2 dla liczb ujemnych nie było oczywistą oczywistością.

Wszystkie znane mi kompilatory C na Amigę używają LSR przy zmiennych bez znaku i ASR przy zmiennych ze znakiem. Czyli tak jak się w tym przypadku spodziewamy. Natomiast po co byś chciał użyć ROXR, to nie wiem...

Przy okazji, odnosząc się do postu #64, sumowanie sampli lepiej robić na 16 bitach, niż 32. Szesnaście z powodzeniem wystarczy, a będzie szybciej. Zwłaszcza na 68000.
3
[#69] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@Krashan, post #68

Teoretycznie to, co co wstawia kompilator od lewej przy przesuwaniu liczby ze znakiem w prawo jest... niezdefiniowane.

Mylisz sie, wynik tej operacji w standardzie c99 jest "implementaion-defined". "undefined" jest wynik przesuniecia w lewo ujemnej liczby oraz przesuniecia o liczbe bitow wieksza od liczby bitow typu integer lub ujemna.

Ostatnia aktualizacja: 31.10.2025 00:25:21 przez docent
1
[#70] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@Krashan, post #68

Dawno nie kodowalem, ale z tego co pamietam to jak np. D0=$FFFFFFFF a D1=$FFFFFFFF, to po dodaniu probek bedzie $fffffffe.
Po przesunieciu o 1 bit i uzyciu roxr.l bedzie $FFFFFFFF, a po uzyciu lsr.l $7FFFFFFF.

Oczywiscie jezeli input/output bedzie 16 bitowy, a dodawanie i przesuniecie 32 bitowe, to wynik bedzie prawidlowy.

A po co roxr.l zamiast lsr.l?
W przypadku miksowania tylko 2 probek, to bedzie ponad 2 razy szybciej niz w przypadku 16 bitowego miksowania.
To jest gra i raczej ma byc szybciej niz wolniej.
Wedlug mnie powinny byc 2 procedury miksujace, jedna dla miksowania jednego i drugiego SFX, a druga dla miksowania trzech i czterech SFX.
Ale to jest wybor autora gry.
[#71] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@Don_Adan, post #70

Trochę się musiałem nad tym skupić, żeby to rozkminić, ale tak, jeżeli sumujemy dwie próbki, to można znacznik X wykorzystać jako ten brakujący dodatkowy bit i potem go "wciągnąć" za pomocą ROXR. Czyli o ile dobrze zrozumiałem, to by to wyglądało tak. Niech a0 wskazuje na jeden bufor, a1 na drugi, to wtedy
MOVE.B  (a0)+,d0
ADD.B   (a1)+,d0
ROXR.B  #1,d0
[#72] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@Krashan, post #71

Tak. Uzywany do obslugi 33 bitu dla 32 bitowych rejestrow.
Albo jak w tym przypadku do obslugi 9 bitu przy 8 bitowych instrukcjach.
Zdaje sie, ze 8 bitowe procesory cos takiego tez mialy.
[#73] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@Don_Adan, post #70

Choc chyba i dla 3-4 SFX sampli, mozna by uzyc i byloby szybsze niz dla miksowania 16 bitow.


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
[#74] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@Don_Adan, post #73

.

Ostatnia aktualizacja: 01.11.2025 17:17:25 przez Krashan
[#75] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@mateusz_s, post #63

Sorry, za off top.
Czy mozesz zamiescic, prosty przyklad kodu dla gry RTG i AGA ?

"simple RTG example"
Na stronie www.PPA.pl, podobnie jak na wielu innych stronach internetowych, wykorzystywane są tzw. cookies (ciasteczka). Służą ona m.in. do tego, aby zalogować się na swoje konto, czy brać udział w ankietach. Ze względu na nowe regulacje prawne jesteśmy zobowiązani do poinformowania Cię o tym w wyraźniejszy niż dotychczas sposób. Dalsze korzystanie z naszej strony bez zmiany ustawień przeglądarki internetowej będzie oznaczać, że zgadzasz się na ich wykorzystywanie.
OK, rozumiem