2012-05-18 10 views
20

Android MediaRecorder ma funkcję Co właściwie daje mi funkcja getMaxAmplitude() Androida dla MediaRecorder?

.getMaxAmplitude();
, która, jak API mówi mi, "Zwraca maksymalną bezwzględną amplitudę próbkowaną od czasu ostatniego wywołania tej metody." ale nie mogę znaleźć jaka to jest amplituda? Czy to w paśmie lub waty?

Znalazłem na kilku stronach internetowych, że można obliczyć wartość ściśle związaną z decybelami za pomocą (zgodnie z sugestią here).

double db = (20 * Math.log10(amplitude/REFERENCE)); 

który pozwolił mi założyć, że wartość zwracana jest w jakiejś skali liniowej (prawdopodobnie coś podobnego milipascal ...)

odniesienia = 0,1 (jestem świadomy, że powinno to być coś podobnego 2 * 10^(- 5) Pascal ((20 uPascal)), ale zwraca dziwne wartości ... 0,1 dziwnie działa lepiej)

teraz zmierzyć MaxAmplitude() używając

getMaxAmplitude()
i umieścić to w zmiennej amplitudzie..

Jest to metoda:

public double getNoiseLevel() 
{ 
    //Log.d("SPLService", "getNoiseLevel() "); 
    int x = mRecorder.getMaxAmplitude(); 
    double x2 = x; 
    Log.d("SPLService", "x="+x); 
    double db = (20 * Math.log10(x2/REFERENCE)); 
    //Log.d("SPLService", "db="+db); 
    if(db>0) 
    { 
     return db; 
    } 
    else 
    { 
     return 0; 
    } 
} 

Odbywa się to 5 razy w pół sekundy, co robi rodzaju przeciętnego

for(int i=0; i<5; i++) 
{ 
    try 
    { 
      Thread.sleep(100); 
    } 
    catch (InterruptedException e) 
    { 
      e.printStackTrace(); 
      return 0; 
    } 
    level = level+getNoiseLevel(); 
    if(level>0) 
    { 
     counter++; 
    } 
} 
level=level/counter; 
Log.d(LOG_TAG, "level="+level); 

uzyskać coś, co trochę wygląda jak decybelach ale jestem nie jestem pewny, czy rzeczywiście decybel w ogóle ...

Czy ktoś mógłby mi w tym pomóc? Wydaje się dziwne, że API nie precyzuje tego, co jest zwracane ...

+0

To zadziałało, dzięki za wyjaśnienie, co robi getMaxAmplitude. Ale nie jestem pewien, czy są to dokładne wartości dB. Kiedy testuję w niektórych przypadkach i próbuję porównać wartości do tego: http://www.newton.dep.anl.gov/askasci/phy99/phy99405.htm, brakuje 30dB. Czy masz jakiś pomysł, dlaczego? – Wissem

+1

Może być kilka przyczyn: 1. Ten algorytm wykorzystuje metodę getMaxAmplitude jako podstawę do obliczeń, co oznacza, że ​​wszystkie mniej głośne zdarzenia w okresie są ignorowane. Prowadzi to do wyników, które mogą być powyżej rzeczywistego poziomu dB (i zwykle w naturalnych środowiskach) 2. Mikrofony telefonów są różne. Niektóre są bardziej wrażliwe niż inne. Algorytm ten nie bierze tego pod uwagę, wykonując te same obliczenia na dowolnym telefonie. Z powodu tych różnic niektóre telefony mogą dawać znacznie wyższe lub niższe wartości. –

+0

Ponadto, ze względu na czynnik ograniczający (wartość wzrasta do 32767), bardzo głośne dźwięki nie są dokładnie wykrywane. Zwykle granica wynosi około 100 dB. –

Odpowiedz

15

Mogę znaleźć odpowiedź na to pytanie, a ja podzielę się tym tutaj dla każdego, kogo to obchodzi: Funkcja MediaRecorder.getMaxAmplitude() zwraca Niepodpisane 16-bitowe liczby całkowite (0-32767). Co jest prawdopodobnie tylko abs() z jakości próbki CD, które wahają się od -32768 do 32767. Oznacza to, że prawdopodobnie reprezentują 16-bitową cyfryzację mocy elektrycznej od 0-100% maksymalnego zakresu napięcia w budowie mikrofonu do tego telefonu komórkowego. Ponieważ nawet w przypadku jednej marki telefonów komórkowych mikrofony te czasami różnią się dokładnym zakresem, nawet podobne telefony nie muszą zwracać tej samej wartości, biorąc pod uwagę tę samą odległość od tego samego źródła dźwięku.

Wartość ta koreluje jednak z ciśnieniem akustycznym w Pascalie, ponieważ jest to również liniowa kwantyzacja ciśnienia solundowego, w obszarze, w którym dźwięk może być mierzony z danym mikrofonem (który nie obejmuje całego spektrum z powodu ograniczeń telefon).

13

Pracowałem nad tym trochę więcej. Korzystając z niektórych testów wykonanych za pomocą skalibrowanych mierników SPL i smartfonów z różnymi czystymi częstotliwościami, białego szumu i różowego szumu, teraz wiem, że mikrofony telefonu komórkowego nie nadają się do niczego, co powinno zarejestrować się w dowolnym miejscu powyżej 90 do 100 dB (SPL) w zależności od telefonu .

Zakładając, że 90 dB (SPL) jest maksymalną, można obliczyć, że odpowiada to ciśnieniu 0,6325 Pa przy mikrofonie. Przyjmując teraz, że p0 = 0,0002 Pa jest minimalnym punktem odniesienia i zakładamy, że zarejestruje to jako 0 (co nigdy by się nie stało) z getMaxAmplitude(), możemy wyznaczyć wartości z funkcji getMaxAmplitude() z maksymalnym ciśnieniem na mikrofonie. Oznacza to, że wynik 16375 z funkcji getMaxAmplitude() odpowiadałby maksymalnemu ciśnieniu 0,3165 Pa. To oczywiście nie jest zbyt naukowe, ponieważ wartości maksymalne i minimalne są czyste, ale daje nam to punkt wyjścia.Można teraz obliczyć P z

p = getMaxAmplitude()/51805.5336

Jeżeli ciśnienie w MIC można obliczyć dB (SPL) -wartość ze znanego wzoru

X = 20 log_10 (p/p0)

To nadal daje wartość, która jest wysoka, ponieważ w obliczeniach używana jest tylko maksymalna amplituda. Aby rozwiązać ten nie musi korzystać getMaxAmplitude(), a jednocześnie jest to nieco spokojniejsza poza naciskiem tej kwestii, będę umieścić kod w każdym razie w nadziei, że pomaga

public class NoiseRecorder 
{ 

private final String TAG = SoundOfTheCityConstants.TAG; 
public static double REFERENCE = 0.00002; 

public double getNoiseLevel() throws NoValidNoiseLevelException 
{ 
    Logging.e(TAG, "start new recording process"); 
    int bufferSize = AudioRecord.getMinBufferSize(44100,AudioFormat.CHANNEL_IN_DEFAULT,AudioFormat.ENCODING_PCM_16BIT); 
    //making the buffer bigger.... 
    bufferSize=bufferSize*4; 
    AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 
      44100, AudioFormat.CHANNEL_IN_DEFAULT, AudioFormat.ENCODING_PCM_16BIT, bufferSize); 

    short data [] = new short[bufferSize]; 
    double average = 0.0; 
    recorder.startRecording(); 
    //recording data; 
    recorder.read(data, 0, bufferSize); 

    recorder.stop(); 
    Logging.e(TAG, "stop"); 
    for (short s : data) 
    { 
     if(s>0) 
     { 
      average += Math.abs(s); 
     } 
     else 
     { 
      bufferSize--; 
     } 
    } 
    //x=max; 
    double x = average/bufferSize; 
    Logging.e(TAG, ""+x); 
    recorder.release(); 
    Logging.d(TAG, "getNoiseLevel() "); 
    double db=0; 
    if (x==0){ 
     NoValidNoiseLevelException e = new NoValidNoiseLevelException(x); 
     throw e; 
    } 
    // calculating the pascal pressure based on the idea that the max amplitude (between 0 and 32767) is 
    // relative to the pressure 
    double pressure = x/51805.5336; //the value 51805.5336 can be derived from asuming that x=32767=0.6325 Pa and x=1 = 0.00002 Pa (the reference value) 
    Logging.d(TAG, "x="+pressure +" Pa"); 
    db = (20 * Math.log10(pressure/REFERENCE)); 
    Logging.d(TAG, "db="+db); 
    if(db>0) 
    { 
     return db; 
    } 
    NoValidNoiseLevelException e = new NoValidNoiseLevelException(x); 
    throw e; 
} 
} 

Wartości te są obecnie pochodzi z średnia wszystkich amplitud w próbce 4-sekundowej, a zatem dokładniejsza. Następnie wykonuje się powyższe obliczenia. To da bardziej realistyczną wartość decybeli. Zwróć uwagę, że mikrofony z telefonu komórkowego wciąż nie są w stanie zasysać i że ten algorytm nie wytworzy rzeczywistego dB (SPL), ale tylko trochę lepiej zbliżone niż poprzednio.

Aby uzyskać wydajność niektórych aplikacji, trzeba zrobić więcej. Większość z tych aplikacji używa przesuwanych okien, co oznacza, że ​​nagrywają i przesuwają okno o wartości x sekund, aby móc ocenić poziom dźwięku. Również dokonam oceny, która wartość db najlepiej nadaje się do użycia jako max, teraz jest to 90 dB (SPL)/0,6325 Pa, co jest po prostu rozsądnym domysłem, prawdopodobnie będzie nieco powyżej tego.

Jak tylko będę mieć więcej, zaktualizuję informacje.

+0

Dziękuję bardzo - jest to bardzo pomocne –

+0

Czy wiesz, jeśli podczas wywoływania metody 'recorder.read (data, 0, bufferSize);', jeśli rekorder jest coraz amplitudy i przechowywanie ich w krótkiej tablicy danych? Nie jestem całkowicie pewien, czy rozumiem, co robi metoda. –

+0

Są to wartości próbkowanych z mikrofonu, które są przechowywane. Będą one (tak jak ciśnienie w mikrofonie) oscylują między wartościami dodatnimi i ujemnymi. Aby uzyskać amplitudę, musielibyśmy użyć jakiejś mediany lub ważonej kalkulacji. –