Subject : Midas'da Muzik Senkronizasyonu Author : pOiSOn Email : poisone@usa.net Irc : irc.ada.net.tr / #scene.tr #manowar #atheist #coders ICQ : 6795916 LastUpdate : 15 Aralik 98 Note : bayilirim gitar sesine.. gelelim muzik senkranizasyonuna.. bir cok demo'da basa bela olan bi konu bu.. ornegin bas'larin doruga ulastigi bir anda ekrandani beyaz'a boyamak nefis bi efekt fekat bunu muzik ile senkronize yapmazsaniz baska bilgisayarlarda bu efekt yerlerde surunur.. peki nasil yapariz ?.. midas'in bu turlu senkronizasyonlari desteklemesi icin hazir fonksiyonlari var.. fakat bunlari yapmadan once nasil yapildigini anlatalim.. Ornek olarak ekranda donen bir kup efekti olsun.. algoritma basitce.. 1. ekran modunu ac 2. esc'ye basildiysa x'e git. 3. kup'un koordinatlarini cevir.. 4. kup'u hesapla. 5. kup'u ciz.. 6. 2'ye git. 7. text mode ve kapat.. simdi bu kisimda anlasilmasi gereken senkranizasyonda ekrana ne cizdiginiz degil ne kadar cizdiginiz onemli (karizma laf oldu walla..).. eger her karede kup'un koordinatlarini bir kez cevirirseniz yavas bir bilgisayarda muzik ilerledigi halde cpu kup ile ugrastigindan muzige yetisemeyecektir.. hmm.. ne yapabiliriz ?.. eger ekrana cizilen ve cizilecek kare sayisini bilirsek gec kalinan kareler icin kup'u ekrana cizmeden sadece cevirmek (sadece cevirmek) yeterlidir.. iste midas bunu hesaplayabilmeniz icin size bir global deisken veriyor frameCount. frameCount, senkronizasyon ile ilgili fonksiyonlari kullanidiginizda ekran karti her tarama cizgisine bir arttirilir. boylece siz efekti ekrana cizmeden once bir onceki ekran ile arada kac kare gectigini hesaplayabilirsiniz.. nasil mi?.. int frameCount; // bu midas'in kullandigi int oldFrame; // buda bizim yardimci deisken.. while (inp(0x60) != 1) { int skipframe; WaitFrame(); // ekranda yarim kalan bir kare varsa // onu bekliyoruz.. skipFrame = frameCount - oldFrame; // son cizilen kare ile arada // kac kare gecti ? oldFrame = frameCount; // son hesaplanan kare burasi idi.. // arada gecen kare sayisi kadar objeleri tasi vs.. // [ama ekrana cizim yapmiyoruz] for(tempCounter = 1; tempCounter <= skipFrame; tempCounter++) { RotateObjects(); ScrollText(); .. bla .. bla .. } // her sey yerli yerinde, artik ekrana her seyi cizebiliriz. DrawObjects(); PrintText(); // ekrana aktar. FlipToScreen(); } programin genel mantigi sanirim anlasildi. [anlamadiysaniz daa napiim ?!] Pekala midas'a senkronize olacagimizi nasil anlatiyoruz ?.. volatile ulong frameCount; /* frame counter */ hemen sirasi gelmisken, neden volatile ?.. cunku derleyicinin bu deiskeni optimize etmesini (bi register'a aktararak islemleri hizlandirmaya calismasi, stack'da bi kopyasini yaratmasi vs..) islemleri kapatmak icin. yani derleyici, mutlaka ve mutlaka bu deisken icin belirlenen bellek alanini kullanacaktir. baska hic bir kopyasi olmayacaktir hafizada. buna ne gerek var denilebilir. geregi su, bu deisken bir interrupt tarafindan deistirilecek ve cok sIk olarak degeri deisecek, bu yuzden interrupt'un biri deisikligi yapamadan baska bir tanesinin o degerin uzerine yazmasi engellenecek. [yada siz en iyisi volatile tanimlayin ve neden boyle tanimlandigini merak etmeyin :)] void WaitFrame(void) { ulong oldFrameCount = frameCount; while ( oldFrameCount == frameCount ); } void CALLING PreVR(void) { frameCount++; } hmm.. ilk once midas'in klasik on tanimlamalari.. midasSetDefaults(); midasDetectSD(); if ( (midasSDNumber != 0) && (midasSDNumber != 4) ) configOK = midasConfig(); else configOK = 1; midas initialize edildikten sonra ekran senkronizasyon rutinleri.. tmrGetScrSync fonksiyonu cagrilarak ekranin tarama hizi bulunur ve bu deger scrSync deiskenine yuklenir. buna gore aklinizda kalmasi gereken bisi bu fonksiyonu video modunu deistirdikten sonra cagirmaniz gerekli, bunun nedeni her modun ayni frekansda (tarama hizi) gosterilmemesi. // ekran tarama frekansini bul. if ( (error = tmrGetScrSync(&scrSync)) != OK ) midasError(error); // bulunamadi ise warning ver. if ( !mSyncScreen ) { vCloseGraph(); printf("\n\nWarning! Unable to synchronize to display refresh!\n" "This can lead to problems in music output and flickering.\n" "This usually happens only when running under Windows 95 - " "please consider\nrunning DOS programs in DOS instead.\n" "Press Esc to quit or any other key to continue\n"); if ( getch() == 27 ) exit(-1); OpenGraph(); // eski ekran cozunurlugune getir.. } // devam... midasInit(); if ( (error = gmpLoadXM("venom.xm", 1, NULL, &module)) != OK ) midasError(error); // simdi muzik icin senkronizasyon'u baslat.. // get timer.. if ( (error = tmrSyncScr(scrSync, &PreVR, NULL, NULL)) != OK ) midasError(error); // artik her tarama cizgisi cizmeye baslatilmadan PreVr rutini cagrilacak midasPlayModule(module, 0); // artik baslayabiliris.. tmrSyncScr(scrSync, &PreVR, NULL, NULL)); kisminda biraz aciklama yapayim.. birinci parametre ekran tarama hizi, ikinci parametre ekran tarama cizgisi cizmeye baslamadan onceki cagrilacak fonksion (bu fonksiyonun cok hizli calismasi gerekli), ucuncu parametre (biz NULL verdik), ekran tarama cizgisi aktif haldeyken cagrilacak fonksiyon (bunun da cok hizli calismasi gerekiyor), son parametre ise ekran tarama cizgisinin isi bittikten sonra cagrilan fonksiyon (bu fonksiyon digerlerine gore daha yavas olabilir, ama fazla abarmayin!). peki neden bu fonksiyonlar hizli olmak zorundalar ?.. nedeni su : CUNKU SANIYEDE ORTALAMA 60 KEZ CAGRILACAKLAR!. simdi anlamisinizdir :)).. senkronizasyon icin gerekli rutinleri tamamladik, artik yapilan isler muzik ile ayni hizda calisacak. fakat burda ufak bir sorun daha var :).. oda su muzik ile ayni hizda gitmek yeterli deil cunku aradaki (ornegin bir resim dosyasini diskten okumak vs..) isler her zaman ayni surede yapilmaz. nasi yani derseniz.. mesela tum hd'lerin hizlari ayni mi ?.. diil!!.. yada demo cd'den calistirilirsa daa yavas olucak hd'den.. bu yuzden iste.. yani muzigin belli noktalarinda belli seylerin olmasini istiyor iseniz ek kontroller ekliyorsunuz. mesela mi ? hmm.. mesela muzik'de bas sesler doruga vurdugunda (!) sizin ekrani flash ettirmenizi istediniz varsayalim.. eger kodunuz biraz gec kalirsa (her hangibir sebepten dolayi) flash'lar ile bas seslerin zamanlamalari ayni ana denk gelmeyebilir.. (ayni hizdalar ama ilerde veya geride kalmis olabilirler).. simdi tam olarak anlatabildim sanirim :).. bunun icin ne yapicaksiniz.. bu isde cok kolay.. yapmaniz gereken iki sey var. birincisi caldiginiz muzik icine ozel isaretler koymaniz gerekior. (mesela hani su bas seslerin doruga ulastigi noktalara) bu isaretler herhangi bir tracker programi ile yapilabilir..(zaten bi cogu buna destek de verir) bu isareti tracker programinda ses efektlerinin yazildigi kisma WXX seklinde verebilirsiniz W sabit yani bu bizim ozel kodumuz. geri kalan XX kismina her hangi bi sayi verebilirsiniz. program icinde bizde bu sayiya bakarak muzigin neresinde oldugu anlayabiliriz.. midas iste size bu isi yapan bi fonksiyon veriyor.. volatile int SyncInfo; simdi SyncInfo die bi deisken tanimladik bu deisken bizim muzik'deki en son rastladigimiz o ozel kodu gosteriyor. eger simdiye kadar hic bi koda rastlanmanmissa degeri -1'dir. void CALLING SyncCallback(unsigned syncNum, unsigned position, unsigned row) { SyncInfo = syncNum; } ........ if ( (error = gmpSetSyncCallback(midasPlayHandle, &SyncCallback)) != OK ) midasError(error); ........ bu fonksiyon ile muzik icinde her senkron koduna rastlandiginda SyncCallBack fonksiyonun cagrilmasini saglamis oluyoruz :).. artik programiniz icinde muzigin neresinde oldugunuzu SyncInfo deiskenine bakarak bulabilirsiniz. biraz onceki ornektekini anlatayim, ekrani hazirladiniz yazilar tamam ve muzikteki o bas sesi bekliyorsunuz, yapmaniz tek gereken su : void WaitMusicFor(int scrInfoByte) { do { if (inp(0x60) == 1) Cikis(strQuit); } while ( SyncInfo < scrInfoByte); } seklinde kendinize ozel bir fonksiyon yazin ve kod icerisinde WaitMusicFor(0x34); dediginizde artik 34'uncu koda rast gelininceye kadar donguden cikilmayacagi icin hersey durur ve ekranda bisi yapilmaz. yes!!.. senkronizasyon konusunda umarim anlasilmayan bisi yokturdur :) elimden geldigi kadar anlatmaya calistim , e bi coder'dan da ancak bu kadar :) hadin bolca bas seslerin doruga ulastigi zamanlarda flash'lar yapan demolar gorme umuduyla...