Player

Basic setup

Now as we have the basic component ready, it is time to add some sound. AlphaTab comes with an audio synthesis engine named AlphaSynth to play the songs via Midi and a SoundFont2 file.

To get the player configured is also quite easy as it is enabled by default in the main control. alphaTab ships a free SoundFont2 file for usage on your website and it is already loaded by default. You can choose to load a different one using the LoadSoundFont method.

We just need to add some UI elements for the user to start/pause the playback and show the current position.

Main player controls

Now we need to add the required controls for the users to play and pause the audio. We will add one button for play/pause which will change the icon depending on the current playback state. And we will also add one button which stops the playback and moves the cursor back to start.

We will use the PlayPause() and Stop() to send the right signals to alphaTab and we use the PlayerStateChanged event to update the button icon. To ensure that the user does not interact with the player before it is ready, we will keep the buttons disabled until the player is ready.

We add the buttons right between the open button and the song info.

<Button Click="OnStopClicked" IsEnabled="{Binding IsPlayerReady}">
<sharp:IconBlock Icon="StepBackward" />
</Button>
<Button Click="OnPlayPauseClicked" IsEnabled="{Binding IsPlayerReady}">
<sharp:IconBlock x:Name="PlayPauseIcon" Icon="Play" />
</Button>

The result looks like this:

Showing the current time

In this step we will add a textual indicator the current position of the playback. You might use the provided information to also build a progress bar indicator for the users which could be even interactive with seeking. This tutorial will skip this part.

As in most other steps we will add some new XAML elements, corresponding properties and then hook it up with some the alphaTab event PlayerPositionChanged fill the necessary data.

We add the new TextBlocks after the song artist.

<TextBlock Text="{Binding CurrentTimePosition, StringFormat=mm\\:ss}" />
<TextBlock>/</TextBlock>
<TextBlock Text="{Binding TotalTimePosition, StringFormat=mm\\:ss}" />

Final Files

<Window
x:Class="AlphaTabTutorial.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:fa="http://schemas.awesome.incremented/wpf/xaml/fontawesome.sharp"
xmlns:local="clr-namespace:AlphaTabTutorial"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wpf="clr-namespace:AlphaTab.Wpf;assembly=AlphaTab.Windows"
Title="MainWindow"
Width="800"
Height="450"
d:DataContext="{d:DesignInstance local:MainWindow}"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Canvas>
<Border
Canvas.Left="0"
Canvas.Top="0"
Width="{Binding RelativeSource={RelativeSource AncestorType=Canvas}, Path=ActualWidth}"
Height="{Binding RelativeSource={RelativeSource AncestorType=Canvas}, Path=ActualHeight}"
Padding="70,0,0,0">
<wpf:AlphaTab x:Name="AlphaTab" Loaded="OnAlphaTabLoaded" />
</Border>
<Border
Canvas.Left="0"
Canvas.Top="0"
Height="{Binding RelativeSource={RelativeSource AncestorType=Canvas}, Path=ActualHeight}"
MinWidth="70"
VerticalAlignment="Stretch"
Background="#f7f7f7"
BorderBrush="#1f000000"
BorderThickness="0,0,1,0"
ClipToBounds="False">
<Border.Resources>
<Style TargetType="ListBox">
<Setter Property="SelectionMode" Value="Single" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Padding" Value="0" />
<Setter Property="MinWidth" Value="70" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="MaxWidth" Value="70" />
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="ListBoxItem">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Margin" Value="0" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="#08000000" />
<Setter Property="fa:IconBlock.Foreground" Value="#4972a1" />
<Setter Property="fa:IconBlock.Opacity" Value="1" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter Property="fa:IconBlock.Opacity" Value="0.5" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#1a000000" />
<Setter Property="fa:IconBlock.Opacity" Value="1" />
</Trigger>
</Style.Triggers>
</Style>
</Border.Resources>
<ListBox ItemsSource="{Binding Score.Tracks}" SelectedItem="{Binding SelectedTrack}">
<ListBox.ItemTemplate>
<ItemContainerTemplate DataType="model:Track">
<Grid Height="64">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="64" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<fa:IconBlock
Grid.Column="0"
Margin="0,0,5,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="32px"
Icon="Guitar"
Opacity="0.5" />
<TextBlock
Grid.Column="1"
VerticalAlignment="Center"
FontWeight="Bold"
Text="{Binding Name}" />
</Grid>
</ItemContainerTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>
</Canvas>
<Grid
Grid.Row="1"
Grid.Column="0"
Background="#436d9d">
<Grid.Resources>
<Style x:Key="ToolbarButtonBaseStyle" TargetType="ButtonBase">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="White" />
<Setter Property="FontSize" Value="16px" />
<Setter Property="Padding" Value="4" />
<Setter Property="Margin" Value="3,0" />
<Setter Property="Width" Value="40" />
<Setter Property="Height" Value="40" />
<Setter Property="Cursor" Value="{x:Static Cursors.Hand}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ButtonBase}">
<Border
Name="Chrome"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
SnapsToDevicePixels="true">
<ContentPresenter
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style BasedOn="{StaticResource ToolbarButtonBaseStyle}" TargetType="Button" />
<Style BasedOn="{StaticResource ToolbarButtonBaseStyle}" TargetType="ToggleButton">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="#5588c7" />
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="White" />
<Setter Property="Margin" Value="3,0" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
<Style TargetType="fa:IconBlock">
<Setter Property="Foreground" Value="White" />
<Setter Property="Margin" Value="3,0" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
<Style TargetType="ComboBox">
<Setter Property="Background" Value="#436d9d" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<Grid>
<ToggleButton
Name="ToggleButton"
ClickMode="Press"
Focusable="False"
IsChecked="{Binding Path=IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}">
<ToggleButton.Template>
<ControlTemplate TargetType="ToggleButton">
<Border Name="Border" Background="Transparent" />
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsChecked" Value="True">
<Setter TargetName="Border" Property="Background" Value="#5588c7" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ToggleButton.Template>
</ToggleButton>
<ContentPresenter
Name="ContentSite"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
IsHitTestVisible="False" />
<TextBox
Name="PART_EditableTextBox"
Padding="{TemplateBinding Padding}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="Transparent"
Focusable="True"
IsReadOnly="{TemplateBinding IsReadOnly}"
Visibility="Hidden" />
<Popup
Name="Popup"
AllowsTransparency="True"
Focusable="False"
IsOpen="{TemplateBinding IsDropDownOpen}"
Placement="Top"
PopupAnimation="Slide">
<Grid
Name="DropDown"
MinWidth="{TemplateBinding ActualWidth}"
MaxHeight="{TemplateBinding MaxDropDownHeight}"
SnapsToDevicePixels="True">
<Border
Name="DropDownBorder"
Background="{TemplateBinding Background}"
CornerRadius="0" />
<ScrollViewer SnapsToDevicePixels="True">
<ItemsPresenter KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel
Grid.Row="0"
Grid.Column="0"
Orientation="Horizontal">
<Button Click="OnOpenClick">
<fa:IconBlock Icon="FolderOpen" />
</Button>
<Button Click="OnStopClicked" IsEnabled="{Binding IsPlayerReady}">
<fa:IconBlock Icon="StepBackward" />
</Button>
<Button Click="OnPlayPauseClicked" IsEnabled="{Binding IsPlayerReady}">
<fa:IconBlock x:Name="PlayPauseIcon" Icon="Play" />
</Button>
<TextBlock FontWeight="Bold" Text="{Binding Score.Title}" />
<TextBlock>-</TextBlock>
<TextBlock Text="{Binding Score.Artist}" />
<TextBlock Text="{Binding CurrentTimePosition, StringFormat=mm\\:ss}" />
<TextBlock>/</TextBlock>
<TextBlock Text="{Binding TotalTimePosition, StringFormat=mm\\:ss}" />
</StackPanel>
<StackPanel
Grid.Row="0"
Grid.Column="1"
HorizontalAlignment="Right"
Orientation="Horizontal">
<ToggleButton IsChecked="{Binding IsMetronomeActive}">
<fa:IconBlock Icon="Edit" />
</ToggleButton>
<ToggleButton IsChecked="{Binding IsLooping}">
<fa:IconBlock Icon="Retweet" />
</ToggleButton>
<fa:IconBlock Icon="Search" />
<ComboBox
ItemStringFormat="{}{0:P0}"
ItemsSource="{Binding ZoomLevels}"
SelectedItem="{Binding CurrentZoomLevel}" />
<ComboBox
ItemStringFormat="{}{0}"
ItemsSource="{Binding LayoutModes}"
SelectedItem="{Binding CurrentLayoutMode}" />
</StackPanel>
</Grid>
<Grid
Grid.Row="0"
Grid.RowSpan="2"
Visibility="{Binding LoadingIndicatorVisibility}">
<Border Background="#80000000" />
<Border
Margin="0,20,0,0"
Padding="10"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Background="White">
<Border.Effect>
<DropShadowEffect
BlurRadius="10"
Direction="-90"
Opacity="0.3" />
</Border.Effect>
<TextBlock>
Music sheet is loading
</TextBlock>
</Border>
</Grid>
</Grid>
</Window>