我有一个在 Ubuntu 笔记本电脑上运行的 Python 脚本,用于从笔记本电脑上的麦克风获取实时环境噪声级别。我认为这个脚本效果不佳,而且我不明白为什么。我怀疑这可能只是一个较长的周期大小,但我不确定是否就是这样。有人可以帮我理解这个脚本有什么问题吗?谢谢!
import alsaaudio
import audioop
import time
import math
# Set the audio parameters
device = 'default'
channels = 1 # mono
sample_rate = 44100 # 44.1 kHz
format = alsaaudio.PCM_FORMAT_S16_LE
# Open the audio input stream
inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NORMAL, device)
inp.setchannels(channels)
inp.setrate(sample_rate)
inp.setformat(format)
inp.setperiodsize(256)
# Main loop to continuously print audio levels
try:
while True:
# Read audio data from the microphone
_, data = inp.read()
# Calculate the peak audio level in decibels
rms = audioop.rms(data, 2) # 2 for sample width 16-bit
# Print the decibel level without dynamic range adjustment
decibels = 20 * math.log10(rms)
print(f"Decibels: {decibels:.2f} dB")
time.sleep(0.01) # Adjust the sleep duration as needed
except KeyboardInterrupt:
print("Stopping the script.")
我希望这个脚本很敏感,如果我发出声音,分贝值会立即跳跃。不幸的是,现在情况并非如此,我不知道为什么。我使用了 sounddevice 库,它似乎运行良好,但我无法使用 pyalsaaudio 获得相同的结果。
编辑: 根据 @fdcpp 的评论,我修改了我的脚本,但得到了负值,但不知道为什么
import alsaaudio
import audioop
import math
import struct
# Set the audio parameters
device = 'default'
channels = 1 # mono
sample_rate = 44100 # 44.1 kHz
format = alsaaudio.PCM_FORMAT_S16_LE
# Open the audio input stream
inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NORMAL, device, channels=channels, rate=sample_rate, format=format, periodsize=1024)
# Main loop to continuously print audio levels
try:
while True:
# Read audio data from the microphone
_, data = inp.read()
# Convert byte data to 16-bit integer format. Have tried with and without this and get the same result.
samples = struct.unpack('<' + ('h' * (len(data) // 2)), data)
# Calculate the peak audio level in decibels
peak_amplitude = max(map(abs, samples))
# Convert amplitude to decibels
decibels = 20 * math.log10(peak_amplitude / 32767) # Assuming 16-bit audio
print(f"Decibels: {decibels:.2f} dB")
except KeyboardInterrupt:
print("Stopping the script.")
根据@fdcpp 的评论,这似乎效果很好。
import alsaaudio
import audioop
import math
# Set the audio parameters
device = 'default'
sample_rate = 44100 # 44.1 kHz
# Open the audio input stream
inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NORMAL, device, channels=1, rate=sample_rate, format=alsaaudio.PCM_FORMAT_S16_LE, periodsize=1024)
# Main loop to continuously print audio levels
try:
while True:
# Read audio data from the microphone
_, data = inp.read()
# Calculate the peak audio level in decibels
peak_amplitude = audioop.max(data, 2)
# Convert amplitude to decibels
decibels = 20 * math.log10(peak_amplitude) # Assuming 16-bit audio
print(f"Decibels: {decibels:.2f} dB")
except KeyboardInterrupt:
print("Stopping the script.")