This walks you through installing JACK, connecting a USB sound card, and copying the audio on the input port onto the output port. The result: you will hear what you say played back immediately from the headphones.
sudo pip install setuptools
sudo apt-get install python-dev
sudo apt-get install libffi-dev
sudo pip install cffi
sudo pip install JACK-Client
This assumes you have a USB sound card with one input jack and one output jack. I tested with the "C-Media USB Headphone Set".
In /boot/config.txt, comment out this line:
dtparam=audio-on
In /lib/modprobe.d/aliases.conf, comment out:
snd-usb-audio index=-2
I used this script taken directly from the JACK audio docs (https://jackclient-python.readthedocs.io/en/0.4.1/)
#!/usr/bin/env python3
"""Create a JACK client that copies input audio directly to the outputs.
This is somewhat modeled after the "thru_client.c" example of JACK 2:
http://github.com/jackaudio/jack2/blob/master/example-clients/thru_client.c
If you have a microphone and loudspeakers connected, this might cause an
acoustical feedback!
"""
import sys
import signal
import os
import jack
import threading
if sys.version_info < (3, 0):
# In Python 2.x, event.wait() cannot be interrupted with Ctrl+C.
# Therefore, we disable the whole KeyboardInterrupt mechanism.
# This will not close the JACK client properly, but at least we can
# use Ctrl+C.
signal.signal(signal.SIGINT, signal.SIG_DFL)
else:
# If you use Python 3.x, everything is fine.
pass
argv = iter(sys.argv)
# By default, use script name without extension as client name:
defaultclientname = os.path.splitext(os.path.basename(next(argv)))[0]
clientname = next(argv, defaultclientname)
servername = next(argv, None)
print "server name";
print servername;
client = jack.Client(clientname, servername=servername)
if client.status.server_started:
print("JACK server started")
if client.status.name_not_unique:
print("unique name {0!r} assigned".format(client.name))
event = threading.Event()
@client.set_process_callback
def process(frames):
print "processing frames"
assert len(client.inports) == len(client.outports)
assert frames == client.blocksize
for i, o in zip(client.inports, client.outports):
o.get_buffer()[:] = i.get_buffer()
@client.set_shutdown_callback
def shutdown(status, reason):
print("JACK shutdown!")
print("status:", status)
print("reason:", reason)
event.set()
# create two port pairs (Eric says: stereo sound?)
for number in 1, 2:
client.inports.register("input_{0}".format(number))
client.outports.register("output_{0}".format(number))
# Eric says: trying with a single input and a single output
# This results in only one side of the audio being heard
#client.inports.register("input_1")
#client.outports.register("output_1")
with client:
# When entering this with-statement, client.activate() is called.
# This tells the JACK server that we are ready to roll.
# Our process() callback will start running now.
# Connect the ports. You can't do this before the client is activated,
# because we can't make connections to clients that aren't running.
# Note the confusing (but necessary) orientation of the driver backend
# ports: playback ports are "input" to the backend, and capture ports
# are "output" from it.
capture = client.get_ports(is_physical=True, is_output=True)
if not capture:
raise RuntimeError("No physical capture ports")
for src, dest in zip(capture, client.inports):
client.connect(src, dest)
playback = client.get_ports(is_physical=True, is_input=True)
if not playback:
raise RuntimeError("No physical playback ports")
for src, dest in zip(client.outports, playback):
client.connect(src, dest)
print("Press Ctrl+C to stop")
try:
event.wait()
except KeyboardInterrupt:
print("\nInterrupted by user")
# When the above with-statement is left (either because the end of the
# code block is reached, or because an exception was raised inside),
# client.deactivate() and client.close() are called automatically.
Run the script, and what you say will be played back in the headphones. Enjoy!