Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/bug_report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ body:
```csharp
// Your MRE code here
```
render: shell
render: csharp
validations:
required: false

Expand All @@ -93,7 +93,7 @@ body:
```
(Paste full error message and stack trace here)
```
render: shell
render: csharp
validations:
required: false

Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/documentation_issue.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ body:
```csharp
// Improved code example
```
render: shell
render: markdown
validations:
required: false

Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/feature_request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ body:
// public class NewComponent : SoundComponent { ... }
// public void ExistingComponent.NewMethod(ParameterType param) { ... }
```
render: shell
render: csharp
validations:
required: false

Expand Down
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/performance_issue.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ body:
```csharp
// Your MRE code here
```
render: shell
render: csharp
validations:
required: false

Expand All @@ -91,7 +91,7 @@ body:
* Exported profiling sessions (if shareable).
* Key findings from the profiler.
placeholder: Paste profiling data, links, or key findings here.
render: shell
render: markdown
validations:
required: false

Expand Down
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/platform_specific_issue.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ body:
```csharp
// Your MRE code here
```
render: shell
render: csharp
validations:
required: false

Expand All @@ -137,7 +137,7 @@ body:
```
(Paste full error message and stack trace here)
```
render: shell
render: csharp
validations:
required: false

Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/question.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ body:
```csharp
// Your code here
```
render: shell
render: csharp
validations:
required: false

Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/security_vulnerability_report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ body:
```csharp
// PoC code (if safe to share publicly)
```
render: shell
render: markdown
validations:
required: false

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-extensions-apm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
cross_file: "linux-arm64.crossfile"

# macOS builds
- os: macos-latest
- os: macos-15-intel
rid: osx-x64
platform: macOS
arch: x86_64
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-ffmpeg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ jobs:
matrix:
include:
- arch: x64
os: macos-13
os: macos-15-intel
cmake_arch: x86_64
- arch: arm64
os: macos-14
Expand Down
17 changes: 8 additions & 9 deletions .github/workflows/build-miniaudio.yml
Original file line number Diff line number Diff line change
Expand Up @@ -160,14 +160,13 @@ jobs:
lib_extension: ".dll"
toolchain: "Visual Studio 17 2022"

# Disabled due to https://github.com/mackron/miniaudio/issues/1045
#- os: windows-latest
# rid: win-arm64
# platform: Windows
# arch: ARM64
# cmake_target_arch: ARM64
# lib_extension: ".dll"
# toolchain: "Visual Studio 17 2022"
- os: windows-latest
rid: win-arm64
platform: Windows
arch: ARM64
cmake_target_arch: ARM64
lib_extension: ".dll"
toolchain: "Visual Studio 17 2022"

# Linux builds
- os: ubuntu-22.04
Expand Down Expand Up @@ -199,7 +198,7 @@ jobs:
cmake_target_arch: arm64
lib_extension: ".dylib"

- os: macos-latest
- os: macos-15-intel
rid: osx-x64
platform: macOS
arch: x86_64
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-portmidi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
cross_compile: true

# macOS (Clang) - Universal binaries are avoided to produce discrete arch-specific libs.
- os: macos-latest
- os: macos-15-intel
rid: osx-x64
platform: macOS
arch: x86_64
Expand Down
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[submodule "Extensions/SoundFlow.Extensions.WebRtc.Apm/Native"]
[submodule "Native/webrtc-audio-processing"]
path = Native/webrtc-audio-processing
url = https://github.com/LSXPrime/webrtc-audio-processing
[submodule "Native/miniaudio-backend/miniaudio"]
Expand Down
31 changes: 31 additions & 0 deletions CITATION.cff
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
cff-version: 1.2.0
message: "If you use this software, please cite it as below."
type: software
authors:
- family-names: "Abdallah"
given-names: "Ahmed"
email: "lsxprime@gmail.com"
title: "SoundFlow: A high-performance, secure audio and MIDI engine for .NET"
version: "1.4.0"
date-released: "2026-01-06"
repository-code: "https://github.com/LSXPrime/SoundFlow"
url: "https://lsxprime.github.io/soundflow-docs/"
license: MIT
keywords:
- "audio-engine"
- ".net"
- "csharp"
- "digital-signal-processing"
- "midi"
- "cross-platform"
- "audio-synthesis"
- "audio-encryption"
- "audio-watermarking"
abstract: >-
A high-performance, modular audio & MIDI engine for .NET8+.
A complete toolkit for the entire audio lifecycle of
Playback, Recording, Multi-track Editing, Pro Synthesis
(MPE/SF2), Real-time DSP, and Visualization. Includes a
unique security suite for AES-256 encryption, acoustic
fingerprinting, and watermarking. Featuring SIMD and
NativeAOT support.
12 changes: 8 additions & 4 deletions Codecs/SoundFlow.Codecs.FFMpeg/FFmpegDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ public FFmpegDecoder(Stream stream, AudioFormat targetFormat)

if (result != FFmpegResult.Success)
{
var logMessage = $"Failed to initialize FFmpeg decoder. Result: {result}";
Log.Error(logMessage);
_handle.Dispose();
throw new FFmpegException(result, $"Failed to initialize FFmpeg decoder. Result: {result}");
throw new FFmpegException(result, logMessage);
}

SampleFormat = targetFormat.Format = nativeFormat;
Expand All @@ -51,8 +53,10 @@ public FFmpegDecoder(Stream stream, AudioFormat targetFormat)
var lengthInFrames = FFmpeg.GetLengthInPcmFrames(_handle);
if (lengthInFrames < 0)
{
const string logMessage = "Failed to get stream length, the decoder handle may be invalid.";
Log.Error(logMessage);
_handle.Dispose();
throw new InvalidOperationException("Failed to get stream length; the decoder handle may be invalid.");
throw new InvalidOperationException(logMessage);
}
Length = (int)(lengthInFrames * Channels);
}
Expand Down Expand Up @@ -120,7 +124,7 @@ private unsafe nuint OnRead(IntPtr pUserData, IntPtr pBuffer, nuint bytesToRead)
}
catch
{
Log.Critical("[FFmpegDecoder] Failed to read from stream.");
Log.Critical("Failed to read from stream.");
// Signal error/EOF to FFmpeg by returning 0. FFmpeg will handle this gracefully as AVERROR_EOF.
return 0;
}
Expand All @@ -135,7 +139,7 @@ private long OnSeek(IntPtr pUserData, long offset, SeekWhence whence)
}
catch
{
Log.Critical("[FFmpegDecoder] Failed to seek stream.");
Log.Critical("Failed to seek stream.");
return -1;
}
}
Expand Down
6 changes: 4 additions & 2 deletions Codecs/SoundFlow.Codecs.FFMpeg/FFmpegEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ public FFmpegEncoder(Stream stream, string formatId, AudioFormat sourceFormat)

if (result != FFmpegResult.Success)
{
var logMessage = $"Failed to initialize FFmpeg encoder for format '{formatId}'. Result: {result}";
Log.Error(logMessage);
_handle.Dispose();
throw new FFmpegException(result, $"Failed to initialize FFmpeg encoder for format '{formatId}'. Result: {result}");
throw new FFmpegException(result, logMessage);
}
}

Expand Down Expand Up @@ -77,7 +79,7 @@ private unsafe nuint OnWrite(IntPtr pUserData, IntPtr pBuffer, nuint bytesToWrit
}
catch
{
Log.Critical("[FFmpegEncoder] Failed to write to stream.");
Log.Critical("Failed to write to stream.");
return 0;
}
}
Expand Down
14 changes: 7 additions & 7 deletions Codecs/SoundFlow.Codecs.FFMpeg/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ By registering this extension with the SoundFlow engine, you can seamlessly load
This extension provides a high-performance and memory-efficient bridge to FFmpeg's audio capabilities:

* **Broad Codec Support:** Adds support for dozens of popular audio formats, including:
* **Lossy:** MP3, AAC, Ogg Vorbis, Opus, WMA, AC3
* **Lossy:** MP3 (encoded via LAME), AAC, Ogg Vorbis, Opus, WMA, AC3
* **Lossless:** FLAC, ALAC (Apple Lossless), APE, WavPack (WV), TTA
* **And many more container and raw formats.**
* **Seamless Integration:** Implements a high-priority `ICodecFactory`, allowing SoundFlow to automatically use FFmpeg for supported formats with no changes to your existing playback or recording code.
* **High Performance & Efficiency:** Works directly with streams using a callback-based native wrapper. This avoids loading entire audio files into memory, making it ideal for large files and network streams.
* **Cross-Platform:** Includes pre-compiled native binaries for Windows, macOS, and Linux (x64, x86, ARM64), ensuring it works wherever SoundFlow runs.
* **Cross-Platform:** Includes pre-compiled native binaries for Windows, macOS, Linux, Android, iOS and FreeBSD (x64, x86, ARM64), ensuring it works wherever SoundFlow runs.
* **Automatic Format Conversion:** The native wrapper intelligently uses FFmpeg's `swresample` library to automatically convert audio from its source format to the format required by your application (e.g., 32-bit float), simplifying your audio pipeline.

## Getting Started
Expand Down Expand Up @@ -93,26 +93,26 @@ device.Stop();

## Technical Details

The native library included in this package is a custom-built, lightweight version of FFmpeg. To minimize binary size, it is configured with a "disable-all, enable-specific" strategy. The build includes a curated set of audio-only components and excludes all video processing, hardware acceleration, networking protocols (except `file` and `pipe`), and other non-essential features.
The native library included in this package is a custom-built, lightweight wrapper around FFmpeg and the LAME MP3 encoder. To minimize binary size, it is configured with a "disable-all, enable-specific" strategy. The build includes a curated set of audio-only components and excludes all video processing, hardware acceleration, networking protocols (except `file` and `pipe`), and other non-essential features.

This results in a small, focused, and highly efficient native dependency tailored specifically for SoundFlow's audio processing needs.

## Origin and Licensing

This `SoundFlow.Codecs.FFMpeg` package consists of C# wrapper code and a custom native library that statically links against FFmpeg libraries.
This `SoundFlow.Codecs.FFMpeg` package consists of C# wrapper code and a custom native library that statically links against FFmpeg and LAME libraries.

* The C# code within this `SoundFlow.Codecs.FFMpeg` package is licensed under the **MIT License**.
* The included FFmpeg build is configured to be compatible with **LGPL v2.1 or later**. It is compiled with `--disable-gpl` and `--disable-nonfree` flags. Your use of this package must comply with the terms of the LGPL. This generally means that if you dynamically link to this library, you can use it in proprietary software, but if you modify the FFmpeg source code itself, you must release those changes.
* The included native library builds upon FFmpeg and LAME, both of which are licensed under the **LGPL v2.1 or later**. The FFmpeg build is configured with `--disable-gpl` and `--disable-nonfree` flags. Your use of this package must comply with the terms of the LGPL. This generally means that if you dynamically link to this library, you can use it in proprietary software, but if you modify the FFmpeg or LAME source code itself, you must release those changes.

**Users of this package must comply with the terms of BOTH the MIT License (for the C# wrapper) and the LGPL (for the underlying FFmpeg components).** For detailed information, please consult the official [FFmpeg Licensing Page](https://ffmpeg.org/legal.html).
**Users of this package must comply with the terms of BOTH the MIT License (for the C# wrapper) and the LGPL (for the underlying FFmpeg and LAME components).** For detailed information, please consult the official [FFmpeg Licensing Page](https://ffmpeg.org/legal.html) and the [LAME Project Website](https://lame.sourceforge.io/).

## Contributing

Contributions to `SoundFlow.Codecs.FFMpeg` are welcome! Please open issues or submit pull requests to the main SoundFlow repository following the general [SoundFlow Contributing Guidelines](https://github.com/LSXPrime/SoundFlow#contributing).

## Acknowledgments

This package would not be possible without the incredible work of the **FFmpeg project team and its contributors**.
This package would not be possible without the incredible work of the **FFmpeg project team and its contributors**. Special thanks to the **LAME project** for the high-quality MP3 encoder.

## License

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<IsAotCompatible>true</IsAotCompatible>
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
<Title>SoundFlow FFmpeg Codecs</Title>
<PackageId>SoundFlow.Codecs.FFMpeg</PackageId>
<Version>1.3.0</Version>
<Version>1.4.0</Version>
<Description>Provides FFmpeg-based audio codecs (MP3, AAC, OGG, Opus, etc.) for the SoundFlow audio engine.</Description>
<PackageTags>soundflow;audio;codec;ffmpeg;mp3;aac;ogg;opus</PackageTags>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
Expand All @@ -33,6 +35,10 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<Pack>true</Pack>
</None>
<None Include="..\..\SOUNDFLOW-THIRD-PARTY-NOTICES.txt"
Pack="true"
PackagePath="\"
CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

<ItemGroup>
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ private void Dispose(bool disposing)
}
}

/// <inheritdoc />
~StreamConfig()
{
Dispose(false);
Expand Down Expand Up @@ -227,7 +228,8 @@ protected virtual void Dispose(bool disposing)
_disposedValue = true;
}
}


/// <inheritdoc />
~ProcessingConfig()
{
Dispose(false);
Expand Down Expand Up @@ -369,6 +371,7 @@ private void Dispose(bool disposing)
}
}

/// <inheritdoc />
~ApmConfig()
{
Dispose(false);
Expand Down Expand Up @@ -760,6 +763,7 @@ private void Dispose(bool disposing)
}
}

/// <inheritdoc />
~AudioProcessingModule()
{
Dispose(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ public void Dispose()
}
}

/// <inheritdoc />
~NoiseSuppressor()
{
Dispose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,7 @@ private void InitializeApmAndFeatures()
}
catch (Exception ex)
{
Log.Error($"[WebRtcApmModifier] Init Exception: {ex.Message}");
Log.Error($"Init Exception: {ex.Message}");
Enabled = false;
DisposeApmNativeResources();
throw;
Expand Down
Loading