我对微控制器游戏还很陌生。最近,我尝试通过模拟驻极体麦克风在
Raspberry Pi Pico
上录制音频。因此,我为麦克风构建了一个(工作良好)前置放大器,并通过 ADC 引脚将其连接,稍后将详细解释。
现在我只想使用 micropython 将其作为
.wav
文件存储在内部闪存上。目前,这个 micropython 代码似乎是主要问题,因为它生成了一个 .wav
文件,其中只包含白噪声。
到目前为止我所做的是以下...
(1)搭建驻极体麦克风的MCU接口前置放大器
我在 microchip.com 上发现了一款有用的前置放大器,它采用 MCP6001 运算放大器。绘图如下所示:
使用此前置放大器进行的测试效果非常好。使用两节 AA 电池作为电源,我用万用表测量电源电压
V_DD = 2.620(1)V
和输出偏置电压 V_out0 = 1.310(1)V
。当我对着麦克风吹口哨时,峰峰值信号是用示波器测量的。信噪比 (SNR) 相当不错,如下所示:然后我将前置放大器与通过 USB 供电的 Pico 的 Pico 引脚
V_out ~ 0.2-0.3V
和
ADC_VREF (GPIO 35)
连接起来。前置放大器输出尚未连接到 Pico,如 所示。现在我得到了电源电压 AGND (GPIO 31)
和输出偏置电压 V_DD = 3.2(1)V
,与电池版本相比,它的稳定性要差得多,但 SNR 应该足够高,可以录制一些我认为的音频:(2) 在 Pico / Micropython shell 上从 ADC 采样当我现在将前置放大器输出连接到
V_0 = 1.58(10)V
并在 Thonny micropython shell 中运行以下代码时
ADC0 (GPIO 31 == Pin 26)
考虑到具有最大值的 16 位 ADC,我得到了一些合理的读数值
>>> from machine import Pin, ADC
>>> mic = ADC(Pin(26))
>>> mic.read_u16()
32551
>>> mic.read_u16()
31911
>>> mic.read_u16()
31815
。
(3) 在 Pico / Micropython 主代码上将样本保存到 .wav 文件中然后,我编写了一段代码来创建
2^16=65536
标头并将其写入 Pico 闪存中的
.wav
(基于 Mike Teachman 的 I2S 示例),将二进制样本读入缓冲区并通过该缓冲附加
test.wav
价值观。test.wav
我知道运行 micropython 固件会占用大量资源,并且由于时序问题,声音应该会很不稳定(找到了一些使用 C++ 和 DMA 来防止这种情况的建议)。不过,我希望至少能在
from machine import Pin
import time
micPin = machine.ADC(Pin(26))
FILE_NAME = 'test17.wav'
sampleRate = 44100 # 44.1 kHz - CD quality
bitsPerSample = 16
num_channels = 1 # 1 - MONO, 2 - STEREO
duration = 3 # in seconds
bufferSize = duration * sampleRate # 1/s * s
num_samples = bufferSize
def create_wav_header(sampleRate, bitsPerSample, num_channels, num_samples):
datasize = num_samples * num_channels * bitsPerSample // 8
o = bytes("RIFF", "ascii") # 1-4 (4byte) Marks file as RIFF
o += (datasize + 36).to_bytes(
4, "little"
) # 5-8 (4byte) File size in bytes excluding this and RIFF marker
o += bytes("WAVE", "ascii") # 9-12 (4bytes) File type
o += bytes("fmt ", "ascii") # 13-16 (4bytes) Format Chunk Marker, trailing 0
o += (16).to_bytes(4, "little") # 17-20 (4bytes) Length of above format data
o += (1).to_bytes(2, "little") # 21-22 (2bytes) Format type (1 - PCM)
o += (num_channels).to_bytes(2, "little") # 23-24 (2bytes)
o += (sampleRate).to_bytes(4, "little") # 25-28 (4bytes)
o += (sampleRate * num_channels * bitsPerSample // 8).to_bytes(4, "little") # 29-32 (4bytes)
o += (num_channels * bitsPerSample // 8).to_bytes(2, "little") # 33-34 (2bytes)
o += (bitsPerSample).to_bytes(2, "little") # 35-36 (2bytes)
o += bytes("data", "ascii") # 37-40 (4bytes) Data Chunk Marker
o += (datasize).to_bytes(4, "little") # 41-44 (4bytes) Data size in bytes
return o
try:
with open('/'+FILE_NAME, 'wb') as recFile:
wav_header = create_wav_header(
sampleRate,
bitsPerSample,
num_channels,
num_samples
)
recFile.write(wav_header)
with open('/'+FILE_NAME, 'ab') as recFile:
buffer = bytearray(bufferSize)
for i in range(bufferSize):
buffer[i] = micPin.read_u16()
# print(buffer[i])
time.sleep(1/sampleRate)
recFile.write(buffer)
except (KeyboardInterrupt, Exception) as e:
print("caught exception {} {}".format(type(e).__name__, e))
中听到一些东西,但我发现的只是白噪音......
.wav
显示类似的内容
hexdump -C test.wav
(摘录)
此外,当我取消注释
00000000 52 49 46 46 bc 09 04 00 57 41 56 45 66 6d 74 20 |RIFF....WAVEfmt |
00000010 10 00 00 00 01 00 01 00 44 ac 00 00 88 58 01 00 |........D....X..|
00000020 02 00 10 00 64 61 74 61 98 09 04 00 a8 88 88 f8 |....data........|
00000030 c8 28 18 98 88 98 d8 18 28 38 d8 b8 c8 88 a8 08 |.(......(8......|
00000040 e8 38 78 98 b8 c8 e8 08 18 28 18 c8 b8 58 38 e8 |.8x......(...X8.|
00000050 58 38 48 18 48 88 d8 38 b8 f8 08 28 28 58 68 88 |X8H.H..8...((Xh.|
00000060 a8 88 58 98 a8 a8 88 08 08 28 58 68 68 58 68 98 |..X......(XhhXh.|
00000070 88 c8 e8 e8 08 38 48 38 28 28 18 68 18 28 38 48 |.....8H8((.h.(8H|
00000080 58 68 88 98 88 68 58 48 38 18 28 38 e8 e8 08 48 |Xh...hXH8.(8...H|
00000090 98 c8 e8 28 18 58 08 48 28 08 68 a8 c8 b8 d8 e8 |...(.X.H(.h.....|
000000a0 18 08 f8 e8 b8 e8 e8 38 88 78 88 58 e8 68 e8 28 |.......8.x.X.h.(|
000000b0 28 48 38 48 88 c8 08 08 28 58 d8 18 48 88 a8 98 |(H8H....(X..H...|
000000c0 b8 a8 c8 a8 b8 b8 b8 d8 d8 18 28 f8 08 28 18 28 |..........(..(.(|
循环中的
print(buffer[i])
命令时,会出现如下所示的值:
for
这些解释了白噪声。但我不明白为什么 84
8
88
200
184
152
似乎在这里失败,而它在 shell 中工作......关于我做错了什么和/或如何改进这个项目有什么想法吗?
提前谢谢您!
祝一切顺利, 修补匠Toadie
您尝试将 16 位数字存储到一个字节中,即 8 位:
micPin.read_u16()
当然,样本的前 8 位将被截掉,留下低 8 位,这绝对不是您想要的。更适合缓冲区的数据类型是带有类型代码
buffer = bytearray(bufferSize)
...
buffer[i] = micPin.read_u16()
array。
此外,为了帮助排除故障,您不应尝试在文件中记录真实的 ADC 读数。只需生成一个正弦波,这样我们就可以确保您的文件系统和 WAV 编码核心正在工作,然后您再担心尝试将真正的麦克风硬件集成到系统中。我通常预计 MicroPython 的垃圾收集器和缓慢的速度会让这个项目无法完成。