Simultaneous record audio from mic and play it back with effect in python

天涯浪子 提交于 2019-11-30 15:57:30

First, the problem you posed (being able to tile audio samples while automatically removing the quiet space between them) is not one that can be solved with threading. You need to analyze the recorded sound to determine where there is or is not silence, or simply allow the user to specify when recording should end. You can accomplish the latter with a simple loop:

  1. Open audio hardware and start recording.
  2. Create an empty list to store chunks of audio
  3. Request a small chunk of audio data, append to the list
  4. Check user has requested the recording to end. If not, loop back to 3.
  5. When finished, assemble the chunks into a single array for playback.

In this simple example, there is no benefit to using threading.

The method suggested, to record and simultaneously play back, seems like a solution to a different problem, one that is much more complex. In this case, there are two major difficulties:

  1. Not all consumer sound cards are capable of recording and playing simultaneously. Look for cards that claim "full duplex" instead of "half duplex".
  2. Speaking into a microphone and hearing yourself with a short delay is extremely distracting. To make this work properly, the recorded audio must be processed and sent back to the sound card in less than about 20 ms. At 44.1 kHz, this means you should be reading fewer than 880 frames per loop-cycle, and if the processing can't keep up, you will have gaps in the output. This is a surprisingly difficult problem unless you have specialized software to help. If you really want to go this way, you might look at Jack (http://jackaudio.org/), which provides low-latency audio access on most platforms and has an easy python library as well (http://sourceforge.net/projects/py-jack/). Threading will probably not be helpful in this type of program.
Jacob

To expand on Luke's answer:

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

In your code is where you commit to a certain time of recording. If you wrote a function "isSilent" that can determine if a chunk is silent, your code might change to:

while len(frames) <= 0 or not isSilent(frames[-1]):
    data = stream.read(CHUNK)
    frames.append(data)

If "isSilent" is to hard to write or if it is to computationally slow you can wait for user input. KeyboardInterrupt is a first hack to play with this method:

try:
    while true:
        data = stream.read(CHUNK)
        frames.append(data)
except KeyboardInterrupt:
    pass

This is a hack, and not the right way to look for user input in production, but it will let you start experimenting with this. you will want to find or make a stopButtonHasBeenPressed function.

while not stopButtonHasBeenPressed():
    data = stream.read(CHUNK)
    frames.append(data)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!