DEUTSCHE VERSION |
|
Links | | | Forums | | | Comments | | | Report news |
Chat | | | Polls | | | Newsticker | | | Archive |
amiga-news.de Forum > Programmierung > Tonerkennung | [ - Search - New posts - Register - Login - ] |
1 2 3 4 -5- 6 7 8 9 10 Last | [ - Post reply - ] |
2006-09-07, 10:34 h Mad_Dog Posts: 1944 User |
Wie versprochen, hier das ganze mit improvisiertem Osziloskop. Das Zeitfenster, welches betrachtet wird, ist 0,05 Sekunden. Die Kanaltrennung (Stereo links/rechts) ist erraten: c code:l = Buffer[i] << 1 & 0xFF; r = Buffer[i] << 2 & 0xFF; WritePixel(rp,i,l+64); WritePixel(rp,i,r+128); ...und mit Sicherheit falsch. ...aber immerhin zucken jetzt zwei Kurven im Fenster, die so ähnlich wie ein Audiosignal aussehen. Die Header Datei: c code:/* parallel.h + * Makros für Low-Level Zugriff auf CIA * */ #ifndef PARALLEL_H #define PARALLEL_H #include <string.h> // Adresse des Datenregisters für Parallelport #define PARALLEL_PORT 0xBFE101 // Adresse des Registers für die Richtung des Parallelports #define PARALLEL_DIR 0xBFE301 // Den Parallelport in den Lesemodus versetzen #define SET_PARALLEL_PORT_READ (memset((void *)PARALLEL_DIR,0x0,1)) // Ein Byte vom Parallelport lesen #define READ_PAR(x) (memmove((&x),(void *)PARALLEL_PORT,1)) #endif Das eigentliche Programm (und ja: war auch ein Nacht- und Nebel Hack). c code:--/* Oszi.c * Osziloskop mit LowLevel Zugriff auf CIA * Liest Daten von einem Parallelportsampler * und gibt sie in einem Intuition-Fenster aus. * Autor: Norman Walter * Datum: 6.9.2006 */ #include <stdio.h> #include <stdlib.h> #include <exec/types.h> #include <exec/exec.h> #include <exec/memory.h> #include <exec/io.h> #include <intuition/intuition.h> #include <graphics/gfx.h> #include <dos/dos.h> #include <devices/timer.h> #include <proto/intuition.h> #include <proto/graphics.h> #include <proto/exec.h> #include <clib/alib_protos.h> #include <clib/dos_protos.h> #include "parallel.h" // Samplingfrequenz (hier 8kHz) #define SAMPLINGFREQ 8000 // Größe des Zeitfensters: Zeit in Sekunden #define TIME 0.05 // Wie groß soll das Zeitfenster sein, das wir betrachten? #define FRAMESIZE SAMPLINGFREQ * TIME // Puffer für das Sample BYTE Buffer[FRAMESIZE]; #define WIDTH 400 // Breite des Fensters #define HEIGHT 256 // Höhe des Fensters struct Window *Fenster; // Zeiger auf Window-Struktur struct IntuitionBase *IntuitionBase; // Zeiger auf IntuitionBase-Struktur struct GfxBase *GfxBase; // Zeiger auf GfxBase-Struktur LONG black,green; // Variablen für die Pen Nummern struct timerequest *TimerIO = NULL; struct MsgPort *TimerMP = NULL; BYTE TimerDevice; // Resourcen freigeben void ShutDown(void) { if (TimerMP) DeleteMsgPort(TimerMP); if (TimerIO) DeleteIORequest((struct IORequest *)TimerIO); if (TimerDevice) CloseDevice((struct IORequest *) TimerIO); if (Fenster) CloseWindow(Fenster); if (GfxBase) CloseLibrary((struct Library *) GfxBase); if (IntuitionBase) CloseLibrary((struct Library *) IntuitionBase); } void ReadFrame(void) { int i; /* Hier werden die Werte gesammelt * Bei einer Samplingfrequenz von 8kHz * und 8000 Werten sollte das genau * eine Sekunde dauern */ for (i=0;i<FRAMESIZE;i++) { WaitPort(TimerMP); if(1UL << TimerMP->mp_SigBit) { WaitIO((struct IORequest *)TimerIO); // Wert vom Parallelport kopieren READ_PAR(Buffer[i]); SendIO((struct IORequest *)TimerIO); } } } void ZeichneOsziloskop(struct Window *Win) { int i; struct RastPort *rp; BYTE l,r; rp = Win->RPort; SetRast(rp,black); SetAPen(rp,green); for (i=0;i<FRAMESIZE;i++) { l = Buffer[i] << 1 & 0xFF; r = Buffer[i] << 2 & 0xFF; WritePixel(rp,i,l+64); WritePixel(rp,i,r+128); } } int main(void) { /* Variablen zur Message-Bearbeitung */ struct MsgPort *Port; // Zeiger auf Message Port Struktur struct IntuiMessage *Nachricht; // Zeiger auf Intuition Message Struktur ULONG klasse; USHORT code; BOOL Ende=FALSE; TimerMP = CreateMsgPort(); if (TimerMP == NULL) ShutDown(); TimerIO = (struct timerequest *) CreateIORequest(TimerMP,sizeof(struct timerequest)); if (TimerIO == NULL) ShutDown(); /* Wichtig: Für diesen Zweck brauchen wir UNIT_MICROHZ. * Die anderen Timer sind zu ungenau, weil wir tatsächlich * 0,000125 Sekunden messen wollen, also 125 Mikroherz. */ TimerDevice = OpenDevice(TIMERNAME,UNIT_MICROHZ,(struct IORequest *)TimerIO,0L); if (TimerDevice !=0) ShutDown(); // Intuition Library öffnen IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",36L); if (IntuitionBase == NULL) ShutDown(); GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",0L); if (GfxBase == NULL) ShutDown(); // Fenster mittels Tags öffnen Fenster = OpenWindowTags(NULL, WA_Left, 100, // Abstand vom linken Rand WA_Top, 100, // Abstand vom oberen Rand WA_Width, WIDTH, // Breite WA_Height, HEIGHT, // Höhe WA_Title, "Osziloskop", // Fenstertitel WA_CloseGadget, TRUE, // Close-Gadget WA_DragBar, TRUE, // Ziehleiste WA_DepthGadget, TRUE, // Depth-Gadget WA_GimmeZeroZero, TRUE, // Ursprung 0/0 WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_INTUITICKS, WA_Activate, TRUE, // Fenster aktivieren TAG_DONE); if (Fenster==NULL) ShutDown(); Port=Fenster->UserPort; /* Pens ermitteln: Schwarz und Grün */ black = ObtainBestPen(Fenster->WScreen->ViewPort.ColorMap, 0x00000000,0x00000000,0x00000000, OBP_Precision,PRECISION_GUI, TAG_DONE); green = ObtainBestPen(Fenster->WScreen->ViewPort.ColorMap, 0x00000000,0xFFFFFFFF,0x00000000, OBP_Precision,PRECISION_GUI, TAG_DONE); /* Issue the command and wait for it to finish, then get the reply */ TimerIO->tr_node.io_Command = TR_GETSYSTIME; SendIO((struct IORequest *) TimerIO); // Den Parallelport in den Lesemodus versetzen SET_PARALLEL_PORT_READ; /* Zyklischen Alarm setzen: * 1/SAMPLINGFREQ entspricht dabei einer Periode. * Nach der Formel T = 1/n * wobei n unsere Samplingfrequenz ist. * (siehe auch jede beliebige Physik-Formelsammlung) */ TimerIO->tr_node.io_Command = TR_ADDREQUEST; TimerIO->tr_time.tv_secs = 0; TimerIO->tr_time.tv_micro = 1/SAMPLINGFREQ; while (!Ende) { // Lese Zeitfenster ReadFrame(); WaitPort(Port); /* Schleife läuft bis alle Ereignisse * abgearbeitet sind. */ while(Nachricht=(struct IntuiMessage *)GetMsg(Port)) { klasse = Nachricht->Class; code = Nachricht->Code; /* Welches Ereignis ist eingetreten? */ switch(klasse) { /* Close Gadget wurde angeklickt */ case CLOSEWINDOW : Ende = TRUE; // Programmende break; /* Intuition hat sich gemeldet */ case INTUITICKS : // Zeichne das Osziloskop ZeichneOsziloskop(Fenster); break; } // Ende der switch-Verzweigung /* Wir sind mit der Bearbeitung fertig * und beantworten die Nachricht. */ ReplyMsg((struct Message *)Nachricht); } } AbortIO((struct IORequest *)TimerIO); WaitIO((struct IORequest *)TimerIO); // Die Pens wieder freigeben ReleasePen(Fenster->WScreen->ViewPort.ColorMap,black); ReleasePen(Fenster->WScreen->ViewPort.ColorMap,green); ShutDown(); return 0; } http://www.norman-interactive.com [ Dieser Beitrag wurde von Mad_Dog am 07.09.2006 um 10:47 Uhr geändert. ] [ - Answer - Quote - Direct link - ] |
2006-09-07, 10:40 h Mad_Dog Posts: 1944 User |
Und hier noch ein Screenshot: Bild: http://w3.norman-interactive.com/files/Oszi_1.png -- http://www.norman-interactive.com [ Dieser Beitrag wurde von Mad_Dog am 07.09.2006 um 10:41 Uhr geändert. ] [ - Answer - Quote - Direct link - ] |
2006-09-07, 10:45 h Mad_Dog Posts: 1944 User |
Zitat: Au weia! Du hast natürlich Recht. Und ja - es war spät. In meim Oszi-Programm ist der selbe Fehler drin. -- http://www.norman-interactive.com [ - Answer - Quote - Direct link - ] |
2006-09-07, 12:03 h Holger Posts: 8116 User |
Zitat: Das hätte mich auch gewundert, wenn das einen Unterschied macht. tr_node% ist 0 (in Worten: null). Und weil es von der Logik her an der Stelle keinen Sinn macht, habe ich es weggelassen. io_Command ist direkter Member der IORequest-Struktur. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Answer - Quote - Direct link - ] |
2006-09-07, 12:13 h Holger Posts: 8116 User |
Zitat:Das ist gar nicht die Frage, die Frage ist eher, was dieser code überhaupt bezwecken soll. Und die andere Frage ist, wieso Du überhaupt glaubst, dass sich Dein sampler im Stereomodus befindet, wenn Du keinerlei Ahnung hast, wie man ihn in diesem Modus abfragt, anders gesagt, wie Du diesen Modus überhaupt einschaltest. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Answer - Quote - Direct link - ] |
2006-09-07, 13:07 h Mad_Dog Posts: 1944 User |
Zitat: Zur Erklärung, warum "ich glaube, daß sich mein Sampler im Stereomodus befindet" Folgendes: Ich hab zuerst einfach die Werte aus dem Array Buffer[] als Linien ausgegeben: Angefangen von x=t (bzw. hier i), also dem Zeitpunkt und y=Buffer[i]+128 (also die Amplitude) mit +128 für die Koordinatentransformation wegen der Nullinie. Ergebnis: Es sah so aus, als ob hier das Audiosignal vom Rechten und Linken Kanal gleichzeitig ankommt. O.k. Du hast jetzt keinen solchen Sampler parat, aber wenn Du's sehen würdest, würdest Du verstehen, was ich meine. Also muß es irgendeine Möglichkeit geben, diesen rechts/links Mix auseinanderzufriemeln. Leider hab ich auch keine Ahnung wie das geht. Ich nehme mal nicht an, daß es im Stereo Modus nur 4 Bit pro Kanal sind. -- http://www.norman-interactive.com [ - Answer - Quote - Direct link - ] |
2006-09-07, 13:35 h Holger Posts: 8116 User |
@Mad_Dog: Du scheinst immer noch nicht akzeptieren zu wollen, dass der Wert unsigned sein könnte. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Answer - Quote - Direct link - ] |
2006-09-07, 13:48 h Mad_Dog Posts: 1944 User |
Zitat: Ja, könnte. Wenn dem so wäre, dann könnte es tatsächlich sein, dass der Wert für den linken/Rechten Kanal jeweils als Halbbyte vorliegt - z.B. mit einem Wertebereich von jeweils 0-127. Vielleicht komm ich heute abend dazu, weiter zu experimentieren. Übrigens: Der "murks-Trenncode" entstand auch so. Hab die Halbbytes gelesen und weil kein 'gscheites Ergebnis rauskam, hab ich eben spaßeshalber die Bits ein wenig rumgeschoben. Ist natürlich quatsch, aber zumindest die obere Kurve sieht halbwegs brauchbar aus. Solange keiner ne Doku hat, bleibt nur Reverse Engineering. Noch was: Für AHI gibt's auch ein parallelport-Sampler Treiber. Das Programm "Advanced AHI Recorder" funktioniert auch (in Stereo) mit meinem "Stereo Master" und vermutlich mit vielen anderen Samplern auch. Also muß es doch einen gewissen gemeinsamen Nenner geben. -- http://www.norman-interactive.com [ Dieser Beitrag wurde von Mad_Dog am 07.09.2006 um 13:51 Uhr geändert. ] [ - Answer - Quote - Direct link - ] |
2006-09-07, 15:22 h Mad_Dog Posts: 1944 User |
Zitat: Verwechselst Du nicht Aufmodulieren und Multiplexen? Am Parallelport kommt ein digitales Signal an, d.h. irgendwelche der 8 Pins sind "heiß". Die ergeben dann zusammen einen 8 Bit Wert. Die einzige Frequenz, die es da noch gibt, ist die Frequenz mit der ich den Port abfrage (also wie oft pro Sekunde). Ich sehe nicht, wo man da was aufmodulieren soll. Falls Du eine Ahnung hast, wie man aus dem einen 8 Bit Wert pro Zeiteinheit den linken/rechten Kanal herausbekommt, dann her damit! -- http://www.norman-interactive.com [ - Answer - Quote - Direct link - ] |
2006-09-07, 15:28 h MaikG Posts: 5172 User |
>Das hätte mich auch gewundert, wenn das einen Unterschied macht. >tr_node% ist 0 (in Worten: null). Und weil es von der Logik her an >der Stelle keinen Sinn macht, habe ich es weggelassen. io_Command >ist direkter Member der IORequest-Struktur. Schade, da dachte ich ich hätte einen Fehler gefunden... Also der Stereomodus wird wohl über Pin12/Paper Out gesteuert. Dieser Pin geht an den 4066, das ist der Stereo-Encoder. Ich denke, da ich nur auf einem Chincheingang ein Signal bekomme, ich mich im "Mono"-Modus befinde. [ - Answer - Quote - Direct link - ] |
2006-09-07, 15:50 h Mad_Dog Posts: 1944 User |
Zitat: Aber wie trennst Du in Deinem Programm die Kanäle? -- http://www.norman-interactive.com [ - Answer - Quote - Direct link - ] |
2006-09-07, 16:05 h Holger Posts: 8116 User |
Zitat: Kleiner Tip: Lass es. Wenn Du nicht bereit bist, einfach mal das als gegeben anzunehmen, was ein anderer schon vorher geschrieben hat, kannst Du noch Jahre ohne sinnvolles Ergebnis rumspielen. Wenn MaikG schreibt, dass es ein unsigned byte ist, dann wäre es doch wohl das Mindeste, genau das einmal auszuprobieren, bevor man anfängt, wild irgendwie bitweise zu verschieben. Übrigens werden aus 8 Bit keine 16, egal wie Du sie hin- und herschiebst. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Answer - Quote - Direct link - ] |
2006-09-07, 18:02 h MaikG Posts: 5172 User |
>Aber wie trennst Du in Deinem Programm die Kanäle? Muss man gar nicht, weil da ja nur einer ankommt. Weil default ist Linker Kanal und nur dieser. [ - Answer - Quote - Direct link - ] |
2006-09-08, 10:27 h Mad_Dog Posts: 1944 User |
Na gut, dann bleiben wir eben vorerst bei Mono. Ich präsentiere Euch das "Monoscope" : Bild: http://w3.norman-interactive.com/files/Monoscope.png Sieht doch schonmal ganz gut aus, oder? Im Vergleich zum vorherigen Code hat sich nicht viel geändert. Und ja - es scheint ein unsigned Byte zu sein. Gleichzeitig habe ich noch die Samplingfrequenz auf 32kHz hochgesetzt und dafür das Zeitfenster kleiner gemacht. c code:/* Monoscope.c * Osziloskop mit LowLevel Zugriff auf CIA * Liest Daten von einem Parallelportsampler (Mono) * und gibt sie in einem Intuition-Fenster aus. * Autor: Norman Walter * Datum: 7.9.2006 */ #include <stdio.h> #include <stdlib.h> #include <exec/types.h> #include <exec/exec.h> #include <exec/memory.h> #include <exec/io.h> #include <intuition/intuition.h> #include <graphics/gfx.h> #include <dos/dos.h> #include <devices/timer.h> #include <proto/intuition.h> #include <proto/graphics.h> #include <proto/exec.h> #include <clib/alib_protos.h> #include <clib/dos_protos.h> #include "parallel.h" // Samplingfrequenz (hier 32kHz) #define SAMPLINGFREQ 32000 // Größe des Zeitfensters: Zeit in Sekunden #define TIME 0.0125 // Wie groß soll das Zeitfenster sein, das wir betrachten? #define FRAMESIZE SAMPLINGFREQ * TIME // Periode in Mikrosekunden #define PERIODE (int)1E6/SAMPLINGFREQ // Puffer für das Sample UBYTE Buffer[FRAMESIZE]; #define WIDTH 400 // Breite des Fensters #define HEIGHT 256 // Höhe des Fensters struct Window *Fenster; // Zeiger auf Window-Struktur struct IntuitionBase *IntuitionBase; // Zeiger auf IntuitionBase-Struktur struct GfxBase *GfxBase; // Zeiger auf GfxBase-Struktur LONG black,green; // Variablen für die Pen Nummern struct timerequest *TimerIO = NULL; struct MsgPort *TimerMP = NULL; UBYTE TimerDevice; // Resourcen freigeben void ShutDown(void) { if (TimerMP) DeleteMsgPort(TimerMP); if (TimerIO) DeleteIORequest((struct IORequest *)TimerIO); if (TimerDevice) CloseDevice((struct IORequest *) TimerIO); if (Fenster) CloseWindow(Fenster); if (GfxBase) CloseLibrary((struct Library *) GfxBase); if (IntuitionBase) CloseLibrary((struct Library *) IntuitionBase); } void ReadFrame(void) { int i; /* Hier werden die Werte gesammelt */ for (i=0;i<FRAMESIZE;i++) { WaitPort(TimerMP); if(1UL << TimerMP->mp_SigBit) { WaitIO((struct IORequest *)TimerIO); // Wert vom Parallelport kopieren READ_PAR(Buffer[i]); SendIO((struct IORequest *)TimerIO); } } } void ZeichneOsziloskop(struct Window *Win) { int t; struct RastPort *rp; rp = Win->RPort; SetRast(rp,black); SetAPen(rp,green); for (t=0;t<FRAMESIZE;t++) { Move(rp,t,Win->Height/2); Draw(rp,t,Buffer[t]); } } int main(void) { /* Variablen zur Message-Bearbeitung */ struct MsgPort *Port; // Zeiger auf Message Port Struktur struct IntuiMessage *Nachricht; // Zeiger auf Intuition Message Struktur ULONG klasse; USHORT code; BOOL Ende=FALSE; TimerMP = CreateMsgPort(); if (TimerMP == NULL) ShutDown(); TimerIO = (struct timerequest *) CreateIORequest(TimerMP,sizeof(struct timerequest)); if (TimerIO == NULL) ShutDown(); /* Wichtig: Für diesen Zweck brauchen wir UNIT_MICROHZ. * Die anderen Timer sind zu ungenau. */ TimerDevice = OpenDevice(TIMERNAME,UNIT_MICROHZ,(struct IORequest *)TimerIO,0L); if (TimerDevice !=0) ShutDown(); // Intuition Library öffnen IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",36L); if (IntuitionBase == NULL) ShutDown(); GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",0L); if (GfxBase == NULL) ShutDown(); // Fenster mittels Tags öffnen Fenster = OpenWindowTags(NULL, WA_Left, 100, // Abstand vom linken Rand WA_Top, 100, // Abstand vom oberen Rand WA_Width, WIDTH, // Breite WA_Height, HEIGHT, // Höhe WA_Title, "Monoscope", // Fenstertitel WA_ScreenTitle,"Monoscope V1.0 © 2006 by Norman Walter", WA_CloseGadget, TRUE, // Close-Gadget WA_DragBar, TRUE, // Ziehleiste WA_DepthGadget, TRUE, // Depth-Gadget WA_GimmeZeroZero, TRUE, // Ursprung 0/0 WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_INTUITICKS, WA_Activate, TRUE, // Fenster aktivieren TAG_DONE); if (Fenster==NULL) ShutDown(); Port=Fenster->UserPort; /* Pens ermitteln: Schwarz und Grün */ black = ObtainBestPen(Fenster->WScreen->ViewPort.ColorMap, 0x00000000,0x00000000,0x00000000, OBP_Precision,PRECISION_GUI, TAG_DONE); green = ObtainBestPen(Fenster->WScreen->ViewPort.ColorMap, 0x00000000,0xFFFFFFFF,0x00000000, OBP_Precision,PRECISION_GUI, TAG_DONE); /* Issue the command and wait for it to finish, then get the reply */ TimerIO->tr_node.io_Command = TR_GETSYSTIME; SendIO((struct IORequest *) TimerIO); // Den Parallelport in den Lesemodus versetzen SET_PARALLEL_PORT_READ; /* Zyklischen Alarm setzen: * 1/SAMPLINGFREQ entspricht dabei einer Periode. * Nach der Formel T = 1/n * wobei n unsere Samplingfrequenz ist. * (siehe auch jede beliebige Physik-Formelsammlung) */ TimerIO->tr_node.io_Command = TR_ADDREQUEST; TimerIO->tr_time.tv_secs = 0; TimerIO->tr_time.tv_micro = PERIODE; while (!Ende) { // Lese Zeitfenster ReadFrame(); WaitPort(Port); /* Schleife läuft bis alle Ereignisse * abgearbeitet sind. */ while(Nachricht=(struct IntuiMessage *)GetMsg(Port)) { klasse = Nachricht->Class; code = Nachricht->Code; /* Welches Ereignis ist eingetreten? */ switch(klasse) { /* Close Gadget wurde angeklickt */ case CLOSEWINDOW : Ende = TRUE; // Programmende break; /* Intuition hat sich gemeldet */ case INTUITICKS : // Zeichne das Osziloskop ZeichneOsziloskop(Fenster); break; } // Ende der switch-Verzweigung /* Wir sind mit der Bearbeitung fertig * und beantworten die Nachricht. */ ReplyMsg((struct Message *)Nachricht); } } AbortIO((struct IORequest *)TimerIO); WaitIO((struct IORequest *)TimerIO); // Die Pens wieder freigeben ReleasePen(Fenster->WScreen->ViewPort.ColorMap,black); ReleasePen(Fenster->WScreen->ViewPort.ColorMap,green); ShutDown(); return 0; } Was mich noch ein wenig stört: Das direkte Rumklopfen auf den CIA Registern. Es wäre schöner, wenn man das über das parallel.device machen könnte. Allerdings habe ich es bis jetzt noch nicht hinbekommen, mittels parallel.device ein Byte vom Parallelport zu lesen. -- http://www.norman-interactive.com [ Dieser Beitrag wurde von Mad_Dog am 08.09.2006 um 10:30 Uhr geändert. ] [ - Answer - Quote - Direct link - ] |
2006-09-08, 10:32 h Mad_Dog Posts: 1944 User |
Zitat: O.k. Für Deinen Zweck reicht Mono aus. Aber mich würde es schon interessieren, wie man Stereo Sound bekommt. -- http://www.norman-interactive.com [ Dieser Beitrag wurde von Mad_Dog am 08.09.2006 um 10:32 Uhr geändert. ] [ - Answer - Quote - Direct link - ] |
2006-09-08, 11:22 h Mad_Dog Posts: 1944 User |
@MaikG: Könntest Du bei Gelegenheit mal ausprobieren, ob mein "Monoscope" auf Deimem Sampler läuft? -- http://www.norman-interactive.com [ Dieser Beitrag wurde von Mad_Dog am 08.09.2006 um 11:25 Uhr geändert. ] [ - Answer - Quote - Direct link - ] |
2006-09-08, 12:56 h Holger Posts: 8116 User |
@Mad_Dog: Ich kann mit nicht vorstellen, dass das Timing bei Deinem Programm wirklich korrekt funktioniert. Das timer.device löscht die Zeitangabe in dem TimeRequest nach der Bearbeitung des TR_ADDREQUEST. Wenn Du also nur einmal am Anfang des Programms die Wartezeit in den Request schreibst, wartest Du nur genau einmal diese Zeit und ab dann 0s,0µs. Das verzögert zwar auch ein bisschen, dass dabei aber eine kontrollierbare Frequenz herauskommen soll, kann ich nicht glauben. Übrigens habe ich bei meinem C-Programm, wenn man den TimeRequest korrekt vor jedem TR_ADDREQUEST mit der gewünschten Wartezeit befüllt, exakt die gleichen Resultate, wie mit dem Basic-Programm. Wenn man kleine Wartezeiten in den Regionen, wie hier benötigt, anfordert, beginnt der timer selbst falsch (meist zu langsam) zu laufen. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Answer - Quote - Direct link - ] |
2006-09-08, 13:22 h Mad_Dog Posts: 1944 User |
Zitat: Hab ich nicht gewußt. Danke für den Hinweis. -- http://www.norman-interactive.com [ - Answer - Quote - Direct link - ] |
2006-09-08, 15:11 h MaikG Posts: 5172 User |
>O.k. Für Deinen Zweck reicht Mono aus. Aber mich würde es schon >interessieren, wie man Stereo Sound bekommt. Hab ich dir doch erklärt, man schaltet Stereo ein und bekommt dann bei einer Rate von 44khz 2x 22khz Samples. Du musst alles was oberhalb von den ersten 22khz liegt auf 0-22khz bringen und von den unteren 22khz Isolieren. Frag mich nicht wie das geht. Ich hab aber im Aminet ein Sampler Schaltplan gesehen, der das mit switching macht, da setzt man dann einen extra Pin, liesst 1 Byte Rechts, löscht den liesst dann 1 Byte Links. Also Stereotechnisch scheint es unterschiedliche Versionen zu geben. >Könntest Du bei Gelegenheit mal ausprobieren, ob mein "Monoscope" >auf Deimem Sampler läuft? Sicher, hast du das auch fertig Compiliert? MaikG492 at directbox.com >Übrigens habe ich bei meinem C-Programm, wenn man den TimeRequest >korrekt vor jedem TR_ADDREQUEST mit der gewünschten Wartezeit >befüllt, exakt die gleichen Resultate, wie mit dem Basic-Programm. >Wenn man kleine Wartezeiten in den Regionen, wie hier benötigt, >anfordert, beginnt der timer selbst falsch (meist zu langsam) zu >laufen. Dachte ich mir, was ist also falsch? a) Die Funktion ist nicht für ein Loop gedacht? oder b) Funktion verkehrt aufgerufen? Muss man das Timing vielleicht direkt über die CIA-Timer laufen lassen? [ - Answer - Quote - Direct link - ] |
2006-09-08, 15:48 h Mad_Dog Posts: 1944 User |
Zitat: O.k. damit kann ich was anfangen. Wenn man mit einem Bit wahlweise den rechten/linken Kanal auslesen kann, ist das ein Multiplexverfahren. Man nimmt einfach die doppelte Samplingfrequenz und liest immer abwechselnd den linken und rechten Kanal aus. So hat man dann jeweils 8 Bit für den linken und rechten Kanal. -- http://www.norman-interactive.com [ - Answer - Quote - Direct link - ] |
2006-09-08, 16:19 h Holger Posts: 8116 User |
Zitat:Na ja, die Dokumentation sagt über den (8520) timer "It has precision down to about 2 microseconds, but will drift as system load increases." Ich hätte nur nicht gedacht, dass es so extrem wird. Zitat:Ich habe testweise auf UNIT_WAITUNTIL umgestellt und auf die vorberechnete Zeit (Programmstartzeitpunkt + n * 125µs) warten lassen. Dabei konnte man feststellen, dass es der timer selbst ist, dessen Geschwindigkeit bei kleinen Intervallen falsch läuft. Wenn Du also mittels GetSysTime vor und nach dem Programm die Zeit nimmst, stellst Du fest, dass die Differenz dem eigentlich gewünschten Wert entspricht. Nur die Realzeit weicht davon ab. Zitat:Da sehe ich momentan keine Alternative. Die vom timer.device angebotenen Optionen sind offenbar unbrauchbar. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Answer - Quote - Direct link - ] |
2006-09-08, 16:35 h bubblebobble Posts: 707 User |
Hier mein Senf dazu: ACHTUNG: GetSysTime hat möglicherweise eine niedrige Auflösung. Unter WinUAE wird dazu der 50Hz BLank verwendet, das reicht natürlich nicht. Eine Möglichkeit zu timen wäre die eclock zu pollen. (ReadEClock) Ansonsten sollte mit WAITECLOCK mit vorherberechnetem Zeitraster funktionieren. (so funktioniert der MID timer in HD-Rec). Der CIA chip wird bei CPU Belastung bis zu 25% schneller. -- Thilo Köhler, Author von: HD-Rec, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, TKUnpacker Homepage: http://www.hd-rec.de [ - Answer - Quote - Direct link - ] |
2006-09-08, 18:01 h MaikG Posts: 5172 User |
>Ich habe testweise auf UNIT_WAITUNTIL umgestellt und auf die >vorberechnete Zeit (Programmstartzeitpunkt + n * 125µs) warten >lassen. Dabei konnte man feststellen, dass es der timer selbst ist, >dessen Geschwindigkeit bei kleinen Intervallen falsch läuft. Wenn Du >also mittels GetSysTime vor und nach dem Programm die Zeit nimmst, >stellst Du fest, dass die Differenz dem eigentlich gewünschten Wert >entspricht. Nur die Realzeit weicht davon ab. Also das Komplette timer.device weicht ab, auch die Systemzeit??? > Zitat: > Muss man das Timing vielleicht direkt über die CIA-Timer laufen lassen? >Da sehe ich momentan keine Alternative. Die vom timer.device >angebotenen Optionen sind offenbar unbrauchbar. Keine alternative zum timer.device? Ich meine irgendwie Funktioniert ja auch diverse Sample-Software. >Eine Möglichkeit zu timen wäre die eclock zu pollen. (ReadEClock) >Ansonsten sollte mit WAITECLOCK mit vorherberechnetem Zeitraster funktionieren. (so funktioniert der MID timer in HD-Rec). Muss ich mal gucken ob ich dazu etwas finde. >Der CIA chip wird bei CPU Belastung bis zu 25% schneller. Taugt also auch nichts? [ - Answer - Quote - Direct link - ] |
2006-09-08, 18:19 h bubblebobble Posts: 707 User |
In meinen Inlcudes findest du Beispiel Code für die direkte Benutzung des CIA chips sowie das gleiche nochmal mit dem timer.device, der jeweils genau das macht was du bräuchtest. Ist aber eben AB2. -- Thilo Köhler, Author von: HD-Rec, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, TKUnpacker Homepage: http://www.hd-rec.de [ - Answer - Quote - Direct link - ] |
2006-09-08, 18:37 h whose Posts: 2156 User |
125 µHz liefern die CIA-Timer relativ problemlos und selbst bei hoher Last ohne große Drift. Viele AHI-Treiber z.B. benutzen diese Timer. Ich vermute, daß irgendwo zu viel Zeit verplempert wird, bevor der Timer neu gestartet wird. Das muß sehr flott gehen, alles andere kann und muss warten. Ich weiß auch nicht, ob es so sonderlich genial ist, ein WaitIO() vor den Neustart des Timers zu setzen (C-Variante). Das würde ich mal weglassen. Im BASIC-Programm dürften die Textausgaben störend wirken, nun weiß ich nicht, wie viele davon schon zu Testzwecken weggelassen wurden, um das Ganze schneller zu kriegen. Da dürfte auf jeden Fall noch was zu holen sein. Grüße -- --- µA1 PPC 750GX-800 A4000 PPC 604e-233 [ Dieser Beitrag wurde von whose am 08.09.2006 um 18:48 Uhr geändert. ] [ - Answer - Quote - Direct link - ] |
2006-09-08, 18:55 h bubblebobble Posts: 707 User |
Textausgaben darf der samplende Task natürlich nicht machen, dasist viel zu langsam. Er sollte besser überhaupt nichts machen ausser samplen, und sollte auch möglichst mit einer TaskPri >20 laufen. -- Thilo Köhler, Author von: HD-Rec, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, TKUnpacker Homepage: http://www.hd-rec.de [ - Answer - Quote - Direct link - ] |
2006-09-08, 22:19 h Holger Posts: 8116 User |
Zitat:Man MUSS den gesendeten Request wieder abholen, bevor man ihn erneut versendet. Und jedesmal einen neuen Request anlegen, wäre genauso unsinnig, dann läuft der Speicher voll. Also auf die Antwort MUSS man warten, ob nun via WaitIO oder WaitPort/GetMsg ist gehupft wie gesprungen. Und da ich in meinem C-Programm mittels WAIT_UNTIL auf die vorberechnete Zeit gewartet habe, kann es gar nicht am Verplempern der Zeit liegen, weil der Request ja sofort zurückkommen müsste, wenn der angegebene Zeitpunkt schon überschritten ist. Es seit denn, der timer selber ist langsamer geworden. An dem Rest des Programms kanns ja nicht liegen, der rennt, wenn man den timer weglässt, in einem zehntel der Zeit durch... mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Answer - Quote - Direct link - ] |
2006-09-08, 23:42 h MaikG Posts: 5172 User |
>In meinen Inlcudes findest du Beispiel Code für die direkte >Benutzung des CIA chips sowie das gleiche nochmal mit dem >timer.device, der jeweils genau das macht was du bräuchtest. Das was ich schonmal runtergeladen habe? >Ich vermute, daß irgendwo zu viel Zeit verplempert wird, >bevor der Timer neu gestartet wird. Das muß sehr flott gehen, >alles andere kann und muss warten. Nee, ich kann zwischen SendIO und WaitIO alles rausnehmen, trotzdem ist das saulahm und liefert keine korrekten werte. 125 wird nicht ganz erreicht, gebe ich z.B. 25 ein wird die gleiche Zeit benötigt. >Im BASIC-Programm dürften die Textausgaben störend wirken, nun weiß >ich nicht, wie viele davon schon zu Testzwecken weggelassen wurden, >um das Ganze schneller zu kriegen. Da dürfte auf jeden Fall noch >was zu holen sein. Ich habe die Textausgaben zu 100% weggelassen, das macht gar keinen unterschied. >Und da ich in meinem C-Programm mittels WAIT_UNTIL auf die >vorberechnete Zeit gewartet habe, kann es gar nicht am Verplempern >der Zeit liegen, weil der Request ja sofort zurückkommen müsste, >wenn der angegebene Zeitpunkt schon überschritten ist. Es seit denn, >der timer selber ist langsamer geworden. WaitUntil ist wie MircoHZ, kein unterschied, allerdings verstehe ich das mit der vorberechneten Zeit nicht. [ - Answer - Quote - Direct link - ] |
2006-09-09, 00:48 h whose Posts: 2156 User |
Zitat: Mal abgesehen davon, daß in dem C-Beispiel ZWEIMAL "gewartet" wird. Einmal mittels WaitPort() auf den TimerMP, dann nochmal mittels WaitIO(). WaitPort()/GetMsg() tut seinen Dienst hervorragend und man kann den Request direkt wiederverwenden. Zitat: Jetzt würde mich mal interessieren, wie Du das "die Timer werden langsamer" gemessen hast. In vielen Fällen (hohe Systemlast) kann es sogar passieren, daß die Timer schneller werden... Zitat: Ja und? Was heißt das? Ich weiß nur, daß die Timer recht genau laufen, auch bei sehr kleinen Zeitabschnitten. Die Drift wird erst dann sehr hoch, wenn ein anderer Task fast 100% der Systemzeit bekommt/frißt. Die Drift kann dabei in beide Richtungen laufen. Wenns denn unbedingt sein muß, nutz doch mal die Zähler der CIA direkt. Irgendwo in den RKMs geistert ein Beispiel dafür rum, wie man das macht. Dann siehst Du ja, ob die Timer tatsächlich "langsamer" werden. Ich glaube da nicht so wirklich dran. Grüße -- --- µA1 PPC 750GX-800 A4000 PPC 604e-233 [ - Answer - Quote - Direct link - ] |
2006-09-09, 00:54 h whose Posts: 2156 User |
Zitat: Das ist schon recht merkwürdig. Den Goertzel hast Du auch rausgenommen und die Werte in ein Array schreiben lassen? Wenn ja, und die Timer sind auch raus, verbockt MB da irgendwas. Zitat: Allein das ist schon merkwürdig. Die Textausgaben kosten eine Menge Zeit, da sollte sich ein Weglassen schon bemerkbar machen. Zitat: Einen Request mit TR_GETSYSTIME schicken, das Ergebnis + 125 micros in den IOrequest eintragen, weg damit zum timer.device, warten. Grüße -- --- µA1 PPC 750GX-800 A4000 PPC 604e-233 [ - Answer - Quote - Direct link - ] |
1 2 3 4 -5- 6 7 8 9 10 Last | [ - Post reply - ] |
amiga-news.de Forum > Programmierung > Tonerkennung | [ - Search - New posts - Register - Login - ] |
Masthead |
Privacy policy |
Netiquette |
Advertising |
Contact
Copyright © 1998-2024 by amiga-news.de - all rights reserved. |