mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2026-05-15 09:14:54 +08:00
Added support for ADPCM codec, new features and bugfix in audio player
This commit is contained in:
+218
-144
@@ -1,78 +1,86 @@
|
||||
using CodeWalker.GameFiles;
|
||||
using SharpDX.Multimedia;
|
||||
using SharpDX.XAudio2;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace CodeWalker.Forms
|
||||
{
|
||||
public partial class AwcForm : Form
|
||||
{
|
||||
public AwcFile Awc { get; set; }
|
||||
|
||||
using CodeWalker.GameFiles;
|
||||
using SharpDX.Multimedia;
|
||||
using SharpDX.XAudio2;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace CodeWalker.Forms
|
||||
{
|
||||
public partial class AwcForm : Form
|
||||
{
|
||||
public AwcFile Awc { get; set; }
|
||||
|
||||
private AwcAudio currentAudio;
|
||||
private XAudio2 xAudio2;
|
||||
private MasteringVoice masteringVoice;
|
||||
private AudioBuffer audioBuffer;
|
||||
private SourceVoice sourceVoice;
|
||||
private SourceVoice sourceVoice;
|
||||
|
||||
private string fileName;
|
||||
public string FileName
|
||||
{
|
||||
get { return fileName; }
|
||||
set
|
||||
{
|
||||
fileName = value;
|
||||
UpdateFormTitle();
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
public AwcForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
playtime = new Stopwatch();
|
||||
}
|
||||
|
||||
private void UpdateFormTitle()
|
||||
{
|
||||
Text = fileName + " - AWC Player - CodeWalker by dexyfex";
|
||||
}
|
||||
|
||||
public void LoadAwc(AwcFile awc)
|
||||
{
|
||||
Awc = awc;
|
||||
DetailsPropertyGrid.SelectedObject = awc;
|
||||
|
||||
fileName = awc?.Name;
|
||||
if (string.IsNullOrEmpty(fileName))
|
||||
{
|
||||
fileName = awc?.FileEntry?.Name;
|
||||
}
|
||||
|
||||
PlayListView.Items.Clear();
|
||||
|
||||
float totalLength = 0;
|
||||
if (awc.Audios != null)
|
||||
{
|
||||
foreach (var audio in awc.Audios)
|
||||
{
|
||||
var item = PlayListView.Items.Add(audio.Name);
|
||||
item.SubItems.Add(audio.Type);
|
||||
item.SubItems.Add(audio.LengthStr);
|
||||
item.SubItems.Add(TextUtil.GetBytesReadable(audio.Data.Length));
|
||||
item.Tag = audio;
|
||||
totalLength += audio.Length;
|
||||
}
|
||||
}
|
||||
|
||||
LabelInfo.Text = awc.Audios.Length.ToString() + " track(s), Length: " + TimeSpan.FromSeconds((float)totalLength).ToString("m\\:ss");
|
||||
UpdateFormTitle();
|
||||
}
|
||||
|
||||
private string fileName;
|
||||
public string FileName
|
||||
{
|
||||
get { return fileName; }
|
||||
set
|
||||
{
|
||||
fileName = value;
|
||||
UpdateFormTitle();
|
||||
}
|
||||
}
|
||||
public string FilePath { get; set; }
|
||||
|
||||
private enum PlayerState { Stopped, Playing, Paused };
|
||||
private PlayerState playerState = PlayerState.Stopped;
|
||||
|
||||
private Stopwatch playtime;
|
||||
private float trackLength;
|
||||
|
||||
public AwcForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
playtime = new Stopwatch();
|
||||
}
|
||||
|
||||
private void UpdateFormTitle()
|
||||
{
|
||||
Text = fileName + " - AWC Player - CodeWalker by dexyfex";
|
||||
}
|
||||
|
||||
public void LoadAwc(AwcFile awc)
|
||||
{
|
||||
Awc = awc;
|
||||
DetailsPropertyGrid.SelectedObject = awc;
|
||||
|
||||
fileName = awc?.Name;
|
||||
if (string.IsNullOrEmpty(fileName))
|
||||
{
|
||||
fileName = awc?.FileEntry?.Name;
|
||||
}
|
||||
|
||||
PlayListView.Items.Clear();
|
||||
if (awc.Audios != null)
|
||||
{
|
||||
foreach (var audio in awc.Audios)
|
||||
{
|
||||
var item = PlayListView.Items.Add(audio.Name);
|
||||
item.SubItems.Add(audio.Type);
|
||||
item.SubItems.Add(audio.LengthStr);
|
||||
item.Tag = audio;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateFormTitle();
|
||||
}
|
||||
|
||||
private void Stop()
|
||||
{
|
||||
if (playerState != PlayerState.Stopped)
|
||||
@@ -82,8 +90,8 @@ namespace CodeWalker.Forms
|
||||
audioBuffer.Stream.Dispose();
|
||||
SetPlayerState(PlayerState.Stopped);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void SetPlayerState(PlayerState newState)
|
||||
{
|
||||
if (playerState != newState)
|
||||
@@ -94,60 +102,88 @@ namespace CodeWalker.Forms
|
||||
if (playerState == PlayerState.Stopped)
|
||||
playtime.Reset();
|
||||
playtime.Start();
|
||||
|
||||
PlayButton.Text = "\u275A\u275A";
|
||||
StopButton.Enabled = true;
|
||||
LabelTime.Visible = true;
|
||||
break;
|
||||
default:
|
||||
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(AwcAudio audio)
|
||||
}
|
||||
|
||||
private void InitializeAudio(AwcAudio audio, float playBegin = 0)
|
||||
{
|
||||
currentAudio = audio;
|
||||
trackLength = audio.Length;
|
||||
|
||||
if (xAudio2 == null)
|
||||
{
|
||||
xAudio2 = new XAudio2();
|
||||
masteringVoice = new MasteringVoice(xAudio2);
|
||||
{
|
||||
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
|
||||
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();
|
||||
|
||||
sourceVoice = new SourceVoice(xAudio2, soundStream.Format, true);
|
||||
trackFinished = false;
|
||||
sourceVoice = new SourceVoice(xAudio2, soundStream.Format, true);
|
||||
sourceVoice.SubmitSourceBuffer(audioBuffer, soundStream.DecodedPacketsInfo);
|
||||
sourceVoice.SetVolume((float)VolumeTrackBar.Value / 100);
|
||||
}
|
||||
|
||||
private void Play()
|
||||
{
|
||||
Stop();
|
||||
|
||||
sourceVoice.BufferEnd += (context) => trackFinished = true;
|
||||
sourceVoice.SetVolume((float)VolumeTrackBar.Value / 100);
|
||||
}
|
||||
|
||||
private void Play()
|
||||
{
|
||||
Stop();
|
||||
|
||||
if (PlayListView.SelectedItems.Count == 1)
|
||||
{
|
||||
var item = PlayListView.SelectedItems[0];
|
||||
var audio = item.Tag as AwcAudio;
|
||||
|
||||
{
|
||||
var item = PlayListView.SelectedItems[0];
|
||||
var audio = item.Tag as AwcAudio;
|
||||
|
||||
if (audio != null)
|
||||
{
|
||||
InitializeAudio(audio);
|
||||
InitializeAudio(audio);
|
||||
sourceVoice.Start();
|
||||
SetPlayerState(PlayerState.Playing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void PlayPrevious()
|
||||
{
|
||||
Stop();
|
||||
@@ -161,8 +197,8 @@ namespace CodeWalker.Forms
|
||||
Play();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void PlayNext()
|
||||
{
|
||||
Stop();
|
||||
@@ -176,33 +212,36 @@ namespace CodeWalker.Forms
|
||||
Play();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Pause()
|
||||
{
|
||||
private void Pause()
|
||||
{
|
||||
if (playerState == PlayerState.Playing)
|
||||
{
|
||||
sourceVoice.Stop();
|
||||
SetPlayerState(PlayerState.Paused);
|
||||
}
|
||||
}
|
||||
|
||||
sourceVoice.Stop();
|
||||
SetPlayerState(PlayerState.Paused);
|
||||
}
|
||||
}
|
||||
|
||||
private void Resume()
|
||||
{
|
||||
if (playerState == PlayerState.Paused)
|
||||
{
|
||||
sourceVoice.Start();
|
||||
SetPlayerState(PlayerState.Playing);
|
||||
sourceVoice.Start();
|
||||
SetPlayerState(PlayerState.Playing);
|
||||
}
|
||||
}
|
||||
|
||||
private void PositionTrackBar_Scroll(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void PlayButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
private void PositionTrackBar_Scroll(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
sourceVoice.Stop();
|
||||
InitializeAudio(currentAudio, PositionTrackBar.Value / 1000);
|
||||
sourceVoice.Start();
|
||||
}
|
||||
|
||||
private void PlayButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
switch (playerState)
|
||||
{
|
||||
case PlayerState.Stopped:
|
||||
@@ -214,33 +253,44 @@ namespace CodeWalker.Forms
|
||||
case PlayerState.Paused:
|
||||
Resume();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void PrevButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
PlayPrevious();
|
||||
}
|
||||
|
||||
private void NextButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
PlayNext();
|
||||
}
|
||||
|
||||
private void VolumeTrackBar_Scroll(object sender, EventArgs e)
|
||||
{
|
||||
if (playerState == PlayerState.Playing)
|
||||
sourceVoice.SetVolume((float)VolumeTrackBar.Value / 100);
|
||||
}
|
||||
}
|
||||
|
||||
private void Timer_Tick(object sender, EventArgs e)
|
||||
private void PrevButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
PlayPrevious();
|
||||
}
|
||||
|
||||
private void NextButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
PlayNext();
|
||||
}
|
||||
|
||||
private void VolumeTrackBar_Scroll(object sender, EventArgs e)
|
||||
{
|
||||
if (playerState == PlayerState.Playing)
|
||||
sourceVoice.SetVolume((float)VolumeTrackBar.Value / 100);
|
||||
}
|
||||
|
||||
private void UpdateUI()
|
||||
{
|
||||
if (playerState != PlayerState.Stopped && trackFinished)
|
||||
{
|
||||
if (chbAutoJump.Checked)
|
||||
PlayNext();
|
||||
else
|
||||
Stop();
|
||||
}
|
||||
|
||||
if (playerState != PlayerState.Stopped)
|
||||
{
|
||||
int playedMs = (int)playtime.Elapsed.TotalMilliseconds;
|
||||
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")
|
||||
+ " / " + TimeSpan.FromSeconds(totalMs / 1000).ToString("m\\:ss");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -248,6 +298,11 @@ namespace CodeWalker.Forms
|
||||
}
|
||||
}
|
||||
|
||||
private void Timer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
UpdateUI();
|
||||
}
|
||||
|
||||
private void PlayListView_DoubleClick(object sender, EventArgs e)
|
||||
{
|
||||
if (playerState == PlayerState.Playing)
|
||||
@@ -263,6 +318,25 @@ namespace CodeWalker.Forms
|
||||
masteringVoice.Dispose();
|
||||
xAudio2.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ExportAsWav_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (PlayListView.SelectedItems.Count == 1)
|
||||
{
|
||||
var item = PlayListView.SelectedItems[0];
|
||||
var audio = item.Tag as AwcAudio;
|
||||
|
||||
saveFileDialog.FileName = audio.Name + ".wav";
|
||||
if (saveFileDialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
Stream wavStream = audio.GetWavStream();
|
||||
FileStream stream = File.Create(saveFileDialog.FileName);
|
||||
wavStream.CopyTo(stream);
|
||||
stream.Close();
|
||||
wavStream.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user