2015-06-04 16 views
13

Właśnie obejrzałem wideo WWDC (sesja 502 AVAudioEngine w praktyce) pod numerem AVAudioEngine i jestem bardzo podekscytowany, że mogę zbudować aplikację na tej technologii.Pomiar poziomu za pomocą AVAudioEngine

Nie byłem w stanie dowiedzieć się, w jaki sposób mogę monitorować poziom wejścia mikrofonowego lub wyjścia miksera.

Czy ktoś może pomóc? Aby było jasne, mówię o monitorowaniu bieżącego sygnału wejściowego (i wyświetlania go w interfejsie użytkownika), a nie ustawieniu głośności wejścia/wyjścia kanału/ścieżki.

Wiem, że można to zrobić z AVAudioRecorder, ale nie jest to AVAudioNode wymagane przez AVAudioEngine.

Odpowiedz

-2

AVAudioPlayer ma funkcje pomiarowe dla sygnału wyjściowego.

AVAudioRecorder ma funkcje pomiaru sygnału wejściowego.

Oto blog post i projekt github, który korzysta z rejestratora.

+3

Dziękuję za przeczytanie mojego posta. -.- Mam świadomość, że te klasy monitorują, ale nie znajdują się w hierarchii AVAudioNode, a zatem nie działają z interfejsem AVAudioEngine API wyższego poziomu. O ile się nie mylę ...? – horseshoe7

-3

AVAudioPlayer i AVAudioRecorder to "wysoki poziom" sposobów na zrobienie tego.

Potrzebujesz "twardego" sposobu.

Następnie zainstaluj zawór na węźle wejściowym silnika. Otrzymasz bufor audio w zamknięciu.

let inputNode = audioEngine.inputNode 
inputNode.installTapOnBus(etc. 
+0

Mogłem być bardziej zrozumiały co do mojego poziomu wiedzy. Tak, czytałem także dokumenty API i oglądałem wideo, w którym omawiane są wszystkie te koncepcje. Kliknięcia '' 'AVAudioNode''' faktycznie wywołują wywołanie zwrotne co około 0.375 s (tak, tutaj http://stackoverflow.com/a/27343266/421797), więc to podejście również nie jest idealne. Kiedy/jeśli to ustalę, podaję odpowiedź. Jestem pewien, że ma to związek z wywołaniami zwrotnymi renderowania AudioUnit. – horseshoe7

+0

Nie chcę na własnej skórze, chcę sposób, który używa wspólnego podejścia "tj. '' 'AVAudioEngine'''. Zastanawiam się, jak osiągnąć to, co chcę, z '' 'AVAudioRecorder''', ale na koniec dnia, moje zadanie lub nie, wydaje się dość powszechnym przypadkiem użycia, biorąc pod uwagę' 'AVAudioEngine'' 'architektura, aby chcieć umieścić mierniki poziomu w dowolnych punktach. – horseshoe7

12

Spróbuj zainstalować podsłuch na głównego miksera, a następnie zrobić to szybciej, ustawiając framelength, a następnie odczytać próbki i dostać średnio coś takiego:

self.mainMixer = [self.engine mainMixerNode]; 
[self.mainMixer installTapOnBus:0 bufferSize:1024 format:[self.mainMixer outputFormatForBus:0] block:^(AVAudioPCMBuffer * _Nonnull buffer, AVAudioTime * _Nonnull when) { 
    [buffer setFrameLength:1024]; 
    UInt32 inNumberFrames = buffer.frameLength; 

    if(buffer.format.channelCount>0) 
    { 
     Float32* samples = (Float32*)buffer.floatChannelData[0]; 
     Float32 avgValue = 0; 

     vDSP_meamgv((Float32*)samples, 1, &avgValue, inNumberFrames); 
     self.averagePowerForChannel0 = (LEVEL_LOWPASS_TRIG*((avgValue==0)?-100:20.0*log10f(avgValue))) + ((1-LEVEL_LOWPASS_TRIG)*self.averagePowerForChannel0) ; 
     self.averagePowerForChannel1 = self.averagePowerForChannel0; 
    } 

    if(buffer.format.channelCount>1) 
    { 
     Float32* samples = (Float32*)buffer.floatChannelData[1]; 
     Float32 avgValue = 0; 

     vDSP_meamgv((Float32*)samples, 1, &avgValue, inNumberFrames); 
     self.averagePowerForChannel1 = (LEVEL_LOWPASS_TRIG*((avgValue==0)?-100:20.0*log10f(avgValue))) + ((1-LEVEL_LOWPASS_TRIG)*self.averagePowerForChannel1) ; 
    } 
}]; 

aby uzyskać wartości szczytowe, użyj vDSP_maxmgv zamiast vDSP_meamgv.


LEVEL_LOWPASS_TRIG jest prosty filtr ceniony od 0,0 do 1,0, jeśli ustawisz 0.0 można filtrować wszystkie wartości i nie dostać żadnych danych. Jeśli ustawisz go na 1.0, dostaniesz za dużo hałasu. Zasadniczo im wyższa wartość, tym większa różnorodność danych. Wygląda na to, że wartość od 0,10 do 0,30 jest dobra dla większości aplikacji.

+7

Jaka jest wartość (lub zakres) używanej dla LEVEL_LOWPASS_TRIG? – apocolipse

+5

Aby użyć vDSP_meamgv, wykonaj polecenie "import Accelerate", aby użyć wysokiej klasy platformy matematycznej Apple. – Josh

+0

Czy możesz opublikować pełny przykład pracy w Github? –

0

Odkryłem inne rozwiązanie, które jest nieco dziwne, ale działa idealnie dobrze i znacznie lepiej niż dotknięcie. Mikser nie ma modułu AudioUnit, ale jeśli przesyłasz go do AVAudioIONode, możesz pobrać moduł AudioUnit i skorzystać z funkcji pomiarowej systemu iOS. Oto jak:

Aby włączyć lub wyłączyć dozowanie:

- (void)setMeteringEnabled:(BOOL)enabled; 
{ 
    UInt32 on = (enabled)?1:0; 
    AVAudioIONode *node = (AVAudioIONode*)self.engine.mainMixerNode; 
    OSStatus err = AudioUnitSetProperty(node.audioUnit, kAudioUnitProperty_MeteringMode, kAudioUnitScope_Output, 0, &on, sizeof(on)); 
} 

Aby zaktualizować metrów:

- (void)updateMeters; 
{ 
    AVAudioIONode *node = (AVAudioIONode*)self.engine.mainMixerNode; 

    AudioUnitParameterValue level; 
    AudioUnitGetParameter(node.audioUnit, kMultiChannelMixerParam_PostAveragePower, kAudioUnitScope_Output, 0, &level); 

    self.averagePowerForChannel1 = self.averagePowerForChannel0 = level; 
    if(self.numberOfChannels>1) 
    { 
     err = AudioUnitGetParameter(node.audioUnit, kMultiChannelMixerParam_PostAveragePower+1, kAudioUnitScope_Output, 0, &level); 
    } 
} 
+1

nie działa dla mnie, czy mógłbyś przedłużyć swoją odpowiedź? –

Powiązane problemy