Skip to content

woolgathering/dbap

Repository files navigation

DBAP Build Status AppVeyor Build

Author: Jacob Sundstrom

Distance-based ampltide panning (DBAP). Based on the paper by Trond Lossius, Pascal Baltazar, and Théo de la Hogue with some significant changes described below.

There are bound to be some bugs lying dormant and the algorithm itself could use some serious tweaking as it requires some serious optimization for a given set up. As written, though, it is a faithful implementation of the original algorithm with the exceptions outlined below.

Changes

This version differs from the version of DBAP put forward by Lossius et al. primarily in the way the gains are calculated for sources outside the "convex hull". In Lossius 2.6, the issue of sources outside the field of speakers is presented. As a source moves further and further away, the difference between the gains for each speaker is reduced, thus causing the source to lose its perceived spatial properties. To counteract this, Lossius suggests projecting the source that is outside the field onto the convex hull of the loudspeaker field and to use this projected point in subsequent calculations of gain. Doing so would likewise give the distance from the source to the speaker field and thus allow the amplitudes to be scaled as a function of the distance from the hull. The projection provides sufficient biasing of the gains to maintain the spatial illusion.

In cases where the projection is orthogonal to the perimeter of the convex hull, this works adequately. However, when a projection is not orthogonal, as in the case of the area beyond the vertices of the convex hull where the projection is one of the vertices, this method fails to provide a unique solution. In particular, all spatial differentiation is lost when different sources share the same projection onto the same vertex. This is the case for all points in the shaded areas below.

shaded

Example

Take the example above of a set of speakers where the convex hull is a square with vertices $l_{0}$, $l_{1}$, $l_{2}$, and $l_{3}$ at (-10,10), (10,10), (10,-10), and (-10,-10), respectively. Given a source, $s_{0}$, at (-20,1), the nearest point on the convex hull is (-10,1) on the segment $\overleftrightarrow{l_{0}l_{3}}$. The segments used for gain calculation are plotted in red. Note further that this projection is orthogonal to the segment and thus provides no problems using the method suggested by Lossius.

Figure

Consider now two sources, $s_{1}$ at (-20,20) and $s_{2}$ at (-13.21, 23.77). The projection onto the convex hull for both of these points is $l_{0}$, (-10,10), and these projections are not orthogonal. Note further that both of these sources are also equidistant from $l_{0}$ with distance $d = 14.14$. Using the method suggested by Lossius, these sources both collapse onto $l_{0}$ and the calculated amplitudes are scaled equally since their distances are identical. The resulting gain calculations then produce the same result and the sources become spatially equivalent though it is clear that, for instance, $d(\overleftrightarrow{s_{1}l_{i}}) \neq d(\overleftrightarrow{s_{2}l_{i}})$ for every $i$ except 0. In the inverse, a given set of gain calculations for a source outside the convex hull does not necessarily yield a unique point and depends only on the distance from the vertex. This problem is exacerbated when the inner angle of the convex hull narrows about a vertex.

Figure 2

This finding further explains the findings of Eckel et al. in their paper "A framework for the choreography of sound" when they write of DBAP: "[W]e discovered that especially the trajectory of moving sounds (as in the example described in section 4.3.2) appears more clearly shaped or ”sharper” [in ADBAP], compared to the unmodified DBAP algorithm." If the implementation was as Lossius suggests, it is no surprise that there was poor spatial differentiation for sources outside the hull.

One Solution

To compensate for this, several changes are made. In the first place, both the distances between the real source position and speakers ($d_{ir}$), as well as the distances from the projection onto the convex hull and the speakers are calculated ($d_{ip}$):




where $x_{ir}$ is the $x$ position of the source's real position, and $y_{ir}$ is the $y$ position of the source's real position. And:




where $x_{ip}$ is the $x$ position of the source's projected position, and $y_{ip}$ is the $y$ position of the source's projected position. A hack occurs when the projected distance becomes less than 1; at this point, the term $k$ as defined in Lossius skyrockets and causes the entire system to collapse. Instead, a value of 1 is added to both distances such that the minimum possible distance is bounded at 1 to stabilize the algorithm. This causes some spatial distortion but in practice it has not proved problematic and is doubtless better than the alternative of allowing the $k$ term to grow very high.

Another term is then introduced to express the ratio between the real distance and the projected distance, $d_{ic}$. For a source inside the convex hull, it is equal to the real distance, $d_{ir}$. If the source is outside the convex hull, it is defined as the square root of the product of the real and projected distances:




From there, $d_{ic}$ is substituted for $d_{i}$ in Equation 9 to calculate the gains for each speaker:




This approach has so far proved sufficient but further testing on more complex speaker arrays is needed to verify its robustness.

Requirements

  • CMake >= 3.5
  • SuperCollider source code
  • Boost Geometry >= 1.65.1.0

Building

Clone the project:

git clone https://woolgathering/dbap
cd dbap
mkdir build
cd build

Then, use CMake to configure and build it:

cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . --config Release
cmake --build . --config Release --target install

You may want to manually specify the install location in the first step to point it at your SuperCollider extensions directory: add the option -DCMAKE_INSTALL_PREFIX=/path/to/extensions.

It's expected that the SuperCollider repo is cloned at ../supercollider relative to this repo. If it's not: add the option -DSC_PATH=/path/to/sc/source.

Developing

Use the command in regenerate to update CMakeLists.txt when you add or remove files from the project. You don't need to run it if you only change the contents of existing files. You may need to edit the command if you add, remove, or rename plugins, to match the new plugin paths. Run the script with --help to see all available options.