1

I want to record the audio being captured by the mic of my laptop and then say after some delay, play it back through the headphones connected to laptop. What I tried is recording the incoming audio in batches of 10 sec as background process & after the 1st audio clip of 10 sec is recorded, start playing it back in the background through the headphones. The problem that I am facing is that when in the end of recording, I combine all the batches of sound clips, some sound samples are lost in the process of stopping one recording & restarting the recording of next incoming sound.

So, is it possible to let the recording continue & after some samples are collected start playing that ongoing recording ? Or is there any other work around to this samples being lost?

DavidS
  • 276
  • 1
  • 17
pypro
  • 447
  • 1
  • 7
  • 13
  • Check SO post over here : http://stackoverflow.com/questions/17711672/simultaneous-record-audio-from-mic-and-play-it-back-with-effect-in-python – Anil_M Oct 18 '16 at 19:35

1 Answers1

0

If you just want record and playback, pyaudio has good basic examples here.

However, if you need to customize delay between record and playback then there are various approaches depending upon complexity and efforts.
One way is to record & save chunks of audio files and play them sequentially after some time delay between recording and playback.

It is possible to save small chunks to objects in memory (although I haven't tried that yet).

The playback and recording can be threaded or spawned to run simultaneously. I attempted multiprocessing, however, since I don't have multi-core CPU it may not be seem to be working. You are welcome to develop it further.

So, as discussed first we record and save chunks of audio files using record_audio function.

import pyaudio
import wave
import time
from multiprocessing import Process

def record_audio(AUDIO_FILE):
    #Create audio stream    
    stream = p.open(format=FORMAT,
                    channels=CHANNELS,
                    rate=RATE,
                    input=True,
                    frames_per_buffer=CHUNK)

    # begin recording
    print"* recording audio clip: ",AUDIO_FILE

    frames = []
    for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
        data = stream.read(CHUNK)
        frames.append(data)

    #print"* done recording audio clip:", AUDIO_FILE

    #cleanup objects
    stream.stop_stream()
    stream.close()

    #save frames to audio clips
    print"* sending data to audio file:", AUDIO_FILE
    wf = wave.open(AUDIO_FILE , 'wb')
    wf.setnchannels(CHANNELS)
    wf.setsampwidth(p.get_sample_size(FORMAT))
    wf.setframerate(RATE)
    wf.writeframes(b''.join(frames))
    wf.close()

Next, we define function to play audio chunks using play_audio function.

def play_audio(AUDIO_FILE):
    #open saved audio clip
    wf2 = wave.open(AUDIO_FILE , 'rb')

    #Introduce  playback delay
    time.sleep(AUDIO_DELAY)


    #Define playback audio stream
    stream2 = p.open(format=p.get_format_from_width(wf2.getsampwidth()),
                channels=wf2.getnchannels(),
                rate=wf2.getframerate(),
                output=True)

    data = wf2.readframes(CHUNK)
    print" *************************** playing back audio file:", AUDIO_FILE
    while data != '':        
        stream2.write(data)
        data = wf2.readframes(CHUNK)

    stream2.stop_stream()
    stream2.close()

    p.terminate()

Then we put two functions together in main and (attempt to ) kick off simultaneously.

if __name__=='__main__':

    CHUNK = 1024
    FORMAT = pyaudio.paInt16
    CHANNELS = 2               #stereo
    RATE = 44100
    RECORD_SECONDS = 5         #record chunks of 5 sec
    TOTAL_RECORD_NUMBER = 5    # total chunks to record and play
    AUDIO_DELAY = 5.0          #playback delay in seconds

    x = 0

    while x < TOTAL_RECORD_NUMBER:

        #define audio file clip
        AUDIO_FILE = "audio{0}.wav".format(x)

        #initialize pyaudio
        p = pyaudio.PyAudio()        

        #Kick off record audio function process
        p1 = Process(target = record_audio(AUDIO_FILE))
        p1.start()

        #kick off play audio function process
        p2 = Process(target = play_audio(AUDIO_FILE))        
        p2.start()

        p1.join()
        p2.join()


        #increment record counter
        x += 1

Output:

Python 2.7.9 (default, Dec 10 2014, 12:24:55) [MSC v.1500 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> ================================ RESTART ================================
>>> 
* recording audio clip:  audio0.wav
* sending data to audio file: audio0.wav
 *************************** playing back audio file: audio0.wav
* recording audio clip:  audio1.wav
* sending data to audio file: audio1.wav
 *************************** playing back audio file: audio1.wav
* recording audio clip:  audio2.wav
* sending data to audio file: audio2.wav
 *************************** playing back audio file: audio2.wav
* recording audio clip:  audio3.wav
* sending data to audio file: audio3.wav
 *************************** playing back audio file: audio3.wav
* recording audio clip:  audio4.wav
* sending data to audio file: audio4.wav
 *************************** playing back audio file: audio4.wav
>>> 

As you can see , the processes did not spawn simultaneously. You may develop it further.

Hope this helps.

Anil_M
  • 10,893
  • 6
  • 47
  • 74