Skip to content

Commit

Permalink
Add sounddevice support
Browse files Browse the repository at this point in the history
  • Loading branch information
ptsmonteiro committed Jan 10, 2024
1 parent 2925bec commit feb9924
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 5 deletions.
6 changes: 5 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,15 @@ For validation, run::
optional arguments:
-h, --help show this help message and exit

`python-sounddevice <https://python-sounddevice.readthedocs.io>` is used by default as the audio library.
This should work out-of-the box on Linux, Windows and macOS, however, other choices are available.

On, Windows you may download the `portaudio` library from `MinGW <https://packages.msys2.org/base/mingw-w64-portaudio>`_.
Then, you should specify the DLL using the following command-line flag::

-l AUDIO_LIBRARY, --audio-library AUDIO_LIBRARY
File name of PortAudio shared library.

The AUDIO_LIBRARY can be 'alsa', 'sd' (the default) or the file name for the PortAudio shared library.


Calibration
Expand Down
10 changes: 7 additions & 3 deletions amodem/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,9 @@ def create_parser(description, interface_factory):
for sub in subparsers.choices.values():
sub.add_argument('-c', '--calibrate', nargs='?', default=False,
metavar='SYSTEM', help=calibration_help)
sub.add_argument('-l', '--audio-library', default='libportaudio.so',
help='File name of PortAudio shared library.')
sub.add_argument('-l', '--audio-library', default='sd',
help="'alsa', 'sd' or file name of "
"PortAudio shared library")
sub.add_argument('-z', '--zlib', default=False, action='store_true',
help='Use zlib to compress/decompress data.')
g = sub.add_mutually_exclusive_group()
Expand Down Expand Up @@ -234,9 +235,12 @@ def interface_factory():
import pylab # pylint: disable=import-error,import-outside-toplevel
args.pylab = pylab

if args.audio_library == 'ALSA':
if args.audio_library == 'alsa':
from . import alsa # pylint: disable=import-outside-toplevel
interface = alsa.Interface(config)
elif args.audio_library == 'sd':
from . import sd # pylint: disable=import-outside-toplevel
interface = sd.Interface(config)
elif args.audio_library == '-':
interface = _Dummy() # manually disable PortAudio
elif args.command == 'send' and args.output is not None:
Expand Down
69 changes: 69 additions & 0 deletions amodem/sd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""
Code which adds sounddevice lib support for interfaces, recording and playing.
"""

import logging
import sounddevice as sd

log = logging.getLogger(__name__)


class Interface:

def __init__(self, config):
self.config = config
bits_per_sample = config.bits_per_sample
assert bits_per_sample == 16

def __enter__(self):
return self

def __exit__(self, *args):
pass

def recorder(self):
return Recorder(self)

def player(self):
return Player(self)


class Recorder:
def __init__(self, lib):
self.bufsize = 4096

self.audio_stream = sd.RawInputStream(
samplerate=lib.config.Fs,
blocksize=self.bufsize,
channels=1, dtype='int16')
self.audio_stream.start()

def read(self, size):
data, overflowed = self.audio_stream.read(size)
if overflowed:
raise OverflowError("Overflow reading from audio device")
return data

def close(self):
self.audio_stream.stop()
self.audio_stream.close()


class Player:
def __init__(self, lib):
self.buffer_length_ms = 10
self.buffer_size = int(lib.config.Fs * (self.buffer_length_ms / 1000))

self.audio_stream = sd.RawOutputStream(
samplerate=lib.config.Fs,
blocksize=self.buffer_size,
channels=1, dtype='int16')

self.audio_stream.start()

def write(self, data):
self.audio_stream.write(data)

def close(self):
self.audio_stream.stop()
self.audio_stream.close()
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def run_tests(self):
packages=['amodem'],
tests_require=['pytest'],
cmdclass={'test': PyTest},
install_requires=['numpy'],
install_requires=['numpy','sounddevice'],
platforms=['POSIX'],
classifiers=[
'Development Status :: 5 - Production/Stable',
Expand Down

0 comments on commit feb9924

Please sign in to comment.