kategoria: ANSI C
[#1] [C] Kilka pytań odnośnie używania muzyki i dzwięków..
Cześć,
jak w tytule, miałbym kilka pytań odnośnie obsługi dzwieków,
może coś podpowiecie, bo wcześniej nie specjalnie z tego korzystałem..

1. Czy ten format dla dzwieku lub muzyki będzie ok?
W Audacity udało mi się skonwertować dzwięk do 8bit MONO, 22050Hz i zapisać jako IFF/SVX8,
pod workbenchem w multiview się odgrywa...

2. Jak wczytać ten plik w C do pamięci?
Czy musze sam ogarnąć format 8SVX czy może są dostepne juz gotowe funkcje w API?
Rozumiem że plik musi sie zmiescić w CHIP RAM.

3. Jak potem odtworzyć ten dzwięk z pamięci? Mam uzyc "audio.device"
i struct IOAudio *audioIO? Generalnie chce pisać "po bożemu" systemowo.
chyba że inny sposób jest wydajniejszy?

4. Amiga ma 2 kanały lewe i 2 kanały prawe. Jak to jest w róznych grach, np. przy wystrzale, wybuchu itp?
dane dzwiek leci tylko z jednego kanału? Czy w ramach "stereo" puszcza się ten sam dzwiek równocześnie z lewego i prawego - ale to chyba bez sensu bo nam zostaje mniej kanałów do działania..

5. Moim docelowym sprzętem są CPU 040+ Zastanawiam się jak uzyskać dobry balans między ciekawa muzyką, a efektami dzwiękowymi bez zagłuszania dzwięków gdy braknie kanału.

a) jeden sposób to mieć muzykę na max 3 kanałach i 4 kanał zostawić na efekty dzwiekowe - ale to bedzie lipa

b) drugi sposób to miksować w czasie rzeczywistym dzwieki zeby sie zmieścic w 4 kanałach - ale to dodatowe obciążenie cpu

c) trzeci sposób, który mi wpadł do głowy, to uzyć zmiksowanej już muzyki, która odgrywana by była najednym kanale, a na 3 pozostałych kanałach były by efekty dzwiękowe. Tutaj minusem byłaby duza wilkośc pliku z muzyką. Ale byc może dałoby sie tak zrobić żeby kopiować z FAST do CHIP muzyke po kawałkach. Np. mamy w pamięci dwa bloki po 400kb, gdy muzyka zaczyna odgrywac się z drugiego bloku kopiuje kolejna cześć do pierwszego bloku, potem kolejna do drugiego itp.. Tylko nie wiem co na to CHIP, bo program korzysta też z C2P w każdej klatce. Albo mniejszymi fragmentami kopwać po 64kb itp..

wiec sie zastanawiam miedzy b) i c) chyba że są jeszcez jakieś inne metody..
[wyróżniony] [#2] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@mateusz_s, post #1

Format dźwięku jest OK. Przy odtwarzaniu przez Paulę zostanie wybrana częstotliwość możliwie najbliższa 22050 Hz, chociaż może się trochę różnić.
Czy musze sam ogarnąć format 8SVX czy może są dostepne juz gotowe funkcje w API?
Są gotowe, zainteresuj się datatypami i datatypes.library. Wtedy w ogóle nie trzeba zajmować się ani zdekodowaniem formatu 8SVX, ani nawet audio.device, po prostu masz metody PLAY i STOP. Możesz też ograniczyć użycie datatypów do załadowania dźwięku, a potem użyć AHI (patrz niżej).
Moim docelowym sprzętem są CPU 040+ Zastanawiam się jak uzyskać dobry balans między ciekawa muzyką, a efektami dzwiękowymi bez zagłuszania dzwięków gdy braknie kanału.
Przy takim docelowym procesorze możesz użyć systemu AHI (Audio Hardware Interface), gdzie masz dowolną (w miarę mocy procesora) ilość kanałów miksowanych programowo.
3
[wyróżniony] [#3] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@mateusz_s, post #1

Mozesz uzyc tego.
Wtedy masz 3 kanaly na muzyke i 4 kanaly na SFX.

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

@Krashan, post #2

Dzięki, przykulam datatypy..

Czy podczas korzystania z AHI mogę mieć większy plik muzyczny w FAST RAM,
a AHI samo to będzie kopiować do CHIP?
[#5] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@Don_Adan, post #3

Dzięki, to też ciekawe jest.. taki gotowy mixer..
[#6] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@mateusz_s, post #4

Czy podczas korzystania z AHI mogę mieć większy plik muzyczny w FAST RAM, a AHI samo to będzie kopiować do CHIP?
Tak.
1
[#7] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@Krashan, post #2

Hej,
chciałem spróbować zrobić proste buforowanie z FAST RAM do CHIP RAM,
małymi kawałkami np. po 768 bajtów, żeby nie obciążyć zbyt CHIP RAMU, ponieważ
korzystam również z C2P który żyłuje chip.

Zastanawiam się tylko jak wykryć w jakim miejscu jest aktualnie odgrywany dzwięk,
czy zbliża się do końca bufora? Moge jakos zwrócic pozycję? Czy to timerem zrobić, zakładając
ze próbka trwa np. 1 sekunde.

Potem chciałem też sprawdzić jaki bedzie efekt, jesli na lewym kanale puszczę lewą sciezke muzyki
a na prawym prawą, żeby osiągnąc jakiś efekt stereo..

nie wiem czy nie przekombinowuje..
ale nie chciałem żeby uzytkownik musiał dodatkowo mieć zainstalowane AHI,
no i chciałem skorzystać z jakiś zwykłych dostępnych utworów .wav których jest dużo,
niż szukać jakis trakerów..
[wyróżniony] [#8] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@mateusz_s, post #7

Zastanawiam się tylko jak wykryć w jakim miejscu jest aktualnie odgrywany dzwięk,
czy zbliża się do końca bufora? Moge jakos zwrócic pozycję? Czy to timerem zrobić, zakładając
ze próbka trwa np. 1 sekunde.

Jeżeli odgrywasz dźwięk przez audio.device, to wystarczy że wyślesz (asynchronicznie) polecenie ADCMD_WAITCYCLE. Zostaniesz wtedy poinformowany o końcu odtwarzania jednego przebiegu sampla za pomocą wiadomości.

Drugim sposobem jest wysłanie polecenia ADCMD_FINISH z włączoną flagą ADIOF_SYNCCYCLE. Sampel zostanie zakończony dopiero gdy zostanie w całości odegrany i niezwłocznie zacznie odgrywać następny sampel.

Ostatnia aktualizacja: 20.11.2024 11:42:39 przez Hexmage960
1
[#9] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@Hexmage960, post #8

super, dzięki.. masz to w małym palcu widzę
[#10] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@Hexmage960, post #8

No nie wiem, on chce odgrywac sample uzywajac malego bufora z chipu.
Jak bedzie w ten sposob odgrywal za pomoca audio.device to raczej bedzie mial trzaski, tak mi sie przynajmniej wydaje.
Chyba, ze zwiekszy wielkosc bufora w chipie, albo sample beda dosc niskiej jakosci.
Chyba zwykle uzywa sie do takich rzeczy audio interrupt (level 5), wtedy na pewno nie bedzie zadnych trzaskow.
[#11] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@mateusz_s, post #7

no i chciałem skorzystać z jakiś zwykłych dostępnych utworów .wav których jest dużo

Dorobisz jeszcze obsługę wav w programie czy będzie konwertował na inny format. ?
A jakie częstotliwości dzwieku przewidujesz ?
[#12] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@Norbert, post #11

konwertuje w Audacity do formatu RAW (bez nagłowka same dane)
8bit - częstotliwość od 8000 od 22050 w zależności od wydajności..

chce żeby leciało to równocześnie na lewym i prawym kanale..
i dwa kanały by mi zostały na efekty dzwiekowe

Ostatnia aktualizacja: 20.11.2024 12:54:21 przez mateusz_s
[#13] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@Hexmage960, post #8

Jeszcze nawiązując do Twojego przykładu.
Żeby otrzymać informację zwrotną od audio device o zakończeniu odgrywania to musiałbym uzyc Wait(..)
Wiec wtedy moja główna pętla programu by się zastopowała bo czekałaby na komunikat. Więc chyba lepiej CheckIO(..) dać w głównej pętli.
[wyróżniony] [#14] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@mateusz_s, post #13

Jeszcze nawiązując do Twojego przykładu.
Żeby otrzymać informację zwrotną od audio device o zakończeniu odgrywania to musiałbym uzyc Wait(..)
Wiec wtedy moja główna pętla programu by się zastopowała bo czekałaby na komunikat. Więc chyba lepiej CheckIO(..) dać w głównej pętli.

Jeżeli nie używasz Wait() w pętli głównej, to myślę, że zamiast CheckIO() bezpieczniej użyć funkcji SetSignal() do odczytania stanu sygnałów.

Następująca konstrukcja:

ULONG signalSet = SetSignal(0L, 0L);

Zwróci Ci aktualny stan sygnałów. Teraz można reagować na wybrane sygnały tak samo jak w przypadku Wait(), np.:

if (signalSet & (1L << audioMsgPort->mp_SigBit))
{
   /* Obsługa sygnału */
}

Następnie żeby wyczyścić obsłużone sygnały podajesz maskę tych sygnałów jako drugi argument tej funkcji, np.:

SetSignal(0L, 1L << audioMsgPort->mp_SigBit);

Pamiętaj, że wyczyszczenie sygnału w systemie może nie wystarczyć i trzeba jeszcze pobrać wiadomość z portu za pomocą GetMsg() lub WaitIO() - (to tak jako ogólna zasada).

Przy czym wydaje mi się, że jeżeli nie masz jakichś sytuacji gdy musisz coś policzyć poza synchronizacją, to można stosować Wait(). W przypadku animacji ja używam przerwań. W amiga.lib jest wygodna funkcja AddTOF() która doda do systemu własną obsługę, ale jej nie stosowałem.

Wracając do audio.device, to z tego co wiem, zapis dźwięków za pomocą CMD_WRITE się kolejkuje z zasady, więc pewnie też wystarczy zrobić podwójnie buforowany zapis (puszczasz dwa dźwięki, następnie czekasz na pierwszy i podmieniasz). W dokumentacji powinien być pełen przykład. Znajdziesz np. na Amiga Developer CD v2.1.

Ostatnia aktualizacja: 20.11.2024 23:54:58 przez Hexmage960
1
[#15] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@mateusz_s, post #13

Wiec wtedy moja główna pętla programu by się zastopowała bo czekałaby na komunikat.

Nie wiem jak bardzo 'os friendly" piszesz, według mnie taka jest idea, że jest Wait i sprawdzanie sygnałów. Dzięki temu inne programy też mogą działać a i Twój nie pożera CPU na lepszych konfiguracjach.
1
[wyróżniony] [#16] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@mateusz_s, post #7

Zastanawiam się tylko jak wykryć w jakim miejscu jest aktualnie odgrywany dzwięk,
czy zbliża się do końca bufora? Moge jakos zwrócic pozycję? Czy to timerem zrobić, zakładając
ze próbka trwa np. 1 sekunde.
Nie da się i nie możesz zwrócić pozycji. Możesz to zrobić timerem, ale zazwyczaj nie ma takiej potrzeby. Doublebuffering organizujesz tak, że najpierw wypełniasz oba bufory, potem puszczasz pierwszy i drugi z synchrem na pierwszy (tak jak opisał Hexmage). Gdy pierwszy się odegra (IORequest "wróci"), wypełniasz jego bufor dźwiękiem i od razu wysyłasz request z synchrem na drugi. Gdy wróci drugi, wypełniasz go i od razu wysyłasz z synchrem na pierwszy. I tak dalej. Synchronizacja jest precyzyjna, efekt końcowy jest dokładnie taki sam, jakbyś to wszystko puścił z jednego długiego bufora.
Potem chciałem też sprawdzić jaki bedzie efekt, jesli na lewym kanale puszczę lewą sciezke muzyki
a na prawym prawą, żeby osiągnąc jakiś efekt stereo...
Audio.device posiada możliwość puszczenia kilku kanałów jednocześnie, precyzyjnie co do próbki. Wtedy jeżeli na dwóch kanałach Pauli puścisz dwa kanały stereo, masz stereo. Oczywiście musisz wybrać kanały Pauli odpowiednio skierowane do L i R stereo.
2
[wyróżniony] [#17] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@mateusz_s, post #13

Żeby otrzymać informację zwrotną od audio device o zakończeniu odgrywania to musiałbym uzyc Wait(..)
W typowej pętli głównej programu i tak masz Wait() więc wystarczy dodać sygnał msgportu od requestów audio do maski. Chyba że timing programu masz sterowany bezpośrednio przerwaniem.
1
[#18] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@Krashan, post #17

dzieki za pomoc i odpowiedzi.. bede to probował implementować..
[#19] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@mateusz_s, post #18

Hej,
udało mi się zrobić to buforowanie, uzyłem muzyki o czestotliwości 22050 Hz
(choc nie zauwazyłem wiekszej róznicy pomiedzy tą wartośćia a 16000 - ale niech bedzie)
i dodatkowo WYŁACZYŁEM filtr audio - i efekt jest naprawdę bardzo dobry, z wlaczonym filtrem audio było zbyt przytłumione...

Mam tylko jeden problem jeszcze, nad którym poległem a mianowicie alokacja kanałów
- coś mi nie działa jak należy. Nie udało mi się zalokować wszystkich 4 kanałów.
Docelowo chcę aby muzyka szła na jednym lewym i jednym prawym,
a drugi prawy i drugi lewy był na efekty dzwiekowe - wiec potrzebuje 4.
Tu pojawia się pytanie jak puścić muzykę równoczesnie z lewego i prawego kanału ? to z automatu powinno iść?
A potem jak wyzwolic dzwieki na pozostałym lewym i prawym.

Podrzucam kod, który mam teraz, na razie jest jaki jest i brakuje testu gdy dochodzimy do końca,
ale wazne działa tak jak chciałem.

struct IOAudio *AudioIO; 
struct MsgPort *Audio_port;  

struct IOAudio *AudioIO_2;   
struct MsgPort *Audio_port_2;  

ULONG           device;

BYTE *chip_mem_1, *chip_mem_2;  // bloki w pamieci chip
BYTE* fast_audio;  // tu w fast ram lezy caly plik

#define CHIP_SIZE   23040   // cały jeden bufor w chip (bedzie podzielony na 2)
#define CHUNK_SIZE  768   // tyle kopiuje bajtów na w kazdej klatce
#define PARTS       ( (CHIP_SIZE/2) / CHUNK_SIZE )   // 15 - tyle razy łacznie musze przekopiować 768 

// init
{
 ...
   chip_mem_1 = (BYTE*)AllocMem( CHIP_SIZE, MEMF_CHIP | MEMF_CLEAR);
   chip_mem_2 =  chip_mem_1 + CHIP_SIZE/2;

  // uzupelniam pierwszy raz obydwa bufory chip
  memcpy(chip_mem_1, fast_audio, CHIP_SIZE/2);
  memcpy(chip_mem_2, fast_audio + CHIP_SIZE/2, CHIP_SIZE/2);


    AudioIO = (struct IOAudio *)AllocMem( sizeof(struct IOAudio),MEMF_PUBLIC | MEMF_CLEAR);
    Audio_port =  CreatePort(0,0);

     AudioIO_2 = (struct IOAudio *)AllocMem( sizeof(struct IOAudio),MEMF_PUBLIC | MEMF_CLEAR);
     Audio_port_2 =  CreatePort(0,0);

AudioIO->ioa_Request.io_Message.mn_ReplyPort   = Audio_port;
AudioIO->ioa_Request.io_Message.mn_Node.ln_Pri = 127;
AudioIO->ioa_Request.io_Command                = ADCMD_ALLOCATE;
AudioIO->ioa_Request.io_Flags                  = ADIOF_NOWAIT;
AudioIO->ioa_AllocKey                          = 0;
AudioIO->ioa_Data                              = (whichannel);
AudioIO->ioa_Length                            = sizeof(whichannel);


 device = OpenDevice(AUDIONAME,0L, (struct IORequest *) AudioIO ,0L);

  // sprawdzam jakie kanaly zostaly zaalokowane - otrzymuje tutaj - 4 - w powinienem chyba 15.
  SYS_CONSOLE__write("\nDEVICES ALLOCATED: %d", AudioIO->ioa_Request.io_Unit->unit_flags & 0x0F);

*AudioIO_2 = *AudioIO; 
AudioIO->ioa_Request.io_Message.mn_ReplyPort =Audio_port;
AudioIO_2->ioa_Request.io_Message.mn_ReplyPort =Audio_port_2;


AudioIO->ioa_Request.io_Command          =CMD_WRITE;
AudioIO->ioa_Request.io_Flags            =ADIOF_PERVOL;
AudioIO->ioa_Data                        =(BYTE *)chip_mem_1;
AudioIO->ioa_Length                      =CHIP_SIZE/2;
AudioIO->ioa_Period                      = (UWORD)(clock / 22050);
AudioIO->ioa_Volume                      =64;
AudioIO->ioa_Cycles                      =1;

AudioIO_2->ioa_Request.io_Command          =CMD_WRITE;
AudioIO_2->ioa_Request.io_Flags            =ADIOF_PERVOL;
AudioIO_2->ioa_Data                        =(BYTE *)chip_mem_2;
AudioIO_2->ioa_Length                      =CHIP_SIZE/2;
AudioIO_2->ioa_Period                      = (UWORD)(clock / 22050);
AudioIO_2->ioa_Volume                      =64;
AudioIO_2->ioa_Cycles                      = 1;

...
}

// pętla głowna
{
...

   // uruchamiam obie probki z chip które się kolejkują.
   BeginIO((struct IORequest *) AudioIO );
   BeginIO((struct IORequest *) AudioIO_2 );

   // wylaczam filtr audio
   *((char *)0x0bfe001)|=0x02;

int start_copy_1 = 0;
int parts_copied_1 = 0;
int start_copy_2 = 0;
int parts_copied_2 = 0;
int offset = CHIP_SIZE;

BYTE*  chip_1_ptr = chip_mem_1;
BYTE*  chip_2_ptr = chip_mem_2;
BYTE* fast_ptr = fast_audio+CHIP_SIZE;

  while (E_io__prefs.is_loop)
  {
           // message loop okna
	    if(SetSignal(0L, signal_mask) & signal_mask)
	    {
		    struct IntuiMessage	*imsg;

                     while( imsg = (struct IntuiMessage *)GetMsg(SYS__window->UserPort) )
                     {
                          switch (imsg->Class)
                         {
                               ..
                          }
                          ReplyMsg((struct Message *)imsg);
                       }       
	    }  


       /// BUFOROWANIE z FAST DO CHIP

       if ( CheckIO((struct IORequest*)AudioIO) )
       {
             WaitIO( (struct IORequest*)AudioIO ) ;
             start_copy_1 = 1;
        }
     
        if (start_copy_1)
       {
           memcpy(chip_1_ptr, fast_ptr, CHUNK_SIZE);
           fast_ptr += CHUNK_SIZE;
           chip_1_ptr += CHUNK_SIZE;
           parts_copied_1++;

            if (parts_copied_1 >= PARTS) 
           {
               parts_copied_1 = 0;
               start_copy_1 = 0;
                chip_1_ptr = chip_mem_1;
                BeginIO((struct IORequest *) AudioIO );
           }
        }

        if ( CheckIO((struct IORequest*)AudioIO_2) )
        {
             WaitIO( (struct IORequest*)AudioIO_2 ) ;
             start_copy_2 = 1;
         }

         if (start_copy_2)
        {
            memcpy(chip_2_ptr, fast_ptr, CHUNK_SIZE);
            fast_ptr += CHUNK_SIZE;
           chip_2_ptr += CHUNK_SIZE;
            parts_copied_2++;

            if (parts_copied_2 >= PARTS) 
           {
               parts_copied_2 = 0;
                start_copy_2 = 0;
                chip_2_ptr = chip_mem_2;
               BeginIO((struct IORequest *) AudioIO_2 );
           }
       }

     // reszta programu/gry
     ....

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

@mateusz_s, post #19

ostatnio siedziałem nad nowym projektem samplera, aby użyc 2 kanałów musisz odpowiednio zmodyfikować flagi, to oczywiście nie pełny kod ale powinno dać Tobie wskazówkę jak to zrobić. Pamiętaj żeby ioalength uwzględniał 2 kanały.

// Definicja kanałów
UBYTE whichannel[] = { 
    1,    // Lewy kanał
    2     // Prawy kanał
};

struct IOAudio *AudioIO; 
struct MsgPort *Audio_port;  
struct IOAudio *AudioIO_2;   
struct MsgPort *Audio_port_2;  


// Konfiguracja portów audio
    AudioIO = (struct IOAudio *)AllocMem(sizeof(struct IOAudio), MEMF_PUBLIC | MEMF_CLEAR);
    Audio_port = CreatePort(0,0);
    AudioIO_2 = (struct IOAudio *)AllocMem(sizeof(struct IOAudio), MEMF_PUBLIC | MEMF_CLEAR);
    Audio_port_2 = CreatePort(0,0);

    // Konfiguracja pierwszego kanału
    AudioIO->ioa_Request.io_Message.mn_ReplyPort = Audio_port;
    AudioIO->ioa_Request.io_Message.mn_Node.ln_Pri = 127;
    AudioIO->ioa_Request.io_Command = ADCMD_ALLOCATE;
    AudioIO->ioa_Request.io_Flags = ADIOF_NOWAIT;
    AudioIO->ioa_AllocKey = 0;
    AudioIO->ioa_Data = whichannel;
    AudioIO->ioa_Length = sizeof(whichannel);

    device = OpenDevice(AUDIONAME, 0L, (struct IORequest *)AudioIO, 0L);

    // Kopiowanie konfiguracji do drugiego kanału
    *AudioIO_2 = *AudioIO;
    AudioIO->ioa_Request.io_Message.mn_ReplyPort = Audio_port;
    AudioIO_2->ioa_Request.io_Message.mn_ReplyPort = Audio_port_2;

    // Konfiguracja parametrów odtwarzania dla pierwszego kanału (lewy)
    AudioIO->ioa_Request.io_Command = CMD_WRITE;
    AudioIO->ioa_Request.io_Flags = ADIOF_PERVOL;
    AudioIO->ioa_Data = (BYTE *)chip_mem_1;
    AudioIO->ioa_Length = CHIP_SIZE/2;
    AudioIO->ioa_Period = (UWORD)(clock / 22050);
    AudioIO->ioa_Volume = 64;
    AudioIO->ioa_Cycles = 1;

    // Konfiguracja parametrów odtwarzania dla drugiego kanału (prawy)
    AudioIO_2->ioa_Request.io_Command = CMD_WRITE;
    AudioIO_2->ioa_Request.io_Flags = ADIOF_PERVOL;
    AudioIO_2->ioa_Data = (BYTE *)chip_mem_2;
    AudioIO_2->ioa_Length = CHIP_SIZE/2;
    AudioIO_2->ioa_Period = (UWORD)(clock / 22050);
    AudioIO_2->ioa_Volume = 64;
    AudioIO_2->ioa_Cycles = 1;
[#21] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@sand, post #20

Z tego co wiem, to ażeby zaalokować wszystkie kanały, należy podać w tablicy whichannel wartość 0xF. Podaje się tam kombinacje bitowe kanałów.

Jeżeli system nie może zaalokować wybranej kombinacji kanałów, przechodzi do następnego elementu tej tablicy i próbuje alokować inne, podane przez nas kombinacje kanałów (dopóki nie wyczerpie tablicy).

Gdy nie ma dostępnej żadnej kombinacji kanałów, alokacja nie powiedzie się.

Żeby odgrywać sampel na jednym wybranym kanale wpisujemy w Unit tego IOAudio maskę bitową tego kanału.

Tutaj przykład programu w C, który odgrywa długi sampel (format IFF) z dysku za pomocą podwójnego buforowania: https://aminet.net/package/mus/play/playsound
4
[#22] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@Hexmage960, post #21

@sand @Hexmage960

Dzięki, jeszcze powalczę z tym dzisiaj,
wczoraj probowałem alokować z wartością 0x0F czyli 15,
ale odczytując ostatnie 4 bity z io_Unit poprzez
AudioIO->ioa_Request.io_Unit->unit_flags & 0x0F
dostawałem chyba 12,

ale moze jeszcze jakies błedy byly, juz chyba z 3 raz czytam o Audio Device na Amiga Wiki,
niby wszsytko jest tam dobrze opisane, ale własnie w praktyce nie do końca działa,
ale jeszcze na spokojnie dziś popracuje nad tym

@Hexmage960
bardzo ciekawy ten przykład który podesłałeś
[#23] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@Hexmage960, post #21

uff.. udało się z pomoca przykłądu od Hexmage960,
przy czym ja uzylem 4 audio requestów i innego buforowania,
nie wiem czy to tak ma być, ale w sumie działa jak należy..


enum	{	AUDIO_LEFT_BUFFER_1, AUDIO_RIGHT_BUFFER_1, AUDIO_LEFT_BUFFER_2, AUDIO_RIGHT_BUFFER_2, AUDIO_COUNT };

struct MsgPort *AudioPort;
struct IOAudio *Audio[AUDIO_COUNT];

UBYTE AnyChannel[] = { 3 }    // dla rezerwacji kanalu lewego 1 i prawego 1
AudioPort = CreateMsgPort();

Audio[AUDIO_LEFT_BUFFER_1] = (struct IOAudio *)AllocMem(sizeof(struct IOAudio), MEMF_PUBLIC | MEMF_CLEAR);
Audio[AUDIO_LEFT_BUFFER_2]	= (struct IOAudio *)AllocMem(sizeof(struct IOAudio), MEMF_PUBLIC | MEMF_CLEAR);
Audio[AUDIO_RIGHT_BUFFER_1] = (struct IOAudio *)AllocMem(sizeof(struct IOAudio), MEMF_PUBLIC | MEMF_CLEAR);
Audio[AUDIO_RIGHT_BUFFER_2] = (struct IOAudio *)AllocMem(sizeof(struct IOAudio), MEMF_PUBLIC | MEMF_CLEAR);

Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Request . io_Message . mn_Node . ln_Type	= 125;
Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Request . io_Message . mn_Length		= sizeof(struct IOAudio);
Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Request . io_Command				= ADCMD_ALLOCATE;
Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Request . io_Flags				= ADIOF_NOWAIT;
Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Data						= AnyChannel;
Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Length						= sizeof(AnyChannel);
Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Request . io_Message . mn_ReplyPort		= AudioPort;


ULONG device = OpenDevice(AUDIONAME,0,(struct IORequest*)Audio[AUDIO_LEFT_BUFFER_1],0);

CopyMem(Audio[AUDIO_LEFT_BUFFER_1],Audio[AUDIO_LEFT_BUFFER_2],sizeof(struct IOAudio));
CopyMem(Audio[AUDIO_LEFT_BUFFER_1],Audio[AUDIO_RIGHT_BUFFER_1],sizeof(struct IOAudio));
 CopyMem(Audio[AUDIO_LEFT_BUFFER_1],Audio[AUDIO_RIGHT_BUFFER_2],sizeof(struct IOAudio));

Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Request . io_Unit	= (APTR)1;  // maska bitowa dla kanalu 1 lewego
Audio[AUDIO_LEFT_BUFFER_2] -> ioa_Request . io_Unit	= (APTR)1;

Audio[AUDIO_RIGHT_BUFFER_1] -> ioa_Request . io_Unit	= (APTR)2; // maska bitowa dla kanalu 1 prewego
Audio[AUDIO_RIGHT_BUFFER_2] -> ioa_Request . io_Unit	= (APTR)2;


	Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Request . io_Command	= CMD_WRITE;
	Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Request . io_Flags	= ADIOF_PERVOL;
	Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Period			= (UWORD)( 3546895 / 22050);
	Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Volume			= 64;
	Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Cycles			= 1;
	Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Data			= chip_mem_1;
	Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Length			= CHIP_SIZE/2;

	Audio[AUDIO_RIGHT_BUFFER_1] -> ioa_Request . io_Command	= CMD_WRITE;
	Audio[AUDIO_RIGHT_BUFFER_1] -> ioa_Request . io_Flags	= ADIOF_PERVOL;
	Audio[AUDIO_RIGHT_BUFFER_1] -> ioa_Period			= (UWORD)( 3546895 / 22050);
	Audio[AUDIO_RIGHT_BUFFER_1] -> ioa_Volume			= 64;
	Audio[AUDIO_RIGHT_BUFFER_1] -> ioa_Cycles			= 1;
	Audio[AUDIO_RIGHT_BUFFER_1] -> ioa_Data			= chip_mem_1;
	Audio[AUDIO_RIGHT_BUFFER_1] -> ioa_Length			= CHIP_SIZE/2;

Audio[AUDIO_LEFT_BUFFER_2] -> ioa_Request . io_Command	= CMD_WRITE;
Audio[AUDIO_LEFT_BUFFER_2] -> ioa_Request . io_Flags	= ADIOF_PERVOL;
Audio[AUDIO_LEFT_BUFFER_2] -> ioa_Period		= (UWORD)( 3546895 / 22050);;
Audio[AUDIO_LEFT_BUFFER_2] -> ioa_Volume		= 64;
Audio[AUDIO_LEFT_BUFFER_2] -> ioa_Cycles		= 1;
Audio[AUDIO_LEFT_BUFFER_2] -> ioa_Data			= chip_mem_2;
Audio[AUDIO_LEFT_BUFFER_2] -> ioa_Length		= CHIP_SIZE/2;

Audio[AUDIO_RIGHT_BUFFER_2] -> ioa_Request . io_Command	= CMD_WRITE;
Audio[AUDIO_RIGHT_BUFFER_2] -> ioa_Request . io_Flags	= ADIOF_PERVOL;
Audio[AUDIO_RIGHT_BUFFER_2] -> ioa_Period		= (UWORD)( 3546895 / 22050);;
Audio[AUDIO_RIGHT_BUFFER_2] -> ioa_Volume		= 64;
Audio[AUDIO_RIGHT_BUFFER_2] -> ioa_Cycles		= 1;
Audio[AUDIO_RIGHT_BUFFER_2] -> ioa_Data			= chip_mem_2;
Audio[AUDIO_RIGHT_BUFFER_2] -> ioa_Length		= CHIP_SIZE/2;

....

BeginIO((struct IORequest*)Audio[AUDIO_LEFT_BUFFER_1]);
BeginIO((struct IORequest*)Audio[AUDIO_RIGHT_BUFFER_1]);
BeginIO((struct IORequest*)Audio[AUDIO_LEFT_BUFFER_2]);
BeginIO((struct IORequest*)Audio[AUDIO_RIGHT_BUFFER_2]);

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

@mateusz_s, post #23

Ja bym proponował nieco "uprościć" kod i zwiększyć czytelność i np. taki kawałek:

Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Request . io_Message . mn_Node . ln_Type	= 125;
Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Request . io_Message . mn_Length		= sizeof(struct IOAudio);
Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Request . io_Command				= ADCMD_ALLOCATE;
Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Request . io_Flags				= ADIOF_NOWAIT;
Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Data						= AnyChannel;
Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Length						= sizeof(AnyChannel);
Audio[AUDIO_LEFT_BUFFER_1] -> ioa_Request . io_Message . mn_ReplyPort		= AudioPort;


zamieniłbym przykładowo na coś takiego:

struct IOAudio *pAudioLeftBuffer1 = Audio[AUDIO_LEFT_BUFFER_1];
pAudioLeftBuffer1 -> ioa_Request . io_Message . mn_Node . ln_Type	= 125;
pAudioLeftBuffer1 -> ioa_Request . io_Message . mn_Length		= sizeof(struct IOAudio);
pAudioLeftBuffer1 -> ioa_Request . io_Command				= ADCMD_ALLOCATE;
pAudioLeftBuffer1 -> ioa_Request . io_Flags				= ADIOF_NOWAIT;
pAudioLeftBuffer1 -> ioa_Data						= AnyChannel;
pAudioLeftBuffer1 -> ioa_Length						= sizeof(AnyChannel);
pAudioLeftBuffer1 -> ioa_Request . io_Message . mn_ReplyPort		= AudioPort;


Najlepiej zamienić na jakąś funkcję przy kolejnej refaktoryzacji kodu. Bo działanie dla obu buforów jest taka sama.
A może już tak jest ...
[#25] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@Rafael/ARMO, post #24

tak, to taki wstepny kod zeby byl czytelny.. wypelnilem jedna strukturę, skopiowałem do pozoztsdałych i tylko uzuprlnilem o te wartosci ktore sie zmieniły
1
[#26] Re: [C] Kilka pytań odnośnie używania muzyki i dzwięków..

@mateusz_s, post #25

Udało mi się zrobić tak jak chciałem, czyli:
- muzyka leci dwóch kanałów, lewego 1 i prawego 1
- a dźwięki z pozostałych dwóch lewego 2 i prawego 2, ale naprzemiennie

Przykładzik:




Dorzucam fragmenty kodu:

// globalne
enum	{   SYS_AUDIO__LEFT_1_BUFFER_1, SYS_AUDIO__RIGHT_1_BUFFER_1, 
            SYS_AUDIO__LEFT_1_BUFFER_2, SYS_AUDIO__RIGHT_1_BUFFER_2, 
            SYS_AUDIO__LEFT_2_BUFFER, SYS_AUDIO__RIGHT_2_BUFFER,
            SYS_AUDIO__COUNT };

static struct MsgPort* sys_audio__port;
static struct IOAudio* sys_audio[SYS_AUDIO__COUNT];

static UBYTE    sys_audio__channels[] = { 15 };  // 15 - For reservation for all 4 channels.


// inicjalizacja audio i wszsytkich kanałów
int     SYS_audio__create(void)
{
    // What clock, PAL or NTSC. 
    GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0L);
    if (GfxBase==0L) return 0;

    if (GfxBase->DisplayFlags & PAL)
        sys_audio__clock = 3546895L;        /* PAL clock */
    else
        sys_audio__clock = 3579545L;        /* NTSC clock */

    if (GfxBase)
        CloseLibrary( (struct Library *) GfxBase);

    // Alloc chip ram for duble buffering long sounds from fast ram.
    sys_audio__chip_buf_1 = (BYTE*)AllocMem( SYS_AUDIO__CHIP_SIZE, MEMF_CHIP | MEMF_CLEAR );
    if (sys_audio__chip_buf_1 == NULL) return 0;
  
    sys_audio__chip_buf_2 =  sys_audio__chip_buf_1 + (SYS_AUDIO__CHIP_SIZE / 2);   
    if (sys_audio__chip_buf_2 == NULL) return 0;

    // Alloc elements for audio.
    sys_audio__port = CreateMsgPort();    
    if (sys_audio__port == NULL) return 0;

    sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1] = (struct IOAudio *)AllocMem(sizeof(struct IOAudio) * SYS_AUDIO__COUNT, MEMF_PUBLIC | MEMF_CLEAR);
    if (sys_audio == NULL) return 0;

    sys_audio[SYS_AUDIO__RIGHT_1_BUFFER_1]	    = sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1] + 1;
    sys_audio[SYS_AUDIO__LEFT_1_BUFFER_2]	    = sys_audio[SYS_AUDIO__RIGHT_1_BUFFER_1] + 1;
    sys_audio[SYS_AUDIO__RIGHT_1_BUFFER_2]	    = sys_audio[SYS_AUDIO__LEFT_1_BUFFER_2] + 1;

    sys_audio[SYS_AUDIO__LEFT_2_BUFFER]	        = sys_audio[SYS_AUDIO__RIGHT_1_BUFFER_2] + 1;
    sys_audio[SYS_AUDIO__RIGHT_2_BUFFER]	    = sys_audio[SYS_AUDIO__LEFT_2_BUFFER] + 1;

    // Open audio.device, allocate the channels on the fly..
    sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1]->ioa_Request.io_Message.mn_Node.ln_Type   = 125;
    sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1]->ioa_Request.io_Message.mn_Length		    = sizeof(struct IOAudio);
    sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1]->ioa_Request.io_Message.mn_ReplyPort	    = sys_audio__port;
    sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1]->ioa_Request.io_Command				    = ADCMD_ALLOCATE;
    sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1]->ioa_Request.io_Flags				        = ADIOF_NOWAIT;
    sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1]->ioa_Length						        = sizeof(sys_audio__channels);
    sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1]->ioa_Data						            = sys_audio__channels;

    ULONG audio_device = OpenDevice(AUDIONAME, 0, (struct IORequest*)sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1], 0);
    if (audio_device != 0)  return 0;

    // Check if all desired channels were allocated.
    if ( (((LONG)sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1]->ioa_Request.io_Unit) & 0x0F) != sys_audio__channels[0] ) return 0;    

    // Initializing all audio requests.
    sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1]->ioa_Request.io_Command   = CMD_WRITE;
	sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1]->ioa_Request.io_Flags	    = ADIOF_PERVOL;
	sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1]->ioa_Period			    = (UWORD)( sys_audio__clock / SYS_AUDIO__FREQ );
	sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1]->ioa_Volume			    = 64;
	sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1]->ioa_Cycles			    = 1;
	sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1]->ioa_Length			    = (SYS_AUDIO__CHIP_SIZE / 2);

    // Copy audio request data to all remaining requests.
    *sys_audio[SYS_AUDIO__LEFT_1_BUFFER_2]      = *sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1];
    *sys_audio[SYS_AUDIO__RIGHT_1_BUFFER_1]     = *sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1];
    *sys_audio[SYS_AUDIO__RIGHT_1_BUFFER_2]     = *sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1];

    *sys_audio[SYS_AUDIO__LEFT_2_BUFFER]        = *sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1];
    *sys_audio[SYS_AUDIO__RIGHT_2_BUFFER]       = *sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1];

    // Assign correct channels to all audio requests.
	sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1]->ioa_Request.io_Unit	= (APTR)SYS_AUDIO__LEFT_1;
    sys_audio[SYS_AUDIO__LEFT_1_BUFFER_2]->ioa_Request.io_Unit	= (APTR)SYS_AUDIO__LEFT_1;

	sys_audio[SYS_AUDIO__RIGHT_1_BUFFER_1]->ioa_Request.io_Unit	= (APTR)SYS_AUDIO__RIGHT_1;
    sys_audio[SYS_AUDIO__RIGHT_1_BUFFER_2]->ioa_Request.io_Unit	= (APTR)SYS_AUDIO__RIGHT_1;

	sys_audio[SYS_AUDIO__LEFT_2_BUFFER]->ioa_Request.io_Unit	= (APTR)SYS_AUDIO__LEFT_2;
    sys_audio[SYS_AUDIO__RIGHT_2_BUFFER]->ioa_Request.io_Unit	= (APTR)SYS_AUDIO__RIGHT_2;

    // Assign correct chip buffers
    sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1]->ioa_Data			    = sys_audio__chip_buf_1;
    sys_audio[SYS_AUDIO__RIGHT_1_BUFFER_1]->ioa_Data		    = sys_audio__chip_buf_1;

    sys_audio[SYS_AUDIO__LEFT_1_BUFFER_2]->ioa_Data			    = sys_audio__chip_buf_2;
    sys_audio[SYS_AUDIO__RIGHT_1_BUFFER_2]->ioa_Data		    = sys_audio__chip_buf_2;

    sys_audio__sfx_current_channel = SYS_AUDIO__LEFT_2_BUFFER;

    // Turn off Amiga Audio Filter for clearer sounds.
    *((char *)0x0bfe001)|=0x02;

    return 1;
}


// przygotowanie do buforowania
void    SYS_audio__music_buffer_prepare(char* _music_buffer, int _size)
{
    sys_audio__music_buf = _music_buffer;
    sys_audio__music_buf_size = _size;

    memcpy(sys_audio__chip_buf_1, sys_audio__music_buf, SYS_AUDIO__CHIP_SIZE / 2);
    memcpy(sys_audio__chip_buf_2, sys_audio__music_buf + SYS_AUDIO__CHIP_SIZE / 2, SYS_AUDIO__CHIP_SIZE / 2);

    sys_audio__chip_buf_1__ptr = sys_audio__chip_buf_1;
    sys_audio__chip_buf_2__ptr = sys_audio__chip_buf_2;

    sys_audio__music_buf__ptr = sys_audio__music_buf + SYS_AUDIO__CHIP_SIZE;
    sys_audio__db_music_buf_position = SYS_AUDIO__CHIP_SIZE;

    sys_audio__db_start_copy_1 = 0;
    sys_audio__db_parts_copied_1 = 0;
    sys_audio__db_start_copy_2 = 0;
    sys_audio__db_parts_copied_2 = 0;
}


// procedura buforowania z fast do chip z zapętleniem
void    SYS_audio__music_buffer_to_chipram(void)
{
    // Perform double buffering routine to copy chunks of sounds from fast to chip buffers.

    // Perform play end test only if any requester sent signal.
    ULONG signal_mask = ( 1 << sys_audio__port->mp_SigBit); 

    if (SetSignal(0L, signal_mask) & signal_mask)
    {
            // If music from chip buffer 1 is finished...
            if ( CheckIO((struct IORequest*)sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1]) && CheckIO((struct IORequest*)sys_audio[SYS_AUDIO__RIGHT_1_BUFFER_1]) )
            {
                WaitIO( (struct IORequest*)sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1] ) ;
                WaitIO( (struct IORequest*)sys_audio[SYS_AUDIO__RIGHT_1_BUFFER_1] ) ;
                sys_audio__db_start_copy_1 = 1;
            }
        
            // If music from chip buffer 2 is finished...
            if ( CheckIO((struct IORequest*)sys_audio[SYS_AUDIO__LEFT_1_BUFFER_2]) && CheckIO((struct IORequest*)sys_audio[SYS_AUDIO__RIGHT_1_BUFFER_2]) )
            {
                WaitIO( (struct IORequest*)sys_audio[SYS_AUDIO__LEFT_1_BUFFER_2] );
                WaitIO( (struct IORequest*)sys_audio[SYS_AUDIO__RIGHT_1_BUFFER_2] );
                sys_audio__db_start_copy_2 = 1;
            }
    }

    // Copying from fast ram to from chip buffer 1.
    if (sys_audio__db_start_copy_1)
    {
        // We need to test against end of music and loop it.
        if ( (sys_audio__db_music_buf_position + SYS_AUDIO__CHUNK_SIZE) >= sys_audio__music_buf_size)
        {
            // If the next chunk exceeds music size we copy the last chunk.
            int last_chunk_size = sys_audio__music_buf_size - sys_audio__db_music_buf_position;
            memcpy(sys_audio__chip_buf_1__ptr, sys_audio__music_buf__ptr, last_chunk_size);

            sys_audio__chip_buf_1__ptr += last_chunk_size;

            // Reset music buffer position and pointer.
            sys_audio__music_buf__ptr = sys_audio__music_buf;
            sys_audio__db_music_buf_position = 0;

            // We also have to copy remaining chunk from the beginning.
            int remaining_chunk_size = SYS_AUDIO__CHUNK_SIZE - last_chunk_size;
            memcpy(sys_audio__chip_buf_1__ptr, sys_audio__music_buf__ptr, remaining_chunk_size);

            sys_audio__chip_buf_1__ptr += remaining_chunk_size;
            sys_audio__music_buf__ptr += remaining_chunk_size;
            sys_audio__db_music_buf_position += remaining_chunk_size;
        }
        else
        {
            // If next chunk doesn't exceed music buffer we copy SYS_AUDIO__CHUNK_SIZE.
            memcpy(sys_audio__chip_buf_1__ptr, sys_audio__music_buf__ptr, SYS_AUDIO__CHUNK_SIZE);

            sys_audio__chip_buf_1__ptr += SYS_AUDIO__CHUNK_SIZE;
            sys_audio__music_buf__ptr += SYS_AUDIO__CHUNK_SIZE;
            sys_audio__db_music_buf_position += SYS_AUDIO__CHUNK_SIZE;
        }
        sys_audio__db_parts_copied_1++;

        if (sys_audio__db_parts_copied_1 >= SYS_AUDIO__PARTS) 
        {
            sys_audio__db_parts_copied_1 = 0;
            sys_audio__db_start_copy_1 = 0;
            sys_audio__chip_buf_1__ptr = sys_audio__chip_buf_1;

            BeginIO((struct IORequest *)sys_audio[SYS_AUDIO__LEFT_1_BUFFER_1] );
            BeginIO((struct IORequest *)sys_audio[SYS_AUDIO__RIGHT_1_BUFFER_1] );
        }
    }

    // Copying from fast ram to from chip buffer 2.
    if (sys_audio__db_start_copy_2)
    {
        // We need to test against end of music and loop it.
        if ( (sys_audio__db_music_buf_position + SYS_AUDIO__CHUNK_SIZE) >= sys_audio__music_buf_size)
        {
            // If the next chunk exceeds music size we copy the last chunk.
            int last_chunk_size = sys_audio__music_buf_size - sys_audio__db_music_buf_position;
            memcpy(sys_audio__chip_buf_2__ptr, sys_audio__music_buf__ptr, last_chunk_size);

            sys_audio__chip_buf_2__ptr += last_chunk_size;

            // Reset music buffer position and pointer.
            sys_audio__music_buf__ptr = sys_audio__music_buf;
            sys_audio__db_music_buf_position = 0;

            // We also have to copy remaining chunk from the beginning.
            int remaining_chunk_size = SYS_AUDIO__CHUNK_SIZE - last_chunk_size;
            memcpy(sys_audio__chip_buf_2__ptr, sys_audio__music_buf__ptr, remaining_chunk_size);

            sys_audio__chip_buf_2__ptr += remaining_chunk_size;
            sys_audio__music_buf__ptr += remaining_chunk_size;
            sys_audio__db_music_buf_position += remaining_chunk_size;
        }
        else
        {
            // If next chunk doesn't exceed music buffer we copy SYS_AUDIO__CHUNK_SIZE.
            memcpy(sys_audio__chip_buf_2__ptr, sys_audio__music_buf__ptr, SYS_AUDIO__CHUNK_SIZE);
            
            sys_audio__chip_buf_2__ptr += SYS_AUDIO__CHUNK_SIZE;
            sys_audio__music_buf__ptr += SYS_AUDIO__CHUNK_SIZE;
            sys_audio__db_music_buf_position += SYS_AUDIO__CHUNK_SIZE;
        }
        sys_audio__db_parts_copied_2++;

        if (sys_audio__db_parts_copied_2 >= SYS_AUDIO__PARTS) 
        {
            sys_audio__db_parts_copied_2 = 0;
            sys_audio__db_start_copy_2 = 0;
            sys_audio__chip_buf_2__ptr = sys_audio__chip_buf_2;

            BeginIO((struct IORequest *)sys_audio[SYS_AUDIO__LEFT_1_BUFFER_2] );
            BeginIO((struct IORequest *)sys_audio[SYS_AUDIO__RIGHT_1_BUFFER_2] );
        }
    }
}


// procedura odtwarzajaca dzwięk ktory jest w chip ram, naprzemiennie - raz na lewym 2 i raz na prawym 2
void    SYS_audio__sfx_start(char* _sfx_buffer, int _size)
{
    // We have 2 channels to use left 2 and right 2,
    // lets use them alternately.
    sys_audio__sfx_current_channel ^= 1;

    sys_audio[sys_audio__sfx_current_channel]->ioa_Request.io_Command 	    = ADCMD_FINISH;
    BeginIO((struct IORequest*)sys_audio[sys_audio__sfx_current_channel]);

    sys_audio[sys_audio__sfx_current_channel]->ioa_Request.io_Command 	    = CMD_WRITE;
    sys_audio[sys_audio__sfx_current_channel]->ioa_Data       = _sfx_buffer;
    sys_audio[sys_audio__sfx_current_channel]->ioa_Length	    = _size;

    BeginIO((struct IORequest*)sys_audio[sys_audio__sfx_current_channel]);
}
4
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