.[ ČeskéHry.cz ].
Synchronizace muziky (BPM)

 
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> Obecné
Zobrazit předchozí téma :: Zobrazit následující téma  
Autor Zpráva
rotacak



Založen: 19. 02. 2009
Příspěvky: 28

PříspěvekZaslal: 19. únor 2009, 20:46:19    Předmět: Synchronizace muziky (BPM) Odpovědět s citátem

Ahoj, nikde jinde jsem nedostal odpověď, tak to zkusím ještě tady Smile

Potřebuji sesynchronizovat puštěnou muziku (wav) s grafikou ve hře. Muziku pustím a nelze ji pauznout, nelze seek, ani nic jiného, prostě běží tak jak má, nelze ovlivnit.

Do toho potřebuju sesynchronizovat grafiku zobrazovanou na obrazovce. Třeba pro příklad při každém zvuku bubnu, zobrazit sprite.

Pokud to udělám tak, že nastavím napevno FPS třeba na 60 a jednou za 30FPS zobrazím sprite a sesynchronizuju to tak aby to sedělo, zdálo by se to ok.

Problém nastane, když buď nebude stačit výkon počítače (třeba jen chvilku, aktualizace antiviru...), tak FPS klesne pod 60, takže sprite se rozsynchronizuje s muzikou a bude se objevovat až do konce ve špatném místě. A nebo když buben nebude znít přesně na třicátým FPS, ale třeba na 30,1FPS, tak ke konci písničky se to taky rozjede mimo sebe.

Sice jsem si vytvořil pomůcku, která mi každou sekundu vrací grafiku na správné místo, pro případ že by se to rozjelo, ale je to nanic. Je vidět jak to skoro každou sekundu cukne.

Takže má někdo nějakou radu jakým způsobem tohle zprovoznit bez cukání? Třeba podobné řešení musí mít různé trackery na tvorbu hudebních modulů, tam se dá snadno měnit BPM (rychlost přehrávání) a nezávisí to absolutně na ničem (fps, vytížení procesoru...).

Použití timeru zklamalo, nedokázal spouštět funkci v přesně stejný čas po celou dobu a jiné spolehlivé/přesné řešení mě nenapadá.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Mem



Založen: 28. 07. 2007
Příspěvky: 1959
Bydliště: Olomouc

PříspěvekZaslal: 19. únor 2009, 21:51:29    Předmět: Odpovědět s citátem

No u té trackované hudby ti knihovna nebo rutina co to přehrává umí určitě podat (např. asynchronním eventem) informaci, když skočí na další řádek, mám dojem, že jsem s něčím podobným i pracoval u přehrávání MODů. To co používáš na přehrávání hudby/samplu by mohlo umět něco podobného. Druhá varianta je detekovat BPM čistě z přehrávaného zvuku, pokud je to tvoje hudba a máš tam třeba pravidelný beat, tak to není problém napsat (já psal pro jeden projekt na Guru.com realtime analyzátor vstupního zvuku pro detekci otáček motoru na sněžném skútru Smile)

Jinak poznámku s FPS a jeho výpadkem jsem nepochopil, víš přece, jak rychle ti běží hudba (a ta se nezasekává, ne) a pokud se ti povede provést synchronizaci, tak víš přesný čas a je ti úplně jedno, kdy budeš kreslit další frame. Prostě si spočítáš čas který uplynul od předchozího obrázku a podle toho animuješ. To samé přece musíš mít už implementované i pro normální kreslení, dělá se to úplně běžně, nebo ty skutečně spoléháš na fixní fps?
_________________


Naposledy upravil Mem dne 19. únor 2009, 21:54:49, celkově upraveno 1 krát
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
Ladis



Založen: 18. 09. 2007
Příspěvky: 1536
Bydliště: u Prahy

PříspěvekZaslal: 19. únor 2009, 21:54:23    Předmět: Odpovědět s citátem

Ve spouste audio knihovnach je mozne na zpracovavana audio data hodit callback, ktery muzes pouzit treba k "zobrazeni" hudby. Tak neco takoveho pohledej v tebou pouzivanem API, vzdyt to pouzivaji vsechny prehravace, co umi "vizualizovat" hudbu.

Samozrejme zalezi na formatu audio souboru, pokud je to MP3/WAV, tak musis bubny apod. jen odhadovat podle hlasitosti v ruznych pasmech frekvenci. Kdyby jsi pouzival MIDI nebo nejaky trackerovy format, tak tam jsou primo "noty", ale to by jsi si musel najit nejaky loader, aby jsi moh pracovat s puvodnimi daty namisto vysledneho WAVE vystupu do zvukovky.

Pokud jde jen o synchronizaci, tak bych to resil taky tim callbackem, pac ten prijde presne na dalsi blok dat, a ten blok dat (audio chunk) ma vzdy pevnou casovou delku (v zavislosti na nastaveni kvality prehravani audia zadanem pri inicializaci).
_________________
Award-winning game developer
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
rotacak



Založen: 19. 02. 2009
Příspěvky: 28

PříspěvekZaslal: 19. únor 2009, 22:31:13    Předmět: Odpovědět s citátem

Detekovat to nepůjde, protože nejde jen o bubny ale o ostatní zvuky a nelze se spolehnout na detekci, která by ve složité muzice ani nešla použít. Ale já mám "noty" puštěné současně s muzikou, jde "jen" o to, aby byly puštěné stejnou rychlostí a nerozjížděly se.

Teď to mám udělané podle FPS jako nouzové řešení. Jak říkám, zkoušel jsem timer a ten nebyl schopen udržet volání funkce v daném čaovém intervalu, jestli je to vůbec možné. Protože dejme tomu, že teď mi to jakž takž funguje na 60FPS. To je 60x provedení hlavní smyčky za sekundu. Kdybych to chtěl mít nezávislé na FPS, použil bych ten timer/event aby spustil popojetí "not" na další řádek každých 16,666666666666666666666666666667 milisekund.

A stejně by se to nejspíš rozjelo, nemluvě o tom, že takhle velké číslo mi to ani nedovolí použít a když tam dám 16,6 nebo 16,7, tak na konci písničky jsem zase mimo.

Takže buď použít spolehlivější timer, nebo to udělat jinak? Jde vůbec v takhle malém čase spolehlivě pravidleně volat funkce? Protože pak se taky může stát, že než se dokončí volaná funkce, tak už je volána znovu a pak si nepomůžu.

Ladis: máš nějakej příklad jaká knihovna by na to byla vhodná? Jedná se o wav. Nejradši bych ale měl nějké svoje řešení.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
franz



Založen: 30. 07. 2007
Příspěvky: 1325

PříspěvekZaslal: 19. únor 2009, 22:33:28    Předmět: Odpovědět s citátem

Musíš se řídit pozicí v hudbě, kterou taky každý přehrávač vrací (například v fmod je to FSOUND_Stream_GetPosition).

Vytvořil bych si proměnnou 0, která se s každým tickem zvýší o 1 tolikrát, dokud bude její hodnota menší, než pozice v hudbě (a s každým zvýšením otestovat událost - zde bude ručně nadefinováno, na které hodnotě se co stane).

// Samozřejmě samotná grafika musí fungovat stejně, nikoliv fixní fps, ale s každým tickem zahýbat grafikou tolik, kolik ms uteklo od ticku minulého.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Marek



Založen: 28. 07. 2007
Příspěvky: 1782
Bydliště: Velká Morava

PříspěvekZaslal: 19. únor 2009, 22:50:29    Předmět: Odpovědět s citátem

Co myslíš slovem "timer"? Používals doufám performance counter, ne? Protože měřit čas něčím jiným ani nemá smysl.
_________________
AMD Open Source Graphics Driver Developer
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
pcmaster



Založen: 28. 07. 2007
Příspěvky: 1824

PříspěvekZaslal: 20. únor 2009, 01:53:19    Předmět: Odpovědět s citátem

Podla mna ma ovela zakladnejsi problem Wink a timerom mysli nejaku blbu timer komponentu v nejakom IDE (Delphi, C#...)

Rotacak: zabudni, ze timery existuju!

Ty potrebujes mat game loop, ktory je asi nasledovny:

kód:

while True:
  timeNow = getCurrentMilliseconds()
  delta = timeNow - lastTime
  lastTime = timeNow
  ..
  update game logic
  ..
  render some stuff

getCurrentMilliseconds() bude nieco ako timeGetTime() alebo queryPerformanceCounter() ako spominal Eosie. Proste to vrati aktualny cas. Delta je cas, ktory uplynul od predchadzajuceho snimku. Nie je tam nijaky sleep (ale moze byt) a bezi to tak rychlo, ako to len ide. To znamena, ze kazdy frame moze byt (a bude) delta trochu odlisne!

V update/render si vygenerujes svoje "reakcie" na hudbu (ktorej frekvencia je dopredu znama!). Mozes to spravit asi takto:

V pripade, ze timeNow >= timeToGenerate, vygenerujes sprite a "posunies" vzhladom na uplynuly cas.
Napr:
kód:
position = startPos + velocity * timeFromStart,
kde timeFromStart=timeNow-timeToGenerate

V pripade, ze to neplati, nevygenerujes nijake sprity/reakcie. V pripade, ze uplynul cas, za ktory sa malo vygenerovat viac spritov, vygenerujes viac spritov a kazdy patricne nastavis. timeToGenerate si spocitas z frekvencie, napriklad timeToGenerate[i] = startOfTheUniverse + i * (1/freq). Dufam, ze chapes Smile

Tymto sposobom budes mat na obrazovke vzdy tolko spritov, kolko potrebujes a bude jedno aky rychly je pocitac (ci to bezi 85 FPS alebo 30 FPS a hudba ma furt frekvenciu 60 Hz)
_________________
Off-topic flame-war addict since the very beginning. Registered since Oct. 2003!
Interproductum fimi omne est.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Mem



Založen: 28. 07. 2007
Příspěvky: 1959
Bydliště: Olomouc

PříspěvekZaslal: 20. únor 2009, 08:23:27    Předmět: Odpovědět s citátem

pcmaster: Díky za rozepsání mé poznámky "Prostě si spočítáš čas který uplynul od předchozího obrázku a podle toho animuješ. To samé přece musíš mít už implementované i pro normální kreslení, dělá se to úplně běžně" Wink
_________________
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
wozembouch



Založen: 03. 09. 2007
Příspěvky: 31

PříspěvekZaslal: 20. únor 2009, 12:06:02    Předmět: Odpovědět s citátem

rotacak napsal:
... použil bych ten timer/event aby spustil popojetí "not" na další řádek každých 16,666666666666666666666666666667 milisekund.

A stejně by se to nejspíš rozjelo, nemluvě o tom, že takhle velké číslo mi to ani nedovolí použít a když tam dám 16,6 nebo 16,7, tak na konci písničky jsem zase mimo.


Ano, protoze s kazdym "uderem" timeru scitas chybu...
Osobne bych pozici v notach pocital v game loopu takhle:

Pozice := (CurrentTimeStamp - StartMusicTimeStamp) / 16.6

StartMusicTimeStamp je casova znacka, kterou si ulozis pri startu hudby. K zjisteni casovych znacek pouzij QueryPerformanceCounter a QueryPerformanceFrequency ...
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
quas4



Založen: 18. 10. 2007
Příspěvky: 199

PříspěvekZaslal: 20. únor 2009, 12:56:01    Předmět: Odpovědět s citátem

pcmaster napsal:

Ty potrebujes mat game loop, ktory je asi nasledovny:

kód:

while True:
  timeNow = getCurrentMilliseconds()
  delta = timeNow - lastTime
  lastTime = timeNow
  ..
  update game logic
  ..
  render some stuff



Tak tohle presne nedoporucuju. Prudka zmena fps je v tomto podani pro oci citelna. Mam velmi dobre zkusenosti s oddelenim logiky (konstantni frekvence) od renderingu. viz zde: http://gafferongames.com/game-physics/fix-your-timestep/
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
pcmaster



Založen: 28. 07. 2007
Příspěvky: 1824

PříspěvekZaslal: 20. únor 2009, 14:25:20    Předmět: Odpovědět s citátem

Ja osobne si myslim, ze je to pre neho velmi vhodne riesenie. Nemusi sa trapit s vlaknami a ich synchronizaciou a tak podobne. A pomoze mu to pochopit, ze timer je zly Razz
Okrem toho, ak rozdelis logiku do viacerych vlaken, tak ti sleep() nikdy nezaruci, ze bude vlakno spat presne tak dlho, ako potrebujes, plus musis este zapocitat cas potrebny na synchronizaciu na zdielanych datach a aj tak si musis nieco podobne vzdy vypocitat.

Netvrdim, ze je to ultimatne najlepsie riesenie, ale pre neho je dobre.
_________________
Off-topic flame-war addict since the very beginning. Registered since Oct. 2003!
Interproductum fimi omne est.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
rotacak



Založen: 19. 02. 2009
Příspěvky: 28

PříspěvekZaslal: 20. únor 2009, 14:35:19    Předmět: Odpovědět s citátem

Díky za rady, pokusím se tím prohrabat.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
quas4



Založen: 18. 10. 2007
Příspěvky: 199

PříspěvekZaslal: 20. únor 2009, 19:37:50    Předmět: Odpovědět s citátem

pcmaster napsal:
Okrem toho, ak rozdelis logiku do viacerych vlaken, tak ti sleep() nikdy nezaruci, ze bude vlakno spat presne tak dlho, ako potrebujes, plus musis este zapocitat cas potrebny na synchronizaciu na zdielanych datach a aj tak si musis nieco podobne vzdy vypocitat.


Moment, o vlaknech jsem nic nepsal a ani v clanku o nich neni zadna zminka (nepocitam diskusi). Je to jen elegantni reseni (vlakna nejsou potreba) jak se vyhnout neprijemnym efektum pri rychlych zmenach fps a zaroven mit fixni frekvenci aktualizace logiky.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
pcmaster



Založen: 28. 07. 2007
Příspěvky: 1824

PříspěvekZaslal: 20. únor 2009, 20:54:26    Předmět: Odpovědět s citátem

Ja sa musim priznat, ze som ten clanok necital a nespravne som vyvodil, ze odporucas druhy pristup.
_________________
Off-topic flame-war addict since the very beginning. Registered since Oct. 2003!
Interproductum fimi omne est.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Augi



Založen: 28. 07. 2007
Příspěvky: 782
Bydliště: Čerčany

PříspěvekZaslal: 20. únor 2009, 21:03:49    Předmět: Odpovědět s citátem

Vlákna taky bylo první, co mě napadlo, ale v tom článku se zjednodušeně řečeno píše jen o tom, že se průběžně sčítají rozdíly času a když ten součet přesáhne určité hodnoty, tak se teprve provede update logiky/fyziky. Příp. se to dá vylepšit o "blendování" předchozího a následujícího stavu.
To je dobrej nápad, kterej jednoduše ošetří případy příliš vysokého FPS. Příliš malé FPS se dá řešit jednoduše rozdělením intervalu a provedení několik aktualizací logiky/fyziky.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
Zobrazit příspěvky z předchozích:   
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> Obecné Časy uváděny v GMT + 1 hodina
Strana 1 z 1

 
Přejdi na:  
Nemůžete odesílat nové téma do tohoto fóra
Nemůžete odpovídat na témata v tomto fóru
Nemůžete upravovat své příspěvky v tomto fóru
Nemůžete mazat své příspěvky v tomto fóru
Nemůžete hlasovat v tomto fóru


Powered by phpBB © 2001, 2005 phpBB Group


Vzhled udelal powermac
Styl "vykraden" z phpBB stylu MonkiDream - upraveno by rezna