Qu'est-ce que la fonction Getmaxamplitude() D'Android pour le MediaRecorder me donne réellement?

L'Android MediaRecorder a une fonction

.getMaxAmplitude();
qui, comme le API me dit, " renvoie l'amplitude maximale absolue qui a été échantillonnée depuis le dernier appel à cette méthode. mais je ne trouve pas quelle amplitude c'est? C'est en pascal ou en watts?

j'ai trouvé sur plusieurs pages du web que vous pouvez calculer une valeur étroitement liée aux décibels en utilisant (comme suggéré ici ).

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

qui me permettrait de supposer que la valeur retournée est dans une certaine échelle linéaire (probablement quelque chose comme milipascal...)

référence=0.1(je suis conscient que cela devrait être quelque chose comme 2*10^(-5) Pascal ((20 uPascal)), mais qui renvoie des valeurs étranges... 0,1 fonctionne étrangement mieux.)

en ce moment je mesure la MaxAmplitude () en utilisant le

getMaxAmplitude()
et mets ceci dans la variable amplitude .

C'est la méthode:

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

ce qui est fait 5 fois en une demi-seconde, qui obtient une sorte de moyenne

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

j'ai quelque chose qui ressemble à du décibel, mais je ne suis pas sûr que ce soit du tout du décibel...

alors, quelqu'un peut-il m'aider? Il semble très étrange que l'API ne spécifie pas du tout ce qui est retourné...

20
demandé sur Community 2012-05-18 19:42:15

2 réponses

je pourrais trouver la réponse à cette question et je la partagerai ici pour tous ceux qui s'en soucient: le MediaRecorder.la fonction getMaxAmplitude () renvoie des valeurs entières non signées de 16 bits (0-32767). Qui est probablement juste l'abs () des valeurs CD-qualité d'échantillon qui vont de -32768 à 32767. Cela signifie qu'ils représentent probablement une digitalisation 16 bits de la sortie électrique de 0-100% de la plage de tension maximale du microphone intégré dans ce téléphone mobile. Car même dans une marque de mobile ces microphones varient parfois dans leur plage de précision, même pour des téléphones similaires, mais ils renvoient nécessairement la même valeur à la même distance à la même source sonore.

cette valeur est cependant corrélée à la pression sonore en Pascal car c'est aussi une quantification linéaire de la pression solund, dans la zone où le son peut être mesuré avec le microphone donné (qui ne couvrira pas la totalité du sprectrum en raison des limites du téléphone).

16
répondu Lukas Ruge 2012-10-17 10:28:41

a encore travaillé là-dessus. En utilisant des tests effectués avec des SPL-mètres calibrés et des téléphones intelligents avec des fréquences pures diférentes, le bruit blanc et le bruit rose je sais maintenant que les microphones de téléphone mobile ne sont pas utilisables pour tout ce qui devrait enregistrer n'importe où au-dessus de 90 à 100 dB(SPL) selon le téléphone.

en supposant que 90 dB(SPL) est le maximum, on peut calculer que cela correspondrait à une pression de 0,6325 Pa à la CMI. En supposant que p0=0.0002 Pa est le en supposant que cela s'inscrirait en tant que 0 (ce qui ne se produirait jamais) de getMaxAmplitude (), nous pouvons faire le lien entre les valeurs de la fonction getMaxAmplitude() et la pression maximale au micro. Cela signifie qu'un résultat de 16375 de getMaxAmplitude() correspondrait à une pression maximale de 0,3165 Pa. Ce n'est évidemment pas très scientifique puisque les valeurs max et min sont de pures conjonctures, mais cela nous donne un point de départ. Nous pouvons maintenant calculer p avec

p=getMaxAmplitude () / 51805.5336

connaissant la pression au micro on peut calculer la valeur dB (SPL) avec la formule bien connue

X = 20 log_10 (p/p0)

Cela donnera quand même une valeur trop élevée puisque seule l'amplitude maximale est utilisée dans les calculs. Pour résoudre ce problème, il ne faut pas utiliser getMaxAmplitude () et bien que cela soit légèrement en dehors de l'objet de cette question, je vais mettre le code de toute façon dans l'espoir qu'il aide

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

ces valeurs sont maintenant dérivées de la moyenne de toutes les amplitudes dans un échantillon de 4 secondes et donc plus précises. Les calculs décrits ci-dessus sont ensuite effectués. Cela donnera une valeur de décibel plus réaliste. Notez que les micros de téléphonie mobile sont toujours nuls et que cet algorithme ne produira pas de dB(SPL) mais seulement une approximation légèrement meilleure que celle d'avant.

Pour obtenir les performances de certaines applications certains plus besoin d'être fait. La plupart de ces applications utilisent des fenêtres coulissantes, ce qui signifie l'enregistrement de garder et de glisser une fenêtre de x secondes pour continuer à évaluer le niveau sonore. En outre, je vais effectuer une évaluation ce que la valeur de db est le mieux adapté pour être utilisé comme max, à l'heure actuelle, il est de 90 dB(SPL)/0,6325 Pa qui est juste une estimation raisonnable, il sera probablement légèrement au-dessus de cela.

dès que j'en aurai plus, je mettrai à jour l'info.

14
répondu Lukas Ruge 2013-02-14 08:16:28