-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Simple audio record example #80
Comments
The most basic approach would be to gather the incoming blocks into an internal large numpy array. From there you could save this data in whatever format you want. This simple approach is probably not a good idea for recordings of really meaningful lengths. You'd have to find a solution to continuously write data on disk during run-time. The Otherwise, on OSX (and probably Linux) I can really recommend ecasound to record and playback an arbitrary number of channels from any JACK client. I believe you'd have to compile it yourself to get JACK support, although that was very painless if I remember correctly. |
Yes please, that would be great! As @HaHeho mentioned, the play_file.py example could be a good starting point. You can also have a look at this example using the |
Hi, don't you have any further clues? I am trying to record about 2 seconds of audio, so I could probably use the "direct" method @HaHeho mentioned, but how exactly could I collect the incoming data? Sorry for this question, but I am a newbie in this area. |
@vyhyb If you know exactly how long the recording is supposed to be, and if the size of the recording easily fits into the available RAM, you can create a NumPy array of the appropriate size and shape (e.g. with Then (after activating the client), in the process callback you can fill this array block by block. You just have to keep track of the place in the array where the next block of data is supposed to be written to (e.g. with a global variable). Also, you have to be careful at the end of the recording, because the last block of data to be written might be smaller than the block size of the data provided to the process callback.
This is no problem at all! But there are very many ways to do this kind of thing, the best way depends on your exact requirements. The more exactly you can specify your requirements, the more and better targeted help we can provide (hopefully!). |
Thanks for your answer! Now I'll try my best and may return with some more specific questions in the near future. |
So I have an example using
The Period size is already quite big so I think the problem is probably somewhere else.. Any suggestions? The original script: import numpy as np
import queue
import sys
import threading
buffersize = 2
clientname = "ImpedanceTubeTest2"
q = queue.Queue(maxsize=buffersize)
global blocks
blocks = 0
global rec_blocks
event = threading.Event()
def print_error(*args):
print(*args, file=sys.stderr)
def xrun(delay):
print_error("An xrun occured, increase JACK's period size?")
def shutdown(status, reason):
print_error('JACK shutdown!')
print_error('status:', status)
print_error('reason:', reason)
event.set()
def stop_callback(msg=''):
if msg:
print_error(msg)
event.set()
raise jack.CallbackExit
def process(frames):
if frames != blocksize:
stop_callback('blocksize must not be changed, I quit!')
try:
q.put_nowait(client.inports[0].get_array()[:])
except (queue.Full):
print("Full Queue")
stop_callback()
if blocks >= rec_blocks:
stop_callback() # Recording is finished
try:
import jack
import soundfile as sf
client = jack.Client(clientname, no_start_server=True)
blocksize = client.blocksize
samplerate = client.samplerate
rec_blocks = 1000
client.set_xrun_callback(xrun)
client.set_shutdown_callback(shutdown)
client.set_process_callback(process)
sf.SoundFile('pok_rec.wav', mode='w', samplerate=samplerate, channels=1)
with sf.SoundFile('pok_rec.wav', mode = 'r+') as f:
client.inports.register('in_1')
with client:
target_ports = client.get_ports(
is_physical=True, is_output=True, is_audio=True)
client.inports[0].connect(target_ports[0])
timeout = blocksize * buffersize / samplerate
f.write(q.get(timeout=timeout))
for i in range(rec_blocks):
f.seek(0,sf.SEEK_END)
f.write(q.get(timeout=timeout))
blocks += 1
event.wait() # # # Wait until recording is finished
except (queue.Empty):
# A timeout occured, i.e. there was an error in the callback
print("Empty Queue") Update: Now it works almost every time with the code above, but sometimes there is still the problem with
Is it caused by hardware or is it just a Python thing? I am using a regular Kubuntu 20.10 on laptop and Steinberg UR22 sound card. |
Sorry, I don't know ... Does the error occur with other examples as well? Did you try to set the The code looks fine except for two little things which are most likely unrelated:
|
Thank you for your response. The error seems to be related only to my code or maybe to the debug mode of VSCode, it is probably not related to the Python module. Now it works again just fine.
I did and it seems to be more stable.
I did not know, how to make every time a new file and then fill it with data. The This is the final code: import numpy as np
import queue
import sys
import threading
buffersize = 3
clientname = "RecTest"
rec_time = 10
q = queue.Queue(maxsize=buffersize)
global rec_end
rec_end = False
event = threading.Event()
def print_error(*args):
print(*args, file=sys.stderr)
def xrun(delay):
print_error("An xrun occured, increase JACK's period size?")
def shutdown(status, reason):
print_error('JACK shutdown!')
print_error('status:', status)
print_error('reason:', reason)
event.set()
def stop_callback(msg=''):
if msg:
print_error(msg)
event.set()
raise jack.CallbackExit
def process(frames):
if frames != blocksize:
stop_callback('blocksize must not be changed, I quit!')
if rec_end:
stop_callback() # Recording is finished
try:
q.put_nowait(client.inports[0].get_array()[:])
except (queue.Full):
print("Full Queue")
stop_callback()
try:
import jack
import soundfile as sf
client = jack.Client(clientname, no_start_server=True)
blocksize = client.blocksize
samplerate = client.samplerate
rec_blocks = int(rec_time * samplerate / blocksize)
client.set_xrun_callback(xrun)
client.set_shutdown_callback(shutdown)
client.set_process_callback(process)
with sf.SoundFile('pok_rec.wav', mode = 'w+', samplerate=samplerate, channels=1) as f:
client.inports.register('in_1')
with client:
target_ports = client.get_ports(
is_physical=True, is_output=True, is_audio=True)
client.inports[0].connect(target_ports[0])
timeout = blocksize * buffersize / samplerate
f.write(q.get(timeout=timeout))
for i in range(rec_blocks):
f.write(q.get(timeout=timeout))
rec_end = True
event.wait() # # # Wait until recording is finished
except (queue.Empty):
# A timeout occured, i.e. there was an error in the callback
print("Empty Queue") |
Are there still any open questions in this issue? Any further comments? If not, I think we can close this. |
All questions resolved, thank you :). |
It would be great if someone could add an example of recording audio to the examples in the documentation. If I figure it out I will try to add it. Thanks for the great library!
The text was updated successfully, but these errors were encountered: