Skip to content

Releases: sbooth/SFBAudioEngine

Version 0.12.0

15 Feb 13:29
108ed7c

Choose a tag to compare

SFBAudioEngine Version 0.12.0 Release Notes

Published: February 15, 2026

🚨 Breaking API Changes

This release contains three breaking API changes that require code updates when migrating from version 0.11.0.

1. Delegate Method: audioPlayer:nowPlayingChanged: (#569)

The previouslyPlaying parameter has been removed from the delegate method signature.

Before (0.11.0 and earlier):

- (void)audioPlayer:(SFBAudioPlayer *)audioPlayer 
    nowPlayingChanged:(SFBAudioPlayerNode *)nowPlaying 
    previouslyPlaying:(SFBAudioPlayerNode *)previouslyPlaying

After (0.12.0):

- (void)audioPlayer:(SFBAudioPlayer *)audioPlayer 
    nowPlayingChanged:(SFBAudioPlayerNode *)nowPlaying

Migration Guide: Remove the previouslyPlaying: parameter from your delegate method implementation. If you need to track the previously playing item, maintain this state in your delegate implementation.

2. Delegate Method: Audio Engine Configuration Change (#692)

The audio engine configuration change notification has been renamed and now includes a userInfo dictionary parameter.

Before (0.11.0 and earlier):

- (void)audioPlayerAVAudioEngineConfigurationChange:(SFBAudioPlayer *)audioPlayer

After (0.12.0):

- (void)audioPlayer:(SFBAudioPlayer *)audioPlayer 
    audioEngineConfigurationChange:(NSDictionary *)userInfo

Migration Guide:

  1. Update the method name to include the audioPlayer: prefix
  2. Add the userInfo: parameter to access configuration change details
  3. Consult the dictionary for specific information about the configuration change

3. Class Rename: OutputSourceOutputTarget (#855)

All references to OutputSource have been renamed to OutputTarget for better semantic clarity.

Migration Guide: Perform a find-and-replace in your codebase:

  • SFBOutputSourceSFBOutputTarget
  • OutputSourceOutputTarget
  • Any related class, method, or variable names

✨ Enhancements

Audio Processing

  • ITU BS.1770 Replay Gain: Implemented revised replay gain calculation using the ITU BS.1770 standard for improved loudness normalization (#842)
  • FLAC Channel Layout Improvements: Channel layouts for FLAC files now match Core Audio conventions (#848)
  • WAVEFORMATEXTENSIBLE Support: Added support for WAVEFORMATEXTENSIBLE_CHANNEL_MASK for better Windows audio format compatibility (#849)

🐛 Bug Fixes

  • Buffer Offset Calculation: Fixed an error in buffer offset calculation that could affect audio encoding (#805)

🔧 Code Quality & Maintenance

Formatting & Style

  • Comprehensive Code Formatting: Applied clang-format across the entire codebase for consistent code style (#794)
  • Clang-tidy Improvements: Applied multiple clang-tidy readability improvements (#802, #804, #807)
  • Modern C++ Practices: Replaced BOOL with bool, NULL with nullptr, and improved pointer checks (#810, #811, #821)

Licensing

  • SPDX File Headers: Added SPDX file headers for better license compliance (#841)
  • MIT License: Updated to use MIT license text from REUSE (#846)

Dependencies

  • Dependency Updates: Updated and refined external dependencies (#833, #866)
  • Removed CXXCoreAudio Dependency: Replaced with internal implementations (#836)
  • Removed CXXAudioToolbox Dependency: (#835)
  • Added CXXDispatchSemaphore: New dependency for synchronization primitives (#838)

CI/CD

  • cpp-linter Workflow: Added automated C++ linting to continuous integration (#869, #870)
  • clang-format Checks: Added automated formatting verification (#798)

📦 Full Changelog

View all 82 changes

This release includes 82 pull requests focused on code quality, modernization, and the breaking API changes listed above. Notable internal improvements include extensive refactoring for better maintainability and standards compliance.

📥 Installation

Swift Package Manager

dependencies: [
    .package(url: "https://github.com/sbooth/SFBAudioEngine", from: "0.12.0")
]

🙏 Credits

All changes in this release were authored by @sbooth.


Need Help? If you encounter any issues migrating to version 0.12.0, please open an issue on GitHub.

Version 0.11.0

19 Jan 19:28
7e67c8e

Choose a tag to compare

SFBAudioEngine Version 0.11.0 Release Notes

Released: January 19, 2026

🚨 Breaking API Changes

Class Rename

Rename LoopableRegionDecoder to AudioRegionDecoder (#765)

The class LoopableRegionDecoder has been renamed to AudioRegionDecoder and improved.

Migration: Update all references from LoopableRegionDecoder to AudioRegionDecoder in your codebase.

📋 What's Changed

🎯 Playback Improvements

  • Fixed a race condition leading to erroneous now playing changes (#702)
  • Simplified playback state calculation (#701)
  • Improved accounting of frames rendered from canceled decoders (#725)
  • Ensure playback state transitions are sequenced properly (#782)
  • Update now playing when decoding starts and not playing (#734)

🔧 Decoder & Encoder Enhancements

  • Enhanced FLAC decoder (#771)
  • Fix bug in FLAC seeking (#766)
  • Improve and rename LoopableRegionDecoder to AudioRegionDecoder (#765) ⚠️ Breaking Change
  • Add decoder read-only property (#768)
  • Cancel decoder when a decoding error occurs (#772)
  • Cancel decoding when a non-recoverable seek error occurs (#731)
  • Clean up Shorten decoder (#730)
  • Catch C++ exceptions in -openReturningError: (#767)

🐛 Bug Fixes

  • Prevent UAF in rendering started and complete notifications (#781)
  • Don't leave decoderState null after processing cancelations (#710)
  • Ensure NSError objects are created on seek failure (#732)
  • Return more appropriate error codes for decoding errors (#733)
  • Log messages about mid-stream format changes as errors (#775)

✨ New Delegate Methods

  • Add -audioPlayer:decodingAborted:error:framesRendered: delegate method (#779)
  • Add audioPlayer:audioSessionInterruption: delegate method (#787)

⚠️ Error Handling Improvements

  • Consolidate error domains for decoding and improve error messages (#735)
  • Update audio player errors (#741)
  • Update error domains/codes and Swift names (#743)
  • Use SFBErrorWithLocalizedDescription throughout the codebase (#745, #747, #748, #749, #751, #753, #754)
  • Improve DSD to PCM and DoP error messages (#764)
  • Improve DSDDecoder error messages (#755)

🏗️ Architecture & Internal Improvements

  • Replace SeekForward and SeekBackward with SeekInTime (#718)
  • Remove EventHeader struct and simplify event processing (#720)
  • Remove Flags::formatMismatch (#726)
  • Move AudioPlayer and DecoderState method implementations (#727)
  • Add fetch_update generic atomic RMW function (#723, #724)
  • Ensure the processing graph is reconfigured before decoding starts (#713)
  • Refactor enqueue logic (#708)
  • Ensure all cancelations are processed in sequence (#707)
  • Ensure all ensuing decoders suspended following seek (#709)
  • Don't access audioRingBuffer_ in event processing thread (#785)
  • Rework host time utilities (#789)

💅 Code Quality & Formatting

  • Adopt a new C++ coding style (#790)
  • Standardize else formatting (#773)
  • Update documentation comments (#739)
  • Add nullability specifiers (#752)
  • Give all ivars in internal headers package visibility (#759)
  • Reformat ReplayGainAnalyzer (#762)
  • Update year to 2026 (#721)

📦 Dependency Updates

  • Update CXXRingBuffer and CXXCoreAudio (#717)
  • Update dependencies and tighten version requirements for pre-1.0 packages (#792)
  • Add header to Package.swift (#728)

🔊 Audio Engine Improvements

  • Increase event buffer sizes (#703)
  • Increase log level for ring buffer write failures (#704)
  • Use a mask in Render to check not playing or muted (#705)
  • Remove unmuteAfterDequeue flag (#716)
  • Clear Flags::formatMismatch when decoding resumed (#712)

🎵 Audio Session Handling

  • Improvements to audio session interruption handling (#787)
  • Rename handleAudioSessionInterruption (#791)

🛠️ Miscellaneous

  • Only use simd packed vectors when dealing with memory (#776)
  • Use reinterpret_cast (#777)
  • Use <<= operator (#778)
  • Use auto * where appropriate (#719)
  • Use kHz for kilohertz (#770)

📝 Full Changelog

Full Changelog: 0.10.0...0.11.0

This release includes 94 pull requests.

📥 Installation

Swift Package Manager

dependencies: [
    .package(url: "https://github.com/sbooth/SFBAudioEngine", from: "0.11.0")
]

🙏 Credits

All changes in this release were authored by @sbooth.


Need Help? If you encounter any issues migrating to version 0.11.0, please open an issue on GitHub.

Version 0.10.0

29 Dec 23:50
196ffcc

Choose a tag to compare

What's Changed

  • Slight simplification to Render by @sbooth in #668
  • Improvements to SubmitDecodingErrorEvent by @sbooth in #669
  • Integrate with new AudioRingBuffer read behavior by @sbooth in #670
  • Remove Flags::ringBufferNeedsReset by @sbooth in #671
  • Simplify ring buffer reset logic by @sbooth in #672
  • Use a longer event semaphore timeout when idle by @sbooth in #676
  • Ensure error is set on short reads by @sbooth in #677
  • Use uint8_t for pointer arithmetic with known types by @sbooth in #678
  • Use unsigned char instead of uint8_t by @sbooth in #679
  • Return an error on decoding failure by @sbooth in #680
  • Fixes to SubmitDecodingErrorEvent() by @sbooth in #682
  • Ensure error object is created on failure by @sbooth in #683
  • Add -closeReturningError: to AudioConverter by @sbooth in #684
  • Don't read past DSF data chunk when decoding by @sbooth in #685
  • Add -description to decoder wrappers by @sbooth in #686
  • Fix warning about implicit conversion by @sbooth in #687
  • Use EINVAL instead of paramErr by @sbooth in #688
  • Replace SFBAudioPlayerNode with AVAudioSourceNode by @sbooth in #664
  • Replace -withEngine: with -modifyProcessingGraph: by @sbooth in #689
  • Add an assert after -audioPlayer:reconfigureProcessingGraph:withFormat: by @sbooth in #690
  • Improve logging in HandleAudioEngineConfigurationChange by @sbooth in #691
  • Add bool return to Pause and Resume by @sbooth in #694
  • Improvements to audio session interruption handling by @sbooth in #693
  • Update to C++17 if syntax by @sbooth in #695
  • Additional error checking in DSF and DFF parsers by @sbooth in #696
  • Update CXXCoreAudio and CXXRingBuffer by @sbooth in #698

Full Changelog: 0.9.1...0.10.0

Version 0.9.1

20 Dec 00:40
720933f

Choose a tag to compare

What's Changed

  • Remove use of GCD semaphores from real-time thread by @sbooth in #663
  • Update CXXRingBuffer to version 0.3.0 by @sbooth in #666
  • Update CXXCoreAudio and CXXAudioToolbox by @sbooth in #667

Full Changelog: 0.9.0...0.9.1

Version 0.9.0

10 Dec 20:49
124da31

Choose a tag to compare

What's Changed

  • Mark -init as designated initializer in SFBMutableDataOutputSource by @sbooth in #647
  • Increase CXXTagLib minimum version to 2.1.1 by @sbooth in #648
  • Ensure input source is open before sending -supportsSeeking by @sbooth in #649
  • Avoid logging a null decoder by @sbooth in #652
  • Refactor processing graph configuration by @sbooth in #654
  • Check if engine is running before sending startAndReturnError: by @sbooth in #655
  • Add a lock protecting enqueues and engine configuration changes by @sbooth in #653
  • Correct name of the player node getter method by @sbooth in #657
  • Additional comments by @sbooth in #658
  • Rename decoder managment methods by @sbooth in #659
  • Remove explicitly deleted move constructor and assignment operator by @sbooth in #660
  • Reset decoder state in -openReturningError: and -closeReturningError: by @sbooth in #578
  • Reset encoder state in -openReturningError: and -closeReturningError: by @sbooth in #661
  • Add a lock protecting the audio player node by @sbooth in #640
  • Add - to source code marks by @sbooth in #662

Full Changelog: 0.8.0...0.9.0

Version 0.8.0

30 Nov 12:53
b82066d

Choose a tag to compare

What's Changed

  • Fix VLA folding warnings by @sbooth in #593
  • Avoid opening file handle unnecessarily by @sbooth in #594
  • Mark SFBInputSource.new and init as unavailable by @sbooth in #596
  • Mark SFBOutputSource.new and init as unavailable by @sbooth in #597
  • Reconfigure the audio processing graph during enqueue if needed by @sbooth in #600
  • Avoid unnecessary calls to AVAudioChannelLayoutsAreEquivalent by @sbooth in #601
  • Add permissions to workflow by @sbooth in #603
  • Replace std::thread with std::jthread by @sbooth in #602
  • Replace SFB::DispatchSemaphore with dispatch_semaphore_t by @sbooth in #604
  • Add noexcept to ~AudioPlayerNode() by @sbooth in #605
  • Small improvements to host time functions by @sbooth in #606
  • Use scoped enumerations for flags by @sbooth in #607
  • CTAD for std::lock_guard by @sbooth in #610
  • Call request_stop and join directly by @sbooth in #611
  • Handle exceptions thrown by jthread::join by @sbooth in #612
  • Refactor SFBAudioPlayer C++ implementation by @sbooth in #608
  • Add DEBUG guard by @sbooth in #614
  • Add getter to SFBAudioPlayer for audioPlayerNode property by @sbooth in #615
  • Inline simple functions by @sbooth in #616
  • Remove audio engine isolation queue by @sbooth in #618
  • Increase log level to fault if mpg123 fails to initialize by @sbooth in #624
  • Refactor package dependencies by @sbooth in #621
  • Skip junk in MP3 files when performing content type detection by @sbooth in #626
  • Update to Monkey's Audio SDK version 11.82 by @sbooth in #627
  • Bump actions/checkout from 5 to 6 by @dependabot[bot] in #628
  • Add explicit memory ordering by @sbooth in #629
  • Throw bad_alloc instead of system_error by @sbooth in #631
  • Rename scoped enumeration enumerators by @sbooth in #632
  • Remove m prefix from data members by @sbooth in #633
  • Reformat else and catch by @sbooth in #634
  • Refactor audio engine setup and player node creation by @sbooth in #635
  • Remove unnecessary assertion by @sbooth in #636
  • Update data member name by @sbooth in #637
  • Update audio player log name by @sbooth in #638
  • Simplify code since playerNode_ will not be nil by @sbooth in #639
  • Update CXXAudioToolbox to version 0.1.1 by @sbooth in #641
  • Update mpg123 to version 1.33.3 by @sbooth in #642
  • Update ogg to version 1.3.6 by @sbooth in #643
  • Use mpg123_reader64 for large file support by @sbooth in #644
  • Capture wvec by reference in lambda by @sbooth in #645
  • Use renamed AudioRingBuffer methods by @sbooth in #646

Full Changelog: 0.7.2...0.8.0

Version 0.7.2

01 Sep 13:10
e5b8fda

Choose a tag to compare

Summary of changes:

Metadata

  1. Shorten properties and metadata now provided by TagLib

Encoding

  1. Fixed a bug in the Monkey's Audio encoder
  2. Fixed a bug in the libsndfile encoder

Miscellaneous

  1. Renamed the _impl pointer in SFBAudioPlayerNode to avoid conflict with AVAudioNode
  2. Updated versions of FLAC, Monkey's Audio, WavPack, mpg123, and TagLib dependencies

Version 0.7.1

12 Mar 13:12
2c36bab

Choose a tag to compare

Summary of changes:

Metadata

  1. Handle C++ exceptions when reading/writing metadata

Version 0.7.0

05 Feb 15:51
3689649

Choose a tag to compare

Summary of changes:

Playback

  1. SFBAudioPlayerNode changes:
  • Added ability to seek backward in a rendering decoder after decoding has finished
  • Fixed race condition accessing active decoders
  • Decoding now uses a dedicated thread
  1. SFBAudioPlayer changes:
  • Changed -audioPlayer:nowPlayingChanged:previouslyPlaying:

Miscellaneous

  1. Minor refactoring of SFBPlaybackPosition and SFBPlaybackTime
  2. Small changes to restore compatibility with older Swift and Xcode versions

Version 0.6.0

17 Jan 22:34
02fa6a4

Choose a tag to compare

Summary of changes:

Playback

  1. Improved continuity of playback state when switching audio formats
  2. Improved handling of multichannel audio channel mapping
  3. SFBAudioPlayerNode changes:
  • Added -audioPlayerNode:renderingDecoder:willChangeToDecoder:atHostTime:
  • Removed -audioPlayerNode:audioWillEndAtHostTime:
  • Changed -audioPlayerNode:decoderCanceled:framesRendered:
  • Removed -delegateQueue
  1. SFBAudioPlayer changes:
  • Added -audioPlayer:reconfigureProcessingGraph:withFormat:
  • Removed audioPlayer:audioWillEndAtHostTime:
  • Changed -audioPlayer:nowPlayingChanged:
  • Changed -audioPlayer:playbackStateChanged:
  • Changed -audioPlayer:decoderCanceled:framesRendered:
  1. Unified playback position and time structures across Objective-C and Swift

Encoding

  1. FLAC and Ogg FLAC encoders now work correctly for bit depths less than 32
  2. FLAC compression level 0 is now supported

Conversion

  1. Improved handling of conversion errors