Skip to content

Commit

Permalink
Initial implementation of MIDI playback.
Browse files Browse the repository at this point in the history
  • Loading branch information
std66 committed Nov 1, 2018
1 parent d286604 commit 3b04429
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 59 deletions.
2 changes: 1 addition & 1 deletion TomiSoft.LyricsEditor/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,5 @@
</ListView>
</DockPanel>
</Grid>
</DockPanel>
</DockPanel>
</Window>
3 changes: 3 additions & 0 deletions TomiSoft.LyricsEditor/TomiSoft.LyricsEditor.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="system.windows.controls.ribbon" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
Expand All @@ -50,6 +51,8 @@
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="UIAutomationProvider" />
<Reference Include="UIAutomationTypes" />
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
Expand Down
3 changes: 0 additions & 3 deletions TomiSoft.MP3Player/Playback/BASS/LocalAudioFilePlayback.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using TomiSoft.MP3Player.Encoder.Lame;
using TomiSoft.MP3Player.MediaInformation;
using TomiSoft.MP3Player.Utils;
using TomiSoft.MP3Player.Utils.Extensions;
using Un4seen.Bass;
using Un4seen.Bass.AddOn.Enc;

namespace TomiSoft.MP3Player.Playback.BASS {
/// <summary>
Expand Down
25 changes: 25 additions & 0 deletions TomiSoft.MP3Player/Playback/BASS/LocalMidiFilePlayback.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using TomiSoft.MP3Player.MediaInformation;
using TomiSoft.MP3Player.Utils;
using Un4seen.Bass.AddOn.Midi;

namespace TomiSoft.MP3Player.Playback.BASS {
class LocalMidiFilePlayback : LocalAudioFilePlayback {
public LocalMidiFilePlayback(string Filename, string SoundfontFilename) : base(Filename) {
this.ApplySoundfontToStream(SoundfontFilename);
}

public LocalMidiFilePlayback(UnmanagedStream MediaStream, ISongInfo SongInfo, string SoundfontFilename)
: base(MediaStream, SongInfo) {
this.ApplySoundfontToStream(SoundfontFilename);
}

private void ApplySoundfontToStream(string SoundfontFilename) {
int FontHandle = BassMidi.BASS_MIDI_FontInit(SoundfontFilename);
if (FontHandle != 0) {
BASS_MIDI_FONT Font = new BASS_MIDI_FONT(FontHandle, -1, 0);

BassMidi.BASS_MIDI_StreamSetFonts(this.ChannelID, new BASS_MIDI_FONT[] { Font }, 1); // apply it to the stream
}
}
}
}
63 changes: 34 additions & 29 deletions TomiSoft.MP3Player/Playback/PlaybackFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@ namespace TomiSoft.MP3Player.Playback {
/// Provides a simple way of loading media to play.
/// </summary>
public class PlaybackFactory {
/// <summary>
/// Stores the last IPlaybackManager instance.
/// </summary>
private static IPlaybackManager lastInstance;

public static event Action<double, string> MediaOpenProgressChanged;

/// <summary>
Expand All @@ -31,8 +26,8 @@ public async static Task<IPlaybackManager> LoadMedia(ISongInfo SongInfo) {
#region Error checking
if (SongInfo == null)
throw new ArgumentNullException(nameof(SongInfo));
#endregion

#endregion
//If the Source is file:
if (File.Exists(SongInfo.Source)) {
string Extension = PlayerUtils.GetFileExtension(SongInfo.Source);
Expand All @@ -42,21 +37,32 @@ public async static Task<IPlaybackManager> LoadMedia(ISongInfo SongInfo) {

//In case of any file supported by BASS:
if (BassManager.GetSupportedExtensions().Contains(Extension)) {
//If Audio CD track:
if (Extension == "cda") {
lastInstance = new AudioCdPlayback(SongInfo.Source);
return lastInstance;
}

//Any other stuff...
using (Stream SourceStream = File.OpenRead(SongInfo.Source)) {
lastInstance = new LocalAudioFilePlayback(
await UnmanagedStream.CreateFromStream(SourceStream, FileOpenProgress),
SongInfo
);
}

return lastInstance;
//If Audio CD track:
if (Extension == "cda") {
return new AudioCdPlayback(SongInfo.Source);
}
else {
using (Stream SourceStream = File.OpenRead(SongInfo.Source)) {
var unmanagedStream = await UnmanagedStream.CreateFromStream(SourceStream, FileOpenProgress);

//If Midi file:
if (new string[] { "mid", "midi", "kar", "rmi" }.Contains(Extension)) {
return new LocalMidiFilePlayback(
unmanagedStream,
SongInfo,
@"C:\SGM-V2.01.sf2"
);
}

//Any other stuff...
else {
return new LocalAudioFilePlayback(
unmanagedStream,
SongInfo
);
}
}
}
}
}

Expand All @@ -67,10 +73,11 @@ await UnmanagedStream.CreateFromStream(SourceStream, FileOpenProgress),
Progress<LongOperationProgress> Progress = new Progress<LongOperationProgress>();
Progress.ProgressChanged += OpenFileProgressChanged;

lastInstance = await YoutubePlayback.DownloadVideoAsync(SongInfo, Progress);
IPlaybackManager Result = await YoutubePlayback.DownloadVideoAsync(SongInfo, Progress);

Progress.ProgressChanged -= OpenFileProgressChanged;
return lastInstance;

return Result;
}
}

Expand All @@ -95,11 +102,9 @@ private static void OpenFileProgressChanged(object sender, LongOperationProgress
/// <param name="Volume">The volume to initialize with.</param>
/// <returns>An <see cref="IPlaybackManager"/> that represents the Null-Playback manager instance</returns>
public static IPlaybackManager NullPlayback(int Volume) {
lastInstance = new NullPlayback() {
Volume = Volume
};

return lastInstance;
return new NullPlayback() {
Volume = Volume
};
}

/// <summary>
Expand Down
1 change: 1 addition & 0 deletions TomiSoft.MP3Player/TomiSoft.MP3Player.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
<Compile Include="MediaInformation\SongInfo.cs" />
<Compile Include="MediaInformation\YoutubeSongInfo.cs" />
<Compile Include="Playback\BASS\AudioCdPlayback.cs" />
<Compile Include="Playback\BASS\LocalMidiFilePlayback.cs" />
<Compile Include="Playback\ISavable.cs" />
<Compile Include="Playback\YouTube\YoutubePlayback.cs" />
<Compile Include="Settings.cs" />
Expand Down
53 changes: 27 additions & 26 deletions TomiSoft.MP3Player/UserInterface/Controls/PlaybackControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,55 +7,56 @@
xmlns:local="clr-namespace:TomiSoft_MP3_Player" x:Class="TomiSoft_MP3_Player.PlaybackControl"
mc:Ignorable="d"
d:DesignHeight="93.999" d:DesignWidth="267">
<UserControl.Resources>
<local:DoubleToTimeConverter x:Key="DoubleToTimeConverter" />
</UserControl.Resources>
<Grid>
<UserControl.Resources>
<local:DoubleToTimeConverter x:Key="DoubleToTimeConverter" />
</UserControl.Resources>
<Grid>

<!-- Playback position and volume control sliders -->
<Slider x:Name="UI_PlaybackPosition" VerticalAlignment="Top" Value="{Binding PlaybackManager.Position, FallbackValue=0}" Margin="9,32,96,0" Maximum="{Binding PlaybackManager.Length, Mode=OneWay}" Height="18"/>
<Slider x:Name="UI_Volume" VerticalAlignment="Top" Value="{Binding PlaybackManager.Volume, FallbackValue=100}" Minimum="0" Margin="0,32,8,0" Maximum="100" Height="18" HorizontalAlignment="Right" Width="73"/>
<Slider x:Name="UI_PlaybackPosition" VerticalAlignment="Top" Value="{Binding PlaybackManager.Position, FallbackValue=0}" Margin="9,32,96,0" Maximum="{Binding PlaybackManager.Length, Mode=OneWay}" Height="18"/>
<Slider x:Name="UI_Volume" VerticalAlignment="Top" Value="{Binding PlaybackManager.Volume, FallbackValue=100}" Minimum="0" Margin="0,32,8,0" Maximum="100" Height="18" HorizontalAlignment="Right" Width="73"/>

<!-- VU meter -->
<ProgressBar x:Name="UI_LeftPeakMeter" VerticalAlignment="Bottom" Value="{Binding PeakMeter.LeftPeak, Mode=OneWay, FallbackValue=0}" Margin="5,0,5,13" Maximum="32768" Height="5" Foreground="White" Background="Black" BorderBrush="#FF535353"/>
<ProgressBar x:Name="UI_RightPeakMeter" VerticalAlignment="Bottom" Value="{Binding PeakMeter.RightPeak, Mode=OneWay, FallbackValue=0}" SmallChange="1" Margin="5,0,5,6" Maximum="32768" Height="5" Foreground="White" BorderBrush="#FF535353" Background="Black" BorderThickness="1"/>
<ProgressBar x:Name="UI_RightPeakMeter" VerticalAlignment="Bottom" Value="{Binding PeakMeter.RightPeak, Mode=OneWay, FallbackValue=0}" SmallChange="1" Margin="5,0,5,6" Maximum="32768" Height="5" Foreground="White" BorderBrush="#FF535353" Background="Black" BorderThickness="1"/>

<Button x:Name="UI_PlayButton" Width="23" VerticalAlignment="Top" Margin="21,7,0,0" Height="20" HorizontalAlignment="Left" Click="UI_PlayButton_Click">
<Button.Content>
<fa:ImageAwesome Icon="Play" Margin="3"/>
</Button.Content>
<fa:ImageAwesome Icon="Play" Margin="3"/>
</Button.Content>
</Button>
<Button x:Name="UI_PauseButton" Width="23" VerticalAlignment="Top" Margin="46,7,0,0" Height="20" HorizontalAlignment="Left" Click="UI_PauseButton_Click">
<Button.Content>
<fa:ImageAwesome Icon="Pause" Margin="3"/>
</Button.Content>
<fa:ImageAwesome Icon="Pause" Margin="3"/>
</Button.Content>
</Button>
<Button x:Name="UI_StopButton" Width="23" VerticalAlignment="Top" Margin="71,7,0,0" Height="20" HorizontalAlignment="Left" Click="UI_StopButton_Click">
<Button.Content>
<fa:ImageAwesome Icon="Stop" Margin="3"/>
</Button.Content>
<fa:ImageAwesome Icon="Stop" Margin="3"/>
</Button.Content>
</Button>

<Button x:Name="UI_MuteButton" VerticalAlignment="Top" Margin="0,7,32,0" Height="20" HorizontalAlignment="Right" Width="23" Click="UI_MuteButton_Click">
<Button.Content>
<fa:ImageAwesome Icon="VolumeUp" Margin="3"/>
</Button.Content>
</Button>
<Button x:Name="UI_MuteButton" VerticalAlignment="Top" Margin="0,7,32,0" Height="20" HorizontalAlignment="Right" Width="23" Click="UI_MuteButton_Click">
<Button.Content>
<fa:ImageAwesome Icon="VolumeUp" Margin="3"/>
</Button.Content>
</Button>

<Label x:Name="UI_CurrentTime" Width="60" VerticalAlignment="Top" Margin="5,50,0,0" Height="25" HorizontalAlignment="Left" Foreground="#FF8D8D8D" Content="{Binding PlaybackManager.Position, Converter={StaticResource ResourceKey=DoubleToTimeConverter}, FallbackValue='00:00:00'}" Background="#00000000"/>
<Label x:Name="UI_TotalTime" VerticalAlignment="Top" Margin="0,50,96,0" Height="25" HorizontalContentAlignment="Right" Foreground="#FF8D8D8D" Content="{Binding PlaybackManager.Length, Converter={StaticResource ResourceKey=DoubleToTimeConverter}, FallbackValue='00:00:00'}" BorderBrush="White" HorizontalAlignment="Right" Width="54" Background="#00000000"/>
<Label x:Name="UI_CurrentTime" Width="60" VerticalAlignment="Top" Margin="5,50,0,0" Height="25" HorizontalAlignment="Left" Foreground="#FF8D8D8D" Content="{Binding PlaybackManager.Position, Converter={StaticResource ResourceKey=DoubleToTimeConverter}, FallbackValue='00:00:00'}" Background="#00000000"/>
<Label x:Name="UI_TotalTime" VerticalAlignment="Top" Margin="0,50,96,0" Height="25" HorizontalContentAlignment="Right" Foreground="#FF8D8D8D" Content="{Binding PlaybackManager.Length, Converter={StaticResource ResourceKey=DoubleToTimeConverter}, FallbackValue='00:00:00'}" BorderBrush="White" HorizontalAlignment="Right" Width="54" Background="#00000000"/>

<!-- Playlist previous and next buttons -->
<Button x:Name="UI_PreviousSong" Width="23" VerticalAlignment="Top" Margin="109,7,0,0" Height="20" HorizontalAlignment="Left" Click="UI_PreviousSong_Click">
<Button.Content>
<fa:ImageAwesome Icon="StepBackward" Margin="3"/>
</Button.Content>
<fa:ImageAwesome Icon="StepBackward" Margin="3"/>
</Button.Content>
</Button>
<Button x:Name="UI_NextSong" Width="23" VerticalAlignment="Top" Margin="134,7,0,0" Height="20" HorizontalAlignment="Left" Click="UI_NextSong_Click">
<Button.Content>
<fa:ImageAwesome Icon="StepForward" Margin="3"/>
</Button.Content>
<fa:ImageAwesome Icon="StepForward" Margin="3"/>
</Button.Content>
</Button>
<ProgressBar x:Name="UI_LeftPeakMeter_Copy" Value="2" Margin="191,61,8,0" Maximum="4" Foreground="White" Background="Black" BorderBrush="#FF535353" Height="5" VerticalAlignment="Top" Visibility="Hidden"/>

</Grid>
</UserControl>

0 comments on commit 3b04429

Please sign in to comment.