Como loop seção de uma música corretamente?

8

Estou programando um pouco do Music Engine para o meu jogo em C # e XNA, e um aspecto disso é a possibilidade de repetir uma seção de uma música. Por exemplo, minha música tem um intropart e, quando chegou ao fim (ou qualquer outro ponto específico), ela volta para onde o intropart acabou. (A - B - B - B ...)

Agora estou usando o IrrKlank, que está funcionando perfeitamente, sem falhas, mas tenho um problema:

O ponto para onde voltar é um pouco impreciso. Aqui está um exemplo de código:

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

Agora, o problema é que a música passa os 10 segundos, mas toca alguns milissegundos até cerca de 10,1f e depois pula para 5 segundos. Não é tão dramático, mas muito incorreto para minhas necessidades. Eu tentei consertar assim:

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

(dt é o tempo delta, o tempo decorrido desde o último quadro)

Mas não acho que seja uma boa solução para isso.

Espero que você possa entender meu problema (e meu inglês, yay / o /) e me ajudar :)

Teflo
fonte
Você pode escolher entre transmitir o som ou carregar tudo de uma vez?
tesselode
Eu acho que é possível. No momento, estou carregando a música completa, porque pensei que pular a música seria mais rápido. Estou tentando Multithreading para resolver este problema, mas ainda tenho azar: /
Teflo 22/12
Tente transmitir o som. Afinal, ele deve ser capaz de carregar um pequeno pedaço da música quase instantaneamente.
Tesselode 22/09/12
Como sua música é codificada?
michael.bartnett
Talvez, em vez de usar "passado", você possa adicionar perguntas (como eventos) que executam uma função de retorno de chamada. Não sei como você administra seu tempo. Mas você não poderia usar a quantidade de bytes lidos até agora e compará-la com a quantidade total de bytes e convertê-la em um tempo preciso? Você deve poder calcular a quantidade de dados lidos em um segundo. Eu não sei o quão rápido isso iria embora. Mas talvez você possa ler o tempo mais preciso.
Sidar

Respostas:

3

Na minha opinião, uma solução mais simples e mais usual é ter duas faixas diferentes: uma introdução e uma seção de loop. Então, o único problema é detectar quando a introdução termina (bastante fácil, embora não seja perfeitamente preciso se estiver usando 30fps). Em seguida, a segunda faixa pode ser reproduzida com o loop ativado.

Assim, você reduz os erros na reprodução a um pequeno atraso ao iniciar o loop pela primeira vez, em vez de sempre que a seção do loop precisar ser rebobinada.

Elideb
fonte
0

A solução ideal seria saber de antemão quais partes da música precisam ser carregadas ao lado do buffer. Cada 'seção' A - B - C teria um horário de início e de término, e seria o seu sistema de streaming de nível inferior que carregaria as partes corretas do arquivo na ordem correta. Você precisaria ter uma taxa de bits fixa para que isso funcionasse, e pode ser bem difícil encontrar onde, no arquivo, você precisa pular para a próxima.

Eu dei uma olhada rápida no site irrKlang e eles se gabam da possibilidade de escrever seus próprios leitores / decodificadores de formato de arquivo para estender o mecanismo com ele, então você pode tentar.

Também há um tutorial aqui para substituir o acesso ao arquivo - você pode dar uma chance à minha ideia original ou misturá-la com vários sons, como Elideb disse. Você pode estender sua classe CMyReadFile para ter acesso a vários arquivos (como PartA.wav, PartB.wav, PartC.wav) e substituir o método de leitura, e não apenas:

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

Você poderia fazer algo como:

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

O que significa que a música mudaria perfeitamente de seção sem ter que sincronizar as execuções e paradas.

Jonathan Connell
fonte