I have PCM audio signal I’m trying to convert a wave file. The audio signal is from a mono (left channel) INMP441 mic which has a bit depth of 24 bits and a sample rate of 31.25kHz. The raw signal I’m getting is laid out as follows.
Each sample is 32 bits wide, arranged in four 8-bit blocks, MSB first.
block 1: * 1 0 1 1 0 0 1 (msb)
block 2: 1 1 0 1 0 0 1 1
block 3: 0 1 0 1 0 0 0 1
block 4: 1 * * * * * * * (lsb)
where * indicates padding bits.
In the following code, I’m trying to shift everything to the left so that the sampled value fits in 24 bits, and change the endianness from big to little to save as a wave file.
import datetime
import io
import serial
import wave
read_until = datetime.datetime.now() + datetime.timedelta(seconds = 30)
with serial.Serial() as ss, io.BytesIO() as f_raw:
ss.port = 'my_port'
ss.baudrate = 115200
ss.open()
# read from serial (USART) at 115200 baudrate in 256 chunks and write raw bytes
# to an in-mem file for 30 seconds:
while ss.is_open and datetime.datetime.now() < read_until:
ss_bytes = ss.read(256)
if ss_bytes != b"":
f_raw.write(ss_bytes)
f_raw.seek(0)
with wave.open('sound.wav', 'wb') as wav:
wav.setnchannels(1)
wav.setframerate(31250)
wav.setsampwidth(3)
# read 4 bytes at a time from the in-mem file containing raw data
while (raw := f_raw.read(4)):
ba = bytearray(raw)
snd = bytearray(3)
# shift left and align in 3 bytes of data (MSB first)
snd[0] = ((ba[0] << 1) | (ba[1] >> 7))
snd[1] = ((ba[1] << 1) | (ba[2] >> 7))
snd[2] = ((ba[2] << 1) | (ba[3] >> 7))
snd.reverse()
wav.writeframes(snd)
The problem is when I play back the sound file, I hear noises instead of the original sound file. Any ideas as to what I’m doing wrong?