Welcome, Guest. Please login or register.


Author Topic: Xep128 (Read 164943 times)

Offline lgb

  • EP addict
  • *
  • Posts: 3563
  • Country: hu
  • æðsta yfirmaður
    • http://lgb.hu/
Re: Xep128
« Reply #195 on: 2016.March.08. 21:50:11 »
A 4.5 az a Z80 ciklusok száma 1 NICK slot alatt, közelítően (4000000 / 889846 = 4.49516). Én alapvetően úgy oldottam meg, hogy minen VRAM és NICK port hozzáférésnél várni kell a következő NICK slotig, 1/2 Z80 ciklus felbontással. Ezen kívül van még egy fix késleltetés is, ami kb. 5/16 NICK slot + egy néhány ns-os érték (ami függ a hozzáférés típusától, azaz kissé eltér M1, normál írás/olvasás, és port I/O esetén, de ez minimális mértékű). Itt található egy program, amellyel tesztelhető a VRAM időzítés, Zozosoft több valódi gépről is küldött eredményeket, amelyekkel az emulátorok összehasonlíthatók.

Az a baj, hogy en itt mar eleve, az elmeletet sem latom tisztan. Most elfeledkezve az emulator adta megvalositasi lehetosegekrol ... hogyan nez ki ez valodi gepen? Amennyire en tudom, a Nick ugye egy fix frekvenciaval olvas. Marmint egy Nick slot alatt 2 byte-ot. De pl mindig? Van olyan videomod ahol eleg egy is, pl LPIXEL, akkor mi van? Masreszt, ezt ugy kell elkepzelni, hogy a Nick altal adott olvasasi jel formaja az szep egyenletes, slot-on kivul, belul, minden, szabalyos? Na, ehhez jon akkor hozza - tudomasom szerint - hogy a Nick szepen kicsit "megnyomoritja" a CPU orajelet (ha o is VRAM-hoz ferne hozza v Nick I/O portjahoz), annak erdekeben, hogy ne utkozzenek. Na ezt eleg nehezen tudom elkepzelni. Egyreszt, mivel a CPU orajelet vmi generalja, azt hogy allitjak meg? Mert az szepen megy "magatol", ha a CPU fele "nyujtani" kell, akkor amikor ennek vege, lehet akar egy csunya tranziens is, mert kozben a kristaly (vagy ami generalja) mar epp a masik szintre menne, stb. Masreszt, a "nyujtas" ha jol tippelek nem is orajel egesz szamu tobbszorose, szoval ezt pontosan emulalni tenyleg nehez lenne (mar ha erdemes egyaltalan ...).

Vagy kiforditom az egesz Xep128-at: jelenleg CPU-ra orajelet szamolja ahhoz idozit, es abbol lesz a Nick slot frekvencia. Lehet inkabb ugy kene, hogy Nick slot-okat renderelek szepen, es ahhoz aztan a CPU-t. Igy "termeszetesebben" adodik, hogyan befolyasolja a Nick mukodese szegeny CPU-t :-P Mondjuk tok jo, akkor mar csak a Dave kavar be, mert az meg jelenleg a CPU-hoz van szinkronizalva (/16 v /24), de ha meg nyujtogatjak szegeny CPU orajelet, abbol a Dave is kap, vagy hat nekem ez az egesz kicsit talanyos :)

Tudom, irtad, hogy lehet kb megoldani, de oszinten en a valodi mukodesbol szeretnem megerteni :)

Quote
A megvalósításnál problémát jelenthet az, hogy a Z80 utasításokon belüli időzítés is fontos, azaz hogy pontosan mikor történnek az egyes memória és I/O műveletek (pl. az OUT (C), A utasításnál 2.0, 6.0, és 11.5 ciklusnál), nem tudom, a z80ex támogatja-e ezt.

Hat ebben nem vagyok biztos, hogy korrektul, de amugy elvileg igen, a t-state infot opcode-on belul is szamolja. Az mas kerdes, hogy korrekt-e a megoldas, marmint a hasznalt ertekek, es nem csak pl a vegeredmeny jo :) Amit irtal abban mondjuk a 11.5 az elgondolkoztatott, mivel tort szamu orajelet viszont tuti nem tart nyilvan ... Mondjuk amit irtal az fura, az OUT (C), A az 12 (?) t-state, akkor ha 11.5-nel kezdodik a port iras, akkor csak fel orajelciklusa van a periferianak, hogy fogja? Vagy mire vonatkozik a 11.5, akkor mi tortenik?

https://github.com/lgblgblgb/xep128/blob/master/z80ex/opcodes/opcodes_ed.c

482. sortol, az OUT() macro 3. parametere, elvileg az (bar z80ex belsejet annyira nem ismerem, csak igy kb), hogy hanyadik ciklusnal. Az opcode ED resze mondjuk kulon van, tehat ugy nezendo a dolog :) Igy csak 8 ciklus, de az ED-re ramegy 4, tehat a 12 elvileg kijon.

Quote
Erről néhány oldallal korábban írtam, az ep128emu-ban gyakorlatilag a hang lejátszás lassítja 100% sebességre az emulációt. Ez a legegyszerűbb esetben annyit jelent, hogy ahol eredetileg usleep() vagy hasonló hívás volt, ott helyette arra vár, hogy legyen hely a hang pufferben. Ez azonban nem ad igazán jó eredményt, az audio puffer gyakran túl nagy ahhoz, hogy jó felbontással lehessen időzíteni, ezért így könnyen előfordulhat, hogy láthatóan és zavaróan akadozik a kép pl. scrollozásnál.

Na. Ismeros :) Amikor MPlayer fejleszto voltam (bar ebben a temaban ott sem jeleskedtem, inkabb mashol), ott is ugy epult fel, hogy az audiohoz van szinkronizalva minden, ha nincs hang vagy "noaudio" opcio akkor vmi fake cuccot csinal. Ott is az volt a gond, hogy nehany "vacak" drivernel a buffer kezeles csapnivalo volt, igy idozitesre hasznalva eleg fura dolgok adodtak neha :)

Offline Zozosoft

  • Global Moderator
  • EP addict
  • *
  • Posts: 14723
  • Country: hu
    • http://enterprise.iko.hu/
Re: Xep128
« Reply #196 on: 2016.March.08. 22:24:59 »
Van a rendszerórajel (normál gépen 8MHz), ezen fut a Dave. A Z80-nak a Nick osztja le, azonban ha olyan dolog van, ami miatt osztoznának a videó buszon, akkor amíg fogja a CPU-t, addig adott szinten marad.
Itt elmélkedtem erről.

NOP futattása VRAM-ban, a képen Z80 clock, és RD:
[ Guests cannot view attachments ]

Offline szipucsu

  • Global Moderator
  • EP addict
  • *
  • Posts: 9898
  • Country: hu
    • Támogató Támogató
    • Webnyelv.hu - Tanuljunk nyelveket!
Re: Xep128
« Reply #197 on: 2016.March.08. 23:40:03 »
NOP futattása VRAM-ban, a képen Z80 clock, és RD:
[ Guests cannot view attachments ]
(Majdnem a "találjuk ki a kép alapján, melyik játék" topikba tettem ezt.)
Ez a folyosó nagyon szűk, elég nehéz lehet rajta átférni.
100 SOUND SOURCE 2,STYLE 128,PITCH 25.2,SYNC 1
110 SOUND PITCH 25,SYNC 1
120 ! Videos

Offline IstvanV

  • EP addict
  • *
  • Posts: 4822
Re: Xep128
« Reply #198 on: 2016.March.09. 00:20:45 »
Quote
Amit irtal abban mondjuk a 11.5 az elgondolkoztatott, mivel tort szamu orajelet viszont tuti nem tart nyilvan ... Mondjuk amit irtal az fura, az OUT (C), A az 12 (?) t-state, akkor ha 11.5-nel kezdodik a port iras, akkor csak fel orajelciklusa van a periferianak, hogy fogja? Vagy mire vonatkozik a 11.5, akkor mi tortenik?

A Z80 dokumentációjában itt lehet olvasni a memória és I/O műveletek időzítéséről (24. oldal, "CPU timing"). Az OUT (C), A három M-state, két utasítás olvasás és egy I/O írás. Ezeken belül az emulátor számára az adatbusz mintavételezésének az időpontja az érdekes, azaz az ábrákon a "VALID DATA", ami M1-nél a T3 felfutó éle (2.0 ciklus), egyéb memória és I/O műveletnél pedig a T3 lefutó éle (2.5 és 3.5 ciklus, mert I/O esetén mindig van egy ciklus várakozás). Feltételezésem szerint az ezeket megelőző fél ciklust kell nyújtani a rendszer órajel (8 MHz) egész számú többszörösével.



|       M1 (EDh)        |          M1           |          I/O          |
|                       |                       |                       |
|T1    T2    T3    T4   |T1    T2    T3    T4   |T1    T2    TW    T3   |
+--+  +--+  +--+  +--+  +--+  +--+  +--+  +--+  +--+  +--+  +--+  +==+  |
|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
+  +--+  +==+  +--+  +--+  +--+  +==+  +--+  +--+  +--+  +--+  +--+  +--|
|           *           |           *           |                    *  |
0          2.0          4          6.0          8                  11.5 12


Az a baj, hogy en itt mar eleve, az elmeletet sem latom tisztan. Most elfeledkezve az emulator adta megvalositasi lehetosegekrol ... hogyan nez ki ez valodi gepen? Amennyire en tudom, a Nick ugye egy fix frekvenciaval olvas. Marmint egy Nick slot alatt 2 byte-ot. De pl mindig? Van olyan videomod ahol eleg egy is, pl LPIXEL, akkor mi van?

A video mód a Z80 időzítése szempontjából nem lényeges, a CPU minden slot-ban csak egy byte-ot olvashat (például a kereten is).

Quote
Na ezt eleg nehezen tudom elkepzelni. Egyreszt, mivel a CPU orajelet vmi generalja, azt hogy allitjak meg? Mert az szepen megy "magatol", ha a CPU fele "nyujtani" kell, akkor amikor ennek vege, lehet akar egy csunya tranziens is, mert kozben a kristaly (vagy ami generalja) mar epp a masik szintre menne, stb. Masreszt, a "nyujtas" ha jol tippelek nem is orajel egesz szamu tobbszorose, szoval ezt pontosan emulalni tenyleg nehez lenne (mar ha erdemes egyaltalan ...).

A CPU várakoztatása valószínűleg 8 MHz-es rendszer (DAVE) órajel ciklusokban történik, tehát nem nagyon rontja el a jelet. Bár Zozosoft oszcilloszkópos képein nem tűnik teljesen szabályosnak az időzítés, az újraindítás utáni első fél ciklus mintha lassabb lenne.

Offline IstvanV

  • EP addict
  • *
  • Posts: 4822
Re: Xep128
« Reply #199 on: 2016.March.09. 12:42:49 »
Vagy kiforditom az egesz Xep128-at: jelenleg CPU-ra orajelet szamolja ahhoz idozit, es abbol lesz a Nick slot frekvencia. Lehet inkabb ugy kene, hogy Nick slot-okat renderelek szepen, es ahhoz aztan a CPU-t. Igy "termeszetesebben" adodik, hogyan befolyasolja a Nick mukodese szegeny CPU-t :-P Mondjuk tok jo, akkor mar csak a Dave kavar be, mert az meg jelenleg a CPU-hoz van szinkronizalva (/16 v /24), de ha meg nyujtogatjak szegeny CPU orajelet, abbol a Dave is kap, vagy hat nekem ez az egesz kicsit talanyos :)

Én a slot-ot használtam a fő emulációs ciklusban az egységnyi időnek, illetve Spectrum és CPC esetén ennek megfelelően egy karakter időtartamát vízszintesen:
Code: C++
  1.     do {
  2.       Ep128VMCallback   *p = firstCallback;
  3.       while (p) {
  4.         Ep128VMCallback *nxt = p->nxt;
  5.         p->func(p->userData);
  6.         p = nxt;
  7.       }
  8.       daveCyclesRemaining += daveCyclesPerNickCycle;
  9.       if (daveCyclesRemaining >= 0L) {
  10.         do {
  11.           daveCyclesRemaining -= (int64_t(1) << 32);
  12.           soundOutputSignal = dave.runOneCycle();
  13.           sendAudioOutput(soundOutputSignal + externalDACOutput);
  14.         } while (EP128EMU_UNLIKELY(daveCyclesRemaining >= 0L));
  15.       }
  16.       cpuCyclesRemaining += cpuCyclesPerNickCycle;
  17.       while (cpuCyclesRemaining >= 0L)
  18.         z80.executeInstruction();
  19.       nick.runOneSlot();
  20.     } while (EP128EMU_EXPECT(--cycleCnt));

A Spectrum és CPC emulációban még további trükköket alkalmaztam annak a megoldására, hogy a Z80 és a többi alkatrész (ULA, CRTC, stb.) között ciklus pontosságú legyen a szinkronizáció utasításon belül is, mivel egy utasítás hosszabb lehet, mint egy slot. Ez a Spectrumos Z80 port írás függvény például hívja az ULA/hang/stb. emulációt (vm.runOneCycle()) ha már elég idő telt el, és hasonló megoldás található a memória írásnál is:
Code: C++
  1.   EP128EMU_REGPARM3 void ZX128VM::Z80_::doOut(uint16_t addr, uint8_t value)
  2.   {
  3.     addressBusState.W = addr;
  4.     vm.ioPortWait(addr);
  5.     while (vm.z80OpcodeHalfCycles >= 8)
  6.       vm.runOneCycle();
  7.     vm.ioPorts.write(addr, value);
  8.     vm.updateCPUHalfCycles(1);
  9.   }

Az EP emulátor egyelőre nem tud ilyet :oops:, de az EP-s programok szerencsére kevésbé érzékenyek az időzítés pontosságára.

A plus4emu-ban a 6502 emulátor nem utasításonként, hanem ciklusonként fut, és a TED emulátor hívja egy karakteren belül megfelelő időzítéssel legfeljebb kétszer.

Offline lgb

  • EP addict
  • *
  • Posts: 3563
  • Country: hu
  • æðsta yfirmaður
    • http://lgb.hu/
Re: Xep128
« Reply #200 on: 2016.March.09. 13:28:41 »
Erdekes a fel ciklusos updateCPUHalfCycles() es hasonlok :) Amugy a z80ex egy library (csak kozben kisse kihereltem ...), amit a FUSE Specrum emu alapjan (is?) irtak. Tud olyat, hogy t-state callback, azaz minden t-state-nel meghiv egy fuggvenyt, az utasitas vegrehajtasa soran. De ilyen fogalom nem igazan van benne ahogy nezem, hogy half cycle ...

Offline IstvanV

  • EP addict
  • *
  • Posts: 4822
Re: Xep128
« Reply #201 on: 2016.March.09. 13:38:47 »
Erdekes a fel ciklusos updateCPUHalfCycles() es hasonlok :) Amugy a z80ex egy library (csak kozben kisse kihereltem ...), amit a FUSE Specrum emu alapjan (is?) irtak. Tud olyat, hogy t-state callback, azaz minden t-state-nel meghiv egy fuggvenyt, az utasitas vegrehajtasa soran. De ilyen fogalom nem igazan van benne ahogy nezem, hogy half cycle ...

Az elég, ha a z80ex annyi információt ad, hogy milyen művelet történik (M1, memória, vagy I/O - ezeken belül az időzítés fix, illetve csak a NICK vagy a DAVE módosíthatja) és az utolsóhoz képest hány Z80 ciklus telt el, a többit már az emulátor valósíthatja meg.

Offline IstvanV

  • EP addict
  • *
  • Posts: 4822
Re: Xep128
« Reply #202 on: 2016.March.09. 18:04:20 »
AEgyreszt, mivel a CPU orajelet vmi generalja, azt hogy allitjak meg? Mert az szepen megy "magatol", ha a CPU fele "nyujtani" kell, akkor amikor ennek vege, lehet akar egy csunya tranziens is, mert kozben a kristaly (vagy ami generalja) mar epp a masik szintre menne, stb. Masreszt, a "nyujtas" ha jol tippelek nem is orajel egesz szamu tobbszorose, szoval ezt pontosan emulalni tenyleg nehez lenne (mar ha erdemes egyaltalan ...).

Ez nem probléma, a Z80 órajelét a NICK csak a 8 MHz-es rendszer órajel egész számú ciklusára állítja meg, azaz Z80 órajelben a várakozás mindig 0.5 ciklus többszöröse (4 MHz-es gépen 1.0, 1.5, ..., 5.0, vagy 5.5 ciklus). Másként nem is nagyon lehetett volna megoldani, mert különben nem lenne szinkronban a Z80 és a DAVE.

Quote
Mondjuk tok jo, akkor mar csak a Dave kavar be, mert az meg jelenleg a CPU-hoz van szinkronizalva (/16 v /24), de ha meg nyujtogatjak szegeny CPU orajelet, abbol a Dave is kap, vagy hat nekem ez az egesz kicsit talanyos :)

A DAVE órajelét nem kell nyújtani, az fix 8 MHz (legalábbis 4 MHz-es gépen). A 16 vagy 24 osztónak (4 MHz-hez képest) a hanggenerátoroknál és az 1/50/1000 Hz-es megszakításnál van jelentősége.

Quote
Na. Ismeros :) Amikor MPlayer fejleszto voltam (bar ebben a temaban ott sem jeleskedtem, inkabb mashol), ott is ugy epult fel, hogy az audiohoz van szinkronizalva minden, ha nincs hang vagy "noaudio" opcio akkor vmi fake cuccot csinal. Ott is az volt a gond, hogy nehany "vacak" drivernel a buffer kezeles csapnivalo volt, igy idozitesre hasznalva eleg fura dolgok adodtak neha :)

Ezért építettem be a korábban leírt megoldást, az emulátor beta verzióiban sokakat zavart az akadozó scroll és egyéb képhibák, amelyeket az audio driver rossz időzítése okozott. Linuxon az ALSA hw és plughw eszközök közvetlenül használva kis pufferrel elég jók, de a PulseAudio és egyéb szoftveres keverők a Windowshoz hasonlóra rontják az időzítést.

A hang emulációnál a DAVE kimenetének a konvertálása is jelenthet kisebb nehézséget, mivel az több száz kHz-es (a BFh port beállításától függően 250 vagy 166.67 kHz a mintavételezési frekvencia), és mindig pozitív (az egyes csatornák 0 és 63 közötti értékeket adnak, ez keverve 0-252). Az ep128emu-ban az snd_conv.cpp végzi a DC szűrést és konvertálást. Az utóbbi megoldható külső lib használatával is, saját kódnál a legegyszerűbb - de nem túl jó minőségű - megoldás 4 vagy 6 (az osztótól függően) hangminta átlagának a számítása, amivel 41667 Hz-es a kimenet.

Offline lgb

  • EP addict
  • *
  • Posts: 3563
  • Country: hu
  • æðsta yfirmaður
    • http://lgb.hu/
Re: Xep128
« Reply #203 on: 2016.March.09. 22:55:47 »
https://github.com/lgblgblgb/xep128/commit/f942616de761b74e02913608a678b24aa5c1d87f

Elso roppant bena, pontatlan, elvi szinten hibas, stb megoldas. Viszont valamit legalabb csinal, haaat, fogjuk ra :) SD au player amugy vegy vele, csak hat neha csuklik, de ez nem is meglepo :)

Ja, es UNIX power, SD kartya device-t be-symlinkeltem sdcard.img -nek, igy az emulator vegulis igazi SD kartyat hasznalt, ha az OS-en at is :-D
« Last Edit: 2016.March.09. 23:03:44 by lgb »

Offline IstvanV

  • EP addict
  • *
  • Posts: 4822
Re: Xep128
« Reply #204 on: 2016.March.10. 12:19:25 »
Elso roppant bena, pontatlan, elvi szinten hibas, stb megoldas. Viszont valamit legalabb csinal, haaat, fogjuk ra :) SD au player amugy vegy vele, csak hat neha csuklik, de ez nem is meglepo :)

Valószínűleg a puffer méretén kellene állítani, ez néha problémás, ami az egyik driveren jól működik, az a másikon nem.

A hanggenerátorok működéséről itt írtam régebben, a 0-2 csatorna lényege egy tároló (flip-flop), amelynek az állapota a következő esetekben változik:
- amikor lefut a számláló, akkor vagy átbillen (ha nincs torzítás), vagy a választott polinom számláló aktuális kimenetét mintavételezi
- felüláteresztő szűrő engedélyezésekor a másik csatorna kimenetének a lefutó élei 0-ra állítják az állapotot
- a sync bit beállítása szintén 0 kimenetet eredményez

A gyűrűmodulációt ezek után kell alkalmazni (ha engedélyezett), ez XNOR műveletet végez a másik csatorna kimenetével.

A tone csatornák polinom számlálói folyamatosan futnak 250 vagy 166.67 kHz frekvencián, és ezzel az algoritmussal valósíthatók meg:
- a számláló aktuális állapotának két bitje között XOR műveletet kell végezni, ez lesz majd az új kimenet és 0. bit
- az értéket egy bittel balra léptetni, és az új 0. bit a XOR eredménye
- inicializálásnál célszerű minden bitet 1-re állítani, a 0 érték érvénytelen (mivel így végtelen ciklusban 0 lenne a kimenet)
Példa 4 bites számlálóra:
Code: C
  1. int polycnt4 = 0x0F;
  2. {
  3.   int output = ((polycnt4 >> 3) ^ (polycnt4 >> 2)) & 1;
  4.   polycnt4 = ((polycnt4 & 0x07) << 1) | output;
  5.   // ...
  6. }

Egyszerű előjel nélküli 8 bites hang kimenetnél probléma lehet még a DC offszet, azaz amikor nincs hang, akkor (előjeles formátumra konvertálva) nagy negatív érték a kimenet 0 (illetve U8 formátumban 128) helyett. Ez - valódi hardverhez hasonlóan megvalósítva - például így szűrhető:
Code: C
  1. double filter_state = 0.0;
  2. const double c = 0.998493172;    // 10 Hz at 41667 Hz sample rate, c ~= exp(-2 * PI * fco / fs)
  3. {
  4.   filter_state = (filter_state * c) + (dave_out * (1.0 - c));
  5.   double filter_output = dave_out - filter_state;
  6.   // ...
  7. }

Offline lgb

  • EP addict
  • *
  • Posts: 3563
  • Country: hu
  • æðsta yfirmaður
    • http://lgb.hu/
Re: Xep128
« Reply #205 on: 2016.March.10. 13:16:06 »
Ja, koszi, olvastam am azokat :) Csak ezzel meg nem foglalkoztam.

Offline lgb

  • EP addict
  • *
  • Posts: 3563
  • Country: hu
  • æðsta yfirmaður
    • http://lgb.hu/
Re: Xep128
« Reply #206 on: 2016.March.10. 13:56:10 »
A szokott helyen van ujabb zip - http://xep128.lgb.hu/ -, benne windows-os exe. Ha minden jol megy, ebben mar ujraforditas nelkul is kiprobalhato a hang, bar tenyleg nem kerek reklamaciokat, ugyanis tudom, hogy kb minden szempontbol rossz :) Kiprobalni meg ugy kell, hogy alapbol nincs hang, viszont ezt az EXOS parancsot beadva:

:XEP AUDIO

akkor utana elvileg lesz, max egy kis ido mulva csak :-P Igen, frekvencia sem teljesen pontos, akad, szaggat, nincs ez, nincs az, stb :) Tiszta JSep audio feeling :)

Offline Zozosoft

  • Global Moderator
  • EP addict
  • *
  • Posts: 14723
  • Country: hu
    • http://enterprise.iko.hu/
Re: Xep128
« Reply #207 on: 2016.March.10. 14:03:51 »
Működik :-D

Offline lgb

  • EP addict
  • *
  • Posts: 3563
  • Country: hu
  • æðsta yfirmaður
    • http://lgb.hu/
Re: Xep128
« Reply #208 on: 2016.March.11. 00:16:17 »
Működik :-D

Az SD AU player is elvileg megy vele, bar - nem meglepo modon - szaggat azert, hala az audio puffer idozitesi/sync problemaknak (is?). Az ep128emu "sd-sitese" kapcsan meg adtam az image-et hozza :)

Offline IstvanV

  • EP addict
  • *
  • Posts: 4822
Re: Xep128
« Reply #209 on: 2016.March.11. 20:22:04 »
akkor utana elvileg lesz, max egy kis ido mulva csak :-P Igen, frekvencia sem teljesen pontos, akad, szaggat, nincs ez, nincs az, stb :)

Az akadozást az okozhatja, hogy az időzítést továbbra is az emu_timekeeping_delay() végzi, és az audio puffer állapotát nem veszi figyelembe. Így idővel "elmászik" az időzítés, és a puffer megtelik (overrun) vagy elfogy az adat (underrun), azaz szaggat a hang. Erre az egyszerűbb megoldás az emu_timekeeping_delay() helyett az audio puffer írásánál várakozni (pl. SDL_SemWait()) ha megtelik, amíg újra lesz szabad hely. Így azonban teljesen az audio drivertől függ az időzítés, tehát könnyen előfordulhat, hogy a kép fog akadozni. Egy másik lehetőség az eredeti időzítő rutinban a sebességet szabályozni az audio puffer állapotától függően (gyorsítani 50% alatt, lassítani 50% felett).