Decidi tentar novamente esse problema hoje e finalmente consegui carregar um arquivo OGG em tempo de execução em um SoundEffect
objeto. Aqui está o que eu fiz! Primeiro baixe a biblioteca abaixo, que contém uma classe capaz de decodificar arquivos OGG:
Pré-requisito - Download da biblioteca
A biblioteca já tem um exemplo, mas usa DynamicSoundEffectInstance
e transmite o áudio. Mas eu queria carregar tudo de uma vez em um SoundEffect
objeto comum, para que o processo fosse um pouco diferente.
Etapa 1 - decodificar arquivo
Primeiro crie uma instância OggDecoder
e inicialize-a com seu arquivo:
decoder = new OggDecoder();
decoder.Initialize(TitleContainer.OpenStream(@"sound.ogg"));
Etapa 2 - Obter dados decodificados
Leia todos os dados em um buffer. Estes são os dados PCM brutos decodificados do arquivo:
byte[] data = decoder.SelectMany(chunk => chunk.Bytes.Take(chunk.Length)).ToArray();
Etapa 3 - Crie o SoundEffect a partir do fluxo que contém o cabeçalho completo do arquivo wave
No entanto, o fluxo que SoundEffect
requer deve conter não apenas os dados brutos, mas também o cabeçalho completo do arquivo wave. Você pode usar este método auxiliar para escrever o cabeçalho mais os dados:
private static void WriteWave(BinaryWriter writer, int channels, int rate, byte[] data)
{
writer.Write(new char[4] { 'R', 'I', 'F', 'F' });
writer.Write((int)(36 + data.Length));
writer.Write(new char[4] { 'W', 'A', 'V', 'E' });
writer.Write(new char[4] { 'f', 'm', 't', ' ' });
writer.Write((int)16);
writer.Write((short)1);
writer.Write((short)channels);
writer.Write((int)rate);
writer.Write((int)(rate * ((16 * channels) / 8)));
writer.Write((short)((16 * channels) / 8));
writer.Write((short)16);
writer.Write(new char[4] { 'd', 'a', 't', 'a' });
writer.Write((int)data.Length);
writer.Write(data);
}
Use esse método para gravar os dados em um fluxo que pode ser alimentado para SoundEffect.FromStream
:
using (MemoryStream stream = new MemoryStream())
using(BinaryWriter writer = new BinaryWriter(stream))
{
WriteWave(writer, decoder.Stereo ? 2 : 1, decoder.SampleRate, data);
stream.Position = 0;
soundEffect = SoundEffect.FromStream(stream);
}
Etapa 4 - Use o SoundEffect normalmente
Seu arquivo OGG agora está carregado e pode ser usado como qualquer outro SoundEffect
carregado pelo pipeline de conteúdo:
soundEffect.Play();