2016-01-10 17 views
7

Pracuję nad projektem IoT winodws, który kontroluje pasek led oparty na wejściu audio. Teraz mam trochę kodu, który pobiera dźwięk i zapisuje go do bufora z interfejsem API AudioGraph, ale nie wiem, jak mogę przetworzyć audio na jakieś użyteczne dane.uwp Przetwarzanie audio AudioGraph

mój kod do tej pory:

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; 


     } 
    } 

Więc kończę z moim buforze jako pływaka. Ale jak mogę to zmienić na przydatne dane, które umożliwiają stworzenie czegoś takiego jak analizator widma?

Edit:

Może muszę zrobić to kwestia mniej specyficzne dla audiograph. Używam API, aby uzyskać moje wejście audio. Dane, które otrzymuję z API to bajt * i mogę rzucić go na float * Jak zmienić to z bajtu * lub float * na inne dane, których mogę użyć do utworzenia kodów kolorów.

Nauczyłem się wykonywać niektóre analizy FFT na float *, aby uzyskać 164 diody led * 3 (rgb) = 492 pojemników. Przetwarzaj te dane dalej, aby uzyskać wartości od 0 do 255.

Jak mogę przetworzyć ten float * lub bajt *, aby uzyskać te przydatne dane? Lub jak zacząć?

+0

Możesz rzucić okiem na https://github.com/filoe/cscore, jest próbka dołączona (patrz zdjęcie poniżej) –

Odpowiedz

10

Te dane są przeplatane IEEE pływak, więc na przemian dane kanału po kroku przez tablicę, a zakres danych dla każdej próbki wynosi od -1 do 1. Na przykład sygnał mono jest tylko jeden kanał, tak w ogóle nie będzie przeplatać danych; ale sygnał stereo posiada dwa kanały audio, i tak:

dataInFloat[0] 

jest pierwsza próbka danych z kanału lewego i

dataInFloat[1] 

jest pierwsza próbka danych z prawego kanału. Następnie

dataInFloat[2] 

jest próbka danych z kanału lewego sekund. i oni po prostu ciągle idą tam iz powrotem. Wszystkie pozostałe dane, które będziesz mieć na uwadze, to: windows.media.mediaproperties.audioencodingproperties.

Po prostu wiedząc o tym, możesz (zasadniczo) od razu uzyskać ogólną objętość sygnału bezpośrednio z tych danych, patrząc na bezwzględna wartość każdej próbki. Na pewno chcesz go wyedytować przez pewien czas. Możesz nawet po prostu dołączyć efekty EQ do różnych węzłów i utworzyć oddzielne węzły analizatora niskiego, średniego i wysokiego oraz nigdy nie dostać się do rzeczy FFT. ALE CO ZABAWIA JEST? (to nadal jest zabawne)

A potem, tak, aby uzyskać złożone dane harmoniczne i stworzyć naprawdę słodki wizualizator, chcesz zrobić FFT na nim. Ludzie lubią używać AForge do nauki scenariuszy, takich jak twoje. Zobacz Sources/Imaging/ComplexImage.cs do wykorzystania, Sources/Math/FourierTransform.cs do implementacji

Następnie możesz łatwo uzyskać swoje klasyczne dane bin i zrobić klasyczny materiał do wizualizacji lub uzyskać więcej creative lub cokolwiek innego! technologia jest niesamowita!

+0

Dzięki!Wciąż mam kilka pytań. Mam zwykle długość bufora 3840 w czasie ramki 0,01 sekundy, więc to oznacza (3840/sizeof (float))/2, że moje lewe i prawe kanały mają długość 480 ruchomych. Czy to jest poprawne? Właściwości kodowania mojego wykresu to szybkość transmisji wynosząca 3072000, bity/próbka 32, próbkowanie 48000 –

+0

Masz rację! Pamiętaj, że zakres danych wynosi [-1, + 1], więc jeśli spojrzysz na średnią wartość ABSOLUTE tych danych, otrzymasz przybliżoną ocenę objętości. (Przejmuję mój post powyżej z tymi informacjami również) Ale naprawdę powinieneś przekazać to do FFT, aby uzyskać prawdziwe wartości danych z powrotem, ale sztuczka amplitudy (średnia bezwzględna wartość zmiennoprzecinkowa) działa dobrze dla szybkiego-n-brudnego analizy i jest znacznie mniej intensywny procesor. Robię to cały czas, jeśli mam tylko jedną zewnętrzną rzecz, którą chcę wyzwolić z muzyki (jedno światło, jeden silnik, wibracje telefonu itp.) – andymule

+0

Okay, Nice! Tak więc teraz tworzę złożoną tablicę z rzeczywistą częścią wartości lewego audio (na przykład coś takiego jak hammingwindow?) I złożona część będzie wynosić 0 (zawsze 0 dla audio prawda?). A jeśli ta tablica ma długość 2^n, to wyrzucę ją przez FFT, która zwróci częstotliwość w funkcji czasu. A potem spodziewam się, że druga połowa jest taka sama jak pierwsza część. Ale to nie jest :(Więc, czy to jest właściwe, co myślę i robię? –

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