### ----------------------------------------------------
### -- Audio::PortAudio
### -- Licenses: Artistic-2.0
### -- Authors: Jonathan Stowe <jns+gh@gellyfish.co.uk>
### -- File: README.md
### ----------------------------------------------------
# Audio::PortAudio

Access to audio input and output devices

![Build Status](https://github.com/Raku-Noise-Gang/Audio-PortAudio/workflows/CI/badge.svg)

## Synopsis

```raku

use Audio::PortAudio;

my $pa = Audio::PortAudio.new;

# get the default stream with no inputs, 2 output channels
# for audio encoded as 32 bit floats at 44100 samplerate
# with a frame buffer of 512;
my $stream = $pa.open-default-stream(0,2,Audio::PortAudio::Float32,44100,512);

$stream.start;

loop {
	# get some audio data in a carray from somewhere
   # frame-count should be no more than the buffer supplied to open
	$stream.write($carray, $frame-count);
}

```

See also [the examples directory](examples)

## Description

This module provides a mechanism to get audio into and out of your
program via a sound card or some other sub-system supported by the
[portaudio](http://www.portaudio.com/), this may include "ALSA", "JACK"
or "OSS" on Linux, "CoreAudio" on Mac and "ASIO" on Windows, (of course
the actual support depends on how the library was built on your system.)

You will need to have the portaudio library installed on your system
to use this, it may be available as a package or come pre-installed,
but the details will be specific to your platform.

The interface is somewhat simplified in comparison to the underlying
library and in particular only "blocking" IO is supported at the current
time (though this does not preclude the use of the callback API in the
future, it's just an interface that is natural to a Raku developer
doesn't suggest itself at the moment.)

It is important to note that the constraints of real-time audio data
handling mean that you have to be careful that you allow for consistent
and timely handing of the data to or from the device for proper results,
you may find that for some applications you will need to avoid the use
of any concurrency whatsoever for instance (the streaming example is
such a case where the time budget was such that any unexpected garbage
collection or other processor stealing activity didn't leave the process
enough time spare to recover and the stream eventually became unusable.)

Also it should be noted that some types of source API ("JACK" in
particular,) require that you use a fixed buffer size that is consistent
with that configured for the host service, unfortunately portaudio doesn't
appear to provide a way of discovering this so you may need to either
check with the source configuration or experiment to find a correct and
working value for buffer sizes.  The symptoms of this may include choppy,
"syncopated" or "phased" output.

This is based on the original work of
[Peschwa](https://github.com/peschwa/Audio-PortAudio) which I forked and
then just completely hijacked when I realised it could be potentially
be made useful :) So most of the credit probably goes to him.

## Installation

This module depends on having the portaudio library installed, your
operating system may offer this is as a package that you can install
with whatever tools the system uses (it may be installed already as it
is quite a common dependency for audio applications,) or you may be able
to obtain and install the source from http://www.portaudio.com/download.html.
If you take the latter route you want to make sure that you install at
least one driver for it to be useful.

If you have *zef* installed you can install this module directly:

    zef install Audio::PortAudio

Or if you have a copy of this source then you can do so from within the
distribution directory:

    zef install .

Depending on what drivers you have installed the tests may cause a lot of
diagnostic output from the drivers themselves, Alsa and Jack seem to be the
worst culprits.

## Support

This probably falls into the 'experimental' category, it is definitely usable
but I will not be surprised if you have difficulty using it because of the
performance constraints alluded to above.  

It is also quite difficult to do automated tests beyond basic sanity checks, as
it would have to be able to "hear" the output or the result of input which may
be beyond our control so the examples stand in as a proxy for proper unit tests.

Anyway if you're still reading and you do have a problem then please provide as
much detail as possible, including the details and configuration of your sound
card and/or host API if possible (e.g. "jack" configuration,)

We'd also be delighted to hear if you don't have problems and have made something
really cool with this, or have patches to improve the interface (in the latter
case a working example that demonstrates that it is usable would be nice,) or
any other suggestions via https://github.com/Raku-Noise-Gang/Audio-PortAudio/issues

We'd be particularly interested in a Raku-ish way of expressing the portaudio
callback API, the native subs support it, it just isn't exposed through the
class API here.

## Licence

This is free software please see the [LICENCE](LICENCE) file in the distribution.

© Peschwa           2015
© Jonathan Stowe    2016
© Raku Noise Gang 2016 - 2021


