2016-01-10 17 views
7

Sto lavorando a un progetto IoT winodws che controlla una striscia led basata su un ingresso audio. Ora ho un codice che riceve l'audio e lo scrive su un buffer con l'API AudioGraph, ma non so come posso elaborare l'audio con alcuni dati utili.uwp Elaborazione audio AudioGraph

mio codice finora:

private async void MainPage_Loaded(object sender, RoutedEventArgs eventArgs) 
{ 
     try 
     { 
      // Initialize the led strip 
      //await this.pixelStrip.Begin(); 

      sampleAggregator.FftCalculated += new EventHandler<FftEventArgs>(FftCalculated); 
      sampleAggregator.PerformFFT = true; 

      // Create graph 
      AudioGraphSettings settings = new AudioGraphSettings(AudioRenderCategory.Media); 
      settings.DesiredSamplesPerQuantum = fftLength; 
      settings.DesiredRenderDeviceAudioProcessing = Windows.Media.AudioProcessing.Default; 
      settings.QuantumSizeSelectionMode = QuantumSizeSelectionMode.ClosestToDesired; 

      CreateAudioGraphResult result = await AudioGraph.CreateAsync(settings); 
      if (result.Status != AudioGraphCreationStatus.Success) 
      { 
       // Cannot create graph 
       return; 
      } 
      graph = result.Graph; 

      // Create a device input node using the default audio input device 
      CreateAudioDeviceInputNodeResult deviceInputNodeResult = await graph.CreateDeviceInputNodeAsync(MediaCategory.Other); 

      if (deviceInputNodeResult.Status != AudioDeviceNodeCreationStatus.Success) 
      { 
       return; 
      } 

      deviceInputNode = deviceInputNodeResult.DeviceInputNode; 

      frameOutputNode = graph.CreateFrameOutputNode(); 
      frameOutputNode.Start(); 
      graph.QuantumProcessed += AudioGraph_QuantumProcessed; 

      // Because we are using lowest latency setting, we need to handle device disconnection errors 
      graph.UnrecoverableErrorOccurred += Graph_UnrecoverableErrorOccurred; 

      graph.Start(); 
     } 
     catch (Exception e) 
     { 
      Debug.WriteLine(e.ToString()); 
     } 
    } 

    private void AudioGraph_QuantumProcessed(AudioGraph sender, object args) 
    { 
     AudioFrame frame = frameOutputNode.GetFrame(); 
     ProcessFrameOutput(frame); 
    } 

    unsafe private void ProcessFrameOutput(AudioFrame frame) 
    { 
     using (AudioBuffer buffer = frame.LockBuffer(AudioBufferAccessMode.Write)) 
     using (IMemoryBufferReference reference = buffer.CreateReference()) 
     { 
      byte* dataInBytes; 
      uint capacityInBytes; 
      float* dataInFloat; 

      // Get the buffer from the AudioFrame 
      ((IMemoryBufferByteAccess)reference).GetBuffer(out dataInBytes, out capacityInBytes); 

      dataInFloat = (float*)dataInBytes; 


     } 
    } 

così finisco con il mio buffer come un galleggiante. Ma come posso cambiarlo in dati utili che rendono possibile creare qualcosa come un analizzatore di spettro?

Edit:

Forse devo fare questa domanda meno specifico per l'audiograph. Io uso un'API per ottenere il mio input audio. I dati che ottengo dall'API sono un byte * e posso lanciarlo su un float * Come posso cambiarlo dal byte * o dal float * con altri dati che posso usare per creare alcuni codici colore.

Ho pensato di fare qualche analisi FFT sul float * per ottenere 164 leds * 3 (rgb) = 492 bin. E elaborare ulteriormente questi dati per ottenere valori compresi tra 0 e 255.

Quindi, come posso elaborare questo float * o byte * per ottenere questi dati utili? O come inizio?

+0

Si può dare un'occhiata a https://github.com/filoe/cscore, c'è un campione incluso (vedi immagine in basso) –

risposta

10

I dati sono interlacciati IEEE float, quindi alterano i dati del canale mentre si passa attraverso l'array e l'intervallo di dati per ciascun campione è compreso tra -1 e 1. Ad esempio, un segnale mono ha solo un canale, quindi non interforderà affatto i dati; ma un segnale stereo ha due canali audio, e così:

dataInFloat[0] 

è il primo campione di dati dal canale sinistro e

dataInFloat[1] 

è il primo campione di dati dal canale destro. Poi,

dataInFloat[2] 

è campione seconda dei dati dal canale sinistro. e continuano a andare avanti e indietro. Tutti gli altri dati di cui ti preoccuperai sono in windows.media.mediaproperties.audioencodingproperties

Quindi, solo sapendo questo, puoi (essenzialmente) ottenere immediatamente il volume complessivo del segnale direttamente da questi dati guardando il valore assoluto di ogni campione. Sicuramente vorrai mediarlo per un po 'di tempo. È anche possibile allegare effetti EQ a nodi diversi, creare nodi separati Low, Mids e High analyzer e non entrare mai nemmeno in oggetti FFT. MA CHE DIVERTIMENTO È QUELLO? (in realtà è ancora divertente)

E quindi, sì, per ottenere i complessi dati armonici e creare un vero e proprio visualizzatore, si vuole fare un FFT su di esso. Alle persone piace usare AForge per scenari di apprendimento come il tuo. Vedi Sources/Imaging/ComplexImage.cs per l'utilizzo, Sources/Math/FourierTransform.cs per l'implementazione

Quindi è possibile ottenere facilmente i dati del cestino classico e fare il classico visualizzatore musicale o ottenere più creative o qualsiasi altra cosa! la tecnologia è fantastica!

+0

Grazie!Ho ancora alcune domande. Ho il più delle volte una lunghezza del buffer di 3840 in un frame time di 0,01 secondi, quindi questo significa (3840/sizeof (float))/2 che i miei chanels sinistro e destro hanno una lunghezza di 480 float. È giusto? Le proprietà di codifica del mio grafico sono bitrate di 3072000, bit/campione 32, samplerate 48000 –

+0

Hai ragione! Si noti che l'intervallo dei dati è [-1, + 1], quindi se si guarda la media del valore ASSOLUTO di quei dati si otterrà una stima approssimativa del volume. (Sto rivedendo il mio post qui sopra con queste informazioni) Ma in realtà dovresti consegnarlo alla FFT per ottenere i valori dei dati veri, ma il trucco di ampiezza (valore float assoluto medio) funziona bene per un quick-n-dirty analisi ed è molto meno impegnativo per la CPU. Lo faccio sempre se ho solo una cosa esterna che voglio far scattare dalla musica (una luce, un motore, vibrazione del telefono, ecc ...) – andymule

+0

Ok, bello! Così ora creo un array complesso con la parte reale i valori dell'audio sinistro (è qualcosa di simile a una finestra hamming necessaria?) Per esempio e la parte complessa sarà 0 (Sempre 0 per l'audio, giusto?). E se quella matrice è la lunghezza di 2^n allora la lancio attraverso la FFT e ciò restituirà la frequenza rispetto al tempo. E quello che poi mi aspetto è che la seconda metà è la stessa della prima parte. (Quindi, è giusto quello che sto pensando e facendo? –

0
dataInFloat = (float*)dataInBytes; 
    float max = 0; 
    for (int i = 0; i < graph.SamplesPerQuantum; i++) 
       { 
        max = Math.Max(Math.Abs(dataInFloat[i]), max); 

       } 

       finalLevel = max; 
       Debug.WriteLine(max);