mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2024-08-19 00:19:19 +08:00
Refactored AudioPlayer code, added seek ability to AwcForm player
This commit is contained in:
parent
93784bbc49
commit
56902d4f8b
39
CodeWalker/Forms/AwcForm.Designer.cs
generated
39
CodeWalker/Forms/AwcForm.Designer.cs
generated
@ -51,10 +51,10 @@
|
|||||||
this.PositionTrackBar = new System.Windows.Forms.TrackBar();
|
this.PositionTrackBar = new System.Windows.Forms.TrackBar();
|
||||||
this.DetailsTabPage = new System.Windows.Forms.TabPage();
|
this.DetailsTabPage = new System.Windows.Forms.TabPage();
|
||||||
this.DetailsPropertyGrid = new CodeWalker.WinForms.PropertyGridFix();
|
this.DetailsPropertyGrid = new CodeWalker.WinForms.PropertyGridFix();
|
||||||
this.Timer = new System.Windows.Forms.Timer(this.components);
|
|
||||||
this.saveFileDialog = new System.Windows.Forms.SaveFileDialog();
|
|
||||||
this.XmlTabPage = new System.Windows.Forms.TabPage();
|
this.XmlTabPage = new System.Windows.Forms.TabPage();
|
||||||
this.XmlTextBox = new FastColoredTextBoxNS.FastColoredTextBox();
|
this.XmlTextBox = new FastColoredTextBoxNS.FastColoredTextBox();
|
||||||
|
this.Timer = new System.Windows.Forms.Timer(this.components);
|
||||||
|
this.saveFileDialog = new System.Windows.Forms.SaveFileDialog();
|
||||||
this.MainTabControl.SuspendLayout();
|
this.MainTabControl.SuspendLayout();
|
||||||
this.PlayerTabPage.SuspendLayout();
|
this.PlayerTabPage.SuspendLayout();
|
||||||
this.contextMenuStrip.SuspendLayout();
|
this.contextMenuStrip.SuspendLayout();
|
||||||
@ -135,7 +135,7 @@
|
|||||||
this.VolumeLabel.AutoSize = true;
|
this.VolumeLabel.AutoSize = true;
|
||||||
this.VolumeLabel.Location = new System.Drawing.Point(538, 395);
|
this.VolumeLabel.Location = new System.Drawing.Point(538, 395);
|
||||||
this.VolumeLabel.Name = "VolumeLabel";
|
this.VolumeLabel.Name = "VolumeLabel";
|
||||||
this.VolumeLabel.Size = new System.Drawing.Size(60, 13);
|
this.VolumeLabel.Size = new System.Drawing.Size(56, 13);
|
||||||
this.VolumeLabel.TabIndex = 9;
|
this.VolumeLabel.TabIndex = 9;
|
||||||
this.VolumeLabel.Text = "🕩 Volume";
|
this.VolumeLabel.Text = "🕩 Volume";
|
||||||
//
|
//
|
||||||
@ -245,12 +245,13 @@
|
|||||||
// VolumeTrackBar
|
// VolumeTrackBar
|
||||||
//
|
//
|
||||||
this.VolumeTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
this.VolumeTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.VolumeTrackBar.AutoSize = false;
|
||||||
this.VolumeTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight;
|
this.VolumeTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight;
|
||||||
this.VolumeTrackBar.LargeChange = 10;
|
this.VolumeTrackBar.LargeChange = 10;
|
||||||
this.VolumeTrackBar.Location = new System.Drawing.Point(588, 391);
|
this.VolumeTrackBar.Location = new System.Drawing.Point(588, 391);
|
||||||
this.VolumeTrackBar.Maximum = 100;
|
this.VolumeTrackBar.Maximum = 100;
|
||||||
this.VolumeTrackBar.Name = "VolumeTrackBar";
|
this.VolumeTrackBar.Name = "VolumeTrackBar";
|
||||||
this.VolumeTrackBar.Size = new System.Drawing.Size(105, 45);
|
this.VolumeTrackBar.Size = new System.Drawing.Size(105, 28);
|
||||||
this.VolumeTrackBar.TabIndex = 6;
|
this.VolumeTrackBar.TabIndex = 6;
|
||||||
this.VolumeTrackBar.TickStyle = System.Windows.Forms.TickStyle.None;
|
this.VolumeTrackBar.TickStyle = System.Windows.Forms.TickStyle.None;
|
||||||
this.VolumeTrackBar.Value = 50;
|
this.VolumeTrackBar.Value = 50;
|
||||||
@ -260,15 +261,17 @@
|
|||||||
//
|
//
|
||||||
this.PositionTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
this.PositionTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.PositionTrackBar.AutoSize = false;
|
||||||
this.PositionTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight;
|
this.PositionTrackBar.BackColor = System.Drawing.SystemColors.ControlLightLight;
|
||||||
this.PositionTrackBar.LargeChange = 1000;
|
this.PositionTrackBar.LargeChange = 0;
|
||||||
this.PositionTrackBar.Location = new System.Drawing.Point(6, 353);
|
this.PositionTrackBar.Location = new System.Drawing.Point(6, 353);
|
||||||
this.PositionTrackBar.Maximum = 1000;
|
this.PositionTrackBar.Maximum = 1000;
|
||||||
this.PositionTrackBar.Name = "PositionTrackBar";
|
this.PositionTrackBar.Name = "PositionTrackBar";
|
||||||
this.PositionTrackBar.Size = new System.Drawing.Size(687, 45);
|
this.PositionTrackBar.Size = new System.Drawing.Size(687, 32);
|
||||||
this.PositionTrackBar.TabIndex = 1;
|
this.PositionTrackBar.TabIndex = 1;
|
||||||
this.PositionTrackBar.TickStyle = System.Windows.Forms.TickStyle.None;
|
this.PositionTrackBar.TickStyle = System.Windows.Forms.TickStyle.None;
|
||||||
this.PositionTrackBar.Scroll += new System.EventHandler(this.PositionTrackBar_Scroll);
|
this.PositionTrackBar.Scroll += new System.EventHandler(this.PositionTrackBar_Scroll);
|
||||||
|
this.PositionTrackBar.MouseUp += new System.Windows.Forms.MouseEventHandler(this.PositionTrackBar_MouseUp);
|
||||||
//
|
//
|
||||||
// DetailsTabPage
|
// DetailsTabPage
|
||||||
//
|
//
|
||||||
@ -290,17 +293,6 @@
|
|||||||
this.DetailsPropertyGrid.Size = new System.Drawing.Size(695, 416);
|
this.DetailsPropertyGrid.Size = new System.Drawing.Size(695, 416);
|
||||||
this.DetailsPropertyGrid.TabIndex = 0;
|
this.DetailsPropertyGrid.TabIndex = 0;
|
||||||
//
|
//
|
||||||
// Timer
|
|
||||||
//
|
|
||||||
this.Timer.Enabled = true;
|
|
||||||
this.Timer.Interval = 25;
|
|
||||||
this.Timer.Tick += new System.EventHandler(this.Timer_Tick);
|
|
||||||
//
|
|
||||||
// saveFileDialog
|
|
||||||
//
|
|
||||||
this.saveFileDialog.DefaultExt = "wav";
|
|
||||||
this.saveFileDialog.Filter = "Wave files (*.wav)|*.wav";
|
|
||||||
//
|
|
||||||
// XmlTabPage
|
// XmlTabPage
|
||||||
//
|
//
|
||||||
this.XmlTabPage.Controls.Add(this.XmlTextBox);
|
this.XmlTabPage.Controls.Add(this.XmlTextBox);
|
||||||
@ -327,7 +319,7 @@
|
|||||||
this.XmlTextBox.AutoIndentChars = false;
|
this.XmlTextBox.AutoIndentChars = false;
|
||||||
this.XmlTextBox.AutoIndentCharsPatterns = "";
|
this.XmlTextBox.AutoIndentCharsPatterns = "";
|
||||||
this.XmlTextBox.AutoIndentExistingLines = false;
|
this.XmlTextBox.AutoIndentExistingLines = false;
|
||||||
this.XmlTextBox.AutoScrollMinSize = new System.Drawing.Size(27, 14);
|
this.XmlTextBox.AutoScrollMinSize = new System.Drawing.Size(2, 14);
|
||||||
this.XmlTextBox.BackBrush = null;
|
this.XmlTextBox.BackBrush = null;
|
||||||
this.XmlTextBox.CharHeight = 14;
|
this.XmlTextBox.CharHeight = 14;
|
||||||
this.XmlTextBox.CharWidth = 8;
|
this.XmlTextBox.CharWidth = 8;
|
||||||
@ -353,6 +345,17 @@
|
|||||||
this.XmlTextBox.TextChanged += new System.EventHandler<FastColoredTextBoxNS.TextChangedEventArgs>(this.XmlTextBox_TextChanged);
|
this.XmlTextBox.TextChanged += new System.EventHandler<FastColoredTextBoxNS.TextChangedEventArgs>(this.XmlTextBox_TextChanged);
|
||||||
this.XmlTextBox.VisibleRangeChangedDelayed += new System.EventHandler(this.XmlTextBox_VisibleRangeChangedDelayed);
|
this.XmlTextBox.VisibleRangeChangedDelayed += new System.EventHandler(this.XmlTextBox_VisibleRangeChangedDelayed);
|
||||||
//
|
//
|
||||||
|
// Timer
|
||||||
|
//
|
||||||
|
this.Timer.Enabled = true;
|
||||||
|
this.Timer.Interval = 25;
|
||||||
|
this.Timer.Tick += new System.EventHandler(this.Timer_Tick);
|
||||||
|
//
|
||||||
|
// saveFileDialog
|
||||||
|
//
|
||||||
|
this.saveFileDialog.DefaultExt = "wav";
|
||||||
|
this.saveFileDialog.Filter = "Wave files (*.wav)|*.wav";
|
||||||
|
//
|
||||||
// AwcForm
|
// AwcForm
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
using CodeWalker.GameFiles;
|
using CodeWalker.GameFiles;
|
||||||
|
using CodeWalker.Utils;
|
||||||
using FastColoredTextBoxNS;
|
using FastColoredTextBoxNS;
|
||||||
using SharpDX.Multimedia;
|
|
||||||
using SharpDX.XAudio2;
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@ -16,12 +15,6 @@ namespace CodeWalker.Forms
|
|||||||
{
|
{
|
||||||
public AwcFile Awc { get; set; }
|
public AwcFile Awc { get; set; }
|
||||||
|
|
||||||
private AwcStream currentAudio;
|
|
||||||
private XAudio2 xAudio2;
|
|
||||||
private MasteringVoice masteringVoice;
|
|
||||||
private AudioBuffer audioBuffer;
|
|
||||||
private SourceVoice sourceVoice;
|
|
||||||
|
|
||||||
private string fileName;
|
private string fileName;
|
||||||
public string FileName
|
public string FileName
|
||||||
{
|
{
|
||||||
@ -34,23 +27,16 @@ namespace CodeWalker.Forms
|
|||||||
}
|
}
|
||||||
public string FilePath { get; set; }
|
public string FilePath { get; set; }
|
||||||
|
|
||||||
private enum PlayerState { Stopped, Playing, Paused };
|
|
||||||
private PlayerState playerState = PlayerState.Stopped;
|
|
||||||
|
|
||||||
private Stopwatch playtime;
|
|
||||||
private int playBeginMs;
|
|
||||||
private float trackLength;
|
|
||||||
private bool trackFinished;
|
|
||||||
|
|
||||||
private bool LoadingXml = false;
|
private bool LoadingXml = false;
|
||||||
private bool DelayHighlight = false;
|
private bool DelayHighlight = false;
|
||||||
|
|
||||||
|
private AudioPlayer Player = new AudioPlayer();
|
||||||
|
|
||||||
|
private bool PositionScrolled = false;
|
||||||
|
|
||||||
public AwcForm()
|
public AwcForm()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
playtime = new Stopwatch();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateFormTitle()
|
private void UpdateFormTitle()
|
||||||
@ -168,89 +154,12 @@ namespace CodeWalker.Forms
|
|||||||
{ }
|
{ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void Stop()
|
private void Stop()
|
||||||
{
|
{
|
||||||
if (playerState != PlayerState.Stopped)
|
Player.Stop();
|
||||||
{
|
UpdateUI();
|
||||||
sourceVoice.DestroyVoice();
|
UpdatePlayerButtons();
|
||||||
sourceVoice.Dispose();
|
|
||||||
audioBuffer.Stream.Dispose();
|
|
||||||
SetPlayerState(PlayerState.Stopped);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetPlayerState(PlayerState newState)
|
|
||||||
{
|
|
||||||
if (playerState != newState)
|
|
||||||
{
|
|
||||||
switch (newState)
|
|
||||||
{
|
|
||||||
case PlayerState.Playing:
|
|
||||||
if (playerState == PlayerState.Stopped)
|
|
||||||
playtime.Reset();
|
|
||||||
playtime.Start();
|
|
||||||
|
|
||||||
PlayButton.Text = "\u275A\u275A";
|
|
||||||
StopButton.Enabled = true;
|
|
||||||
LabelTime.Visible = true;
|
|
||||||
break;
|
|
||||||
case PlayerState.Paused:
|
|
||||||
playtime.Stop();
|
|
||||||
PlayButton.Text = "\u25B6";
|
|
||||||
StopButton.Enabled = true;
|
|
||||||
LabelTime.Visible = true;
|
|
||||||
break;
|
|
||||||
case PlayerState.Stopped:
|
|
||||||
playtime.Stop();
|
|
||||||
PlayButton.Text = "\u25B6";
|
|
||||||
LabelTime.Visible = false;
|
|
||||||
StopButton.Enabled = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
playerState = newState;
|
|
||||||
UpdateUI();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitializeAudio(AwcStream audio, float playBegin = 0)
|
|
||||||
{
|
|
||||||
currentAudio = audio;
|
|
||||||
trackLength = audio.Length;
|
|
||||||
|
|
||||||
if (xAudio2 == null)
|
|
||||||
{
|
|
||||||
xAudio2 = new XAudio2();
|
|
||||||
masteringVoice = new MasteringVoice(xAudio2);
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream wavStream = audio.GetWavStream();
|
|
||||||
SoundStream soundStream = new SoundStream(wavStream);
|
|
||||||
audioBuffer = new AudioBuffer
|
|
||||||
{
|
|
||||||
Stream = soundStream.ToDataStream(),
|
|
||||||
AudioBytes = (int)soundStream.Length,
|
|
||||||
Flags = BufferFlags.EndOfStream
|
|
||||||
};
|
|
||||||
if (playBegin > 0)
|
|
||||||
{
|
|
||||||
audioBuffer.PlayBegin = (int)(soundStream.Format.SampleRate * playBegin) / 128 * 128;
|
|
||||||
if (playtime.IsRunning)
|
|
||||||
playtime.Restart();
|
|
||||||
else
|
|
||||||
playtime.Reset();
|
|
||||||
playBeginMs = (int)(playBegin * 1000);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
playBeginMs = 0;
|
|
||||||
soundStream.Close();
|
|
||||||
wavStream.Close();
|
|
||||||
|
|
||||||
trackFinished = false;
|
|
||||||
sourceVoice = new SourceVoice(xAudio2, soundStream.Format, true);
|
|
||||||
sourceVoice.SubmitSourceBuffer(audioBuffer, soundStream.DecodedPacketsInfo);
|
|
||||||
sourceVoice.BufferEnd += (context) => trackFinished = true;
|
|
||||||
sourceVoice.SetVolume((float)VolumeTrackBar.Value / 100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Play()
|
private void Play()
|
||||||
@ -264,15 +173,18 @@ namespace CodeWalker.Forms
|
|||||||
|
|
||||||
if ((audio?.FormatChunk != null) || (audio?.StreamFormat != null))
|
if ((audio?.FormatChunk != null) || (audio?.StreamFormat != null))
|
||||||
{
|
{
|
||||||
InitializeAudio(audio);
|
Player.SetVolume(VolumeTrackBar.Value / 100.0f);
|
||||||
sourceVoice.Start();
|
Player.LoadAudio(audio);
|
||||||
SetPlayerState(PlayerState.Playing);
|
Player.Play();
|
||||||
}
|
}
|
||||||
else if (audio.MidiChunk != null)
|
else if (audio.MidiChunk != null)
|
||||||
{
|
{
|
||||||
//todo: play MIDI?
|
//todo: play MIDI?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateUI();
|
||||||
|
UpdatePlayerButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PlayPrevious()
|
private void PlayPrevious()
|
||||||
@ -307,41 +219,76 @@ namespace CodeWalker.Forms
|
|||||||
|
|
||||||
private void Pause()
|
private void Pause()
|
||||||
{
|
{
|
||||||
if (playerState == PlayerState.Playing)
|
Player.Pause();
|
||||||
{
|
UpdatePlayerButtons();
|
||||||
sourceVoice.Stop();
|
|
||||||
SetPlayerState(PlayerState.Paused);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Resume()
|
private void Resume()
|
||||||
{
|
{
|
||||||
if (playerState == PlayerState.Paused)
|
Player.Resume();
|
||||||
|
UpdatePlayerButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateUI()
|
||||||
|
{
|
||||||
|
if ((Player.State != AudioPlayer.PlayerState.Stopped) && Player.trackFinished)
|
||||||
{
|
{
|
||||||
sourceVoice.Start();
|
if (chbAutoJump.Checked)
|
||||||
SetPlayerState(PlayerState.Playing);
|
PlayNext();
|
||||||
|
else
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Player.State != AudioPlayer.PlayerState.Stopped)
|
||||||
|
{
|
||||||
|
int playedMs = Player.PlayTimeMS;
|
||||||
|
int totalMs = Player.TotalTimeMS;
|
||||||
|
PositionTrackBar.Maximum = totalMs;
|
||||||
|
PositionTrackBar.Value = playedMs < totalMs ? playedMs : totalMs;
|
||||||
|
|
||||||
|
LabelTime.Text = TimeSpan.FromSeconds(playedMs / 1000).ToString("m\\:ss")
|
||||||
|
+ " / " + TimeSpan.FromSeconds(totalMs / 1000).ToString("m\\:ss");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PositionTrackBar.Value = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PositionTrackBar_Scroll(object sender, EventArgs e)
|
private void UpdatePlayerButtons()
|
||||||
{
|
{
|
||||||
|
switch (Player.State)
|
||||||
//sourceVoice.Stop();
|
{
|
||||||
//InitializeAudio(currentAudio, PositionTrackBar.Value / 1000);
|
case AudioPlayer.PlayerState.Playing:
|
||||||
//sourceVoice.Start();
|
PlayButton.Text = "\u275A\u275A";
|
||||||
|
StopButton.Enabled = true;
|
||||||
|
LabelTime.Visible = true;
|
||||||
|
break;
|
||||||
|
case AudioPlayer.PlayerState.Paused:
|
||||||
|
PlayButton.Text = "\u25B6";
|
||||||
|
StopButton.Enabled = true;
|
||||||
|
LabelTime.Visible = true;
|
||||||
|
break;
|
||||||
|
case AudioPlayer.PlayerState.Stopped:
|
||||||
|
PlayButton.Text = "\u25B6";
|
||||||
|
StopButton.Enabled = true;
|
||||||
|
LabelTime.Visible = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void PlayButton_Click(object sender, EventArgs e)
|
private void PlayButton_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
switch (playerState)
|
switch (Player.State)
|
||||||
{
|
{
|
||||||
case PlayerState.Stopped:
|
case AudioPlayer.PlayerState.Stopped:
|
||||||
Play();
|
Play();
|
||||||
break;
|
break;
|
||||||
case PlayerState.Playing:
|
case AudioPlayer.PlayerState.Playing:
|
||||||
Pause();
|
Pause();
|
||||||
break;
|
break;
|
||||||
case PlayerState.Paused:
|
case AudioPlayer.PlayerState.Paused:
|
||||||
Resume();
|
Resume();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -362,36 +309,33 @@ namespace CodeWalker.Forms
|
|||||||
PlayNext();
|
PlayNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void VolumeTrackBar_Scroll(object sender, EventArgs e)
|
private void PositionTrackBar_Scroll(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (playerState == PlayerState.Playing)
|
PositionScrolled = true;
|
||||||
sourceVoice.SetVolume((float)VolumeTrackBar.Value / 100);
|
|
||||||
|
var t = PositionTrackBar.Value / 1000.0f;
|
||||||
|
|
||||||
|
Player.Seek(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateUI()
|
private void PositionTrackBar_MouseUp(object sender, MouseEventArgs e)
|
||||||
{
|
{
|
||||||
if (playerState != PlayerState.Stopped && trackFinished)
|
if (PositionScrolled)
|
||||||
{
|
{
|
||||||
if (chbAutoJump.Checked)
|
PositionScrolled = false;
|
||||||
PlayNext();
|
return;
|
||||||
else
|
|
||||||
Stop();
|
|
||||||
}
|
}
|
||||||
|
PositionScrolled = false;
|
||||||
|
|
||||||
if (playerState != PlayerState.Stopped)
|
var f = Math.Min(Math.Max((e.X-13.0f) / (PositionTrackBar.Width-26.0f), 0.0f), 1.0f);
|
||||||
{
|
var v = f * (PositionTrackBar.Maximum / 1000.0f);
|
||||||
int playedMs = (int)playtime.Elapsed.TotalMilliseconds + playBeginMs;
|
|
||||||
int totalMs = (int)(trackLength * 1000);
|
|
||||||
PositionTrackBar.Maximum = totalMs;
|
|
||||||
PositionTrackBar.Value = playedMs < totalMs ? playedMs : totalMs;
|
|
||||||
|
|
||||||
LabelTime.Text = TimeSpan.FromSeconds(playedMs / 1000).ToString("m\\:ss")
|
Player.Seek(v);
|
||||||
+ " / " + TimeSpan.FromSeconds(totalMs / 1000).ToString("m\\:ss");
|
}
|
||||||
}
|
|
||||||
else
|
private void VolumeTrackBar_Scroll(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
PositionTrackBar.Value = 0;
|
Player.SetVolume((float)VolumeTrackBar.Value / 100);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Timer_Tick(object sender, EventArgs e)
|
private void Timer_Tick(object sender, EventArgs e)
|
||||||
@ -401,19 +345,13 @@ namespace CodeWalker.Forms
|
|||||||
|
|
||||||
private void PlayListView_DoubleClick(object sender, EventArgs e)
|
private void PlayListView_DoubleClick(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (playerState == PlayerState.Playing)
|
|
||||||
Stop();
|
|
||||||
Play();
|
Play();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AwcForm_FormClosing(object sender, FormClosingEventArgs e)
|
private void AwcForm_FormClosing(object sender, FormClosingEventArgs e)
|
||||||
{
|
{
|
||||||
Stop();
|
Stop();
|
||||||
if (xAudio2 != null)
|
Player.DisposeAudio();
|
||||||
{
|
|
||||||
masteringVoice.Dispose();
|
|
||||||
xAudio2.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExportAsWav_Click(object sender, EventArgs e)
|
private void ExportAsWav_Click(object sender, EventArgs e)
|
||||||
|
223
CodeWalker/Utils/AudioUtils.cs
Normal file
223
CodeWalker/Utils/AudioUtils.cs
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
using CodeWalker.GameFiles;
|
||||||
|
using SharpDX.Multimedia;
|
||||||
|
using SharpDX.XAudio2;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace CodeWalker.Utils
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class AudioPlayer
|
||||||
|
{
|
||||||
|
|
||||||
|
private AwcStream currentAudio;
|
||||||
|
private Stream wavStream;
|
||||||
|
private SoundStream soundStream;
|
||||||
|
private XAudio2 xAudio2;
|
||||||
|
private MasteringVoice masteringVoice;
|
||||||
|
private AudioBuffer audioBuffer;
|
||||||
|
private SourceVoice sourceVoice;
|
||||||
|
|
||||||
|
public enum PlayerState { Stopped, Playing, Paused };
|
||||||
|
public PlayerState State { get; private set; } = PlayerState.Stopped;
|
||||||
|
|
||||||
|
private Stopwatch playtimer = new Stopwatch();
|
||||||
|
private int playBeginMs;
|
||||||
|
private float trackLength;
|
||||||
|
public bool trackFinished;
|
||||||
|
|
||||||
|
private float volume = 1.0f;
|
||||||
|
|
||||||
|
|
||||||
|
public int PlayTimeMS
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (int)playtimer.Elapsed.TotalMilliseconds + playBeginMs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public int TotalTimeMS
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (int)(trackLength * 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void LoadAudio(AwcStream audio)
|
||||||
|
{
|
||||||
|
if (audio != currentAudio)
|
||||||
|
{
|
||||||
|
CloseStreams();
|
||||||
|
|
||||||
|
currentAudio = audio;
|
||||||
|
trackLength = audio.Length;
|
||||||
|
wavStream = audio.GetWavStream();
|
||||||
|
soundStream = new SoundStream(wavStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CloseStreams()
|
||||||
|
{
|
||||||
|
if (soundStream != null)
|
||||||
|
{
|
||||||
|
soundStream.Close();
|
||||||
|
}
|
||||||
|
if (wavStream != null)
|
||||||
|
{
|
||||||
|
wavStream.Close();//is this necessary?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeAudio(float playBegin = 0)
|
||||||
|
{
|
||||||
|
if (xAudio2 == null)
|
||||||
|
{
|
||||||
|
xAudio2 = new XAudio2();
|
||||||
|
masteringVoice = new MasteringVoice(xAudio2);
|
||||||
|
}
|
||||||
|
|
||||||
|
wavStream.Position = 0;
|
||||||
|
soundStream.Position = 0;
|
||||||
|
audioBuffer = new AudioBuffer
|
||||||
|
{
|
||||||
|
Stream = soundStream.ToDataStream(),
|
||||||
|
AudioBytes = (int)soundStream.Length,
|
||||||
|
Flags = BufferFlags.EndOfStream
|
||||||
|
};
|
||||||
|
if (playBegin > 0)
|
||||||
|
{
|
||||||
|
audioBuffer.PlayBegin = (int)(soundStream.Format.SampleRate * playBegin) / 128 * 128;
|
||||||
|
if (playtimer.IsRunning)
|
||||||
|
{
|
||||||
|
playtimer.Restart();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
playtimer.Reset();
|
||||||
|
}
|
||||||
|
playBeginMs = (int)(playBegin * 1000);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
playBeginMs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
trackFinished = false;
|
||||||
|
sourceVoice = new SourceVoice(xAudio2, soundStream.Format, true);
|
||||||
|
sourceVoice.SubmitSourceBuffer(audioBuffer, soundStream.DecodedPacketsInfo);
|
||||||
|
sourceVoice.BufferEnd += (context) => trackFinished = true;
|
||||||
|
sourceVoice.SetVolume(volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetPlayerState(PlayerState newState)
|
||||||
|
{
|
||||||
|
if (State != newState)
|
||||||
|
{
|
||||||
|
switch (newState)
|
||||||
|
{
|
||||||
|
case PlayerState.Playing:
|
||||||
|
if (State == PlayerState.Stopped)
|
||||||
|
{
|
||||||
|
playtimer.Reset();
|
||||||
|
}
|
||||||
|
playtimer.Start();
|
||||||
|
break;
|
||||||
|
case PlayerState.Paused:
|
||||||
|
playtimer.Stop();
|
||||||
|
break;
|
||||||
|
case PlayerState.Stopped:
|
||||||
|
playtimer.Stop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
State = newState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetVolume(float v)
|
||||||
|
{
|
||||||
|
volume = v;
|
||||||
|
if (State == PlayerState.Playing)
|
||||||
|
{
|
||||||
|
sourceVoice.SetVolume(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DisposeAudio()
|
||||||
|
{
|
||||||
|
CloseStreams();
|
||||||
|
if (xAudio2 != null)
|
||||||
|
{
|
||||||
|
masteringVoice.Dispose();
|
||||||
|
xAudio2.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
if (State != PlayerState.Stopped)
|
||||||
|
{
|
||||||
|
sourceVoice.DestroyVoice();
|
||||||
|
sourceVoice.Dispose();
|
||||||
|
audioBuffer.Stream.Dispose();
|
||||||
|
SetPlayerState(PlayerState.Stopped);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Play(float playBegin = 0)
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
InitializeAudio(playBegin);
|
||||||
|
sourceVoice.Start();
|
||||||
|
SetPlayerState(PlayerState.Playing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Seek(float playBegin = 0)
|
||||||
|
{
|
||||||
|
if (State == PlayerState.Playing)
|
||||||
|
{
|
||||||
|
Play(playBegin);
|
||||||
|
}
|
||||||
|
else if (State == PlayerState.Paused)
|
||||||
|
{
|
||||||
|
var state = State;
|
||||||
|
Stop();
|
||||||
|
InitializeAudio(playBegin);
|
||||||
|
State = state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Pause()
|
||||||
|
{
|
||||||
|
if (State == PlayerState.Playing)
|
||||||
|
{
|
||||||
|
sourceVoice.Stop();
|
||||||
|
SetPlayerState(PlayerState.Paused);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Resume()
|
||||||
|
{
|
||||||
|
if (State == PlayerState.Paused)
|
||||||
|
{
|
||||||
|
sourceVoice.Start();
|
||||||
|
SetPlayerState(PlayerState.Playing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user