2012-09-22 21 views
5

Estoy portar alguna C# para Windows Phone 7 a Windows 8.Reproducción de un sonido de una memoria intermedia generada en una aplicación de Windows 8

Las aplicaciones del teléfono que utiliza una XNA SoundEffect para reproducir sonidos arbitrarios desde un buffer. En los casos más simples, crearía una onda sinusoidal de la duración y frecuencia requeridas. Tanto la duración como la frecuencia pueden variar mucho, así que prefiero no confiar en MediaElements (a menos que haya algún modo de cambiar la frecuencia de un archivo base, pero eso solo me ayudará con la generación de frecuencia única).

¿Cuál es el equivalente de XNA SoundEffectInstance en WinRT?

Supongo que tendré que usar DirectX para esto, pero no estoy seguro de cómo hacerlo desde una aplicación C#/XAML. He echado un vistazo al SharpDX, pero no parecía tener las clases DirectSound, SecondaryBuffer, SecondaryBuffer que supongo que necesitaría usar.

He hecho una serie de suposiciones arriba. Puede ser que esté buscando las clases incorrectas o hay una forma completamente separada de generar un sonido arbitrario desde una aplicación de Windows 8.


Encontré an example using XAudio2 from SharpDX to play a wav file via an AudioBuffer. Esto parece prometedor, solo necesitaría sustituir mi buffer de audio generado por el flujo de archivos nativo.

PM> Install-Package SharpDX

PM> Install-Package SharpDX.XAudio2

public void PlaySound() 
    { 
     XAudio2 xaudio; 
     MasteringVoice masteringVoice; 

     xaudio = new XAudio2(); 
     masteringVoice = new MasteringVoice(xaudio); 

     var nativefilestream = new NativeFileStream(
      @"Assets\SpeechOn.wav", 
      NativeFileMode.Open, 
      NativeFileAccess.Read, 
      NativeFileShare.Read); 

     var soundstream = new SoundStream(nativefilestream); 


     var waveFormat = soundstream.Format; 
     var buffer = new AudioBuffer 
     { 
      Stream = soundstream.ToDataStream(), 
      AudioBytes = (int)soundstream.Length, 
      Flags = BufferFlags.EndOfStream 
     }; 

     var sourceVoice = new SourceVoice(xaudio, waveFormat, true); 

     // There is also support for shifting the frequency. 
     sourceVoice.SetFrequencyRatio(0.5f); 

     sourceVoice.SubmitSourceBuffer(buffer, soundstream.DecodedPacketsInfo); 

     sourceVoice.Start(); 
    } 
+0

Estoy buscando una solución en la que debería ser capaz de reproducir audio directamente desde paquetes de audio en búfer en Windows Phone 8? ¿Puedes redirigir a un ejemplo de trabajo? – sunder

Respuesta

8

La única manera de generar un sonido dinámico en Win8RT es utilizar XAudio2, por lo que debe poder hacer esto con SharpDX.XAudio2.

En lugar de utilizar NativeFileStream, simplemente crea una instancia de un DataStream directamente dando tu búfer administrado (o puedes usar un búfer no administrado o deja que instale DataStream uno para ti). El código sería así: método

// Initialization phase, keep this buffer during the life of your application 
// Allocate 10s at 44.1Khz of stereo 16bit signals 
var myBufferOfSamples = new short[44100 * 10 * 2]; 

// Create a DataStream with pinned managed buffer 
var dataStream = DataStream.Create(myBufferOfSamples, true, true); 

var buffer = new AudioBuffer 
     { 
      Stream = dataStream, 
      AudioBytes = (int)dataStream.Length, 
      Flags = BufferFlags.EndOfStream 
     }; 

//... 
// Fill myBufferOfSamples 
//... 

// PCM 44.1Khz stereo 16 bit format 
var waveFormat = new WaveFormat(); 

XAudio2 xaudio = new XAudio2(); 
MasteringVoice masteringVoice = new MasteringVoice(xaudio); 
var sourceVoice = new SourceVoice(xaudio, waveFormat, true); 

// Submit the buffer 
sourceVoice.SubmitSourceBuffer(buffer, null); 

// Start playing 
sourceVoice.Start(); 

de muestra para llenar la memoria intermedia con una onda sinusoidal:

private void FillBuffer(short[] buffer, int sampleRate, double frequency) 
    { 
     double totalTime = 0; 

     for (int i = 0; i < buffer.Length - 1; i += 2) 
     { 
      double time = (double)totalTime/(double)sampleRate; 
      short currentSample = (short)(Math.Sin(2 * Math.PI * frequency * time) * (double)short.MaxValue); 

      buffer[i] = currentSample; //(short)(currentSample & 0xFF); 
      buffer[i + 1] = currentSample; //(short)(currentSample >> 8); 

      totalTime += 2; 
     } 

    } 
+0

Genial, gracias. Expandí tu ejemplo con la creación de la instancia de XAudio2. Ahora estoy generando un sonido del buffer. Parece un poco distorsionado en este momento. Tendré que volver a verificar mi método FillBuffer, que también agregué a su respuesta para que otros la usen. –

+0

Mi método FillBuffer solía llenar un byte [] cuando estaba trabajando en XNA. Al eliminar los operadores bitwise y shift right >>, se corrigió este problema.Ahora obtengo un tono claro generado. –

+0

Esto tiene un error: 'totalTime + = 2' significa que está generando algo dos veces la frecuencia. Debería ser 'totalTime ++'. (¡Probé yo mismo!) –

3

También puede utilizar WASAPI para jugar buffers de sonido generadas dinámicamente en WinRT. (xaudio2 no es la única solución).

que escribió el código de ejemplo para él en VB aquí (C# será esencialmente la misma): http://www.codeproject.com/Articles/460145/Recording-and-playing-PCM-audio-on-Windows-8-VB

Creo que el chico NAudio está planeando para traducir + incorporar mi código de ejemplo en NAudio, para un Win8 compatible con la versión, por lo que será más fácil de usar.

Cuestiones relacionadas