volumen tabla sonido ruido que permitidos para oido niveles humano fisica decibeles cuanto calculo bel c# audio audio-recording

c# - tabla - Calcular decibeles



que es un bel (3)

Agradezco la publicación de Han y escribí una rutina que puede calcular decibeles en formatos de audio de 8 y 16 bits, con múltiples canales usando su ejemplo.

public double MeasureDecibels(byte[] samples, int length, int bitsPerSample, int numChannels, params int[] channelsToMeasure) { if (samples == null || length == 0 || samples.Length == 0) { throw new ArgumentException("Missing samples to measure."); } //check bits are 8 or 16. if (bitsPerSample != 8 && bitsPerSample != 16) { throw new ArgumentException("Only 8 and 16 bit samples allowed."); } //check channels are valid if (channelsToMeasure == null || channelsToMeasure.Length == 0) { throw new ArgumentException("Must have target channels."); } //check each channel is in proper range. foreach (int channel in channelsToMeasure) { if (channel < 0 || channel >= numChannels) { throw new ArgumentException("Invalid channel requested."); } } //ensure we have only full blocks. A half a block isn''t considered valid. int sampleSizeInBytes = bitsPerSample / 8; int blockSizeInBytes = sampleSizeInBytes * numChannels; if (length % blockSizeInBytes != 0) { throw new ArgumentException("Non-integral number of bytes passed for given audio format."); } double sum = 0; for (var i = 0; i < length; i = i + blockSizeInBytes) { double sumOfChannels = 0; for (int j = 0; j < channelsToMeasure.Length; j++) { int channelOffset = channelsToMeasure[j] * sampleSizeInBytes; int channelIndex = i + channelOffset; if (bitsPerSample == 8) { sumOfChannels = (127 - samples[channelIndex]) / byte.MaxValue; } else { double sampleValue = BitConverter.ToInt16(samples, channelIndex); sumOfChannels += (sampleValue / short.MaxValue); } } double averageOfChannels = sumOfChannels / channelsToMeasure.Length; sum += (averageOfChannels * averageOfChannels); } int numberSamples = length / blockSizeInBytes; double rootMeanSquared = Math.Sqrt(sum / numberSamples); if (rootMeanSquared == 0) { return 0; } else { double logvalue = Math.Log10(rootMeanSquared); double decibel = 20 * logvalue; return decibel; } }

Estoy grabando entrada de micrófono usando la biblioteca XNA (no creo que esto sea realmente específico de la tecnología, pero nunca duele). Cada vez que obtengo una muestra me gustaría calcular los decibelios. He hecho muchas búsquedas en Internet y no he encontrado un ejemplo sólido como una roca ...

Aquí está mi intento de calcular decibeles a partir de una muestra:

double peak = 0; for (var i = 0; i < _buffer.Length; i = i + 2) { var sample = BitConverter.ToInt16(_buffer, i); if (sample > peak) peak = sample; else if (sample < -peak) peak = -sample; } var decibel = (20 * Math.Log10(peak/32768));

Si envío el valor de decibeles a la pantalla, puedo ver que los valores aumentan a medida que me hago más fuerte y más bajo a medida que hablo más suave. Sin embargo, siempre se sitúa alrededor de -40 cuando estoy absolutamente callado ... Supongo que sería -90. Debo tener un cálculo equivocado en el bloque de arriba? por lo que he leído en algunos sitios -40 es equivalente a "hablar suave" ... sin embargo, es totalmente silencioso.

Además, si silencia mi micrófono, va directo a -90.

¿Lo estoy haciendo mal?


Al medir el nivel de una señal de sonido, debe calcular los dB a partir del valor RMS. En tu muestra, estás viendo el nivel máximo absoluto. Un único valor de muestra (pico) determina su valor de dB, incluso cuando todas las demás muestras son exactamente 0.

prueba esto:

double sum = 0; for (var i = 0; i < _buffer.length; i = i + 2) { double sample = BitConverter.ToInt16(_buffer, i) / 32768.0; sum += (sample * sample); } double rms = Math.Sqrt(sum / (_buffer.length / 2)); var decibel = 20 * Math.Log10(rms);

Para niveles de dB ''instantáneos'' normalmente se calcularía el RMS en un segmento de 20-50 ms. Tenga en cuenta que el valor de dB calculado es relativo a escala completa. Para el sonido, el valor de dB debe relacionarse con 20 uPa, y deberá calibrar su señal para encontrar la conversión adecuada de valores digitales a valores de presión.


Creo que Yann quiere decir que los decibelios son una escala relativa. Si está tratando de medir el nivel real de presión acústica o SPL, debería calibrar. Lo que estás midiendo es dBFS (decibeles a escala real, creo). Está midiendo cuántos decibelios más silenciosa es la señal que la señal más alta posible que el sistema puede representar (la señal de "escala completa", o 32768 para estas muestras de 16 bits). Es por eso que todos los valores son negativos.