Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?
Autor opracowania: 'dmx81'
Korekta redakcyjna: Piotr Szawdyński
Inne artykuły

[Allegro, C++] Zaawansowana obsługa dźwięku

[artykuł] Artykuł opisuje zaawansowane funkcje biblioteki Allegro do obsługi dźwięku w C++.

VOICE ROUTINES - czyli rozwinięcie SAMPLE ROUTINES

Do podstawowych funkcji pozwalających nam na używanie dźwieków w aplikacjach napisanych w bibliotece Allegro należą te, które operują na strukturach SAMPLE. Jeśli już je poznałeś, a oczekujesz nieco większej kontroli nad dzwiękiem to polecam zapoznanie się z VOICE ROUTINES, czyli z funkcjami do obsługi dźwięku niższego poziomu - czytaj: dających większe możliwości ingerencji w dźwięk oraz większą kontrolę nad tym co się z nim dzieje :)

Wiesz już czym się zajmiemy? No to do dzieła!

W niniejszym artykule skupię się jedynie na samych funkcjach. Zakładam bowiem, że wiesz, jak uruchomić Allegro i odpowiednio wkomponowac poniższe funkcje do swojego kodu :)

Po pierwsze, po staremu, czyli:
C/C++
SAMPLE * muzyczka = load_sample( "dzwiek.wav" );
if( !muzyczka )
{
    set_gfx_mode( GFX_TEXT, 0, 0, 0, 0 );
    allegro_message( "nie mogę załadować dzwieku muzyczka!" );
    allegro_exit();
    return 0;
}
Czyli ładujemy do SAMPLE jakiś dźwięk z dysku i sprawdzamy czy został załadowany.

Drugim krokiem jest:
C/C++
allocate_voice( muzyczka );
Tutaj przypisujemy do voice nasz dźwięk. Warto wiedzieć, że każdy załadowany dźwięk jest numerowany - pierwszy ma numer 0. Chcąc się dostać do dźwięku w kolejnych funkcjach, będziemy podawali numer dźwięku, który otrzymaliśmy (kolejny dźwięk miałby wartość 1). Po drugie warto wiedzieć, że Allegro zapewnia nam obsługę do 255 takich voice'ów oraz nie gwarantuje, że ta liczba jest wspierana przez posiadany sprzęt, więc raczej nie należy przesadzać :)

Odtwarzanie dźwięku

Mamy teraz przypisany dźwiek do voice nr 0. Możemy go teraz zacząc odtwarzać, ewentualnie najpierw ustalić pewne parametry.
C/C++
voice_start( 0 );
Powyższe wywołanie spowoduje odtwarzanie dźwięku z domyślnymi parametrami(ustawione na początku przez allocate_voice, a więc max glośność, moc rozłożona L50%/P50%, bez zmiany tempa odtwarzania, bez pętli odtwarzania - czyli jednorazowe). Jeśli chcielibyśmy jednak coś zmienić, skorzystamy z innych funkcji, jakie są dostępne w bibliotece Allegro.

Głośność dźwięku

C/C++
void voice_set_volume( int voice, int volume ); //voice to nasz nr dzwieku, volume to glosnosc 0-255, damy np://
voice_set_volume( 0, 100 );

Balansowanie mocy dźwięku na głośniki

Zmiana balansu/rozlozenia mocy na glosniki:
C/C++
void voice_set_pan( int voice, int pan ); // voice - nr, pan - 0 max lewy, 255 max prawy, 127 - po srodku//

void voice_sweep_pan( int voice, int time, int endpan ); // time - czas operacji, endpan - zadany balans, czyli uzywajac tej funkcji program zmieni nam balans w ciagu zadanego czasu//

void voice_stop_pan_sweep( int voice ); //przerywa operacje powyzej//

Odtwarzanie jednokrotne i wielokrotne

Funkcja, która umożliwia zadecydowanie, czy dźwięk będzie odtworzony jeden raz czy ma być on powtarzany również istnieje i jest nią voice_set_playmode. Za pomocą tej funkcji możemy również ustalić, czy dźwięk będzie odtworzany od przodu do tyłu, czy też w rewersie.
C/C++
void voice_set_playmode( int voice, int playmode );
Za playmode wybieramy:
  • PLAYMODE_PLAY - domyślny tryb, gra jednorazowo od początku do końca
  • PLAYMODE_LOOP - granie z powtarzaniem, czyli w pętli
  • PLAYMODE_FORWARD - granie od początku do końca, przeciwieństwo PLAYMODE_BACKWARD
  • PLAYMODE_BACKWARD - rewers, czyli odwrócenie kierunku odtwarzania
  • PLAYMODE_BIDIR - kombinacja dwóch powyższych, czyli gra od początku do końca, po czym zmienia kierunek odtwarzania na od końca do początku

Zatrzymanie dźwięku

C/C++
voice_stop( 0 );
Zatrzymujemy odtwarzanie dźwięku, ale trzeba pamietać, ze ta funkcja zapamiętuje pozycję, w jakiej dźwięk jest zatrzymany, więc ponowne uruchomienie go nastąpi od miejsca, w którym go zatrzymalismy - można samemu ustalić pozycję odtwarzania, ale to poźniej.

Obecna pozycja odtwarzanego dźwięku

Inną przydatną funkcją może być:
C/C++
int voice_get_position( int voice );
//przyklad wykorzystania//
if( voice_get_position( 0 ) < 0 )
{
    voice_start( 0 );
}
Funkcja zwraca pozycję w odtwarzanym utworze. Jeśli odtwarzanie zostało zakończone funkcja zwraca -1, dzięki czemu możemy np zablokować wielokrotne odtwarzanie samego utworu jeżeli jest on odtwarzany.

Ustawienie pozycji odtwarzania dźwięku

Możemy też ustalić pozycję od której ma nastąpić odtwarzanie dźwięku. Przykładowo po jego zatrzymaniu można ustawić odtwarzanie od początku (przypominam, że voice_stop zapamiętuje pozycję odtwarzania i jej nie zmienia).
C/C++
void voice_set_position( int voice, int position ); //podajac za position -1(*lub chyba 0-trzeba sprawdzic) ustawimy pozycje na poczatek utworu//

Efekty dźwiękowe

Teraz kolejna ciekawa funkcja:
C/C++
void voice_ramp_volume( int voice, int time, int endvol );
voice - nr dzwieku, time - czas w milisekundach, endvol - zadana glosnosc.
funkcja ta sluzy do zmiany glosnosci w ciagu zadanego czasu, czyli:
C/C++
voice_ramp_volume( 0, 1000, 255 )
Powyższe wywołanie spowoduje zgłośnienie się naszego dźwięku (głos ustawiliśmy na 100 na początku), więc program przekręci pokretło głośności ze 100 na 255 w ciągu 1 sekundy. Operację tą można przerwać przez
C/C++
void voice_stop_volumeramp( int voice );

Zwalnianie zasobów po dźwięku

Na koniec pracy z dźwiękiem, należy zwolnić pamięć. W tym celu użyjemy
C/C++
void release_voice( int voice );
//  lub  //
void deallocate_voice( int voice );
Funkcje mają to samo zadanie - różnią się jednak tym, że pierwsza pozwala dźwiękowi dograć do końca, druga go zatrzymuje. To z której funkcji skorzystamy będzie więc zależne od naszych potrzeb. Nie zapominajmy, ze SAMPLE również trzeba zwolnić z pamięci przez:
C/C++
destroy_sample( muzyczka );

Ponowne wykorzystanie tego samego zasobu

Jeśli chcemy, aby nasz zaalokowany voice wskazywał na inny dźwięk, nie musimy tworzyć nowego, jeśli stary na nic juz nie wskazuje. Możemy go realokowac, czyli:
C/C++
void reallocate_voice( int voice, const SAMPLE * spl ); // co jest rownoznaczne z ://
deallocate_voice( muzyczka );
voice = allocate_voice( nowy_sample );
Warto tutaj pamiętać o zwolnieniu pamięci przez SAMPLE, który już nie jest przypisany do voice, a jest już nieużywany.

Sprawdzenie czy dźwięk posiada przypisaną ścieżkę dźwiękową

C/C++
SAMPLE * voice_check( int voice );
W ten sposób sprawdzamy, czy voice wskazuje na jakiś dźwięk. Jeśli funkcja nie używa żadnego sampla to funkcja zwróci NULL.

Priorytet dźwięku

Funkcja poniżej służy do ustawienia priorytetu dla voice:
C/C++
void voice_set_priority( int voice, int priority );
Po co? a po to, że jeśli nasz sprzęt nie będzie mógł obsłużyć więcej dźwięków to te z najniższym priorytetem zostaną odrzucone.

Częstotliwość odtwarzania dźwięku

C/C++
void voice_set_frequency( int voice, int frequency );
Ta funkcja pozwala ustalić częstotliwość odtwarzania. Frequency podajemy w Hz.

Efekty związane z częstotliwością dźwięku

C/C++
void voice_sweep_frequency( int voice, int time, int endfreq );

void voice_stop_frequency_sweep( int voice );
Cos jak z samozgłaśnianiem. Tutaj ustalamy żadaną częstotliwość i czas, w jakim ma się zmienić od obecnej do żądanej, oraz funkcja przerywająca działanie te pierwszej.

Funkcje odczytujące informacje o dźwięku

Poza tym są funkcje pobierające wartości, takie jak głośność, balans, częstotliwość
C/C++
int voice_get_volume( int voice ); //zwraca int, 0-255
int voice_get_frequency( int voice ); // zwraca int, Hz
int voice_get_pan( int voice ); // zwraca int, 0-255

Obsługa kilku dźwięków

Chcąc załadować więcej dźwięków, postępujemy podobnie, jak na początku, czyli:
C/C++
SAMPLE * kroki = load_sample( "dzwiek42.wav" );
SAMPLE * podskok = load_sample( "dzwiek76.wav" );
//+sprawdzenie, czy udalo sie zaladowac
allocate_voice( kroki );
allocate_voice( podskok );

Teraz dostęp do tych dźwięków mamy poprzez:
C/C++
voice_start( 1 );
if( get_voice_position( 1 ) < 0 )
{
    voice_start( 2 );
}
Mam nadzieję, że chociaż trochę przybliżyłem temat wykorzystania tych funkcji i ze komuś się one przydadzą, to mój pierwszy artykuł tego typu, więc mam nadzieję, że mój język pisania jest w miarę czytelny, dzięki :)