Icons changed. README added.

This commit is contained in:
Alexander Shabarshov 2026-07-26 11:20:25 +01:00
parent 7410073224
commit d8e1317a74
4 changed files with 247 additions and 55 deletions

BIN
ABStemPlayer-UI.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

View File

@ -12,10 +12,15 @@ public class PlayPauseGeometryConverter : IValueConverter
// Pause icon // Pause icon
if (isPlaying) if (isPlaying)
return Geometry.Parse("M 12 8 L 18 8 L 18 32 L 12 32 Z M 22 8 L 28 8 L 28 32 L 22 32 Z"); return Geometry.Parse("""
M10 5C10 3.34315 8.65686 2 7 2H5C3.34315 2 2 3.34315 2 5V19C2 20.6569 3.34315 22 5 22H7C8.65686 22 10 20.6569 10 19V5Z
M8 5C8 4.44772 7.55229 4 7 4H5C4.44772 4 4 4.44772 4 5V19C4 19.5523 4.44772 20 5 20H7C7.55229 20 8 19.5523 8 19V5Z
M22 5C22 3.34315 20.6569 2 19 2H17C15.3431 2 14 3.34315 14 5V19C14 20.6569 15.3431 22 17 22H19C20.6569 22 22 20.6569 22 19V5Z
M20 5C20 4.44772 19.5523 4 19 4H17C16.4477 4 16 4.44772 16 5V19C16 19.5523 16.4477 20 17 20H19C19.5523 20 20 19.5523 20 19V5Z
""");
// Play icon // Play icon
return Geometry.Parse("M 10 8 L 32 20 L 10 32 Z"); return Geometry.Parse("M5.46484 3.92349C4.79896 3.5739 4 4.05683 4 4.80888V19.1911C4 19.9432 4.79896 20.4261 5.46483 20.0765L19.1622 12.8854C19.8758 12.5108 19.8758 11.4892 19.1622 11.1146L5.46484 3.92349ZM2 4.80888C2 2.55271 4.3969 1.10395 6.39451 2.15269L20.0919 9.34382C22.2326 10.4677 22.2325 13.5324 20.0919 14.6562L6.3945 21.8473C4.39689 22.8961 2 21.4473 2 19.1911V4.80888Z");
} }
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
=> throw new NotSupportedException(); => throw new NotSupportedException();

View File

@ -37,47 +37,43 @@
<!-- File Open --> <!-- File Open -->
<Button Command="{Binding OpenFileCommand}" <Button Command="{Binding OpenFileCommand}"
Width="40" Width="32"
Height="40" Height="32"
Background="Black"
Grid.Column="0" Grid.Column="0"
Margin="0,0,6,0" Margin="0,0,6,0"
ToolTip.Tip="Open File"> ToolTip.Tip="Open File">
<Path Fill="#e0e0e0" <Path Fill="#e0e0e0"
Stretch="None" Stretch="None"
RenderTransformOrigin="0,0"> RenderTransformOrigin="0,0">
<Path.RenderTransform>
<TranslateTransform X="-8" Y="-8"/>
</Path.RenderTransform>
<Path.Data> <Path.Data>
M 6 10 H 18 L 22 14 H 34 V 30 H 6 Z M1 4C1 2.34315 2.34315 1 4 1H7.76393C8.90025 1 9.93904 1.64201 10.4472 2.65836L11.3416 4.44721C11.511 4.786 11.8573 5 12.2361 5H20C21.6569 5 23 6.34315 23 8V20C23 21.6569 21.6569 23 20 23H4C2.34315 23 1 21.6569 1 20V4ZM4 3C3.44772 3 3 3.44772 3 4V20C3 20.5523 3.44772 21 4 21H20C20.5523 21 21 20.5523 21 20V8C21 7.44772 20.5523 7 20 7H12.2361C11.0998 7 10.061 6.35799 9.55279 5.34164L8.65836 3.55279C8.48897 3.214 8.1427 3 7.76393 3H4Z
</Path.Data> </Path.Data>
</Path> </Path>
</Button> </Button>
<!-- Rewind --> <!-- Rewind -->
<Button Command="{Binding RewindCommand}" <Button Command="{Binding RewindCommand}"
Width="40" Width="32"
Height="40" Height="32"
Background="Black"
Grid.Column="1" Grid.Column="1"
Margin="0,0,6,0" Margin="0,0,6,0"
ToolTip.Tip="Rewind"> ToolTip.Tip="Rewind">
<Path Fill="#e0e0e0" <Path Fill="#e0e0e0"
Stretch="None" Stretch="None"
RenderTransformOrigin="0,0"> RenderTransformOrigin="0,0">
<Path.RenderTransform>
<TranslateTransform X="-6" Y="-8"/>
</Path.RenderTransform>
<Path.Data> <Path.Data>
M 30 8 L 10 20 L 30 32 Z M 18 8 L -2 20 L 18 32 Z M18.3956 19.7691C19.0541 20.2687 20 19.799 20 18.9724L20 5.02764C20 4.20106 19.0541 3.73137 18.3956 4.23095L9.20476 11.2033C8.67727 11.6035 8.67727 12.3965 9.20476 12.7967L18.3956 19.7691ZM22 18.9724C22 21.4521 19.1624 22.8612 17.1868 21.3625L7.99598 14.3901C6.41353 13.1896 6.41353 10.8104 7.99599 9.60994L17.1868 2.63757C19.1624 1.13885 22 2.5479 22 5.02764L22 18.9724Z
M2 3C2 2.44772 2.44772 2 3 2C3.55228 2 4 2.44772 4 3V21C4 21.5523 3.55228 22 3 22C2.44772 22 2 21.5523 2 21V3Z
</Path.Data> </Path.Data>
</Path> </Path>
</Button> </Button>
<!-- Play --> <!-- Play -->
<Button Width="40" <Button Width="32"
Height="40" Height="32"
Background="Black"
Grid.Column="2" Grid.Column="2"
Margin="0,0,6,0" Margin="0,0,6,0"
ToolTip.Tip="Play/Pause" ToolTip.Tip="Play/Pause"
@ -87,47 +83,39 @@
Stretch="None" Stretch="None"
RenderTransformOrigin="0,0" RenderTransformOrigin="0,0"
Data="{Binding IsPlaying, Converter={StaticResource PlayPauseGeometry}}"> Data="{Binding IsPlaying, Converter={StaticResource PlayPauseGeometry}}">
<Path.RenderTransform>
<TranslateTransform X="-8" Y="-8"/>
</Path.RenderTransform>
</Path> </Path>
</Button> </Button>
<!-- Stop --> <!-- Stop -->
<Button Command="{Binding StopCommand}" <Button Command="{Binding StopCommand}"
Width="40" Width="32"
Height="40" Height="32"
Background="Black"
Grid.Column="4" Grid.Column="4"
Margin="0,0,6,0" Margin="0,0,6,0"
ToolTip.Tip="Stop"> ToolTip.Tip="Stop">
<Path Fill="#e0e0e0" <Path Fill="#e0e0e0"
Stretch="None" Stretch="None"
RenderTransformOrigin="0,0"> RenderTransformOrigin="0,0">
<Path.RenderTransform>
<TranslateTransform X="-8" Y="-8"/>
</Path.RenderTransform>
<Path.Data> <Path.Data>
M 8 8 H 32 V 32 H 8 Z M22 5C22 3.34315 20.6569 2 19 2H5C3.34315 2 2 3.34315 2 5V19C2 20.6569 3.34315 22 5 22H19C20.6569 22 22 20.6569 22 19V5ZM20 5C20 4.44772 19.5523 4 19 4H5C4.44772 4 4 4.44772 4 5V19C4 19.5523 4.44772 20 5 20H19C19.5523 20 20 19.5523 20 19V5Z
</Path.Data> </Path.Data>
</Path> </Path>
</Button> </Button>
<!-- Fast Forward --> <!-- Fast Forward -->
<Button Command="{Binding FastForwardCommand}" <Button Command="{Binding FastForwardCommand}"
Width="40" Width="32"
Height="40" Height="32"
Background="Black"
Grid.Column="5" Grid.Column="5"
ToolTip.Tip="Fast Forward"> ToolTip.Tip="Fast Forward">
<Path Fill="#e0e0e0" <Path Fill="#e0e0e0"
Stretch="None" Stretch="None"
RenderTransformOrigin="0,0"> RenderTransformOrigin="0,0">
<Path.RenderTransform>
<TranslateTransform X="-14" Y="-8"/>
</Path.RenderTransform>
<Path.Data> <Path.Data>
M 10 8 L 30 20 L 10 32 Z M 22 8 L 42 20 L 22 32 Z M5.60439 4.23093C4.94586 3.73136 4 4.20105 4 5.02762V18.9724C4 19.799 4.94586 20.2686 5.60439 19.7691L14.7952 12.7967C15.3227 12.3965 15.3227 11.6035 14.7952 11.2033L5.60439 4.23093ZM2 5.02762C2 2.54789 4.83758 1.13883 6.81316 2.63755L16.004 9.60993C17.5865 10.8104 17.5865 13.1896 16.004 14.3901L6.81316 21.3625C4.83758 22.8612 2 21.4521 2 18.9724V5.02762Z
M20 3C20 2.44772 20.4477 2 21 2C21.5523 2 22 2.44772 22 3V21C22 21.5523 21.5523 22 21 22C20.4477 22 20 21.5523 20 21V3Z
</Path.Data> </Path.Data>
</Path> </Path>
</Button> </Button>
@ -147,14 +135,14 @@
Foreground="#f0f0f0" Foreground="#f0f0f0"
VerticalAlignment="Center" VerticalAlignment="Center"
Grid.Column="0" Grid.Column="0"
Margin="20,10,8,0"/> Margin="20,4,8,0"/>
<Slider Minimum="0.25" <Slider Minimum="0.25"
Maximum="2.0" Maximum="2.0"
Value="{Binding PlaybackSpeed}" Value="{Binding PlaybackSpeed}"
Width="260" Width="260"
Grid.Column="1" Grid.Column="1"
Margin="0,10,8,0"/> Margin="0,4,8,0"/>
<TextBlock Text="{Binding PlaybackSpeed, StringFormat='x{0:F2}'}" <TextBlock Text="{Binding PlaybackSpeed, StringFormat='x{0:F2}'}"
Foreground="#c0c0c0" Foreground="#c0c0c0"
@ -181,35 +169,39 @@
Margin="0,0,6,0"/> Margin="0,0,6,0"/>
<Button Command="{Binding SetPointACommand}" <Button Command="{Binding SetPointACommand}"
Width="40" Width="32"
Height="40" Height="32"
Grid.Column="1" Grid.Column="1"
Background="Black"
Margin="0,0,6,0" Margin="0,0,6,0"
ToolTip.Tip="Set Loop Point A"> ToolTip.Tip="Set Loop Point A">
<Grid> <Grid>
<Path Fill="#0080ff" <Path Fill="#e0e0e0"
Data="M 26 8 Stretch="None"
L 26 32 RenderTransformOrigin="0,0">
L 14 32 <Path.Data>
L 24 20 M18.3956 19.7691C19.0541 20.2687 20 19.799 20 18.9724L20 5.02764C20 4.20106 19.0541 3.73137 18.3956 4.23095L9.20476 11.2033C8.67727 11.6035 8.67727 12.3965 9.20476 12.7967L18.3956 19.7691ZM22 18.9724C22 21.4521 19.1624 22.8612 17.1868 21.3625L7.99598 14.3901C6.41353 13.1896 6.41353 10.8104 7.99599 9.60994L17.1868 2.63757C19.1624 1.13885 22 2.5479 22 5.02764L22 18.9724Z
L 14 8 M2 3C2 2.44772 2.44772 2 3 2C3.55228 2 4 2.44772 4 3V21C4 21.5523 3.55228 22 3 22C2.44772 22 2 21.5523 2 21V3Z
L 26 8" /> </Path.Data>
</Path>
</Grid> </Grid>
</Button> </Button>
<Button Command="{Binding SetPointBCommand}" <Button Command="{Binding SetPointBCommand}"
Width="40" Width="32"
Height="40" Height="32"
Background="Black"
Grid.Column="2" Grid.Column="2"
ToolTip.Tip="Set Loop Point B"> ToolTip.Tip="Set Loop Point B">
<Grid> <Grid>
<Path Fill="#0080ff" <Path Fill="#e0e0e0"
Data="M 14 8 Stretch="None"
L 14 32 RenderTransformOrigin="0,0">
L 26 32 <Path.Data>
L 16 20 M5.60439 4.23093C4.94586 3.73136 4 4.20105 4 5.02762V18.9724C4 19.799 4.94586 20.2686 5.60439 19.7691L14.7952 12.7967C15.3227 12.3965 15.3227 11.6035 14.7952 11.2033L5.60439 4.23093ZM2 5.02762C2 2.54789 4.83758 1.13883 6.81316 2.63755L16.004 9.60993C17.5865 10.8104 17.5865 13.1896 16.004 14.3901L6.81316 21.3625C4.83758 22.8612 2 21.4521 2 18.9724V5.02762Z
L 26 8 M20 3C20 2.44772 20.4477 2 21 2C21.5523 2 22 2.44772 22 3V21C22 21.5523 21.5523 22 21 22C20.4477 22 20 21.5523 20 21V3Z
L 14 8"/> </Path.Data>
</Path>
</Grid> </Grid>
</Button> </Button>
</Grid> </Grid>

195
README.md Normal file
View File

@ -0,0 +1,195 @@
# ABStemPlayer
ABStemPlayer is a Avalonia 12 audio player application built with .NET, designed for
realtime media processing, modern UI rendering, and crossplatform deployment.
The project focuses on predictable performance, clean architecture, and productiongrade
engineering practices.
![ABStemPlayer-UI](ABStemPlayer-UI.png)
## Features
- Stem splitting and mixing
- Drums
- Bass
- Other
- Vocals
- Guitar
- Piano
- Turn each stem on and off independently
- Pan stems left or right
- Audio player with A/B looping and speed control
**Techy stuff:**
- .NET 10
- Crossplatform UI built with Avalonia 12
- ONNX Runtime integration for ML inference
- htdemucs_6s.onnx for stem splitting
> YOU HAVE TO DOWNLOAD htdemucs_6s.onnx YOURSELF DUE TO GITHUB SIZE LIMITATIONS
> https://huggingface.co/StemSplitio/htdemucs-6s-onnx/blob/main/htdemucs_6s.onnx
## Requirements
- .NET 10 or later
- Avalonia 12
- ONNX Runtime (CPU or GPU)
- FFmpeg
# HTDemucs 6Stem ONNX Model Guide
## Overview
**HTDemucs6s** is a stateoftheart music source separation model capable of splitting a stereo mix into **six distinct stems**:
- Drums
- Bass
- Vocals
- Guitar
- Piano
- Other
The model is designed for **highfidelity separation**, **low artifacts**, and **robust performance** on modern CPU inference engines.
---
## Required Model File
```
File Name: htdemucs_6s.onnx
Placement: Place the model inside your application's data directory: /Data/htdemucs_6s.onnx
```
### Why this model
This ONNX export is specifically built for:
- **CPU inference**
- **float32 audio processing**
- **6stem output**
- **44.1 kHz stereo input**
Using any other Demucs variant (4stem, hybrid, GPUoptimized, etc.) will result in incompatible tensor shapes.
---
## Model Input Specification
### Input Tensor Name
```
mix
```
### Input Shape
```
[1, 2, N]
```
Where:
- `1` = batch size
- `2` = stereo channels
- `N` = number of audio samples in the segment
### Audio Requirements
- **Sample rate:** 44,100 Hz
- **Channels:** Stereo
- **Format:** float32 PCM
- **Normalization:** Standard waveform scaling
---
## Model Output Specification
### Output Tensor Name
```
stems
```
### Output Shape
```
[1, 6, 2, N]
```
Where:
- `1` = batch
- `6` = stems
- `2` = stereo
- `N` = same segment length as input
Each stem is returned as a stereo float32 waveform.
---
## Technical Details
HTDemucs6s is based on the **Hybrid Demucs architecture**, combining:
- Convolutional encoder/decoder
- Multiband processing
- Transformer blocks for longrange context
- Overlapadd reconstruction
- Sixhead output layer
This design allows the model to preserve transients, maintain stereo imaging, and reduce musical bleed between stems.
### Supported ONNX Operations
The model uses only standard ONNX ops, including:
- Conv / ConvTranspose
- LayerNorm / GroupNorm
- MultiHead Attention
- GELU / ReLU
- Reshape / Transpose
- Basic arithmetic ops
This ensures full compatibility with CPU execution providers.
---
## Downloading the Correct Model
Make sure you download the **HTDemucs 6stem ONNX export**, not:
- 4stem Demucs
- Hybrid Demucs v3/v4 PyTorch checkpoints
- GPUoptimized ONNX models
- Models with different sample rates
If you need a verified download link, choose:
- **https://huggingface.co/StemSplitio/htdemucs-6s-onnx/blob/main/htdemucs_6s.onnx**
---
## Verification
To ensure you have the correct model, check:
| Property | Expected |
|---------|----------|
| File name | `htdemucs_6s.onnx` |
| Input tensor | `mix` |
| Input shape | `[1, 2, N]` |
| Output tensor | `stems` |
| Output shape | `[1, 6, 2, N]` |
| Sample rate | 44.1 kHz |
| Channels | Stereo |
| Stems | 6 |
| Execution | CPU |
SHA256: `48F8E84945579F8AB340E083339E9221E03785DBE733A52C388200B6D3CA779A`
---
# Copyright notices
## Icons
```
COLLECTION: Gentlecons Interface Icons
LICENSE: CC Attribution License
AUTHOR: Konstantin Filatov
```