Frage

Gibt es eine Möglichkeit, um Feuer Ereignisse in C # mit einer Auflösung von wenigen Mikrosekunden?

Ich baue einen MIDI-Sequenzer, und es erfordert ein Ereignis jeden MIDI-tick abgefeuert werden, die dann jede Note zu diesem Zeitpunkt registriert werden spielen.

Bei 120 Schlägen pro Minute und bei einer Auflösung von 120 ppqn (Pulse pro Takt / Viertelnote), sollte das Ereignis alle 4,16666 Millisekunden ausgelöst. Moderne Sequenzern haben höhere Auflösungen wie 768ppqn, die dieses Ereignis erfordern würde, um alle 651 Mikrosekunden abgefeuert werden.

Die beste Auflösung für kurzzeitige Ereignisse, die ich gefunden habe, ist von 1 Millisekunde. Wie kann ich darüber hinaus gehen?

Dieses Problem muss bereits von einer C # MIDI-Sequenzer oder MIDI-File-Player gelöst wurden. Vielleicht bin ich einfach nicht auf das Problem durch den rechten Winkel an.

Vielen Dank für Ihre Hilfe.

War es hilfreich?

Lösung

Die meisten MIDI-Sequenzer / Midi-Spieler werden entweder große Blöcke von Zeit zu Wellenform umwandeln (für die Wiedergabe durch Computer-Lautsprecher) oder einen großen Block von MIDI-Befehle nehmen (für ein externes Gerät an einen MIDI-Port angeschlossen ist). So oder so, ein Block von Daten an die Soundkarte kopiert, und die Soundkarte sorgt für exakte Timing.

Sie können an der Multimedia-Steuerung APIs suchen.

Siehe dieser Beitrag über bei der Microsoft Diskussionsforum

Andere Tipps

Ich denke, dass Sie wahrscheinlich nicht von einem Zeitgeber genau die richtige Auflösung zu erhalten. Ein besserer Ansatz wäre es, das 1ms genaue Timer zu verwenden, und wenn es feuert, zu prüfen, welche MIDI-Event anstehen und sie zu feuern.

So gehen die MIDI-Event in einer sortierten Warteschlange, können Sie die ersten flüchtigen Blick, und stellen Sie den Timer auf Feuer so nah wie möglich zu dieser Zeit. Wenn der Zeitgeber ausgelöst, verbrauchen alle Ereignisse aus der Warteschlange, die vergangen sind, bis Sie ein Ereignis in der Zukunft zu begegnen. Berechnen Zeit für diese Veranstaltung. Reschedule Timer.

Natürlich, wenn Sie auf Ihre Soundkarte ausgeben, der Ansatz unterscheidet sich grundlegend, und Sie sollten das Zählen Proben für alle Ihre Timings sein.

Es ist nicht möglich, Ereignisse zu haben, genau beschossen Mikrosekunden-Intervalle in .NET.

In der Tat, da Windows selbst keine Echtzeit-Betriebssystem ist, alles mit 100% Genauigkeit zu bestimmten Mikrosekunden durchgeführt wird, in Benutzermodus-Software, ist so ziemlich unmöglich.

Für weitere Informationen darüber, warum dies so schwierig ist, den MSDN Magazin-Artikel: implementieren Sie eine kontinuierliche Aktualisierung, Hochauflösender Zeitanbieter für Windows . Während es über Windows NT spricht, das nach wie vor gilt generell für spätere Versionen von Windows.

Der Abschluss dieses Artikels bringt es auf gut:

  

Wenn Sie jetzt denken, dass Sie erhalten   die Systemzeit mit einem fast   beliebige Genauigkeit hier, nur ein   leichte Warnung: vergessen Sie nicht, die   preemptiveness eines Multitasking   System wie Windows NT. Am besten   Fall der Zeitstempel erhalten Sie ist weg   nur durch die Zeit es braucht, die lesen   Leistungsindikator und verwandeln diese   Lesen in eine absolute Zeit. In dem   schlimmsten Fall die verstrichene Zeit konnte   leicht in der Größenordnung von einigen zehn   Millisekunden.

     

Obwohl dies   zeigen Sie durch all dies ging   für nichts, Ruhe, dass Sie sicher sein,   tat es nicht. Auch die Ausführung der Aufruf an die   Win32 API GetSystemTimeAsFileTime (oder   gettimeofday unter Unix) unterliegt   die gleichen Bedingungen, so dass Sie   tatsächlich tun, nicht schlechter als das. Im   eine Mehrheit der Fälle, müssen Sie   gute Ergebnisse. Nur nicht durchführen   alles in Echtzeit erfordern,   Vorhersagbarkeit auf der Grundlage der Zeit   Briefmarken in Windows NT.

anstelle von Timer

Stoppuhr

Beispiel 10x für 1 Sekunde

    static void Main(string[] args)
    {
        Stopwatch masterSW;
        Stopwatch sw=null;
        int count;

        sw = Stopwatch.StartNew();
        sw.Reset();

        for (int i = 0; i < 10; i++)
        {
            count = 0;
            masterSW = Stopwatch.StartNew();
            while (count!=1536) //1537*651 microsecond is about a second (1.0005870 second)
            {
                if (!sw.IsRunning)
                    sw.Start();

                if (sw.Elapsed.Ticks >= 6510)
                {
                    count++;
                    sw.Reset();
                }
            }

            Debug.WriteLine("Ticks: " + masterSW.Elapsed.Ticks.ToString());
        }
    }

AUSGABE:

  

Ticks: 10005392 (die 1,0005392 Sekunden ist)
  Ticks: 10004792
  Ticks: 10004376
  Ticks: 10005408
  Ticks: 10004398
  Ticks: 10004426
  Ticks: 10004268
  Ticks: 10004427
  Ticks: 10005161
  Ticks: 10004306

, welche Art von ok

scheinen
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top