在 "if" 条件下录制音频会导致静态
Recording audio in "if" condition results in static
我的目标是在按下按钮时录制声音。
第一步实际上是录制音频。以下脚本非常有效:
import alsaaudio, wave, numpy
inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NORMAL, "default:CARD=C525")
inp.setchannels(1)
inp.setrate(44100)
inp.setformat(alsaaudio.PCM_FORMAT_S16_LE)
inp.setperiodsize(1024)
w = wave.open('test.wav', 'w')
w.setnchannels(1)
w.setsampwidth(2)
w.setframerate(44100)
while True:
l, data = inp.read()
a = numpy.fromstring(data, dtype='int16')
print numpy.abs(a).mean()
w.writeframes(data)
test.wav 文件播放得很好,声音正在正确录制。
现在我只想在按下按钮时录制音频。我正在使用带有按钮的 GrovePi。这个按钮很好用。它检测到按钮被按下,它生成 .wav 文件,但它生成的音频文件包含纯静态。
import time
import grovepi
import alsaaudio
import os
import wave
import numpy
button = 4 #grovepi D4
grovepi.pinMode(button,"INPUT")
inputSoundDevice = "default:CARD=C525"
path = os.path.realpath(__file__).rstrip(os.path.basename(__file__))
def start():
print "started"
while True:
if grovepi.digitalRead(button) == 1:
inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NORMAL, inputSoundDevice)
inp.setchannels(1)
inp.setrate(44100)
inp.setformat(alsaaudio.PCM_FORMAT_S16_LE)
inp.setperiodsize(1024)
time.sleep(.5)
print "inp setup"
w = wave.open('test.wav', 'w')
w.setnchannels(1)
w.setsampwidth(2)
w.setframerate(44100)
print "wave setup"
while(grovepi.digitalRead(button) == 1):
l, data = inp.read()
a = numpy.fromstring(data, dtype='int16')
print numpy.abs(a).mean()
w.writeframes(data)
time.sleep(.5)
w.close()
inp = None
print "closed"
start()
任何人都可以指出正确的方向来解决这个问题吗?我想不通这个。
测试中:
这些操作会产生相同的静态音频文件:
- 按下按钮时终止脚本
- 在按下按钮一次后终止脚本
- 按下按钮两次后终止脚本
- 用循环计数器代替按钮按下并记录循环计数是否在 20 到 40 之间,以确保按钮不是问题所在。
numpy 出错
File "buttonWhilePressedLight.py", line 43, in <module>
start()
File "buttonWhilePressedLight.py", line 34, in start
a = numpy.fromstring(data, dtype='int16')
ValueError: string size must be a multiple of element size
"print l" 在循环中用 numpy 注释掉
started
inp setup
wave setup
940
-32
940
-32
940
<-etc,etc,etc->
closed
您调用 read 的速度不够快。 -32
是 unix 错误代码 -EPIPE
.* Alsa docs 表示:
-EPIPE
This error means xrun (underrun for playback or overrun for capture). ... The overrun can happen when an application does not take new captured samples in time from alsa-lib.
因此声音设备生成样本的速度比您使用它们的速度更快。将按钮 digitalRead
添加到您的工作循环中会减慢它的速度。您已将 ALSA 设置为在 44100 samples/second 处生成 1024 个样本块,这意味着您需要调用 read
每 23 毫秒。我会计时一个空循环读取按钮,看看需要多长时间。
根据按钮代码的速度,有几种可能的解决方案。降低采样率肯定会降低你需要调用的频率read
,但也会降低音频质量。增加 periodsize 将填充更大的缓冲区,这意味着您需要减少读取它们的频率。缺点是对按钮按下的响应较差。使用 8 位样本还可以以质量为代价来减少处理负荷。
一个结构性的解决方案是去掉这个循环中的按钮读取,只监视一个事件,你可以在中断处理程序中设置这个事件,或者在监视 I/O 的独立线程中设置。
*顺便说一句,这似乎是 pyalsaaudio documentation 中的一个漏洞,或者是实现中的一个错误。没有提到 read
函数可以 return 错误代码。
我的目标是在按下按钮时录制声音。
第一步实际上是录制音频。以下脚本非常有效:
import alsaaudio, wave, numpy
inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NORMAL, "default:CARD=C525")
inp.setchannels(1)
inp.setrate(44100)
inp.setformat(alsaaudio.PCM_FORMAT_S16_LE)
inp.setperiodsize(1024)
w = wave.open('test.wav', 'w')
w.setnchannels(1)
w.setsampwidth(2)
w.setframerate(44100)
while True:
l, data = inp.read()
a = numpy.fromstring(data, dtype='int16')
print numpy.abs(a).mean()
w.writeframes(data)
test.wav 文件播放得很好,声音正在正确录制。
现在我只想在按下按钮时录制音频。我正在使用带有按钮的 GrovePi。这个按钮很好用。它检测到按钮被按下,它生成 .wav 文件,但它生成的音频文件包含纯静态。
import time
import grovepi
import alsaaudio
import os
import wave
import numpy
button = 4 #grovepi D4
grovepi.pinMode(button,"INPUT")
inputSoundDevice = "default:CARD=C525"
path = os.path.realpath(__file__).rstrip(os.path.basename(__file__))
def start():
print "started"
while True:
if grovepi.digitalRead(button) == 1:
inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NORMAL, inputSoundDevice)
inp.setchannels(1)
inp.setrate(44100)
inp.setformat(alsaaudio.PCM_FORMAT_S16_LE)
inp.setperiodsize(1024)
time.sleep(.5)
print "inp setup"
w = wave.open('test.wav', 'w')
w.setnchannels(1)
w.setsampwidth(2)
w.setframerate(44100)
print "wave setup"
while(grovepi.digitalRead(button) == 1):
l, data = inp.read()
a = numpy.fromstring(data, dtype='int16')
print numpy.abs(a).mean()
w.writeframes(data)
time.sleep(.5)
w.close()
inp = None
print "closed"
start()
任何人都可以指出正确的方向来解决这个问题吗?我想不通这个。
测试中: 这些操作会产生相同的静态音频文件:
- 按下按钮时终止脚本
- 在按下按钮一次后终止脚本
- 按下按钮两次后终止脚本
- 用循环计数器代替按钮按下并记录循环计数是否在 20 到 40 之间,以确保按钮不是问题所在。
numpy 出错
File "buttonWhilePressedLight.py", line 43, in <module>
start()
File "buttonWhilePressedLight.py", line 34, in start
a = numpy.fromstring(data, dtype='int16')
ValueError: string size must be a multiple of element size
"print l" 在循环中用 numpy 注释掉
started
inp setup
wave setup
940
-32
940
-32
940
<-etc,etc,etc->
closed
您调用 read 的速度不够快。 -32
是 unix 错误代码 -EPIPE
.* Alsa docs 表示:
-EPIPE
This error means xrun (underrun for playback or overrun for capture). ... The overrun can happen when an application does not take new captured samples in time from alsa-lib.
因此声音设备生成样本的速度比您使用它们的速度更快。将按钮 digitalRead
添加到您的工作循环中会减慢它的速度。您已将 ALSA 设置为在 44100 samples/second 处生成 1024 个样本块,这意味着您需要调用 read
每 23 毫秒。我会计时一个空循环读取按钮,看看需要多长时间。
根据按钮代码的速度,有几种可能的解决方案。降低采样率肯定会降低你需要调用的频率read
,但也会降低音频质量。增加 periodsize 将填充更大的缓冲区,这意味着您需要减少读取它们的频率。缺点是对按钮按下的响应较差。使用 8 位样本还可以以质量为代价来减少处理负荷。
一个结构性的解决方案是去掉这个循环中的按钮读取,只监视一个事件,你可以在中断处理程序中设置这个事件,或者在监视 I/O 的独立线程中设置。
*顺便说一句,这似乎是 pyalsaaudio documentation 中的一个漏洞,或者是实现中的一个错误。没有提到 read
函数可以 return 错误代码。