ENGLISH VERSION |
|
Links | | | Forum | | | Kommentare | | | News melden |
Chat | | | Umfragen | | | Newsticker | | | Archiv |
amiga-news.de Forum > Programmierung > Registerzugriff in C | [ - Suche - Neue Beiträge - Registrieren - Login - ] |
1 2 -3- 4 | [ - Beitrag schreiben - ] |
08.11.2007, 23:47 Uhr MaikG Posts: 5172 Nutzer |
>Ach ja, Du kannst STARTOFFSET auch einen größeren Wert zuweisen - dann startet die Audio-Ausgabe verzögert und somit stehen mehr Daten bereit, bevor eine hörbare Ausgabe erfolgt (kannst ja mal die halbe Größe von AUDSIZE probieren). >STARTOFFSET ist hier zu finden: Und dann knackt es nicht? >Da die maximale Sampling-Frequenz 28801 Hertz beträgt Bei einen DBL-PAL Screen geht dann das doppelte? Nee, ich hab das jetzt auf 18005 HZ geändert, geht. Ausserdem benutze ich jetzt nur noch 2 Audiokanäle, 4 nehmen nur mehr Resourcen. Da man kein Dolby hat braucht man das ja nicht. >Anbei, wieso sind 16000 Hz nicht ausreichend? Weil es qualitativ schlecht ist. Da sind dann solche zischlaute und so >Ich habe früher mit >14000 Hz digitalisiert - und zwar ganze Musikstücke und diese sind >selbst nach heutigen Standards noch ganz manierlich anzuhören. Ähm, mit PC-Lautsprecher vielleicht. Ich bin da doch anspruchsvoller. Früher habe ich immer in etwa 22khz gesamplet. Heute 44khz in 16 Bit, also bei Musik die ich brennen will. >Selbst das Senden eines CTRL-C Signals bringt Dir alleine rein gar >nichts - weißt Du wo die Daten liegen, damit diese von Deinem Hauptprogramm >aus gelesen werden können? Und, gibt es überhaupt einen Datenbereich? Weiterhin, was passiert, wenn das Programm ein CTRL-C Signal empfängt? Soweit bin ich noch lang nicht... Prinzipell brauche ich ja a) einen Monitor und b) ein (Speicher) aufzeichungsprogramm. Also das ist jetzt a. Mit "Scout" kann ich dem ASM-Programm ein "Break" senden und es beendet sich problemlos. Selbiges müsste man doch bewerkstelligen können. Hab es schon mit Signal + SetSignal probiert, erfolglos. >Ich kann Dir alternativ anbieten, eine Shared-Library für Dein >Problem zu programmieren - falls Du diese von Basic aus benutzen >kannst. Eine Library die Samplen kann? Klingt nicht schlecht. Unter Basic kann man prinzipell alle Librarys benutzen, nur die Includes muss man sich ggf. selber machen. >Frage: Meinst Du auf Prozess/Task-Ebene oder das Beispiel mit dem Software-Interrupt? Ein Standard warten mittels timer.device, also momentan sende ich Infrarot Signale mit etwa 1000-1500HZ. Beim 060er gebe ich 560 micros beim 030er 250 micros um das selbe ergebniss zu erhalten. Von Timing, Maschienenunabhängig kann also keine Rede sein. >Es würde mich interessieren, ob unter MorphOS/OS4 diese Einschränkung >weiterhin besteht. Ich nehme an dem timer.device fehlt es an effizienz, daher dürfte eine PPC-CPU da einiges kompensieren können. >Ich hatte ihm schon einmal zu verstehen gegeben, daß das Multitasking >da eine Rolle spielen kann. Ja, hab ich aber aus mit forbid/permit. >Den DTMF-Decoder können wir jetzt aber sicherlich "zum Laufen" >bewegen, das Sampling ist ja nun einigermaßen "sicher" und das >Decoding kann dadurch auch asynchron ablaufen (wobei ich denke, >daß der Decoder selbst schnell genug sein sollte, um mit nicht >allzu großem Nachlauf decodieren zu können). Ja, wenn man die Daten jetzt noch Speichern kann. Görtzel macht unter Basic ohne timer.device ohne Probleme Echtzeit. >Schau Dir das Kapitel "Exec: Interrupts" im RKM nochmal an, dort >vor allem das Beispiel für den VBlank-Interrupt-Server und probier >damit mal etwas rum. Dann verstehst Du auch den timer- und >Soft-Interrupt besser, könnte ich mir vorstellen. Ich hab nur NDK3.9, ein C-Kurs Hefter, ein Basic Buch, ein Assembler Buch. Das Prinzip von Interrupts hab ich verstanden, nur bei weiten nicht so das ich es in Basic Integrieren könnte. [ - Antworten - Zitieren - Direktlink - ] |
09.11.2007, 01:17 Uhr whose Posts: 2156 Nutzer |
Zitat: Genau die Annahme ist wohl ziemlich verkehrt... im Endeffekt arbeitet das timer.device auf Task-Ebene nicht anders als auf Interrupt-Ebene. Es wird halt für einen Task ein Signal ausgelöst (was aber, je nach Systemlast, unterschiedliche Laufzeiten haben kann) und das wiederum wird ausgelöst durch... einen Interrupt! Wie gesagt, es ist mir ein absolutes Rätsel, wie bei Dir diese gigantischen Laufzeitunterschiede zustande kommen und bei mir auf 4 verschiedenen Amigas (von 060 über 040, 030 bis hin zum EC020) nicht. Du hattest mehrere Sekunden Unterschied, ich nicht mal im 10tel-Bereich. Egal auf welcher Maschine. Da muß es eine Ursache für geben, die ich aber mangels Kenntnis Deines Systems nicht benennen kann. Zitat: Das kann aber (und wird auch) "durchbrochen" werden. Z.B. durch das "Wait()en" auf das Signal vom timer.device, schau mal in die RKMs/AutoDocs (NDK3.9) zum Thema "Forbid()", da stehts nochmal. Mit Polling würdest Du es (relativ) zuverlässig ausschalten, hättest allerdings 100% Last und ob das gegen die monströsen Abweichungen helfen würde wage ich inzwischen stark zu bezweifeln. Zitat: Öhm... wo liegt das Problem? Open(), Write(), Close(), fertig. Die Adressen der Puffer sind Dir doch bekannt und die Größen auch. Mal davon ab, wenn die Puffer groß genug sind kannst Du den Goertzel sicherlich auch "direkt" drüberrennen lassen, es wird ja im Interrupt weitergesamplet (am schlauesten in den nächsten Puffer). Du kannst dem Interrupt sogar den Job mitgeben, sich zu melden, wenn er einen von der Null-Linie abweichenden Wert am CIA-Port bemerkt und dann, nach Füllen des ersten Puffers (weiteres Signal), parallel mit dem Decodieren loslegen. Zitat: Das macht er auch mit dem timer.device, zumindest hier und in C. Zitat: DevCD 2.1 wäre noch eine Maßnahme, die ich Dir dringend ans Herz legen möchte. Da sind auch die RKMs drauf. Und dann gibts ja noch diese Suchmaschine fürs Internet *hust* Zitat: Bei den Basic-Compilern kann ich Dir auch relativ wenig helfen, aber wenn Du da Assembler-Teile "integrieren" kannst, dann wars das im Groben schon (irgendwie muß dem System die Adresse auf den Interrupt-Code bekannt gemacht werden, in C geschieht das durch Übergabe eines Zeigers auf die Funktion in der Interrupt Struktur. Wenn es in MaxonBasic etwas ähnliches zur Ermittlung der Adresse z.B. von Assembler-Code gibt, ist es das schon). Der Rest der Kommunikation zwischen Interrupt und Deinem Programm erfolgt über (von Deinem Programm allozierten) Speicher und/oder MessagePorts und Messages. Das Anlegen des Interrupt-Servers/Handlers erledigt das System für Dich. Wenn Du mir versprichst, nicht wieder in wüstes Hacken zu verfallen , kann ich Dir ja mal den C-Sourcecode zu dem VBI-Beispiel aus dem RKM zukommen lassen. Dann siehst Du, wie simpel Interrupts in AmigaOS zu handhaben sind. Ok, der macht nichts anderes, als einen Zähler hochzuzählen, aber die Grundlage ist die selbe wie bei jolos wirklich tollem Audio/Timer-Beispiel (und funktioniert sogar unter OS4 problemlos). Grüße -- --- µA1 PPC 750GX-800 A4000 PPC 604e-233 [ - Antworten - Zitieren - Direktlink - ] |
09.11.2007, 10:16 Uhr MaikG Posts: 5172 Nutzer |
>Wie gesagt, es ist mir ein absolutes Rätsel, wie bei Dir diese >gigantischen Laufzeitunterschiede zustande kommen und bei mir auf >4 verschiedenen Amigas (von 060 über 040, 030 bis hin zum EC020) >nicht. Glaub ich weniger. Sagtest du nicht, du hättest gar keinen Sampler? Ausserdem verwendete ich das selbe Programm... Dann hab ich es sogar Prozessorspezifisch Compiliert... >Das kann aber (und wird auch) "durchbrochen" werden. Z.B. durch das >"Wait()en" auf das Signal vom timer.device, schau mal in die >RKMs/AutoDocs (NDK3.9) zum Thema "Forbid()", da stehts nochmal. Half aber gegen das leiern und Stoppte den Mauscursor. Sollte ich Forbid dann wohl mehrfach innerhalb der Schleife benutzen? >Mit Polling würdest Du es (relativ) zuverlässig ausschalten, hättest >allerdings 100% Last und ob das gegen die monströsen Abweichungen >helfen würde wage ich inzwischen stark zu bezweifeln. Ich hab hier auf 030 18000 HZ ohne Probleme, ohne timer.device, mit For...Next zum warten. >Öhm... wo liegt das Problem? Open(), Write(), Close(), fertig. In Assembler sind die aufrufe etwas schwieriger... >Mal davon ab, wenn die Puffer groß genug sind kannst Du den Goertzel >sicherlich auch "direkt" drüberrennen lassen, es wird ja im >Interrupt weitergesamplet (am schlauesten in den nächsten Puffer). Ja, da müsste ich dann wieder zu C übergehen. >Das macht er auch mit dem timer.device, zumindest hier und in C. siehe oben... >DevCD 2.1 wäre noch eine Maßnahme, die ich Dir dringend ans Herz >legen möchte. Da sind auch die RKMs drauf. Und dann gibts ja noch >diese Suchmaschine fürs Internet *hust* Heisst die sicher 2.1? Finde nur 1.2 Im Internet hab ich schon gesucht, ausser was mit dem Seriell Port fand ich nichts. >Wenn es in MaxonBasic etwas ähnliches zur Ermittlung der Adresse >z.B. von Assembler-Code gibt, ist es das schon). Ja, ich glaube das geht. Die Adresse des Codes herrausfinden. Währe cool wenn halt da nur so ein Assembler Part währe, welcher nur Parallel->Buffer schiebt und ich alles andere in Basic erledigen kann. >Wenn Du mir versprichst, nicht wieder in wüstes Hacken zu >verfallen , kann ich Dir ja mal den C-Sourcecode zu dem >VBI-Beispiel aus dem RKM zukommen lassen. Dann siehst Du, wie >simpel Interrupts in AmigaOS zu handhaben sind. "Hacken" im sinne von dirkten Hardwarezugriff mache ich nur wenn nötig... Hast du meine Mail Adresse? [ Dieser Beitrag wurde von MaikG am 09.11.2007 um 10:17 Uhr geändert. ] [ Dieser Beitrag wurde von MaikG am 09.11.2007 um 18:26 Uhr geändert. ] [ - Antworten - Zitieren - Direktlink - ] |
10.11.2007, 08:25 Uhr whose Posts: 2156 Nutzer |
Zitat: Brauche ich denn einen, um festzustellen, ob sich das timer.device einigermaßen genau "meldet"? Ich glaube nicht. Zitat: Ich habe nie etwas anderes gesagt. Zitat: Nein, solltest Du nicht Wenn das Interrupt-Beispiel von jolo bei Dir besser läuft, arbeite damit. Zitat: Was das Ganze noch mysteriöser macht. Zitat: Finde ich nicht, und der Riesen-Assembler-Crack bin ich auch nicht. Mal abgesehen davon, daß Du gar kein Assembler brauchst, wenn MaxonBasic mitspielt. Zitat: Ich dachte, der Basic-Goertzel wäre schnell genug für Echtzeit? Zitat: Die letzte (aktuelle) heißt 2.1. Gibts bei Vesalia für schlappe 16,90. Und ist der erste Treffer, wenn Du "Developer" bei Suche eingibst. Zitat: Wenn Dein Basic-Compiler mitspielt ists im Endeffekt genauso aufgebaut wie jolos Beispiel und Du kannst die "Haushaltung" komplett auf der Basic-Seite erledigen. Auch Speichern der Werte usw. Zitat: Naja, ein paar Blicke ins NDK könnten Dir auch nicht schaden manchmal... Zitat: Noch nicht, aber das sollte sich übers Forum-Profil bewerkstelligen lassen, daß Du sie mir zukommen läßt Ist allerdings reiner C-Code, wobei ich den Assembler-Teil entsprechend in C "übersetzt" habe (was wirklich kein großes Problem war bei diesem Beispiel). Du solltest mal zusehen, daß Du eine funktionierende vbcc-Installation hinbekommst, um Beispiele in C nachvollziehen zu können. Den Assembler-Teil kann ich Dir aber auch als Quellcode geben. Grüße -- --- µA1 PPC 750GX-800 A4000 PPC 604e-233 [ - Antworten - Zitieren - Direktlink - ] |
10.11.2007, 09:45 Uhr jolo Posts: 110 Nutzer |
@whose: Moin Moin Zitat: Ungeachtet dessen behauptet Maik, dass mittels einer Schleife und ausgeschalteten Multitasking er 18000 Hz erreichen kann - was ich aber anzweifle da 18000 Lesezugriffe pro Sekunde nicht gleichzusetzen sind mit 18000 Hz. Es kommt auf die Zeitspanne zwischen den einzelnen Lesezyklen an - ist diese immer gleich (kontinuierlich) für alle Lesezugriffe, so könnte er mit Fug und Recht behaupten, dass er das auf Task-Ebene schafft - aber das wage ich zu bezweifeln, da ihm alle mögliche Interrupts einen Strich durch die Rechnung machen. Es kann sein, dass ein Teil der Lesezyklen tatsächlich in gleichen Abständen gelesen wird, aber der Rest? Somit kommt es beim Einsatz eines Prozesses für diese Aufgabe zu Unregelmäßigkeiten, die in einer verfälschten Wiedergabe resultieren. Zitat: Hmmm, wie kann ich Dir nur schonend beibringen, dass ich diesen Abschnitt heutzutage als nicht mehr aktuell betrachte - ohne dass Du mich gleich steinigst. :} Wir müssen uns heutzutage auch mit AROS, MorphOS und OS4 auseinander setzen - und dies beinhaltet, dass Interrupts dort ganz anders aussehen weil ja die Hardware eine andere ist. Okay, für Classics mag das alles noch seine Gültigkeit besitzen, aber schon unter einer Emulation kann ein VBlank Interrupt-Code, der unter Classics fünfzig Mal in der Sekunde aufgerufen wird, weitaus öfter aufgerufen werden. Unter WinUAE ist es keine Schwierigkeit, einen VBlank zweihundert Mal pro Sekunde zu initiieren. Das Timer-Device bleibt davon allerdings verschont... CIA Interrupts, um die es in diesen Beispielen geht, werden auch nicht von Exec verwaltet sondern von der betreffenden Ressource - somit ist die Abhandlung im RKM nicht vollständig. Wer allerdings die Interna verstehen will, der sollte Deinem Rat folgen und diese Abhandlung im RKM lesen. Anbei, C-Compiler berücksichtigen heutzutage solche Feinheiten wie Interrupts (vbcc geht hier noch einen Schritt weiter als gcc, da vbcc, wenn ich es richtig verstanden habe, auch anbietet Interrupts mit einem "rte" beenden zu lassen, was hilfreich ist, falls man einen Interrupt-Server/Handler schreiben will oder die Auto-Vektoren direkt, ohne Umweg übers Betriebssystem benutzt). Auch bin ich persönlich der Meinung, dass gerade Anfänger, nicht Programmieranfänger sondern in Bezug auf Interrupts, nicht zu viel auf einmal zugemutet werden sollte - man kann einfache Dinge auch verkomplizieren. Als es noch Stand der Dinge war, Intros/Demos zu schreiben, haben wir ja die Auto-Vektoren direkt benutzt und deren Handhabung ist ja wirklich alles andere als schwer. Zitat: Viele Dinge haben einen Einfluss darauf. Die verwendete Programmiersprache zum Beispiel - Basic ist langsamer als C. Wenn dann noch der verwandte Basic-Compiler nicht der schnellste ist, wird's langsam eng (je mehr Sicherheit geboten wird desto langsamer muss das erstellte Programm sein; alle Überprüfungen kosten Laufzeit). Zudem haben viele Leute den Wunsch, das Aussehen der Oberfläche aufzupeppen - wenn dann noch Patches verwandt werden, die sich unsauber ins System einklinken und Ressourcen verschwenden, geht die CPU-Last rauf und die Leistungsfähigkeit runter. Es kann aber auch sein, das ein simpler Fehler in seinem Programm so drastische Unterschiede zu Tage bringt. Kann man irgendwo einen Blick auf seinen Code werfen? Zitat: Wenn er den gleichen Algorithmus meint wie ich und er mit 28kHz oder gar 44kHz digitalisieren will, wird das nicht in Echtzeit unter Basic gehen - zumindest nicht mit 'ner 030 CPU. Tschö! [ - Antworten - Zitieren - Direktlink - ] |
10.11.2007, 10:04 Uhr jolo Posts: 110 Nutzer |
@MaikG: Hi. Zitat: Das Knacken rührt daher, weil die Audio-Abtastrate nicht hundertprozentig dem der Abtastrate des CIA-B Interrupts entspricht. Du solltest Dir vergegenwärtigen, dass die Audio-Hardware unabhängig von Deinem Interrupt werkelt. Du sagst dieser nur, wie schnell sie von dem Puffer Daten lesen soll (Periode 214 oder 124) und wo das erste Byte des Puffers zu finden ist (Anfangsadresse) und wie groß der Puffer ist (Endadresse). Danach macht sie alles selbstständig - wenn die Endadresse erreicht wurde, beginnt sie wieder mit der Ausgabe bei der Anfangsadresse - und das fortlaufend. Zwischenzeitlich und unabhängig davon werkelt Dein CIA-B Interrupt - der die Daten einliest, die die Audio-Hardware ausgeben soll. Falls nun der CIA-B Interrupt etwas langsamer Daten einliest als die Audio-Hardware ausgibt, gibt die Audio-Hardware die Daten aus, die beim letzten Durchlauf gesammelt worden sind - und nicht die, die beim jetzigen Durchlauf aktuell sind. Wie gesagt, dies passiert aber nur bei der Wiedergabe in Echtzeit - die Daten, die der Interrupt sammelt, sind davon nicht betroffen. Zweiter Grund (falls die Audio-Hardware keinen Prefetch benutzt - müsste das mal selber nachlesen - also ist diese Aussage nur mit Vorsicht zu genießen): Je kleiner der verwendete Puffer, desto mehr Störgeräusche. Da der CIA-B Interrupt und die Audio-Hardware sich einen Speicherbereich teilen, und es sein kann, dass beide zum gleichen Zeitpunkt auf ein bestimmtes Datenword zugreifen wollen, bedingt durch die nicht hundertprozentige analoge Abtastrate, bekommt derjenige den Zugriff, der die höhere Priorität hat - und das ist der CIA-B Interrupt. Somit kommt es kurzzeitig zu diesem Effekt. Probiere wie im letzten Posting beschrieben AUDSIZE eine andere Größe zu geben und den STARTOFFSET auf die Hälfte von AUDSIZE zu setzen. Dann nämlich fängt die Audio-Hardware erst dann an, wenn der CIA-B Interrupt die Hälfte des Puffers schon gefüllt hat. Dann ist das Ganze aber zeitlich versetzt... Zitat: Theoretisch ja, praktisch kann ich nichts dazu beisteuern, da ich es nie selber ausprobiert habe. Da die Datenmenge, die die Custom-Chips, welche ja nach wie vor mit 7 MHz getaktet werden, bewältigen müssen um den Faktor 2 ansteigen würde (jeweils für Audio und Video), könnte es zu viel des Guten sein. Aber wie gesagt, ich selber habe es nicht ausprobiert. Zitat: Nein, tun sie nicht. Die Audio-Hardware hat rein gar nichts mit Deiner CPU zu tun. Zitat: Zitat: Du vergleichst da Äpfel mit Birnen. 44kHz in 16-Bit sind was anderes als 44kHz in 8-Bit. Du hast im Amiga kein 16-Bit Sound, nur 8-Bit, es sei denn Du benutzt eine Soundkarte. Wenn Du 16-Bit Samples benötigst, musst Du erst die 8-Bit Samples in 16-bittige umwandeln bevor Du diese als solche benutzen kannst. Und Digitizer für Amigas waren immer als 8-Bit Lösungen ausgelegt - nicht 16 Bit. Zitat: Da widerspreche ich Dir - zwar ungern, aber tue es trotzdem. AudioGrabber2 bietet Dir beides. Schau Dir das Beispiel mal an. Zitat: Studiere mal die Beispiele - speziell die Interaktion zwischen Interrupt und Programm (Task). Dann weißt Du wie es gemacht wird. Aber abgesehen davon, selbst das Senden eines CTRL-C Signals wird Dir nichts bringen - denn eine Frage bleibt: Wo hat das Programm (AudioGrabber) nun die Daten versteckt - und was passiert, wenn es ein CTRL-C Signal empfängt? Beim Eintreffen des Signals werden alle Ressourcen freigegeben - und somit auch der Datenpuffer. Dementsprechend existieren die Daten nicht mehr! Zitat: Brauchst Du eine FD oder SFD Datei um eine BMAP Datei zu erstellen? Zitat: 1000 oder 1500 Signale pro Sekunde bedeuten nicht, dass Du 1000 oder 1500 Hz verwendest. Der Zeitabstand zwischen den einzelnen Zyklen ist ausschlaggebend. Dieser muss konstant sein. Hz bedeutet das etwas in periodischen Abständen auftritt - und nicht soundsooft innerhalb eines bestimmten Zeitrahmens. Ich kann in der ersten halben Sekunde die 1500 Signale raushauen und die restliche Zeit warten. Das hat dann allerdings nichts mit periodischen Intervallen zu tun. Zitat: Auf Task-Ebene bestimmt nicht... aber annähernd sollte es schon funktionieren. Gehe ich recht in der Annahme, dass Du *nicht* am Anfang Deines Loops die "Auszeit" spezifizierst sowie DoIO anstelle von SendIO verwendest? Müsste ungefähr so aussehen damit es richtig funktioniert: code:LOOP SendIO( timerrequest) .... Sende Infrarot-Signal .... signale = Wait( (1 << TimerSigBit) ) IF signale AND (1 <<TimerSigBit) <> 0 GOTO LOOP ENDIF ENDLOOP Zitat: Du würdest das nicht behaupten, wenn Du die betreffenden Routinen mal disassembliert hättest. Diejenigen, die das originale AmigaOS programmierten, verstanden effizient und ressourcenschonend zu programmieren. Leider hat das aber auch seine Kehrseiten... Zitat: Ihr könnt mich ja dumm sterben lassen aber es wäre nett von euch wenn ihr mir stattdessen mal sagt, über welches Programm ihr euch unterhaltet... Erbarmen, bitte... Zitat: Verwendet ihr DoIO()? Dann habt ihr euer Wait() gefunden... Forbid() in einer Schleife zu verwenden ohne entsprechendes Permit() wird das System lahm legen. Vergiss die Existenz von Forbid()! Zitat: Nö. code:_WriteBufferContents movem.l D2-D4/A6,-(sp) movea.l _DOSBase(pc),A6 move.l _DateiName(pc),D1 move.l #1006,D2 jsr _LVOOpen(A6) move.l D0,D4 beq.s _error move.l D0,D1 move.l _PufferAdresse(pc),D2 move.l _PufferLaenge(pc),D3 jsr _LVOWrite(A6) move.l D0,D2 move.l D4,D1 jsr _LVOClose(A6) cmp.l D2,D3 bne.s _error moveq #1,D0 _out movem.l (sp)+,D2-D4/A6 rts _error moveq #0,D0 bra.s _out _DOSBase ds.l 1 DateiName ds.l 1 PufferAdresse ds.l 1 PufferLaenge ds.l 1 Zitat: http://gega.homelinux.net/AmigaDevDocs/ Zitat: Selbst mit dem Beispiel für Software-Interrupts kann man nachvollziehen, wie oft pro Sekunde der Interrupt aufgerufen wurde - man braucht dazu nur die Ausgabe im Auge zu behalten. Gruß [ - Antworten - Zitieren - Direktlink - ] |
10.11.2007, 10:22 Uhr MaikG Posts: 5172 Nutzer |
>Das Knacken rührt daher, weil die Audio-Abtastrate nicht hundertprozentig >dem der Abtastrate des CIA-B Interrupts entspricht. Multimon macht in etwa das selbe und knackt nicht. Also muss es ja möglich sein... >Probiere wie im letzten Posting beschrieben AUDSIZE eine andere >Größe zu geben Das hab ich schon, da wird ein kurzer part dann mehrmals wiederholt. >Nein, tun sie nicht. Die Audio-Hardware hat rein gar nichts mit >Deiner CPU zu tun. Wenn ich gleichzeitig dnetc laufen habe und ein Benchmark mache bekomme ich mit 4 Kanälen um die 96000 keys/s. Mit 2 Kanälen 102000 keys/s und mit Multimon auf der selben Frequenz 116000 keys/s. Der Wert ohne Monitor liegt bei 176000 keys/s. >Du hast im Amiga kein 16-Bit Sound, nur 8-Bit, es sei denn Du benutzt >eine Soundkarte. Ja, natürlich. >Studiere mal die Beispiele - speziell die Interaktion zwischen Interrupt und Programm (Task). Hab ich, laaange - weiss es trotzdem nicht. >Brauchst Du eine FD oder SFD Datei um eine BMAP Datei zu erstellen? FD >Gehe ich recht in der Annahme, dass Du *nicht* am Anfang Deines Loops die "Auszeit" spezifizierst sowie DoIO anstelle von SendIO verwendest? code:LOOP SendIO( timerrequest) .... Sende Infrarot-Signal .... WaitIO( timerrequest) ENDLOOP >Ihr könnt mich ja dumm sterben lassen aber es wäre nett von euch >wenn ihr mir stattdessen mal sagt, über welches Programm ihr euch >unterhaltet... Erbarmen, bitte... Eine erkennung von DTMF tönen(Tonwahl) welche von einem Handy in den Sampler kommen decodieren. >Verwendet ihr DoIO()? Dann habt ihr euer Wait() gefunden... Nein DoIO lässt ja keine Zeit mehr für die Aufgabe selbst. >Vergiss die Existenz von Forbid()! Dann geht gar nichts mehr. [ - Antworten - Zitieren - Direktlink - ] |
10.11.2007, 10:34 Uhr whose Posts: 2156 Nutzer |
Zitat: Es geht um diesen Thread. Samplen und dann nen Goertzel drüberrödeln lassen, um DTMF zu erkennen. Zitat:Zitat: Sag das nicht mir Im Grunde war das nur ein verzweifelter Versuch, seine enormen Abweichungen zu ergründen. Wie gesagt, auf meinen Kisten läuft das timer.device recht genau, bei ihm hingegen nicht. Zitat:Zitat: Das bezog sich wieder auf das Goertzel-Problem. Ich hatte hier (bis auf das Sampling, mangels passender Hardware) das gleiche Programm (nur in C) laufen (compiliert für 020). Bei ihm ergaben sich Timing-Abweichungen von mehreren Sekunden (auf einem 060!), hier max. wenige Zehntel, gemessen per Eclock (also nicht sonderlich genau, aber ausreichend. Es ging dabei ja mehr ums Prinzip). Er hatte dann etwas experimentiert, darunter auch prozessorspezifische Compiles (mit dem gleichen Ergebnis). Was da nun genau verkehrt läuft: Frag mich was Leichteres Grüße -- --- µA1 PPC 750GX-800 A4000 PPC 604e-233 [ - Antworten - Zitieren - Direktlink - ] |
11.11.2007, 15:53 Uhr Holger Posts: 8116 Nutzer |
Zitat:Ich versteh nicht, warum Du diesen Part einfach nicht begreifen willst: die Eclock läuft falsch, zumindest, wenn Du das timer.device in dieser hohen Rate ansprichst. Maik misst mit Echtzeit-Uhr, um die Zeitabweichung festzustellen, während Du immer noch darauf rumreitest, dass das Timing, verglichen mit der Uhr, die ja falsch geht, keine nennenswerte Abweichung besitzt. Natürlich besitzt die Eclock keine Abweichung, "gemessen per Eclock". mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
11.11.2007, 19:42 Uhr whose Posts: 2156 Nutzer |
Zitat: Ich wiederum verstehe nicht, warum Du einfach nicht begreifen willst, daß, wenn überhaupt, die EClock nicht pauschal um mehrere Sekunden falsch läuft. Mal davon ab habe ich mit dem EClock-Zähler auch nicht UNIT_ECLOCK gemessen sondern UNIT_MICROHZ. Oder glaubst Du wirklich, mir würde der Unterschied zwischen "2 Sekunden Meßintervall" und "5 Sekunden tatsächliche Laufzeit" nicht auffallen, wenn es den gäbe? Wir waren uns (stillschweigend) darüber einig, daß sich die Laufzeitabweichungen über ein wirklich großes Intervall hinweg aufsummieren (und diese Abweichungen des timer.device sind bekannt und dokumentiert). Das hat (und hatte) aber nichts mit einer "falsch laufenden EClock" zu tun sondern mit Euer beider Unvermögen, diese Tatsache einfach mal anzuerkennen und umzusetzen. Oder seit ihr zwei mal auf die Idee gekommen, das Programm in Sachen Dekodierintervall auf das wirklich Benötigte an Laufzeit zu kürzen? Wie es sich derzeit liest wohl eher nicht. Jetzt hat er ein schönes Beispiel für die ganze Geschichte im Interrupt, wenn das nicht funktioniert weiß ich auch nicht mehr weiter. Hier gings auch ohne. -- --- µA1 PPC 750GX-800 A4000 PPC 604e-233 [ - Antworten - Zitieren - Direktlink - ] |
13.11.2007, 10:09 Uhr Holger Posts: 8116 Nutzer |
Zitat:Nur noch mal als kurze Verständnisfrage: UNIT_MICROHZ wird auf welche Art und Weise implementiert? Zitat:Ich weiß es nicht. Die Art und Weise, wie Du postest, erweckt den Eindruck. Sonst würdest Du ja evtl. in Betracht ziehen, eine ernstzunehmende Zeitmessung vorzunehmen und die Ergebnisse zu posten. Statt dessen betonst Du ja immer wieder, dass eine Zeitbasis, gemessen an sich selbst, "nur minimale Abweichungen" hat. Wo ich nicht mal weiß, wo Du die eigentlich her hast. Bei mir weicht die Eclock von sich selber überhaupt nicht ab. Zitat:Nun ja. Zitat:Da diese Abweichung laut Deinen Postings ja gar nicht existiert, bzw. nicht wesentliche ist, wüsste ich nicht, was man daran "umsetzen" sollte. Ich kann auch nicht nachvollziehen, warum es "nichts mit einer 'falsch laufenden EClock' zu tun" hat, wenn alle Zeitmessungen, die auf Eclock basieren, also sowohl die absolute, als auch die relative des bewussten Programms synchron sind, und gleichermaßen von der Realzeit abweichen. UNIT_MICROHZ gehört natürlich mit in diese Kategorie. Die Abweichung ist dokumentiert, ja, wenn man eine unspezifische Nennung einer Abweichung mit einem unspezifischen Zusammenhang ("Systemlast") als Dokumentation bezeichnen will. Die interessante Frage ist nur noch, warum es zu dieser Abweichung kommt. Alles deutet zwar auf einen ziemlich dämliche Implementierung innerhalb des timer.device hin, nämlich auf ein Anhalten des Timers während des Auslesens, was erklären würde, warum die Aweichung mit kleinerem Abfrageintervall steigt, aber da ja hier immer wieder betont wird, wie perfekt und effizient das timer.device wäre (wieso kommt es dann zu der Abweichung?), der Fehler definitiv nicht im timer.device liegen könne, kann das ja nicht sein. Zitat: Kannst Du diesen Satz bitte ins Deutsche übersetzen? Für mich liest er sich so, also versuchst Du gerade zu empfehlen, das Programm möglicht kurz laufen zu lassen, damit die angeblich nicht existente (nicht wesentliche) Abweichung möglichst klein bleibt. Das kann es ja wohl nicht sein... mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
13.11.2007, 10:47 Uhr whose Posts: 2156 Nutzer |
Zitat: Weißt Du, genau deswegen werfe ich Dir immer wieder gerne Großkotzigkeit vor. Wer sagt Dir denn, daß ich keine "ernstzunehmende" Zeitmessung vorgenommen habe? Selbst wenn es Dir unglaublich erscheinen sollte: Ich kann genau wie Maik auch eine Stoppuhr bedienen. Ich kann sogar, auch wenns für Dich weniger ernstzunehmen sein sollte, 2 Sekunden Laufzeit im Kopf abschätzen und was soll ich sagen: Die Stoppuhr sagt dann das Gleiche. Und UNIT_ECLOCK (evtl. mit winzigen Abweichungen) auch. Zitat: Wenn Du Dich mit dem timer.device eingehender beschäftigt hättest, wüßtest Du eine Möglichkeit, wie Du die "Abweichung von sich selbst" von UNIT_ECLOCK mit Bordmitteln feststellen könntest... Zitat:Zitat:Nun ja. Ja nich? Zitat:Zitat:Da diese Abweichung laut Deinen Postings ja gar nicht existiert, bzw. nicht wesentliche ist, wüsste ich nicht, was man daran "umsetzen" sollte. Zum Beispiel das Sampling/Goertzel nicht "minutenlang" durchlaufen lassen sondern "takten". Nur so ne Idee... Andererseits kann Maik es jetzt mal mit Interrupts probieren, vielleicht ist das für ihn einfacher. -- --- µA1 PPC 750GX-800 A4000 PPC 604e-233 [ - Antworten - Zitieren - Direktlink - ] |
17.11.2007, 11:39 Uhr jolo Posts: 110 Nutzer |
Hi Maik, habe mein Versprechen gehalten und eine Bibliothek für Dein Problem erstellt. Kriege ich jetzt meinen Lutscher? Zitat: Diese Aussage von mir hat ihre Gültigkeit und war dafür verantwortlich, dass die Audio-Hardware nicht störungsfrei betrieben werden konnte... Zitat: Zitat: Ja, Du hast Recht. Siehe erstes Zitat. Es hat sich herausgestellt, dass der CIA-B Interrupt wirklich die Audio-Hardware stört - dementsprechend verwende ich jetzt einen CIA-A Interrupt. Jetzt sind die hörbaren Störungen minimal - die gesammelten Daten waren ja davon nie betroffen (FAST-RAM Puffer). Zitat: Benchmark-Ergebnisse sind generell mit Vorsicht zu genießen - zu viele Faktoren beeinflussen das Ergebnis. Das Audio-Device (also die Hardware) hat, auch wenn Du mir das nicht glaubst, rein gar nichts mit der CPU und ihrer Last zu tun. Die CUSTOM-CHIPS sind entworfen worden, um die CPU zu entlasten. Das einzige was die CPU und die CUTSOM-CHIP gemeinsam verwenden ist der Daten- und Adressbus. Nur wenn beide auf ein- und demselben Speicherbereich zugreifen wollen, gibt es Konflikte - sprich eine Verzögerung. Diese liegen aber im Millisekundenbereich. Zitat: Und dafür brauchst Du CD Qualität (44,1 kHz) ? So, nun zu der Bibliothek: Diese nennt sich "ire" und muss ins Libs-Verzeichnis. Die "bmap" Datei habe ich mittels "fd2pragma" erstellt und sollte von Dir ohne weitere Anpassung unter MaxonBasic benutzt werden können. Es gibt nur 5 Funktionen: InitIRQ StartIRQ DeleteIRQ SetIRQAttrI GetIRQAttrI InitIRQ kann sowohl normale Interrupts auslösen als auch digitalisieren. void * InitIRQ( ULONG callsPerSecond, STRPTR irqname, LONG (*usersCode)(), APTR usersData, UBYTE **buffers, ULONG singleBufSize) (d0,a0,a1,d1,a2,d2) callsPerSecond --- wie oft pro Sekunde soll der Interrupt aufgerufen werden, z.B. 16668. irqname --- Name Deines Interrupts, z.B. "Maik's Interrupt". usersCode --- Zeiger auf die Funktion die innerhalb des Interrupts aufgerufen wird - oder null falls keine eigene Routine aufgerufen werden soll. usersData --- Zeiger auf eine Struktur oder Variable die dein "usersCode" auf dem Stack empfängt, darf auch null sein. buffers --- falls gesetzt, wird der Digitizer aufgerufen! buffers zeigt auf einen Speicherbereich, in dem Du die Adressen Deiner FAST-RAM Puffer vermerkt hast. Der letzte Eintrag muss NULL (0) sein. singleBufSize --- die Größe *eines* Puffer, d.h. falls Du jeden Puffer eine Größe von 20000 Bytes zugewiesen hast, musst Du hier 20000 eintragen. Bei zwei Puffern (buffers: Puffer1, Puffer2, NULL) macht das Summa Summarum 40000 Bytes FAST-RAM. Die einzelnen Puffer dürfen nicht in der Größe variieren! Ein paar Beispiele: ihandle = InitIRQ( 50, "Maik's Interrupt", NULL, 0, NULL, 0) Hier wird dann jede fünfzigstel Sekunde ein Interrupt ausgelöst und ein Signal zu Deinem Hauptprogramm gesendet. Du kannst mittels: GetIRQAttr( ihandle, 2) das Signal-Bit ermitteln, welches Dir signalisiert wird (z.B. für die Verwendung mit Wait() ). Für Wait() musst Du das Signal-Bit in eine Signal-Maske umwandeln: sigmask = (1 << GetIRQAttr( ihandle, 2)) ihandle = InitIRQ( 50, "Maik's Interrupt", (*usersCode)() &yourcode, &counter, NULL, 0) Wie oben, nur wird hier noch deine "yourcode"-Routine aufgerufen und bekommt als Argument auf dem Stack die Adresse der Variable "counter". Falls "yourcode" null zurückgibt, wird kein Signal an Dein Hauptprogramm gesendet. Nur wenn Du irgendeinen Wert zurückgibst, wird das Signal gesendet. Du musst wissen, welche Prozessor-Register MaxonBasic benötigt und deren Inhalt irgendwo vor Aufruf von StartIRQ() ablegen und dann innerhalb von "yourcode" diese Registerinhalte restaurieren - und beim Verlassen von "yourcode" die ursprünglichen Registerinhalte für den originalen Interrupt-Code, der "yourcode" aufgerufen hat, wieder instand setzen. ------------------------------------- ihandle = InitIRQ( 50, "Maik's Interrupt", SADD yourcode, SADD counter, 0, 0) #asm move.l a4,inhaltA4 move.l a5,inhaltA5 move.l a6,inhaltA6 #endasm StartIRQ( ihandle) ------------------------------------ SUB yourcode( arg) STATIC #asm move.l 4(sp),argument ; Adresse von "counter" movem.l D2-D7/A2-A6,-(sp) movea.l inhaltA4,A4 movea.l inhaltA5,A5 movea.l inhaltA6,A6 #endasm Dein Basic-Code hier - "argument" zeigt aufs Argument für "yourcode" returnWert = 0 ; Kein Signal senden #asm movem.l (sp)+,D2-D7/A2/A6 move.l returnWert,D0 rts ; Muss RTS für Basic angegeben werden? #endasm ------------------------------------- DIM pufferListe (12) DIM puffer1 (20000) DIM puffer2 (20000) POKEL( pufferListe(0), SADD puffer1) POKEL( pufferListe(4), SADD puffer2) POKEL( pufferListe(8), 0) ihandle = InitIRQ( 16668, "Maik's Interrupt", 0, 0, SADD pufferListe, 20000) Da wir nicht wollen, dass wir ein Signal für jeden Eintritt in den Interrupt erlangen, müssen wir das Signal-Handling für normale Signale ausschalten: SetIRQAttrI( ihandle, 4) Jetzt kann man (frau auch) StartIRQ( ihandle) aufrufen. Und da wir informiert werden wollen, wann einer der beiden Puffer voll ist, müssen wir dessen Signal-Bit ermitteln: sigmask = (1 << GetIRQAttr( ihandle, 1)) Jetzt mittels Wait( sigmask) horchen, ob eine Nachricht eintrifft. Um die Adresse des Puffers zu erfahren, welcher voll ist, muss man dies verwenden: vollerPuffer = GetIRQAttr( ihandle, 16) Flaggen für Get/SetIRQAttrI(): 1 = (get) - hole Signal-Bit das signalsiert, das ein Puffer voll ist. 2 = (get) - hole Signal-Bit das signalsiert, das Interrupt aufgerufen wurde. 4 = (set) - normale Signal-Handhabung ausschalten (Interrupt wird nicht signalsiert). 8 = (set) - normale Signal-Handhabung einschalten (Interrupt wird signalsiert). 16 = (get) - hole Adresse des Puffers, welcher voll ist. Ich spreche kein Basic, daher weiß ich nicht ob das was ich oben verbrochen habe, so von einem Basic-Compiler/Interpreter akzeptiert wird - ich glaube kaum... Archiv kann unter http://www.amimedic.de heruntergeladen werden. Das (nährlose) Beispiel TimerIRQ digitalisiert und kann auch mit anderen Werten betrieben werden: TimerIRQ 28801 - digitalsiert mit 28801 Hz! Gruß [ - Antworten - Zitieren - Direktlink - ] |
17.11.2007, 11:42 Uhr jolo Posts: 110 Nutzer |
@whose: Tach, Zitat: Zu Deiner Information: Auch hier ist das Timer-Device sehr genau - und dass unter WindowsXP/WinUAE. Also gehe ich davon aus, dass er einen simplen Programmierfehler irgendwo eingebaut hat. Habe leider keine Zeit gefunden, den anderen Thread zu lesen. Werde das aber nächste Woche mal nachholen. Vielleicht fällt mir irgendetwas Ungewöhnliches auf. Zitat: Wenn Du mich schon so fragst: Wie wird das Wetter nächste Woche? Gruß [ - Antworten - Zitieren - Direktlink - ] |
17.11.2007, 18:30 Uhr MaikG Posts: 5172 Nutzer |
>habe mein Versprechen gehalten und eine Bibliothek für Dein Problem >erstellt. Cool, danke erstmal. Ich muss mir die beschreibung erstmal ausdrucken und in ruhe lesen. >Zu Deiner Information: Auch hier ist das Timer-Device sehr genau - >und dass unter WindowsXP/WinUAE. >Also gehe ich davon aus, dass er einen simplen Programmierfehler >irgendwo eingebaut hat. Es gab mehrere Programme von verschiedensten Programmierern die alle Fehlgeschlagen sind. UAE ist kein echter Amiga, er Syncronisiert das Timing mit der Echtzeit auf kosten anderer aktivitäten. [ - Antworten - Zitieren - Direktlink - ] |
17.11.2007, 22:09 Uhr MaikG Posts: 5172 Nutzer |
ich habs erstmal was einfaches zusammengebastelt. Also es geht bis 16000 HZ auf 060. Allerdings sind im Sample solche Knackser drin. Hört sich an wie eine sehr zerkratzte Platte. Es gehen Spikes auf -127. Beeinflusst der Interrupt irgenwie den BFE101 Register? code:' $INCLUDE Exec.bh ' $INCLUDE dos.bh ' $INCLUDE Timer.bh LIBRARY "ire.library" LIBRARY OPEN "exec.library" LIBRARY OPEN "dos.library" DECLARE FUNCTION InitIRQ& LIBRARY DECLARE FUNCTION StartIRQ& LIBRARY DECLARE FUNCTION DeleteIRQ& LIBRARY DECLARE FUNCTION GetIRQAttrI& LIBRARY DECLARE FUNCTION SetIRQAttrI& LIBRARY REM $NOEVENT REM $NOOVERFLOW REM $NOLINES MySample&=AllocVec(200004, MEMF_PUBLIC& OR MEMF_CLEAR&) test&=&h45454545 ihandle&=InitIRQ&(16000, VARPTR(test&),NULL&,0,NULL&,0) REM 16000 sigmask&=(1<<GetIRQAttrI&(ihandle&,2)) junk&=StartIRQ&(ihandle&) count&=0 WHILE count&<200000 POKEB MySample&+count&, PEEKB(&hBFE101):INCR count& junk& = xWait&(sigmask&) WEND PRINT count& junk&=DeleteIRQ&(ihandle&) fh& = xOpen&(SADD("ram:sample"+CHR$(0)), MODE_NEWFILE&) IF fh& THEN junk& = xWrite&(fh&,MySample&,200000) junk& = xClose&(fh&) END IF FreeVec MySample& [ - Antworten - Zitieren - Direktlink - ] |
18.11.2007, 12:17 Uhr jolo Posts: 110 Nutzer |
Hallo Maik,Zitat: Wie, UAE ist kein echter Amiga? Soll das heißen, isch haabe gaar keinen Amiga? Ische nix Amiganer? Nee, Recht hast Du - aber was ich eigentlich sagen wollte ist, dass ich unter WindowsXP arge Probleme hatte, ein korrektes Timing hinzubekommen - dementsprechend war ich einigermaßen erfreulich erstaunt, dass das Timer-Device unter WinUAE ziemlich genau arbeitet. Zitat: Normalerweise sollte das Empfangen der Daten keinen Einfluss auf einen der beiden Timer haben, ansonsten wären die Timer nur Makulatur. Ich könnte aber die anderen Interrupts sperren die nicht benötigt werden - allerdings wird dann nichts mehr richtig funktionieren, was die serielle Schnittstelle betrifft - und das will ich vermeiden. Was mir aber aufgefallen ist, dass Du einen Wert "peekst", ohne das gelesene Datenbyte vorzeichengerecht zu erweitern (+128) - müsste in etwas so aussehen: code:POKEB MySample&+count&, PEEKB(&hBFE101) + 128 INCR count& Anbei, das kleine Tool "TimerIRQ" kannst Du benutzen um festzustellen, ob der von mir favorisierte CIA-A Timer überhaupt mit der Seriellen-Schnittstelle harmonisiert. Um Deinem Beispiel zu folgen, brauchst Du nur "timerirq 16000" im CLI zu tippen. Es digitalisiert dann mit 16000 Hz. Was mir zudem aufgefallen ist, dass Du das Digitalisieren wieder auf Prozess-Ebene verlagerst, wo wir uns doch einig waren, dass das nie und nimmer richtig funktioniert kann. Wieso benutzt Du nicht den "eingebauten" Digitizer? Dafür habe ich ihn ja geschrieben. Im Prinzip musst Du nur einen Speicherbereich allozieren/definieren, der groß genug ist, die Zeiger auf die einzelnen Puffer aufzunehmen; bei einem Puffer also 8 Bytes, weil ja der zusätzliche, letzte Zeiger genullt werden muss. code:DIM pufferListe 8 REM 8 Bytes reservieren = 2 Langworte Jetzt musst Du die Adresse von "MySample" dort als erstes Langwort eintragen: code:POKEL pufferliste&, VARPTR(MySample&) und zum Schluss das zweite Langwort nullen: code:POKEL pufferlist& + 4, 0 REM Ende der Puffer-Liste Das war's. Jetzt kannst Du den eingebauten Digitizer verwenden: code:ihandle& = InitIRQ&( 16000, "DigiTest", 0, 0, pufferListe&, 200004) REM Puffergröße = 200004 Bytes Das "normale" Signal-Handling solltest Du dann auch ausschalten, ansonsten wird Dein Prozess 16000-mal pro Sekunde wieder aufgeweckt - was nicht gerade im Sinne des Erfinders ist. code:SetIRQAttrI&(ihandle&, 4) REM Normales Signal-Handling ausschalten Beim Eintreffen des "Puffer ist voll" Signals ( sigmask&=(1<<GetIRQAttrI&(ihandle&,1)) ) kannst Du den Interrupt und damit auch den Digitizer beenden. Am Besten wäre es aber, wenn Du eine kleine Mini-Funktion mitlaufen lassen würdest, die entscheidet, wann ein "normales" Signal zum Hauptprogramm gesendet wird, um den Hauptprogramm zu irgendeiner Aktivität (Goertzel) verleitet sobald genug Daten bereitstehen. Wie gesagt, die Mini-Funktion wird im Interrupt-Code ausgeführt und muss dementsprechend die Register auf die von MaxonBasic verwendete verbiegen, ansonsten ist ein Crash nicht fern. Wie schon gesagt, falls Deine Mini-Funktion null retourniert, wird *kein* Signal an Dein Hauptprogramm gesendet, nur wenn Deine Mini-Funktion irgendeinen Wert ungleich null zurückgibt, wird der Interrupt-Code, der Deine Mini-Funktion aufrief, dem Hauptprogramm das "normale" Signal signalisieren. Anbei, das ist der echte Interrupt-Code der u.a. auch Deinen Code (Mini-Funktion) aufruft/aufrufen könnte: C code:SUPERIOR ULONG CIAA_Code( REG(a1, struct TimeOutIRQData *tid) ) { LONG i; i = 2; /* Dürfen wir eine Aktion ausführen? */ if ( tid->TimeOutFlag == ALIVE ) { if (tid->IntType == IRQ_DIGITIZE) CallDigitizerCode( tid); /* Rufe Digitizer auf */ /* Falls Benutzer-Code vorhanden, diesen jetzt anspringen */ if (tid->IRQUsersCode) tid->SendSignal = (LONG) tid->IRQUsersCode( (APTR) tid->IRQUsersData); /* Falls SendSignal != 0 wird Signal gesendet! */ if (tid->SendSignal) Signal( tid->TimeOutTask, (1 << tid->TimeOutSignal) ); } else /* Nee, keine Aktion ausführen. Ende? */ { if (tid->TimeOutFlag == KILL) /* DeleteIrq() setzt dies - hat für uns */ tid->TimeOutFlag = KILLED; /* aber eigentlich Bedeutung, da wir */ } /* diesen Punkt nie erreichen (Interrupt */ /* schon gestoppt falls KILL gesetzt) */ return i - 2; } Gruß [ - Antworten - Zitieren - Direktlink - ] |
18.11.2007, 18:09 Uhr MaikG Posts: 5172 Nutzer |
>Was mir aber aufgefallen ist, dass Du einen Wert "peekst", ohne das >gelesene Datenbyte vorzeichengerecht zu erweitern (+128) >- müsste in etwas so aussehen: Hab ich aus Zeitgründen (hier) nicht gemacht, es macht aber keinen unterschied in bezug auf die Störungen. >Was mir zudem aufgefallen ist, dass Du das Digitalisieren wieder auf >Prozess-Ebene verlagerst, wo wir uns doch einig waren, dass das nie >und nimmer richtig funktioniert kann. Das mache ich weil das viel einfacher ist. Und es geht schon erheblich besser als mit dem timer.device. Speziell bei 030<->060 sind die abweichungen minimal. >Wieso benutzt Du nicht den "eingebauten" Digitizer? Dafür habe ich >ihn ja geschrieben. Ja, das versuche ich auch noch. Erstmal habe ich versucht das mit den Infrarot-Senden zu Timen. >Anbei, das kleine Tool "TimerIRQ" kannst Du benutzen um festzustellen, ob der von mir favorisierte CIA-A Timer überhaupt mit der Seriellen-Schnittstelle harmonisiert. Serielle Schnittstelle? Das ist doch die Parallele. Das Prog knackt genauso, zusätzlich wiederholt es bereits gespielte Teile und scheidet andere weg. [ Dieser Beitrag wurde von MaikG am 18.11.2007 um 19:18 Uhr geändert. ] [ - Antworten - Zitieren - Direktlink - ] |
20.11.2007, 20:33 Uhr jolo Posts: 110 Nutzer |
Hi Maik, ich habe vorhin diverse Tests durchgeführt und alles was ich sagen kann ist, dass selbst hier unter WinUAE und einem nicht geraden langsamen PC ca. 14000 Aufrufe pro Sekunde das Maximum sind, dass der CIA-A Interrupt im Multitasking-Betrieb mit diversen anderen Interrupts eingeschaltet, imstande ist zu signalisieren, ohne aus dem Ruder zu laufen. Alles was darüber hinausgeht, klappt hier bei mir nicht! Ich habe eine gefakte Bibliothek dafür benutzt, die einen Sound beinhaltet, der mit 14880 Hz (Periode 240) abgespielt werden muss. Tests mit 18896 erbrachten, dass maximal 15000-mal pro Sekunde ein Interrupt generiert wurde - anstelle von fast 19000-mal. Aber wie gesagt, die Schmerzgrenze liegt irgendwo im Bereich von 14000. Betreffend der Störungen: Dazu kann ich im Moment nicht viel sagen, da mein 4000er im Keller schön verpackt dahin vegetiert - und ich derzeit keine Motivation verspüre, diesen neu aufzubauen (Festplatte und diverse Kleinigkeiten fehlen). Dementsprechend kann ich nicht selber digitalisieren. Wie oben schon erwähnt, versuch es mal mit 12000 bzw. 14000 Hz - und benutze zu Testzwecken mal TimerIRQ - es zeigt Dir an, wie viele Daten pro Sekunde wirklich gesampelt werden können (der Wert den TimerIRQ ausgibt entspricht nicht hundertprozentig dem gewählten Wert bedingt durch die Integer-Arithmetik - sollte aber nichtsdestotrotz einen groben Überblick gewähren). Bei Abweichungen von mehr als 400 Samples kannst Du davon ausgehen, dass Dein gewählter Wert zu groß ist. Ich habe die Bibliothek auch dahingehend geändert, dass der parallele Port nun auf Eingang geschaltet wird. Die Wiederholungen resultieren aus der nicht hundertprozentigen Synchronisation - allerdings wird jetzt die Audio-Hardware dahingehen ausspioniert, wie viele Bytes (annähernd) pro Sekunde ausgegeben werden und dementsprechend wird die Abspiellänge beschnitten (ac_len). Das sollte schon mal etwas bessere Ergebnisse liefern; aber wie gesagt, hundertprozentig bekomme ich das ohne vorherige Synchronisation nicht hin. Zitat: Klappt das? Wäre schön - dann funktioniert nämlich etwas. Zitat: Autsch. Natürlich. Manchmal bin ich nicht im Vollbesitz meiner geistigen Kräfte... Zitat: Sollte mit der neueren Version besser gelingen, allerdings, wie gesagt, musst Du dann Deine Ansprüche (Hz) herunterschrauben. Ob's allerdings nach wie vor knackt, kann ich nicht sagen - hier hilft nur ausprobieren. Wiederholungen sollten jetzt seltener auftreten - da ja die Abspiellänge auf einen regulären Wert beschnitten wird. Neue Version (auch die getürkte) kann von der bekannten Seite heruntergeladen werden. Archiv ist jetzt allerdings 2.6 MBytes groß - bedingt durch den Sound. Installiere mal die getürkte Bibliothek anstelle der echten und rufe TimerIRQ mit 14880 Hz auf - die Anzahl Bytes die der CIA-A Interrupt der Audio-Hardware pro Sekunde zur Verfügung stellt, wird ausgegeben - und das sollte eine Orientierungshilfe sein. Wenn der Wert unter 14400 liegt weißt Du, dass der CIA-A Interrupt überfordert ist. Gruß [ - Antworten - Zitieren - Direktlink - ] |
20.11.2007, 23:02 Uhr MaikG Posts: 5172 Nutzer |
>ich habe vorhin diverse Tests durchgeführt und alles was ich sagen >kann ist, dass selbst hier unter WinUAE und einem nicht geraden >langsamen PC ca. 14000 Aufrufe pro Sekunde das Maximum sind, dass >der CIA-A Interrupt im Multitasking-Betrieb mit diversen anderen >Interrupts eingeschaltet, imstande ist zu signalisieren, ohne aus >dem Ruder zu laufen. Tja, wenn das mit dem Timer.device so währe okay... Aber mit Interrupts muss ich sagen das UAE bei der Customchip benutzung extrem in die Knie geht. Versuch mal nur die WB in AGA zu fahren, das ist auf einem 500 MHZ Rechner langsamer als mit einem A600. >Ich habe die Bibliothek auch dahingehend geändert, dass der parallele >Port nun auf Eingang geschaltet wird. Das wird nicht helfen, es sei denn du schaltst den ParPort in der alten Version immer auf Ausgang. Kannst du den anderen CIA-Timer wieder benutzen(da ging es ja)? >Die Wiederholungen resultieren aus der nicht hundertprozentigen Nein, das passiert wenn man einen zu großen Puffer nimmt, das hatte ich beim ASM Programm auch. Lässt man den Puffer beim Standard wert ist es okay. >Klappt das? Wäre schön - dann funktioniert nämlich etwas. Ja, wesentlich besser als mit dem timer.device, vor allem weil ich auf den beiden Prozessoren nicht 2 verschidene Zeiten angeben muss. Der Joyport scheint nicht gestört zu werden. >Ob's allerdings nach wie vor knackt, kann ich nicht sagen - >hier hilft nur ausprobieren. Du verwechselst jetzt das Knacken was mit dem ASM+C Programm minimal da war mit dem was ich jetzt meine - welches die Parallel Information immer zwischendurch auf -127 runterschaltet. Das jetzt ist viel schlimmer. >Wenn der Wert unter 14400 liegt weißt Du, dass der CIA-A Interrupt >überfordert ist. Ein Echter Amiga macht 28000 trotz Emulation des Samplers ohne schwierigkeiten. Die Zahl liegt immer minimal unter dem gewünschten, aber das sollte bedingt durch den Zeitmessungstart+Rundungsungenauigkeit (41, 42) normal sein. So nun wollte ich das mit dem Samplen über die Lib mal machen, wie ich gesehen habe muss man dazu diesen ASM-Teil nicht verwenden. Aber, es stürzt einerseits mit einigen Hits ab, andererseits scheint es so als würde die Lib ebenfalls den Audio-Wiedergabe Teil übernehen. Was schlecht ist, denn die Audiokanäle werden ja schon von dem Programm benutzt wo das Sampling mal rein soll. code:POKEB &hBFE301,0 REM Parallelport auf Eingang MySample&=AllocVec(200004, MEMF_PUBLIC& OR MEMF_CLEAR&) test&=&h45454545 count&=0 DIM pufferliste&(12) POKEL(pufferliste&(0)), MySample& POKEL(pufferliste&(1)), NULL& POKEL(pufferliste&(2)), NULL& ihandle&=InitIRQ&(20000, VARPTR(test&),NULL&,0,VARPTR(pufferliste&(0)),50000) REM 16000 sigmask&=(1<<GetIRQAttrI&(ihandle&,1)) junk&=SetIRQAttrI&(ihandle&,4) junk&=StartIRQ&(ihandle&) junk& = xWait&(sigmask&) junk&=DeleteIRQ&(ihandle&) Das mit der Pufferliste hab ich nicht Verstanden: (0) (4) (8) damit würde man unter Basic jeweils 3 LONG's freilassen. Also hab ich es in (0), (1), (2) geändert, also folgen die Adressen hintereinander. Geholfen hats aber nicht. [ Dieser Beitrag wurde von MaikG am 21.11.2007 um 10:24 Uhr geändert. ] [ - Antworten - Zitieren - Direktlink - ] |
21.11.2007, 16:55 Uhr Holger Posts: 8116 Nutzer |
Zitat:Ich glaube nicht, dass eine höhere Geschwindigkeit des PCs daran etwas ändern würde. UAE emuliert den Amiga halt exakt. Eine Turbo-Option für die CIAs gibt es nicht, und auch negative Auswirkungen schlechter Implementierungen des timer.device werden korrekt emuliert. Nehme ich mal an... Zitat:Ich glaube nicht, dass es Dir gelingen wird, auf einem A600 die "WB in AGA zu fahren", somit kann UAE in dieser Disziplin kaum langsamer als der A600 sein. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
21.11.2007, 17:47 Uhr MaikG Posts: 5172 Nutzer |
>Ich glaube nicht, dass eine höhere Geschwindigkeit des PCs daran >etwas ändern würde. UAE emuliert den Amiga halt exakt. Scheinbar nicht exakt, ein echter Amiga bringt mehr CIA-Speed. Hat mit Turbo nichts zu tun, denn ich habe den CIA ja nicht übertaktet oder so. >Ich glaube nicht, dass es Dir gelingen wird, auf einem A600 die >"WB in AGA zu fahren", somit kann UAE in dieser Disziplin kaum >langsamer als der A600 sein. Verschrieben nimm ECS/A600 oder AGA/A1200 dann stimmts. [ - Antworten - Zitieren - Direktlink - ] |
21.11.2007, 23:31 Uhr jolo Posts: 110 Nutzer |
@MaikG: Hi. Zitat: Habe ich bis dato nicht wahrgenommen - aber es stimmt. Zitat: Bei nur 500 MHz würde ich Amithlon empfehlen. WinUAE läuft erst ab 2 GHz aufwärts manierlich. Zitat: Meines Wissens nach spielt es keine Rolle beim Lesen von Daten die an der parallelen Schnittstelle anliegen, ob Eingang oder Ausgang spezifiziert wurde; es wird immer der aktuelle Wert der anliegt, zurückgegeben. Falls ich mich täusche berichtige ich das im Programm-Code. Zitat: Du meinst anstelle des CIA-A Interrupts einen CIA-B? Kann ich machen - hatte aber hier Probleme, da der CIA-B sich nicht richtig mit der Audio-Hardware verträgt und der Cause()-Aufruf, der die Audio-Hardware in Gang setzt, nur zu bestimmten Zeiten eine Aktion durchführt. Bei der Verwendung des CIA-A Interrupts konnte ich die Audio-Hardware von innerhalb des Interrupts starten - ohne Umweg über Cause(). Zitat: Der Puffer ist genau für eine Sekunde Abspielzeit ausreichend - falls aber der Interrupt nicht genügend Daten, sprich Bytes bereit stellt, werden aufgrund des mangelnden Timings nur ca. 2/3 des Puffers innerhalb einer Sekunde gefüllt. Der Audio-Hardware Interrupt beginnt dann schon wieder diesen Puffer abzuspielen (nach exakt einer Sekunde), während die Routine, die mit dem Interrupt synchronisiert ist, sich erst bei 2/3 des Puffer-Inhalts und damit bei 2/3 einer Sekunde wähnt. Wie gesagt, bis 14 KHz klappts, danach läuft der CIA-A Interrupt aus dem Ruder, sprich, er kann nicht so oft pro Sekunde ausgeführt werden. Zitat: Na, dann war ja meine Mühe nicht ganz umsonst. Zitat: Jetzt verstehe ich so langsam. Es könnte sein, dass dem CIA-A-CHIP dadurch mitgeteilt wird, das Daten anstehen. Müsste das aber erst mal nachlesen. Probehalber wird jetzt der FLAG-Interrupt unterdrückt. Zitat: 1. Parameter: Frequenz pro Sekunde. 2. Parameter: Adresse Zeichenkette für Namen des Interrupt. 3. Parameter: Benutzer definierter Code der im Interrupt ausgeführt werden soll. 4. Parameter: Daten/Struktur für Benutzer definierten Code (halt irgendwelche Argumente). 5. Parameter: Pufferliste - zeigt auf einen Speicherbereich, in dem die Adresse(n) Deine(s)(r) FAST-RAM Puffer vermerkt sind; InitIRQ() zählt die gesetzten Langworte und interpretiert diese als Adressen zu den einzelnen Puffern. Deshalb muss als letztes Element ein NULL-Zeiger gesetzt sein (Ende der Pufferliste). Da ich kein Basic verstehe, habe ich den POKEL-Befehl falsch eingesetzt - so wie Du es macht müsste es klappen. 6. Parameter: Größe in Bytes eines einzelnen Puffers - das heißt dann aber auch, das alle Puffer von der gleichen Größe sein müssen. In Deinem Beispiel allozierst Du 200004 Bytes für einen Puffer - sagst InitIRQ() aber, dass der Puffer nur 50000 Bytes groß ist. Warum? Und ja, falls eine Pufferliste spezifiziert wird, also nicht NULL ist, wird die Audio-Hardware in Gang gesetzt. Falls Du das nicht wünscht, kann ich das ausbauen. Weshalb bei Dir der Digitizer abschmiert kann ich (derzeit) noch nicht sagen. Probiere mal TimerIRQ() - wenn's damit klappt, ist dein Basic-Programm für die Hits verantwortlich (falsche Parameter?). Allerdings ist auch ein Programmierfehler meinerseits nicht auszuschließen. Habe die Bibliothek wieder ein klein wenig modifiziert und dabei festgestellt, dass das CIA-A Kontrollregister eine falsche Bitmaske abbekam - zudem wird jetzt auch der FLAG-Interrupt gesperrt (zuständig für das Handshake-Signal des parallelen Ports). Die Audio-Ausgabe habe ich dahingehend geändert, dass kein Puffer mehr verwendet wird. Kann das aber hier nicht ausprobieren weil WinUAE da nicht mehr mitspielt (zu viele Daten in zu kurzen Intervallen). Wenn's leiert oder blechern klingt baue ich das wieder raus. Ich verwende nach wie vor noch einen CIA-A Interrupt - falls es wider Erwarten damit Probleme gibt, werde ich einen CIA-B Interrupt verwenden - dann muss ich die Audio-Ausgabe aber wieder gepuffert durchführen. Tut mir leid, dass Du das Versuchskaninchen spielen musst - aber ich habe wirklich keine Lust, meinen A4000 wieder zu reanimieren. Neues Archiv wurde hochgeladen. Gruß [ - Antworten - Zitieren - Direktlink - ] |
21.11.2007, 23:46 Uhr jolo Posts: 110 Nutzer |
Hi.Zitat: Das Problem einer jeden Emulation ist, dass diese sukzessiv vorgehen muss - denke ich zumindest. Ich habe noch keine geschrieben - und habe es auch nicht vor. Der Amiga und seine Custom-Chips verarbeiten aber Daten parallel zueinander, d.h. unabhängig von einander. Dementsprechend sind die Zeitabstände in denen eine Aktion stattfinden kann, auf der echten Hardware immer kleiner als unter einer Emulation - zudem laufen die meisten Emulationen noch unter einem Host-Betriebssystem, d.h. im Multitasking. Amithlon ist hier eine Besonderheit und daraus resultiert auch eine mehrfach höhere Ausführungsgeschwindigkeit gegenüber (Win)UAE. Und ja, Maik hat Recht - unter der echten Hardware sind ohne Probleme Frequenzen bis zu 28000 Hz möglich, da die CIA-Chips Hardwarebausteine sind denen es egal ist, ob die CPU mitkommt oder nicht, da diese eh keine Ahnung von der Existenz einer CPU haben. Man legt von Außen eine Taktfrequenz an und die CIAs werkeln vor sich hin - entsprechend dem Inhalt ihrer Register. Die CPU kann hier eingreifen falls sie nicht mitkommt - aber das ist ein anderes Thema. Nehmen wir mal unser Beispiel zum Digitalisieren: Die Emulation muss bei 14 kHz Frequenz 14000-mal pro Sekunde das Verhalten des CIA-Chips emulieren, 4 * 14000-mal das Verhalten der Audio-Hardware (abgesehen davon, das 8-Bit Sounds in 16-bittige gewandelt werden müssen), 14000-mal das Verhalten der Centronics-Schnittstelle und das Abgleichen mit der Host-Hardware. Zudem kommt noch hinzu, das eine CPU emuliert werden muss und die Video-Ausgabe. Lange Rede, kurzer Sinn: Je mehr Aufgaben eine Emulation gleichzeitig zu bewältigen hat, desto weiter entfernt sie sich vom Original. Gruß [ - Antworten - Zitieren - Direktlink - ] |
22.11.2007, 12:35 Uhr MaikG Posts: 5172 Nutzer |
>Bei nur 500 MHz würde ich Amithlon empfehlen. Das kostet doch Geld und hat keine Custom Chip Emu? Ich verwende UAE eh nicht, hab ja echte Amigas. Ist nur um bestimmte Sachen zu testen oder für langzeitberechnungen, wenn ich mein Haupt-Amiga frei halten will. >Meines Wissens nach spielt es keine Rolle beim Lesen von Daten die an >der parallelen Schnittstelle anliegen, ob Eingang oder Ausgang >spezifiziert wurde; es wird immer der aktuelle Wert der anliegt, >zurückgegeben. >Falls ich mich täusche berichtige ich das im Programm-Code. Am besten ist gar nicht schalten, das kann ich ja in mein Prog machen und L/R wähle ich ja auch selbst. >Du meinst anstelle des CIA-A Interrupts einen CIA-B? Ähm, so wie es im ASM-Beispiel ist. >Wie gesagt, bis 14 KHz klappts, danach läuft der CIA-A Interrupt aus dem Ruder, >sprich, er kann nicht so oft pro Sekunde ausgeführt werden. Also das "kleine" Kacken, vermute ich kommt daher das der CIA-Counter nicht Syncron mit der Wiedergabe läuft. Man macht ja eine User angabe z.B. 22050 Hz, nun ist das mit den 709379 nicht grade zu Teilen -> abweichung von 0.17138322. >Na, dann war ja meine Mühe nicht ganz umsonst. Ja, das ist schon Klasse, hab schon mehrere Praxistests gemacht und es immer Funktioniert. >In Deinem Beispiel allozierst Du 200004 Bytes für einen Puffer - >sagst InitIRQ() aber, dass der Puffer nur 50000 Bytes groß ist. >Warum? Nur so zum testen. >Und ja, falls eine Pufferliste spezifiziert wird, also nicht NULL >ist, wird die Audio-Hardware in Gang gesetzt. Benutzt aber Random-Speicherbereiche. Nach einem Neustart spielte es noch daten die vom voherigen Versuch waren >Falls Du das nicht wünscht, kann ich das ausbauen. Ich denke mal, dies ist vom Hauptprogramm sinnvoller. Sonst wäre es ja nicht so sinnvoll das das Programm die Puffer zur verfügung stellt. >Tut mir leid, dass Du das Versuchskaninchen spielen musst - Das ist absolut kein Problem, ich bin sehr froh das du mir bei diesem Timing Problem hilfst... [ Dieser Beitrag wurde von MaikG am 22.11.2007 um 12:36 Uhr geändert. ] [ - Antworten - Zitieren - Direktlink - ] |
22.11.2007, 17:38 Uhr MaikG Posts: 5172 Nutzer |
>Wenn's leiert oder blechern klingt baue ich das wieder raus. Leiern und blechern nicht, aber da sind massive Störungen drauf. Wie soll ich die beschreiben, brummen, schnarren? >Probiere mal TimerIRQ() - wenn's damit klappt, ist dein >Basic-Programm für die Hits verantwortlich (falsche Parameter?). Ja, sag mir gleich nochmal, die Puffer, benötigst du da einen Pointer auf einen Pointer der auf den Allocierten Speicher Zeigt? Ich hab jetzt nur den Pointer in der Pufferliste geschrieben welcher von AllocVec kommt. Und Fast-Mem ist richtig? [ - Antworten - Zitieren - Direktlink - ] |
23.11.2007, 00:25 Uhr jolo Posts: 110 Nutzer |
@MaikG: Hi. Zitat: Stimmt schon - allerdings *fühlt* sich Amithlon wie ein echter Amiga an. Ist kein Vergleich zu (Win)UAE. Da es nicht mehr vertrieben und weiterentwickelt wird und die meisten, die es besitzen, nicht verkaufen/missen wollen, kommt man kaum noch an Amithlon ran. Zitat: In Ordnung. Wird gemacht. Zitat: Das Assembler-Beispiel benutzt einen der beiden CIA-B Timer. Wie Du aus meinen Postings ersehen kannst, möchte ich das Ganze auf Basis der CIA-A Timer belassen und zwar weil dadurch das System nicht bei unsachgemäßer, sprich übergebührlicher Benutzung in die Knie geht. Falls es mit dem CIA-A Timern klappt, lassen wir es so wie es ist, falls allerdings nicht, stelle ich auf CIA-B um. Zitat: Ja, aber man könnte dem mit einigem Aufwand entgegentreten - ich persönlich kann aber mit diesen kurzen Blips gut leben, da diese ja nicht als Daten in die FAST-RAM Puffer übernommen werden. Zitat: Nee, nur AllocVec() ohne MEMF_CLEAR Flagge - dementsprechend ist der Puffer (CHIP-RAM) in einen undefinierten Zustand - verwende ich, um Initialisierungs-Fehler aufzuspüren. Wird zu einem späteren Zeitpunkt - wenn alles klappt wie es soll, geändert. Zitat: Hier missverstehen wir uns. Deine Puffer (FAST-RAM) werden mit Werten gefüllt - sie werden aber nicht für die Audio-Ausgabe verwendet. Dafür fordert InitIRQ() vom System CHIP-RAM an. Dieser CHIP-RAM Puffer ist allerdings privat, d.h. Du hast keinen Zugriff darauf. CHIP-RAM bremst eine CPU ein - im FAST-RAM Bereich kann die CPU mit voller Geschwindigkeit werkeln. Dementsprechend sollte man nur dann CHIP-RAM verwenden, wenn es unbedingt nötig ist (Custom-Chips) und die CPU soweit möglich, nicht auf diesen Speicherbereich zugreifen lassen. Eine 68060 die aufs CHIP-RAM zugreifen muss, ist nur unwesentlich schneller als eine 68000er. Anbei, die letzte wie auch die aktuelle Version verwenden überhaupt keinen CHIP-RAM Puffer - obschon dieser nach wie vor alloziert wird. Die Audio-Ausgabe erfolgt ohne DMA - das heißt ohne Speicherzugriffe seitens der Custom-Chips. Zitat: Mache ich gerne weil es mir Spaß bereitet, die Hardware wieder direkt anzusprechen. Zitat: Das habe ich befürchtet - Mist! Komisch, nachdem ich alle Preprozessor-Kommandos durch Laufzeitvariabeln ersetzt habe, lief es plötzlich auch hier. Nach mehreren Tests hat sich herausgestellt, dass im Falle einer Veränderung am Inhalt des Audio-Puffers (CHIP-RAM), der ja eigentlich bei der Verwendung der Audio-Hardware ohne DMA, dass heißt Speicherzugriffe durch die Custom-Chips, keinerlei Bedeutung hat, diese Veränderung am Pufferinhalt von der Audio-Hardware registriert und in irgendeiner Weise mit negative Folgen quittiert wird. Hmmm, nachdem der CHIP-RAM Puffer nicht mehr verändert wird, kann selbst unter WinUAE DMA-freie Audio-Ausgabe erzeugt werden. Kann mir jemand dieses Verhalten erklären? Um noch einen drauf zu setzen: Cause() kann beliebig oft innerhalb einer Sekunde aufgerufen werden. Meine Spekulation bezüglich des Timings ist vollkommen falsch. Dies bedeutet im Umkehrschluss, dass es mittels des Timer-Device theoretisch möglich sein sollte, zigtausend Prozessor-Unterbrechungen pro Sekunde zu generieren. Auch unter MorphOS/OS4! Dementsprechend brauch man/frau keine CIAs. Kann aber noch nicht sagen, welche Voraussetzungen für das Timer-Device geschaffen werden müssen um das zu erreichen (doppelte Interrupt-Struktur?). Zitat: Der Digitizer-Code funktioniert - und schmiert nicht ab? Okay, das mit der Pufferliste ist easy. Wenn Du nur einen Puffer verwenden willst, muss die Pufferliste acht Bytes groß sein - wegen des terminierenden NULL-Pointers. Pufferliste 0 - 0xnnnnnnnn Adresse Deines Puffer (also hier die Adresse die AllocVec() zurück gibt eintragen) 4 - 0x00000000 NULL-Pointer Ende der Pufferliste InitIRQ() erwartet nun die Adresse der besagten acht Bytes - also einen einfachen Zeiger. Im Prinzip könntest Du AllocVec() mit acht Bytes aufrufen - die zurückgegebene Adresse ist dann die Pufferliste. Jetzt allozierst Du 50000 Bytes und trägst die retournierte Adresse an erster Stelle in Deine Pufferliste. Das Langwort an zweiter Stelle in der Pufferliste musst Du jetzt löschen - das war's. Oder für zwei Puffer: pufferliste = AllocVec( 12, MEMF_CLEAR) puffer1 = AllocVec( 50000, MEMF_CLEAR) puffer2 = AllocVec( 50000, MEMF_CLEAR) Nehme jetzt mal an, 'pufferliste' liegt ab Adresse 3000 im Speicher, 'puffer1' ab 15000 und 'puffer2' ab 90000. Dann müsste nach der korrekten Initialisierung der Speicherbereich ab 3000 so aussehen: (3000 = $BB8, 15000 = $3A98, 90000 = $15F90, 3016 = $BC8) code:__________1. Langwort 2. Langwort 3. Langwort 4. Langwort 00000BB8: 00 00 3A 98 00 01 5F 90 00 00 00 00 XX XX XX XX 00000BC8: XX XX XX XX usw. InitIRQ() benötig in diesem Beispiel als fünften Parameter den Wert $BB8 - ab diesem Speicherbereich stehen die Langworte (Adressen) zu den einzelnen Puffern. Und solange es kein Langwort dessen Wert null ist findet, interpretiert es jedes gesetzte Langwort als Adresse (in oberen Beispiel zwei). Nehme zudem an, dass ab Adresse 9999 der String steht, der dem Interrupt einen Namen gibt, dann lautet der Aufruf für InitIRQ mit 22050 Hz wie folgt: InitIRQ( 22050, 9999, 0, 0, 3000, 50000) oder ausgeschrieben - in C: InitIRQ( 22050, "Test", 0, 0, pufferliste, 50000) Im Prinzip ganz einfach zu handhaben. Und ja, Deine Puffer dürfen im FAST-RAM Bereich liegen - sie werden vom Interrupt nur gefüllt (ein Byte pro Timer-Tick) und dann nicht weiter beachtet. Neue Version wurde hochgeladen. Benutzt weiterhin einen CIA-A Interrupt und eine DMA-freie Audio-Ausagbe. DMA-frei bedeutet, dass kein CHIP-RAM Puffer verwendet wird. Du kannst das ändern, indem Du SetIRQAttrI( ihandle, 64) aufrufst (habe ich aber noch nicht ausprobiert). Ein nochmaliger Aufruf stellt den voreingestellten Modus wieder her. Gleiches gilt für die Audio-Ausgabe: Die Audio-Ausgabe kannst Du unterdrücken, indem Du SetIRQAttrI( ihandle, 128) verwendest - oder wieder einschalten, bei nochmaligen, gleich lautenden Aufruf. Habe ich auch noch nicht ausprobiert... Die Werte 64 und 128 sind Kippschalter. An, aus, an, aus, an, aus... Sag mir mal ob jetzt die Audio-Ausgabe ansatzweise in Ordnung ist. Gruß [ - Antworten - Zitieren - Direktlink - ] |
23.11.2007, 17:49 Uhr MaikG Posts: 5172 Nutzer |
>Ja, aber man könnte dem mit einigem Aufwand entgegentreten - ich >persönlich kann aber mit diesen kurzen Blips gut leben, >da diese ja nicht als Daten in die FAST-RAM Puffer übernommen >werden. Na wenn ich die Audio-Ausgabe selbst machen kann und das nicht in den Puffer geschrieben wird, bekomme ich das auch irgendwie in den griff. >Der Digitizer-Code funktioniert - und schmiert nicht ab? Jetzt soweit ja, ins Array Poke't man nicht, da nimmt man =. Poken macht man dann bei AllocVec bereich. >Sag mir mal ob jetzt die Audio-Ausgabe ansatzweise in Ordnung ist. Das schnarren ist weg, aber jetzt hört sich es bei 22050 etwa so an wie bei 14000 HZ. Also nicht in der Geschwindigkeit sondern in der Qualität. Ja, per MBasic habe ich diese Knackser die voll in den -127er bereich gehen. Das ist im Puffer(Audioausgabe aus) und bei der Aktiven Audioausgabe so. Beim beiligenden Tool hab ich das nicht mehr vernommen. [ - Antworten - Zitieren - Direktlink - ] |
25.11.2007, 15:44 Uhr jolo Posts: 110 Nutzer |
@MaikG: Hi. Zitat: Ohne Dir zu nahe treten zu wollen: Wenn ich schon Schwierigkeiten habe dass korrekte Timing hinzubekommen, wie willst Du dann von Basic aus vorgehen? Zitat: Höre ich da leichte Kritik bezüglich meiner BASIC-Programmierkenntnisse? ;-) Zitat: Das dürfte normal sein - das Timining-Verhalten ist bei DMA-freier Wiedergabe was gänzlich anderes als mit DMA. Nichtsdestotrotz ist es die einzige Möglichkeit ein absolut exaktes Timing hinzubekommen. Zitat: Heißt das, dass Deine eigenen Routinen zum Digitalisieren diese Knackser beinhalten und TimerIRQ solche Mätzchen nicht macht? Habe jetzt so was wie die endgültige Fassung der Bibliothek fertig gestellt. Das Timing wurde komplett geändert. Es basiert nicht mehr auf 60 Hz Netzspannungen... War ein Fehler zur Berechnung der Periode (Audio-Ausgabe). Jetzt wird die Periode anhand der Frequenz berechnet und danach die Frequenz anhand der Periode. Danach wird aufgrund der neu berechneten Frequenz einer der beiden CIA-A Timer mit dem korrekten Wert initialisiert. Beispiel: Falls Du 14880 Hz als "callsPerSecond" spezifizierst, wird stattdessen eine Frequenz von 14840 verwandt. Du kannst das abfragen, indem Du GetIRQAttrI( 32) aufrufst. Um die Periode zu ermitteln, kannst Du GetIRQAttrI( 256) verwenden. Als nächstes habe ich die DMA-freie Audio-Ausgabe überarbeitet: Das INTEN-Bit im Interrupt-Kontrollregister wird jetzt immer gelöscht - damit man DMA-freie und DMA-unterstützende Ausgabe während der Audio-Wiedergabe wechseln kann. Hoffentlich hat das keine negativen Seiteneffekte auf den Blitter/Copper… Das Programm Digi wechselt alle 5 Sekunden den Modus während es digitalisiert. Voreingestellt ist jetzt der Typ DMA-freie Audio-Ausgabe. Falls Du das nicht willst, musst Du SetIRQAttrI( 64) einmalig aufrufen. Das Programm Digi digitalisiert wirklich - es schreibt Dateien mit maximal 540000 Bytes in die RAM-Disk - allerdings kann eine einzige Audio-Ausgabe aus mehreren solcher Dateien bestehen. CTRL-C beendet es wie gewohnt. Habe das Programm SampleEngine beigefügt (dafür muss die noise.library ins LIBS-Verzeichnis), mit dem Du diese Dateien abspielen kannst. Ist allerdings ein Uralt-Tool - könnte ein paar Macken haben. Eine ist z.B. dass die einzuladende Datei komplett ins CHIP-RAM passen muss - ich hoffe Du hast 1 bis 2 MBytes CHIP-RAM? Wenn keine Audio-Ausgabe erfolgt, kann das an einem Bug im Programm liegen. Einfach solange den Play Button betätigen bis es geht (evt. solange warten, bis der Warten-Mauszeiger verschwindet). Mit diesem Programm kannst Du verifizieren, dass die Audio-Ausgabe mehr oder weniger unabhängig von dem Digitalisieren ist, was bedeutet, das selbst eine inkorrekte Audio-Ausgabe nicht gleichzusetzen ist mit einer inkorrekten Digitalisierung. Probiere es mal aus - dann verstehst Du was ich meine. Anbei, DMA-unterstützende Audio-Wiedergabe (also mittels CHIP-RAM Puffer) sollte jetzt seltener einen Abschnitt doppelt wiedergeben - bedingt durch die korrekte 50 Hz Initialisierung. Ach ja, und zu guter Letzt: Cause() kann doch nicht beliebig oft innerhalb einer Sekunde aufgerufen werden. Es wäre nett, wenn Du mir sagen könntest, ob mittels Digi digitalisierte Dateien und mittels SampleEngine wiedergegebene Dateien korrekt sind - d.h. ob keine Fehler (Blips) darin enthalten sind. Gruß [ - Antworten - Zitieren - Direktlink - ] |
25.11.2007, 18:00 Uhr MaikG Posts: 5172 Nutzer |
>Ohne Dir zu nahe treten zu wollen: Wenn ich schon Schwierigkeiten >habe dass korrekte Timing hinzubekommen, wie willst Du dann von >Basic aus vorgehen? Einfach einen Wert nehmen der grade Teilbar ist. >Das dürfte normal sein - das Timining-Verhalten ist bei DMA-freier >Wiedergabe was gänzlich anderes als mit DMA. Warum eigentlich ohne DMA? Besser als das ASM beispiel und hört es sich nicht an. Das Timing war doch ohnehin exakt. >Heißt das, dass Deine eigenen Routinen zum Digitalisieren diese >Knackser beinhalten und TimerIRQ solche Mätzchen nicht macht? Ich glaube schon. Muss ich bei der Lib verwendung ohne eigenen Code etwa die Register sichern? [ - Antworten - Zitieren - Direktlink - ] |
1 2 -3- 4 | [ - Beitrag schreiben - ] |
amiga-news.de Forum > Programmierung > Registerzugriff in C | [ - Suche - Neue Beiträge - Registrieren - Login - ] |
Impressum |
Datenschutzerklärung |
Netiquette |
Werbung |
Kontakt
Copyright © 1998-2024 by amiga-news.de - alle Rechte vorbehalten. |