c# - submultiplos - Disparando eventos a una resolución de microsegundo para el secuenciador midi
multiplos y submultiplos de tiempo wikipedia (4)
Creo que es poco probable que obtengas exactamente la resolución correcta de un temporizador. Un mejor enfoque sería utilizar el temporizador preciso de 1 ms y, cuando se dispara, verificar qué eventos MIDI están pendientes y dispararlos.
Por lo tanto, los eventos MIDI van en una cola ordenada, echas un vistazo al primero y configura el temporizador para disparar lo más cerca posible de ese momento. Cuando el temporizador se dispara, consuma todos los eventos de la cola que han transcurrido, hasta que encuentre un evento futuro. Calcula el tiempo para este evento. Reprogramar el temporizador
Por supuesto, si está enviando a su tarjeta de sonido, el enfoque es fundamentalmente diferente, y debe contar muestras para todos sus tiempos.
¿Hay alguna manera de disparar eventos en C # con una resolución de unos pocos microsegundos?
Estoy construyendo un secuenciador MIDI, y requiere que se active un evento cada tic MIDI, que luego reproducirá cualquier nota registrada en ese momento.
A 120 latidos por minuto y a una resolución de 120 ppqn (pulsos por latido / negra), ese evento debería disparar cada 4.16666 milisegundos. Los secuenciadores modernos tienen resoluciones más altas, como 768ppqn, lo que requeriría que ese evento se disparara cada 651 microsegundos.
La mejor resolución para eventos a corto plazo que he encontrado es de 1 milisegundo. ¿Cómo puedo ir más allá de eso?
Este problema ya debe haber sido resuelto por cualquier secuenciador C # MIDI o reproductor de archivos MIDI. Quizás no estoy viendo el problema desde el ángulo correcto.
Gracias por tu ayuda.
La mayoría de los secuenciadores midi / midi reproductores convertirán grandes bloques de tiempo a formas de onda (para tocar a través de altavoces de computadoras) o tomarán un gran bloque de instrucciones MIDI (para un dispositivo externo conectado a un puerto MIDI). De cualquier forma, se copia un bloque de datos a la tarjeta de sonido y la tarjeta de sonido se ocupa de la sincronización exacta.
Es posible que desee ver las API de control multimedia.
en lugar de usar el temporizador
usar cronómetro
ejemplo, por 10x 1 segundo
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());
}
}
dará salida:
Ticks: 10005392 (que es 1.0005392 segundos)
Ticks: 10004792
Ticks: 10004376
Ticks: 10005408
Ticks: 10004398
Ticks: 10004426
Ticks: 10004268
Ticks: 10004427
Ticks: 10005161
Ticks: 10004306
que parecen estar bien
No es posible tener eventos disparados con precisión en intervalos de microsegundos en .NET.
De hecho, debido a que Windows en sí no es un sistema operativo en tiempo real, realizar cualquier cosa con 100% de precisión en ciertos microsegundos, en el software de modo de usuario, es prácticamente imposible.
Para obtener más información sobre por qué esto es tan difícil, consulte el artículo de la revista MSDN: Implemente un proveedor de tiempo de alta resolución y actualización continua para Windows . Mientras habla sobre Windows NT, esto todavía se aplica generalmente a las versiones posteriores de Windows.
La conclusión de este artículo lo resume bien:
Si ahora cree que puede obtener la hora del sistema con una precisión casi arbitraria aquí, solo una ligera advertencia: no olvide la prioridad de un sistema multitarea como Windows NT. En el mejor de los casos, la marca de tiempo que obtendrá está desactivada solo por el tiempo que toma leer el contador de rendimiento y transformar esta lectura en un tiempo absoluto. En el peor de los casos, el tiempo transcurrido podría ser fácilmente del orden de decenas de milisegundos.
Aunque esto podría indicar que atravesó todo esto por nada, puede estar seguro de que no lo hizo. Incluso al ejecutar la llamada a la API Win32 GetSystemTimeAsFileTime (o gettimeofday bajo Unix) está sujeto a las mismas condiciones, por lo que en realidad no lo está haciendo peor. En la mayoría de los casos, obtendrá buenos resultados. Simplemente no realice nada que requiera previsibilidad en tiempo real sobre la base de marcas de tiempo en Windows NT.