timeBeginPeriod (uResolution);w celu zasygnalizowarua najmniejszej rozdzielczości zegara, jakiej będzie wymagałprogram...

Jak cię złapią, to znaczy, że oszukiwałeś. Jak nie, to znaczy, że posłużyłeś się odpowiednią taktyką.
Wartość ta powinna należeć do przedziału zdefiniowanego w struktu-
rze TIMECAPS. Wywołanie umożliwia optymalizację pracy urządzenia zegara,
który po zgromadzeniu niezbędnych informacji od kilku działających programów
będzie w stanie zapewniać im najlepszy sposób obsługi. Każde wywołanie funk-
cji timeBeginPeriod musi być związane z późniejszym wywołaniem funkcji time-
EndPeriod, którą niebawem opiszę.
Teraz jesteś gotowy do zaprogramowania zdarzeń zegara:
idTimer = timeSetEvent (uDelay, uResolution, CallBackFunc, dwData, uFlag);
Jeżeli wystąpi błąd, zwrócona z tego wywołania wartość idTimer będzie równa
zero. Od tego wywołania po czasie uDelay milisekund Windows wywoła funkcję
CalIBackFunc z dozwolonym błędem, określonym przez uResolution. Wartość uRe-
solution musi być większa lub równa rozdzielczości przekazanej do timeBeginPe-
riod. Parametr dwData jest wartością definiowaną przez program, przekazywaną
później do funkcji CalIBackFunc. Ostatni parametrem może być albo TIME_ONE-
SHOT (aby uzyskać pojedyncze wywołanie funkcji CallBackFunc w uDelay mili- '
sekund), albo TIMĘ PERIODIC (aby uzyskać wiele wywołań funkcji CallBackFunc
co uDelay milisekund).
Chcąc zatrzymać harmonogram jednorazowy zegara, zanim zostanie.wywołana
funkcja CallBackFunc, albo harmonogram okresowy, należy wywołać funkcję:
timeKillEvent (idTimer);
Harmonogramu jednorazowego nie trzeba zabijać, jeśli funkcja CaIlBackFunc zo-
stała już wywołana. Po zakończeniu korzystania z zegara, należy wywołać funk-
timeEndPeriod (wResolution);
z tym samym argumentem co w przypadku timeBeginPeriod.
Dwie pozostałe funkcje także zaczynają się prefiksem time. Funkcja
dwSysTime = timeGetTime (); ,
zwraca czas systemowy w milisekundach od pierwszego uruchomierua Windows.
Funkcja:
timeGetSystemTime (&mmtime. uSize);
Rozdział 22: Dźwięk i muryka 1247
wymaga jako pierwszego argumentu wskaźnika do struktury MMTIME, a jako
drugiego rozmiaru tej struktury. Struktura MMTIME może w innych okoliczno-
ściach posłużyć do odczytarua czasu systemowego w innym formacie niż w mili-
sekundach, ale w tych okolicznościach nie może. Tak więc funkcja timeGetSystem-
Time jest zbędna.
W Windows z poziomu funkcji zwrotnej rue można wywołać dowolnej funkcji.
Funkcja zwrotna może wywoływać PostMessage, cztery funkcje zegarowe (time-
SetEvent, timeKillEvent, timeGetTime i zbędną timeGetSystemTime), dwie funkcje
wyjściowe MIDI (midiOutShortMsg i midiOutLongMsg) oraz funkcję testową Out-
putDebugStr.
Oczywiście, zegar multimediów został zaprojektowany specjalnie do odtwarza-
nia sekwencji MIDI i ma bardzo ograniczone zastosowanie w innych sytuacjach.
Można za pomocą PostMessage informować procedurę okna o zdarzeniach zega-
ra, po czym procedura okna może sobie zrobić, co tylko zechce, ale jej reakcja nie
będzie tak precyzyjnie umiejscowiona w czasie, jak byłaby umiejscowiona reak-
cja samej zegarowej funkcji zwrotnej.
Funkcja zwrotna ma pięć parametrów, ale używa tylko dwóch z nich: numeru
identyfikacyjnego zegara zwróconego z timeSetEvent oraz wartości dwData, prze-
kazanej wcześruej w postaci argumentu do timeSetEvent.
Moduł DRUM.C w programie DRUMTIME.C wywołuje funkcję DrumSetParams
kilka razy: podczas tworzenia okna programu DRUM, gdy użytkownik kliknie
macierz albo zmieni położenie paska przewijania, kiedy program załaduje plik
.DRM oraz kiedy czyszczona jest macierz. Jedynym argumentem DrumSetParams
jest wskaźnik do struktury typu DRUM, zdefiniowanej w pliku nagłówkowym
DRUMTIME.H. Struktura ta służy do przechowywania długości trwania kwan-
tu czasu (w milisekundach), siły naciskania klawiszy (w uproszczeniu: głośno-
ści), liczby kwantów w sekwencji, a także dwóch zestawów czterdziestu siedmiu
32-bitowych liczb całkowitych tworzących macierz (instrumenty perkusyjne x
kwanty czasu). Każda z tych liczb odpowiada jednemu uderzeniu w instrument
perkusyjny. Struktura typu DRUM w module DRUM.C jest przechowywana w pa-
mięci statycznej, do DrumSetParams zostaje przekazany jedynie wskaźnik do struk-
tury. Funkcja DrumSetParams kopiuje po prostu jej zawartość.
Aby rozpocząć działanie sekwencji, DRUM wywołuje funkcję DrumBeginSequen-
ce (w DRUMTTME). Jej jedynym argumentem jest uchwyt okna. Służy on do po-
wiadamiania. DrumBeginSequence otwiera urządzenie wyjściowe MIDI Mapper
i wysyła komunikaty Program Change, wybierające instrument numer 0 dla ka-
nałów MIDI numer 0 i 9. Instrumenty są numerowane od zera, więc 9 oznacza
w rzeczywistości kanał MIDI numer 10, czyli perkusyjny. Drugi kanał (a raczej
pierwszy) służy do uzyskiwania nut pianina. Następnie (nadal w DrumBeginSe-
guence) wywoływane są funkcje timeGetDevCaps i timeBeginPeriod. Żądaną rozdziel-
czością, zdefiniowaną za pomocą stałej TIMER RES, jest 5 milisekund, ale zdefi-
niowałem makro o nazwie minmax, które ułatwia wyliczanie rozdzielczości w gra-
nicach uzyskanych z timeGetDevCaps.
Następnie wywoływana jest funkcja timeSetEvent, w której określono czas kwan-
tu czasu, wyliczoną rozdzielczość, funkcję zwrotną DrumTimerFunc oraz stałą
1248 Część III: Zagadnienia zaawansowane
TIMĘ ONESHOT. W programie DRUMTIME zegar programowany jest na zda-
rzerua jednorazowe, a nie okresowe, aby można było dynamicznie zmieniać tem-
po podczas trwania sekwencji. Po wywołaniu funkcji timeSetEvent, kiedy minie
już zaprogramowany czas zwłoki, urządzenie zegara wywoła funkcję DrumTi-
merFunc.
Najwięcej dzieje się w funkcji zwrotnej DrumTimerFunc. W zmiennej ilndex zapi-
sana jest bieżąca wartość kwantu sekwencji. Funkcja zaczyna się od przesłania
komunikatów Note Off dla obecnie odgrywanych dźwięków. Początkowa war-
tość ilndex wynosząca -1 zapobiega tej operacji podczas pierwszego uruchamia-
nia sekwencji.
Następnie zmienna ilndex jest zwiększana, a jej wartość dostarczana do procedu-
ry okna programu DRUM za pomocą komunikatu niestandardowego o nazwie
WM LISEIRNOTTFY. Argumentowi komunikatu wParam przypisywana jest war-
tość ilndex, aby procedura WndProc z DRUM.C mogła uaktualnić położenie "ska-
czącej piłeczki".
Funkcja DrumTimerFunc kończy się wysłaniem komunikatów Note On do kana-
łów syntezatora o numerach 0 i 9 (wartości z kratek są zapamiętywane, aby nuty
można było wyłączyć w następnym przebiegu pętli) oraz zaprogramowaniem
zegara jednorazowego za pomocą funkcji timeSetEvent.
Aby zatrzymać sekwencję, program DRUM wywohzje funkcję DrumEndSequence
z jednym argumentem, który może mieć wartość TRUE lub FALSE. Jeżeli ma
wartość TRUE, funkcja DrumEndSequence kończy sekwencję od razu: zabijając
wszelkie oczekujące zdarzenia zegara, wywołując funkcję timeEndPeriod, wysy-
łając komunikaty wyłączające wszystkie nuty do dwóch kanałów MIDI i zamy-
kając wyjściowy port MIDI. Funkcja DrumEndSequence jest wywoływana z para-
metrem TRUE wtedy, gdy użytkownik zdecyduje się zakończyć program.
Jeśli jednak wybierze polecenie Stopped z menu Sequence, program wywoła funk-
cję DrumEndSequence z argumentem FALSE. W ten sposób sekwencja przed za-
WÄ…tki
Powered by wordpress | Theme: simpletex | © Jak ciÄ™ zĹ‚apiÄ…, to znaczy, ĹĽe oszukiwaĹ‚eĹ›. Jak nie, to znaczy, ĹĽe posĹ‚uĹĽyĹ‚eĹ› siÄ™ odpowiedniÄ… taktykÄ….