4

I'm streaming microphone input from my laptop computer using Python. I'm currently using PyAudio and .wav to create a 2 second batches (code below) and then read out the frame representations of the newly created .wav file in a loop.

However I really just want the np.ndarray represented by "signal" in the code that is the Int16 representation of the .wav file. Is there a way to bypass writing to .wav entirely and make my application appear to be "real-time" instead of micro-batch?

import pyaudio
import wave

#AUDIO INPUT
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
CHUNK = 1024
RECORD_SECONDS = 2
WAVE_OUTPUT_FILENAME = "output.wav"

audio = pyaudio.PyAudio()

# start Recording
stream = audio.open(format=FORMAT, channels=CHANNELS,
                rate=RATE, input=True,
                frames_per_buffer=CHUNK)
while(1):
  print "recording"
  frames = []
  for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
      data = stream.read(CHUNK)
      frames.append(data)
  waveFile = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
  waveFile.setnchannels(CHANNELS)
  waveFile.setsampwidth(audio.get_sample_size(FORMAT))
  waveFile.setframerate(RATE)
  waveFile.writeframes(b''.join(frames))
  waveFile.close()
  spf = wave.open(WAVE_OUTPUT_FILENAME,'r')

  #Extract Raw Audio from Wav File
  signal = spf.readframes(-1)
  signal = np.fromstring(signal, 'Int16')   
  copy= signal.copy()

# stop Recording stream.stop_stream() stream.close() audio.terminate()

John Wiseman
  • 3,081
  • 1
  • 22
  • 31
knowads
  • 705
  • 2
  • 7
  • 24

1 Answers1

3

Yes, you can give a callback to the stream variable and do with that audio whatever you would like:

def callback(input_data, frame_count, time_info, flags):
    ...

    return input_data, pyaudio.paContinue

stream = audio.open(format=FORMAT,
                    channels=CHANNELS,
                    rate=RATE,
                    input=True,
                    stream_callback=callback,
                    frames_per_buffer=CHUNK)

More here.

  • It looks like the callback runs whenever data is available? What exactly is input_data in regards to audio.open? Is it equivalent to stream.read()? – knowads Nov 08 '17 at 21:38
  • 1
    It looks like it's an np.int16. One can use `np.fromstring(input_data, dtype=np.int16)` to read it –  Nov 08 '17 at 21:40
  • 1
    More generally, I believe it's based off of the `FORMAT` passed to `audio.open`. It will be the equivalent numpy format for that data type. –  Nov 08 '17 at 21:42
  • 1
    But what does it replace in my implementation? If I took your example and had it run the stream for RECORD_SECONDS is equivalent to spf.readframes()? – knowads Nov 08 '17 at 22:13