0

I want to create a speech jammer. It is essentially something that repeats back to you what you just said, but it is continuous. I was trying to use the sounddevice library and record what I am saying while also playing it back. Then I changed it to originally record what I was saying, then play it back while also recording something new. However it is not functioning as I would like it. Any suggestions for other libraries? Or if someone sees a suggestion for the code I already have.

Instead of constantly playing back to me, it is starting and stopping. It does this at intervals of the duration specified. So it will record for 500 ms, then play that back for 500 ms and then start recording again. Wanted behavior would be - recording for 500ms while playing back the audio it is recording at some ms delay.

import sounddevice as sd
import numpy as np

fs = 44100
sd.default.samplerate = fs
sd.default.channels = 2
#the above is to avoid having to specify arguments in every function call
duration = .5

myarray = sd.rec(int(duration*fs))
while(True):
    sd.wait()
    myarray = sd.playrec(myarray)
    sd.wait()
Mataan P
  • 117
  • 1
  • 8
  • can you clarify "its not functioning as i would like it" - really hard to suggest anything when we have no idea whats wrong – murksiuke Mar 06 '19 at 19:55
  • Right, instead of constantly playing back to me, it is starting and stopping. It does this at intervals of the duration specified. So it will record for 500 ms, then play that back for 500 ms and then start recording again. Wanted behavior would be - recording for 500ms while playing back the audio it is recording at some ms delay. @murksiuke – Mataan P Mar 06 '19 at 20:12

2 Answers2

0

I'm seeing a potential problem here of you trying to use myarray as both the input and the output of the .playrec() function. I would recommend having two arrays, one for recording the live audio, and one for playing back the recorded audio.

Instead of using the .playrec() command, you could just rapidly alternate between the use of .record() and .play() with a small delay between within your while-loop.

For example, the following code should record for one millisecond, wait a millisecond, and then playback the one millisecond of audio:

duration = 0.001

while(True):
    myarray= sd.rec(int(duration*fs))
    sd.wait()
    sd.play(myarray, (int(duration*fs)))

There is no millisecond delay after the playback because you want to go right back to recording the next millisecond straight away. It should be noted, however, that this does not keep a recording of your audio for more than one millisecond! You would have to add your own code that adds to the array of a specified size and fills it up over time.

ConcernedHobbit
  • 764
  • 1
  • 8
  • 17
  • Please note that `sd.rec()` will internally call `sd.stop()`, which will stop the previous playback. And even if it would work, there would still be audible gaps. See my answer for alternatives. – Matthias Mar 07 '19 at 08:03
  • Thanks for the feedback - you clearly have more experience with the module! – ConcernedHobbit Mar 07 '19 at 15:21
0

Paraphrasing my own answer from https://stackoverflow.com/a/54569667:

The functions sd.play(), sd.rec() and sd.playrec() are not meant to be used repeatedly in rapid succession. Internally, they each time create an sd.OutputStream, sd.InputStream or sd.Stream (respectively), play/record the audio data and close the stream again. Because of opening and closing the stream, gaps will occur. This is expected.

For continuous playback you can use the so-called "blocking mode" by creating a single stream and calling the read() and/or write() methods on it.

Or, what I normally prefer, you can use the so-called "non-blocking mode" by creating a custom "callback" function and passing it to the stream on creation. In this callback function, you can e.g. write the input data to a queue.Queue and read the output data from the same queue. By filling the queue by a certain amount of zeros beforehand, you can specify how long the delay between input and output shall be.

You can have a look at the examples to see how callback functions and queues are used.

Let me know if you need more help, then I can try to come up with a concrete code example.

Matthias
  • 4,524
  • 2
  • 31
  • 50