2012-09-22 14 views
5

sto porting qualche C# Windows Phone 7 le applicazioni verso Windows 8.Riproduzione di un suono da un buffer generato in un Windows 8 app

Le applicazioni del telefono utilizzato un XNA SoundEffect per riprodurre i suoni arbitrari da un buffer. Nei casi più semplici creerei solo un'onda sinusoidale della durata e della frequenza richieste. Sia la durata che la frequenza possono variare notevolmente, quindi preferirei non fare affidamento su MediaElements (a meno che non ci sia un qualche modo per spostare la frequenza di un file di base, ma questo mi aiuterà solo con la generazione a singola frequenza).

Qual è l'equivalente di XNA SoundEffectInstance in WinRT?

Suppongo che dovrò usare DirectX per questo, ma non sono sicuro di come farlo da un'altra app C#/XAML. Ho dato un'occhiata a SharpDX, ma non sembrava avere le classi DirectSound, SecondaryBuffer, SecondaryBuffer che presumo avrei bisogno di usare.

Ho fatto una serie di ipotesi sopra. Potrebbe essere che sto cercando le classi sbagliate o c'è un modo completamente separato per generare un suono arbitrario da un'app di Windows 8.


Ho trovato an example using XAudio2 from SharpDX to play a wav file via an AudioBuffer. Questo sembra promettente, dovrei solo sostituire il mio buffer audio generato per il flusso di file nativo.

PM> Installa-Package SharpDX

PM> Installa-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

Sto cercando una soluzione in cui dovrei essere in grado di riprodurre l'audio direttamente da pacchetti audio bufferizzati in Windows Phone 8? Puoi reindirizzare a un esempio funzionante. – sunder

risposta

8

L'unico modo per generare un suono dinamico in Win8RT è quello di utilizzare XAudio2, così si dovrebbe essere in grado di farlo con SharpDX.XAudio2.

Invece di utilizzare NativeFileStream, è sufficiente creare un'istanza di DataStream che fornisce direttamente il buffer gestito (oppure è possibile utilizzare un buffer non gestito o consentire a DataStream di crearne uno per te). Il codice dovrebbe essere simile a questo: il metodo

// 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(); 

di esempio per riempire il buffer con una sinusoide:

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

Grande, grazie. Ho ampliato il tuo esempio con la creazione dell'istanza XAudio2. Sto generando un suono dal buffer. Sembra un po 'distorto al momento. Dovrò ricontrollare il mio metodo FillBuffer, che ho anche aggiunto alla tua risposta per gli altri utenti. –

+0

Il metodo FillBuffer utilizzato per popolare un byte [] quando lavoravo in XNA. Rimozione del bit a bit e dello spostamento a destra >> gli operatori hanno risolto questo problema.Ora ho generato un tono chiaro. –

+0

Questo ha un bug: 'totalTime + = 2' significa che genera qualcosa il doppio della frequenza. Dovrebbe essere 'totalTime ++'. (Testato da solo!) –

3

È inoltre possibile utilizzare per giocare WASAPI buffer audio generate dinamicamente in WinRT. (xaudio2 non è l'unica soluzione).

Ho scritto il codice di esempio per esso in VB qui (il C# sarà essenzialmente lo stesso): http://www.codeproject.com/Articles/460145/Recording-and-playing-PCM-audio-on-Windows-8-VB

Credo che il ragazzo NAudio sta progettando di tradurre + inserire il mio codice di esempio in NAudio, per un Win8 - versione supportata, quindi sarà più facile da usare.

Problemi correlati