Skip to content
Draft
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 src/Beutl.Engine/Audio/Platforms/XAudio2/XAudioContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ static XAudioContext()
}
}

Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing the constructor from XAudioContext() to XAudioContext(int sampleRate = 44100) keeps source compatibility for this repo, but it removes the parameterless .ctor and is a binary breaking change for any already-compiled consumers/plugins. If Beutl.Engine is intended to be consumed externally, consider keeping a parameterless constructor overload that delegates to the new one to preserve binary compatibility.

Suggested change
public XAudioContext()
: this(44100)
{
}

Copilot uses AI. Check for mistakes.
public XAudioContext()
public XAudioContext(int sampleRate = 44100)
{
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sampleRate is accepted as int and then cast to uint for CreateMasteringVoice. If the project/composer sample rate is 0 or negative (e.g., malformed project variable), this will turn into an unexpected large uint and can make XAudio2 initialization fail in hard-to-diagnose ways. Please validate sampleRate > 0 (and ideally throw ArgumentOutOfRangeException, consistent with other audio types like AudioBuffer/AudioProcessContext) before creating the mastering voice.

Suggested change
{
{
if (sampleRate <= 0)
{
throw new ArgumentOutOfRangeException(nameof(sampleRate), "Sample rate must be greater than zero.");
}

Copilot uses AI. Check for mistakes.
Device = Vortice.XAudio2.XAudio2.XAudio2Create();
MasteringVoice = Device.CreateMasteringVoice(2, 44100, AudioStreamCategory.Other);
MasteringVoice = Device.CreateMasteringVoice(2, (uint)sampleRate, AudioStreamCategory.Other);
}

~XAudioContext()
Expand Down
3 changes: 2 additions & 1 deletion src/Beutl/ViewModels/PlayerViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,8 @@ private async Task PlayAudio(Scene scene)
{
if (OperatingSystem.IsWindows())
{
using var audioContext = new XAudioContext();
int sampleRate = EditViewModel.Composer.Value.SampleRate;
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sampleRate is taken directly from EditViewModel.Composer.Value.SampleRate and passed into XAudioContext. Unlike GetFrameRate() (which clamps invalid values), there’s no guard here; if SampleRate is 0/negative, Windows playback can fail when the mastering voice is created. Consider applying the same pattern as GetFrameRate() (fallback to 44100 or project default) before constructing the audio context, or ensure the composer always exposes a validated positive rate.

Suggested change
int sampleRate = EditViewModel.Composer.Value.SampleRate;
int sampleRate = EditViewModel.Composer.Value.SampleRate;
if (sampleRate <= 0)
{
sampleRate = 44100;
}

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Read sample rate from project settings before creating XAudioContext

On Windows playback this value still resolves to 44.1kHz because EditViewModel constructs SceneComposer without initializing SampleRate (src/Beutl/ViewModels/EditViewModel.cs:61-64), and Composer sets SampleRate = 44100 by default (src/Beutl.Engine/Audio/Composing/Composer.cs:32-35). That means new XAudioContext(sampleRate) here effectively keeps using 44100 for all projects, so 48kHz projects remain on a mismatched mastering voice and the audio-drop issue this patch targets is not actually fixed.

Useful? React with 👍 / 👎.

using var audioContext = new XAudioContext(sampleRate);
await PlayWithXA2(audioContext, scene).ConfigureAwait(false);
}
else
Expand Down
Loading