The library which implements all the routines necessary for loudspeaker beamforming on a computer.
To run and playback processed signals, the minimum you need is a laptop and some standalone speakers. However, to really experience beamforming you need a beamforming array and way to physically output to more than just one audio channel simultaneously. It is recomended to use something like this paired with a USB hub to drive a large amount of speakers.
You need some version of Python 3 to use PyBeam, preferably Python 3.6 or higher. Moreover, PyBeam also has a dependancy on some Python libraries found here.
To install PyBeam, you can run the following commands:
$ git clone https://github.com/smtm1209/PyBeam.git
$ pip install -r ./PyBeam/requirements.txt
Until PyBeam becomes a proper module, add these lines towards the top of any file that need to use PyBeam's routines.
import sys
import os
sys.path.insert(0, os.path.abspath('path/to/PyBeam/'))
import pybeamInitialization entails creating a speaker mapping. This process entails identifying which PyAudio output stream index corresponds to which physical speaker pair in your beamforming array. A sample routine designed around the speakers mentioned above is here. In order to gain insight into the streams present on your computer, consider looking at this simple script.
The first step in processing an audio signal is to initialize a source point matrix and a verification point matrix using pybeam.get_source_matrix and pybeam.get_verification_matrix, following the scheme below as an example.
In this diagram, there are 16 source points centered at the origin in a line parallel to the x-axis. The sources are space out at a distance of two centimeters. There are also 37 verification points, all at a radius of 3 meters from the origin, with five degrees between each point. The point in the very center is the bright point, or the point where the signal will be beamformed to. The code generate this scheme is here.
# source matrix creation
Y = pybeam.get_source_matrix(dim=(16, 1), delta=(0.02, 0))
# verification matrix creation
X = pybeam.get_verification_matrix(R=3, dim=(37, 1), b=(90, 90))The next step is to load the .wav file that we want to process using pybeam.read_wav_file.
signal, samp_freq, dtype = pybeam.read_wav_file('path/to/wav/file.wav')From here, we're able to generate the filters we will use to process the data. PyBeam has two routines for this sort of computation: pybeam.get_DAS_filters and pybeam.get_PM_filters. These two functions have the same type of output, and only really differ in the algorithm used to come to that result, delay and sum and pressure matching, respectively. Those algorithms, and the more theoretical components of this project, are detailed here.
To calculate the filters with pressure matching, you would use this code.
Q = pybeam.get_PM_filters(X=X, Y=Y,
E_max=pybeam.get_max_energy(Y=Y, sigma=25, R=3),
p_hat=pybeam.get_target_sound_pressures(X=X, onval=1, offval=0),
samp_freq=samp_freq, samples=1024, modeling_delay=0, verbose=False)On the other hand, to calculate the filters with delay and sum, use this code.
Q = pybeam.get_DAS_filters(X=X, Y=Y,
samp_freq=samp_freq, samples=1024, modeling_delay=0)The next step is to map the filters we just calculated onto the signal from the .wav file we read in earlier. To do this, we use the pybeam.map_filters function. The code to use this function is here.
output = pybeam.map_filters(Q, signal)The final step is writing the output as a directory of .wav files with a mapping pickle file so that it can be played back later. This functionality is contained in the pybeam.write_wav_dir function. Here's some sample code for interfacing with this function.
mapping = pkl.load(open('path/to/mastermap.pkl', 'rb'))
pybeam.write_wav_dir('path/to/output_directory', output, mapping, samp_freq)To playback, all you have to do is invoke the pybeam.playback_wav_dir function.
pybeam.playback_wav_dir('path/to/output_directory') A powerful feature of PyBeam is the ability to generate visualizations using a built-in function. Visualizations can be generated using the pybeam.visualize function.
This code, using filters generated by pybeam.get_PM_filters...
pybeam.visualize(Q, X, Y,
onval=1, R=3, test_index=40, dpu=60,
sample_size=1024, rate=samp_freq, verbose=False)...generates this plot using matplotlib.
On the other hand, using filters generated by pybeam.get_DAS_filters and simply substituting Q in the above function call, this plot is generated.


