¿Cómo hacer un bucle en la sección de una canción correctamente?

8

Estoy programando un pequeño Music Engine para mi juego en C # y XNA, y uno de sus aspectos es la posibilidad de repetir una sección de una canción. Por ejemplo, mi canción tiene una intropart, y cuando la canción llegó al final (o cualquier otro punto específico), salta hacia atrás donde acaba la intropart. (A - B - B - B ...)

Ahora estoy usando IrrKlank, que funciona perfectamente, sin espacios, pero tengo un problema:

El punto donde retroceder es un poco impreciso. Aquí hay un código de ejemplo:

public bool Passed(float time)
    {
        if ( PlayPosition >= time )
            return true;
        return false;
    }
//somewhere else
if( song.Passed( 10.0f ) )
   song.JumpTo( 5.0f );

Ahora el problema es que la canción pasa los 10 segundos, pero reproduce algunos milisegundos hasta 10.1f más o menos, y luego salta a 5 segundos. No es tan dramático, pero muy incorrecto para mis necesidades. Traté de arreglarlo así:

public bool Passed( float time )
{
      if( PlayPosition + 3 * dt >= time && PlayPosition <= time )
             return true;
      return false;
}

(dt es el tiempo delta, el tiempo transcurrido desde el último fotograma)

Pero no creo, esa es una buena solución para eso.

Espero que puedas entender mi problema (y mi inglés, yay / o /) y ayudarme :)

Teflo
fuente
¿Puedes elegir entre transmitir el sonido o cargarlo todo de una vez?
tesselode
Creo que es posible En este momento estoy cargando la canción completa, porque pensé, saltar en la canción sería más rápido. Estoy tratando de Multithreading para resolver este problema, pero todavía tengo mala suerte: /
Teflo
Intenta transmitir el sonido en su lugar. Después de todo, debería poder cargar una pequeña parte de la canción casi al instante.
tesselode
¿Cómo está codificada tu canción?
michael.bartnett
Quizás en lugar de usar "aprobado" podría agregar preguntas (como eventos) que realizan una función de devolución de llamada. No sé cómo manejas tu tiempo. Pero, ¿no podría usar la cantidad de bytes leídos hasta ahora y compararlo con la cantidad total de bytes y traducirlo a un tiempo preciso? Debería poder calcular cuántos datos se leen en un segundo. Sin embargo, no sé qué tan rápido iría esto. Pero tal vez entonces podrías leer el tiempo con mayor precisión.
Sidar

Respuestas:

3

En mi opinión, una solución más simple y más habitual es tener dos pistas diferentes: una introducción y una sección de bucle. Entonces, el único problema es detectar cuándo termina la introducción (bastante fácil, aunque no es perfectamente preciso si se usan 30 fps). Luego, la segunda pista se puede reproducir con el bucle habilitado.

Por lo tanto, reduce los errores en la reproducción a un ligero retraso al iniciar el bucle por primera vez, en lugar de cada vez que se debe rebobinar la sección del bucle.

Elideb
fuente
0

La solución ideal sería saber de antemano qué partes de la canción deben cargarse luego en el búfer. Cada 'sección' A - B - C tendría una hora de inicio y finalización, y sería su sistema de transmisión de nivel inferior el que cargaría las partes correctas del archivo en el orden correcto. Sin embargo, tendría que tener una tasa de bits fija para que esto funcione, y podría ser bastante difícil encontrar en qué parte del archivo debe pasar al siguiente.

Eché un vistazo rápido al sitio de irrKlang y se jactan de la posibilidad de escribir sus propios lectores / decodificadores de formato de archivo para extender el motor con él, por lo que es posible que desee probarlo.

También hay un tutorial aquí para anular el acceso al archivo: podría darle una oportunidad a mi idea original, o podría mezclarlo con múltiples sonidos como dijo Elideb. Puede extender su clase CMyReadFile para tener acceso a múltiples archivos (como PartA.wav, PartB.wav, PartC.wav), y puede anular el método de lectura, en lugar de solo:

return (s32)fread(buffer, 1, sizeToRead, File);

Podrías hacer algo como:

switch(CurrentSectionToPlay)
{
case A:
    return (s32)fread(buffer, 1, sizeToRead, FileA);
case B:
    return (s32)fread(buffer, 1, sizeToRead, FileB);
}

Lo que significa que la canción cambiaría de sección a la perfección sin tener que sincronizar Plays & Stops.

Jonathan Connell
fuente