Come eseguire correttamente il loop della sezione di una canzone?


8

Sto programmando un piccolo Music Engine per il mio gioco in C # e XNA, e un aspetto da esso è la possibilità di riprodurre in loop una sezione di una canzone. Ad esempio, la mia canzone ha un'intropart e quando la canzone ha raggiunto la fine (o qualsiasi altro punto specifico), torna indietro dove l'intropart è appena finito. (A - B - B - B ...)

Ora sto usando IrrKlank, che funziona perfettamente, senza lacune, ma ho un problema:

Il punto in cui tornare indietro è un po 'impreciso. Ecco qualche esempio di codice:

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

Ora il problema è che la canzone passa i 10 secondi, ma suona alcuni millisecondi fino a 10,1 o giù di lì, quindi passa a 5 secondi. Non è così drammatico, ma molto errato per le mie esigenze. Ho provato a risolverlo in questo modo:

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

(dt è il tempo delta, il tempo trascorso dall'ultimo fotogramma)

Ma non credo, questa è una buona soluzione per questo.

Spero che tu possa capire il mio problema (e il mio inglese, yay / o /) e aiutarmi :)


Puoi scegliere tra trasmettere l'audio o caricarlo tutto in una volta?
tesselode,

Penso che sia possibile. Al momento sto caricando la canzone completa, perché pensavo che saltare nella canzone sarebbe più veloce. Sto provando il multithreading per risolvere questo problema, ma sono ancora sfortunato: /
Teflo

Prova invece a trasmettere l'audio. Dopotutto, dovrebbe essere in grado di caricare un piccolo pezzo della canzone quasi all'istante.
tesselode,

Come viene codificata la tua canzone?
michael.bartnett,

Forse invece di usare "passato" potresti aggiungere ques (come eventi) che svolgono una funzione di callback. Non so come gestisci il tuo tempo. Ma non potresti usare la quantità di byte letti finora e confrontarla con la quantità totale di byte per tradurla in un tempo preciso? Dovresti essere in grado di calcolare quanti dati vengono letti in un secondo. Non so quanto veloce andrebbe comunque. Ma forse allora potresti leggere l'ora più precisa.
Sidar,

Risposte:


3

Secondo me, una soluzione più semplice e più consueta sta avendo due tracce diverse: un'introduzione e una sezione loop. Quindi, l'unico problema è rilevare quando termina l'intro (abbastanza semplice, anche se non perfettamente preciso se si usa 30fps). Quindi la seconda traccia può essere riprodotta con il looping abilitato.

Pertanto, si riducono gli errori nella riproduzione a un leggero ritardo quando si avvia il loop per la prima volta, anziché ogni volta che è necessario riavvolgere la sezione del loop.


0

La soluzione ideale sarebbe sapere in anticipo quali parti del brano devono essere caricate successivamente nel buffer. Ogni 'sezione' A - B - C avrebbe un orario di inizio e fine, e sarebbe il tuo sistema di streaming di livello inferiore a caricare le parti corrette del file nell'ordine corretto. Dovresti avere un bitrate fisso perché questo funzioni, e potrebbe essere abbastanza difficile trovare dove nel file devi saltare al prossimo.

Ho dato una rapida occhiata al sito irrKlang e si vantano della possibilità di scrivere i propri lettori / decodificatori in formato file per estendere il motore con esso, quindi potresti provare.

C'è anche un tutorial qui per sovrascrivere l'accesso ai file: potresti dare una idea alla mia idea originale o mescolarlo con più suoni come Elideb ha detto. È possibile estendere la classe CMyReadFile per avere accesso a più file (come PartA.wav, PartB.wav, PartC.wav) e si può ignorare il metodo di lettura, quindi piuttosto che semplicemente:

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

Potresti fare qualcosa del tipo:

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

Ciò significa che la canzone cambierebbe perfettamente sezione senza dover sincronizzare Plays & Stops.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.