Synthizer 0.8.x

Highlights of this Release

This release is about performance, and undoing the Linux rollback in 0.7.7. As of this release, all code paths from the external interface don't block on the audio thread in the best case. An internal refactor and introduction of a new command architecture unify a bunch of ad-hoc interfaces for fast inter-thread synchronization.

Specifically:

  • Property reads are now a couple of atomic operations as opposed to a semaphore and waiting on the next audio tick. Put another way, they're literally millions of times faster, and it's now possible to read things like BufferGenerator.position without issue.
  • property writes are now roughly 5 times faster than they used to be
  • object creation is essentially free
  • adding and removing generators from sources doesn't block
  • configuring routes for effects doesn't block

There is one exception to the lack of blocking: if code does around 10000 operations per audio tick, Synthizer will have no choice but to block due to internal resource exhaustion. If this proves to be an issue in practice, it is trivial to raise this limit further.

A Note on Breakage

The above changes were a complex refactor. In order to make them with as little chaos as possible Synthizer has begun introducing some basic unit tests, but nonetheless it is nearly impossible to make a release like this one without issues. You are encouraged to report issues against Synthizer's GitHub repository.

Compatibility

Synthizer introduces the following compatibility breakages in this release:

In order to get the above performance increases, it was necessary to remove the ability to read object properties. This has the side effect of hiding details of object lifetime, which Synthizer may rely on in future.

FdnReverb.input_filter_enabled and FdnReverb.input_filter_cutoff were removed. Synthizer will be replacing these with a dedicated filter property type in the near future and opted to remove them now as to avoid an excessive number of releases that introduce backward-incompatible changes.

Property reads are now actually eventually consistent. The manual preivously stated that it's possible for a read that comes after a write to read a stale value, so code shouldn't have been relying on it. In any case, Synthizer now uses this reservation for the above performance increases, and may break code that incorrectly relied on the old behavior.

Synthizer has also changed the default panner strategy to SYZ_PANNER_STRATEGY_STEREO. To re-enable HRTF, set this on a per-source basis. The ability to set this default on a per-context basis will be introduced in the 0.8.x series. This change was made because HRTF is only useful for headphone users, and it is not possible for Synthizer to reliably detect that case. In general, stereo panning is safe on every audio configuration including surround sound systems.

Patch Notes

0.8.0

  • Initial release
  • Undo the rollbacks in 0.7.7 and reintroduce MSVC and Linux support.
  • Internal fix for wire filters, which now don't play silence.
  • A number of small fixes and slight quality improvements to reverb.
  • All of the massive performance increases from above.

0.8.1

  • Miniaudio was improperly configured to use a conservative profile, rather than a low latency profile. Caused extreme audio latency.

0.8.3

  • Fix: FdnReverb.t60 = 0.0 no longer internally divides by 0.
  • fix: BufferGenerator again uses seconds for positions. This was refactored incorrectly during 0.8.0's major changes.
  • Objects should now die faster when their handles are freed, due to holding only weak references internally where possible when dispatching commands to the audio thread.

0.8.4

  • Contexts and all generators now support SYZ_P_GAIN.
  • Contexts, sources, and generators now support play/pause via syz_pause and syz_play.
    • In Python, this is src.pause() and similar.
  • As the first part of the event system, all Synthizer objects may now have arbitrary userdata associated with them:
    • In C, this is syz_getUserdata and syz_setUserdata
    • In Python, this is get_userdata and set_userdata
    • This will be documented properly when the rest of the event system exists, but can be used to link Synthizer objects to non-Synthizer objects without having to maintain a custom mapping yourself.
  • Slight memory savings.
  • Fix: deleting contexts no longer crashes.

0.8.5

  • New function syz_getObjectType which queries the object type. Primarily intended for bindings developers.
  • Fix: Synthizer no longer leaks megabytes of memory per second (issue #44).

0.8.6

This release contains somewhat experimental code to make decoding buffers faster by approximately 2X. Please report any perceptible audio quality issues with BufferGenerator.

  • syz_handleFree now no-ops when passed handle = 0.
  • Fix: deleting sources in specific orders no longer causes audio artifacts (issue #46)

0.8.7

  • Fix: the library no longer crashes due to internal races between handle deletion and execution of audio commands on the background thread
    • This fixes a number of crashes, most notably issue #50, which highlighted the issue due to effects relying heavily on commands.
  • Fix: streaming generators no longer spuriously seek to the beginning of their audio after generating the first few MS of audio (issue #49)
  • Fix: panning_scalar will once more properly take effect if set immediately after PannedSource creation (issue #52)

0.8.8

  • An event system. This is alpha, and changes are expected in 0.9.
  • Add SYZ_P_PANNER_STRATEGY to Context to default panner strategies for new sources.

0.8.9

  • Fix: non-looping BufferGenerator with a pitch bend is no longer silent
  • Fix/improvement: In Python, Synthizer events inherit from a common base class.

0.8.10

This release is the long-awaited improved HRTF. This might not be the final version, but it's much better in quality and the scripts to generate it are now much easier to maintain. Please leave any feedback here. in particular, it is not feasible to test the entire sphere, so it may be possible to find azimuth/elevation combinations which do weird things.

0.8.11-0.8.16

These releases are a test series for moving CI to GitHub Actions. Though not user-facing, 0.8.14 now blocks on successful Linux CI for Ubuntu 20 and thus gives Linux support which is on par with Windows.

0.8.17

The flagship feature of this release is filters. Python users should see the Python tutorial. Also:

  • Synthizer now builds on Ubuntu 18.
  • Python no longer eroniously exports top-level enums due to undocumented Cython behavior.
    • If you were using ints as property values instead of enums or relying on the topp-level definition, you will need to update your code. This was never intended to be part of the public API.
  • It is possible to set generator gain before adding it to a source without triggering a crossfade. Internal changes to the crossfade helpers should make bugs like this much rarer, and probably fixed others that were yet to be reported.