1

This is my first post so I will try to format it logically. I am creating a live (real-time) audio modulation code in Python primarily using PyAudio.

First, I store small chunks of the audio in format pyaudio.paInt16 . Later in the code, I will modulate the audio which I know how to do to an Int array, but not a byte array. Although I set the format to pa.Int16, the variable x holds a byte array that generally looks like this:

\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1e\x00 \x00"\x00#\x00&\x00)\x00*\x00,\x00*\x00)\x00&\x00!\x00\x1e\x00\x1c\x00\x1c\x00\x1c\x00\x1e\x00\x1d\x00\x1e\x00!\x00 \x00!\x00!\x00!\x00 \x00\x1e\x00\x19\x00\x16\x00\x14\x00\x13\x00\x14\x00\x13\x00\x14\x00\x11\x00\x11\x00\x11\x00\x13\x00\x13\x00\x11\x00\x11\x00\x10\x00\x0f\x00\x10\x00\x11\x00\x0f\x00\x0c\x00\x0c\x00\x0b\x00\x08\x00\x06\x00\x02\x00\x00\x00\xfe\xff\xfe\xff\xfb\xff\xf8\xff\xf8\xff\xf8\xff\xfa\xff\xfb\xff\xff\xff\xff\xff\xff\xff\x01\x00\x00\x00\x02\x00\x03\x00\x02\x00\x04\x00\x04\x00\x04\x00\x02\x00\x03\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x02\x00\x02\x00\x04\x00\x02\x00\xfd\xff\xfb\xff\xf7\xff\xf4\xff\xf4\xff\xef\xff\xec\xff\xea\xff\xe6\xff\xe3\xff\xde\xff\xdc\xff\xd9\xff\xd4\xff\xd0\xff\xcb\xff\xc8\

I then convert the byte array to an integer version using a for loop. The for loop does not declare whether they are int, pyaudio, or numpy.ndarrays, but they come out as an ndarray. At first, I tried to run the for loop like this:

for thenew in range(0,CHUNK - 1):
xx[thenew] = x[thenew]  

but I realized that since the byte array was storing each integer as 2 bytes (Int16), it was missing out on some data. Now, I'm doing it like this:

for thenew in range(0,CHUNK - 1):
xx[thenew] = x[thenew*2  ]  

whereas the most significant byte is stored and converted to an integer, and each integer lines up with just the most significant byte that composes it. The values in the int array seem to line up with the hex values from the byte array. Finally as proof of concept for the rest of the code, I try to convert back into a byte array that pyaudio.write() can sound out loud. However, when I check the values output by:

np.ndarray.tobytes(xx)

the new byte array tends to be almost entirely composed of zeros, regardless of the integers in the array xx, and the write function outputs a loud crackling sound.

Please let me know if I can provide any more information to help solve this, it's been driving me a little crazy! :( Thank you for your help in advance!

CHUNK = 1024  # number of audio samples per frame (1024 samples/ chunk)
FORMAT = pyaudio.paInt16

CHANNELS = 1

RATE = 44100

p = pyaudio.PyAudio()

stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, output=True, frames_per_buffer=CHUNK)



while True:

for b in range(0,5): #THIS IS RUN SO THAT X STORES VALUES (0's AT FIRST WHEN STREAM.READ IS CALLED)
    x = stream.read(CHUNK, exception_on_overflow=False)

x = stream.read(CHUNK, exception_on_overflow=False)
xx = np.zeros(CHUNK)

for thenew in range(0,CHUNK - 1):
    xx[thenew] = x[thenew*2  ]  # xx is np array


stream.write(np.ndarray.tobytes(xx))

I’m wondering if the issue has to do with trying to convert ints based on half of Int16 byte data back into Int16s but the Ints in xx are essentially created by Int8 because I’m using every other? Tl;Dr is why is the output of np.ndarray.tobytes(xx) zeros?

frido
  • 13,065
  • 5
  • 42
  • 56
  • This explains how to convert bytes to `int16`: https://nbviewer.jupyter.org/github/mgeier/python-audio/blob/master/audio-files/audio-files-with-wave.ipynb. Alternatively, you could also use https://python-sounddevice.readthedocs.io/, which does the conversion to NumPy arrays for you (full disclosure: I'm the author). – Matthias Feb 23 '19 at 09:59
  • @Matthias Thank you so much! The conversion using this line: ' xx = np.frombuffer(x, dtype = ' – Benjamin Crystal Feb 25 '19 at 16:03

0 Answers0