From 44756e0277955dfb90c44f83b84928ca5126326e Mon Sep 17 00:00:00 2001 From: dexy Date: Sat, 7 Mar 2020 23:05:03 +1100 Subject: [PATCH] Added audio playback to cutscene viewer --- CodeWalker/World/CutsceneForm.Designer.cs | 112 ++++++-- CodeWalker/World/CutsceneForm.cs | 300 +++++++++++++++++++++- 2 files changed, 376 insertions(+), 36 deletions(-) diff --git a/CodeWalker/World/CutsceneForm.Designer.cs b/CodeWalker/World/CutsceneForm.Designer.cs index 0f9cc69..911daa0 100644 --- a/CodeWalker/World/CutsceneForm.Designer.cs +++ b/CodeWalker/World/CutsceneForm.Designer.cs @@ -40,11 +40,16 @@ this.TimeLabel = new System.Windows.Forms.Label(); this.PlayStopButton = new System.Windows.Forms.Button(); this.PlaybackTimer = new System.Windows.Forms.Timer(this.components); + this.VolumeLabel = new System.Windows.Forms.Label(); + this.VolumeTrackBar = new System.Windows.Forms.TrackBar(); + this.SubtitlesCheckBox = new System.Windows.Forms.CheckBox(); + this.AudioCheckBox = new System.Windows.Forms.CheckBox(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); this.splitContainer1.Panel1.SuspendLayout(); this.splitContainer1.Panel2.SuspendLayout(); this.splitContainer1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.TimeTrackBar)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.VolumeTrackBar)).BeginInit(); this.SuspendLayout(); // // label3 @@ -53,7 +58,7 @@ this.label3.Location = new System.Drawing.Point(10, 10); this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(55, 13); - this.label3.TabIndex = 3; + this.label3.TabIndex = 0; this.label3.Text = "Cutscene:"; // // CutsceneComboBox @@ -65,8 +70,8 @@ this.CutsceneComboBox.FormattingEnabled = true; this.CutsceneComboBox.Location = new System.Drawing.Point(71, 7); this.CutsceneComboBox.Name = "CutsceneComboBox"; - this.CutsceneComboBox.Size = new System.Drawing.Size(529, 21); - this.CutsceneComboBox.TabIndex = 2; + this.CutsceneComboBox.Size = new System.Drawing.Size(639, 21); + this.CutsceneComboBox.TabIndex = 1; this.CutsceneComboBox.SelectedIndexChanged += new System.EventHandler(this.CutsceneComboBox_SelectedIndexChanged); // // splitContainer1 @@ -74,7 +79,7 @@ this.splitContainer1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.splitContainer1.Location = new System.Drawing.Point(1, 70); + this.splitContainer1.Location = new System.Drawing.Point(1, 99); this.splitContainer1.Name = "splitContainer1"; // // splitContainer1.Panel1 @@ -84,9 +89,9 @@ // splitContainer1.Panel2 // this.splitContainer1.Panel2.Controls.Add(this.InfoPropertyGrid); - this.splitContainer1.Size = new System.Drawing.Size(722, 330); + this.splitContainer1.Size = new System.Drawing.Size(722, 361); this.splitContainer1.SplitterDistance = 259; - this.splitContainer1.TabIndex = 4; + this.splitContainer1.TabIndex = 13; // // CutsceneTreeView // @@ -98,8 +103,8 @@ this.CutsceneTreeView.Name = "CutsceneTreeView"; this.CutsceneTreeView.ShowLines = false; this.CutsceneTreeView.ShowRootLines = false; - this.CutsceneTreeView.Size = new System.Drawing.Size(259, 330); - this.CutsceneTreeView.TabIndex = 1; + this.CutsceneTreeView.Size = new System.Drawing.Size(259, 361); + this.CutsceneTreeView.TabIndex = 14; this.CutsceneTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.CutsceneTreeView_AfterSelect); // // InfoPropertyGrid @@ -108,19 +113,18 @@ this.InfoPropertyGrid.HelpVisible = false; this.InfoPropertyGrid.Location = new System.Drawing.Point(0, 0); this.InfoPropertyGrid.Name = "InfoPropertyGrid"; - this.InfoPropertyGrid.Size = new System.Drawing.Size(459, 330); - this.InfoPropertyGrid.TabIndex = 0; + this.InfoPropertyGrid.Size = new System.Drawing.Size(459, 361); + this.InfoPropertyGrid.TabIndex = 15; // // AnimateCameraCheckBox // - this.AnimateCameraCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.AnimateCameraCheckBox.AutoSize = true; this.AnimateCameraCheckBox.Checked = true; this.AnimateCameraCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; - this.AnimateCameraCheckBox.Location = new System.Drawing.Point(617, 9); + this.AnimateCameraCheckBox.Location = new System.Drawing.Point(250, 74); this.AnimateCameraCheckBox.Name = "AnimateCameraCheckBox"; this.AnimateCameraCheckBox.Size = new System.Drawing.Size(102, 17); - this.AnimateCameraCheckBox.TabIndex = 5; + this.AnimateCameraCheckBox.TabIndex = 8; this.AnimateCameraCheckBox.Text = "Animate camera"; this.AnimateCameraCheckBox.UseVisualStyleBackColor = true; this.AnimateCameraCheckBox.CheckedChanged += new System.EventHandler(this.AnimateCameraCheckBox_CheckedChanged); @@ -131,30 +135,29 @@ | System.Windows.Forms.AnchorStyles.Right))); this.TimeTrackBar.AutoSize = false; this.TimeTrackBar.LargeChange = 0; - this.TimeTrackBar.Location = new System.Drawing.Point(91, 34); + this.TimeTrackBar.Location = new System.Drawing.Point(12, 34); this.TimeTrackBar.Maximum = 100; this.TimeTrackBar.Name = "TimeTrackBar"; - this.TimeTrackBar.Size = new System.Drawing.Size(509, 30); - this.TimeTrackBar.TabIndex = 7; + this.TimeTrackBar.Size = new System.Drawing.Size(700, 30); + this.TimeTrackBar.TabIndex = 2; this.TimeTrackBar.Scroll += new System.EventHandler(this.TimeTrackBar_Scroll); this.TimeTrackBar.MouseUp += new System.Windows.Forms.MouseEventHandler(this.TimeTrackBar_MouseUp); // // TimeLabel // - this.TimeLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.TimeLabel.AutoSize = true; - this.TimeLabel.Location = new System.Drawing.Point(614, 41); + this.TimeLabel.Location = new System.Drawing.Point(103, 75); this.TimeLabel.Name = "TimeLabel"; - this.TimeLabel.Size = new System.Drawing.Size(60, 13); - this.TimeLabel.TabIndex = 8; + this.TimeLabel.Size = new System.Drawing.Size(129, 16); + this.TimeLabel.TabIndex = 7; this.TimeLabel.Text = "0.00 / 0.00"; + this.TimeLabel.TextAlign = System.Drawing.ContentAlignment.TopCenter; // // PlayStopButton // - this.PlayStopButton.Location = new System.Drawing.Point(10, 36); + this.PlayStopButton.Location = new System.Drawing.Point(13, 70); this.PlayStopButton.Name = "PlayStopButton"; this.PlayStopButton.Size = new System.Drawing.Size(75, 23); - this.PlayStopButton.TabIndex = 9; + this.PlayStopButton.TabIndex = 3; this.PlayStopButton.Text = "Play"; this.PlayStopButton.UseVisualStyleBackColor = true; this.PlayStopButton.Click += new System.EventHandler(this.PlayStopButton_Click); @@ -163,11 +166,66 @@ // this.PlaybackTimer.Tick += new System.EventHandler(this.PlaybackTimer_Tick); // + // VolumeLabel + // + this.VolumeLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.VolumeLabel.AutoSize = true; + this.VolumeLabel.Location = new System.Drawing.Point(549, 75); + this.VolumeLabel.Name = "VolumeLabel"; + this.VolumeLabel.Size = new System.Drawing.Size(56, 13); + this.VolumeLabel.TabIndex = 11; + this.VolumeLabel.Text = "🕩 Volume"; + // + // VolumeTrackBar + // + this.VolumeTrackBar.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.VolumeTrackBar.AutoSize = false; + this.VolumeTrackBar.BackColor = System.Drawing.SystemColors.Control; + this.VolumeTrackBar.LargeChange = 10; + this.VolumeTrackBar.Location = new System.Drawing.Point(605, 71); + this.VolumeTrackBar.Maximum = 100; + this.VolumeTrackBar.Name = "VolumeTrackBar"; + this.VolumeTrackBar.Size = new System.Drawing.Size(105, 28); + this.VolumeTrackBar.TabIndex = 12; + this.VolumeTrackBar.TickStyle = System.Windows.Forms.TickStyle.None; + this.VolumeTrackBar.Value = 50; + this.VolumeTrackBar.Scroll += new System.EventHandler(this.VolumeTrackBar_Scroll); + // + // SubtitlesCheckBox + // + this.SubtitlesCheckBox.AutoSize = true; + this.SubtitlesCheckBox.Checked = true; + this.SubtitlesCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.SubtitlesCheckBox.Location = new System.Drawing.Point(368, 74); + this.SubtitlesCheckBox.Name = "SubtitlesCheckBox"; + this.SubtitlesCheckBox.Size = new System.Drawing.Size(66, 17); + this.SubtitlesCheckBox.TabIndex = 9; + this.SubtitlesCheckBox.Text = "Subtitles"; + this.SubtitlesCheckBox.UseVisualStyleBackColor = true; + this.SubtitlesCheckBox.CheckedChanged += new System.EventHandler(this.SubtitlesCheckBox_CheckedChanged); + // + // AudioCheckBox + // + this.AudioCheckBox.AutoSize = true; + this.AudioCheckBox.Checked = true; + this.AudioCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.AudioCheckBox.Location = new System.Drawing.Point(450, 74); + this.AudioCheckBox.Name = "AudioCheckBox"; + this.AudioCheckBox.Size = new System.Drawing.Size(53, 17); + this.AudioCheckBox.TabIndex = 10; + this.AudioCheckBox.Text = "Audio"; + this.AudioCheckBox.UseVisualStyleBackColor = true; + this.AudioCheckBox.CheckedChanged += new System.EventHandler(this.AudioCheckBox_CheckedChanged); + // // CutsceneForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(724, 401); + this.ClientSize = new System.Drawing.Size(724, 461); + this.Controls.Add(this.VolumeTrackBar); + this.Controls.Add(this.AudioCheckBox); + this.Controls.Add(this.SubtitlesCheckBox); + this.Controls.Add(this.VolumeLabel); this.Controls.Add(this.PlayStopButton); this.Controls.Add(this.TimeLabel); this.Controls.Add(this.TimeTrackBar); @@ -178,6 +236,7 @@ this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Name = "CutsceneForm"; this.Text = "Cutscene Viewer - CodeWalker by dexyfex"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.CutsceneForm_FormClosing); this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.CutsceneForm_FormClosed); this.Load += new System.EventHandler(this.CutsceneForm_Load); this.splitContainer1.Panel1.ResumeLayout(false); @@ -185,6 +244,7 @@ ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); this.splitContainer1.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.TimeTrackBar)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.VolumeTrackBar)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -202,5 +262,9 @@ private System.Windows.Forms.Label TimeLabel; private System.Windows.Forms.Button PlayStopButton; private System.Windows.Forms.Timer PlaybackTimer; + private System.Windows.Forms.Label VolumeLabel; + private System.Windows.Forms.TrackBar VolumeTrackBar; + private System.Windows.Forms.CheckBox SubtitlesCheckBox; + private System.Windows.Forms.CheckBox AudioCheckBox; } } \ No newline at end of file diff --git a/CodeWalker/World/CutsceneForm.cs b/CodeWalker/World/CutsceneForm.cs index 9a116bb..0a5c26f 100644 --- a/CodeWalker/World/CutsceneForm.cs +++ b/CodeWalker/World/CutsceneForm.cs @@ -1,5 +1,6 @@ using CodeWalker.GameFiles; using CodeWalker.Rendering; +using CodeWalker.Utils; using SharpDX; using System; using System.Collections.Generic; @@ -18,13 +19,16 @@ namespace CodeWalker.World { private WorldForm WorldForm; private GameFileCache GameFileCache; + private AudioDatabase AudioDatabase; private Cutscene Cutscene = null; private bool AnimateCamera = true; + private bool EnableSubtitles = true; + private bool EnableAudio = true; private bool Playing = false; private bool PositionScrolled = false; - + private float Volume = 0.5f; class CutsceneDropdownItem { @@ -40,6 +44,7 @@ namespace CodeWalker.World { WorldForm = worldForm; GameFileCache = WorldForm.GameFileCache; + AudioDatabase = new AudioDatabase(); InitializeComponent(); } @@ -53,6 +58,14 @@ namespace CodeWalker.World { var newt = Cutscene.PlaybackTime + elapsed; Cutscene.Update(newt); + + if (Cutscene.PlaybackTime != newt) + { + if (EnableAudio) // handle looping cutscenes, loop the audio also + { + BeginInvoke(new Action(() => PlayAudio(Cutscene.PlaybackTime))); + } + } } if (AnimateCamera && (Cutscene.CameraObject != null)) @@ -99,6 +112,11 @@ namespace CodeWalker.World if (GameFileCache.IsInited) { + if (!AudioDatabase.IsInited) + { + AudioDatabase.Init(GameFileCache); + } + var entry = dditem?.RpfEntry as RpfFileEntry; if (entry != null) { @@ -107,7 +125,7 @@ namespace CodeWalker.World GameFileCache.RpfMan.LoadFile(cutFile, entry); cutscene = new Cutscene(); - cutscene.Init(cutFile, GameFileCache, WorldForm); + cutscene.Init(cutFile, GameFileCache, WorldForm, AudioDatabase); } } @@ -129,8 +147,20 @@ namespace CodeWalker.World return; } + DisposeAudio(); + Cutscene = cs; + if (cs != null) + { + cs.EnableSubtitles = EnableSubtitles; + + if (Playing) + { + PlayAudio(cs.PlaybackTime); + } + } + LoadTreeView(cs); TimeTrackBar.Maximum = (int)(cs.Duration * 10.0f); @@ -211,8 +241,52 @@ namespace CodeWalker.World - - + private void PlayAudio(float playTime = 0.0f) + { + StopAudio(); + if (!EnableAudio) return; + var sp = Cutscene?.SoundPlayer; + if (sp != null) + { + sp.SetVolume(Volume); + sp.Play(Cutscene.SoundStartOffset + playTime); + } + } + private void StopAudio() + { + var sp = Cutscene?.SoundPlayer; + if (sp != null) + { + sp.Stop(); + } + } + private void PauseAudio() + { + if (!EnableAudio) return; + var sp = Cutscene?.SoundPlayer; + if (sp != null) + { + sp.Pause(); + } + } + private void ResumeAudio() + { + if (!EnableAudio) return; + var sp = Cutscene?.SoundPlayer; + if (sp != null) + { + sp.Resume(); + } + } + private void DisposeAudio() + { + var sp = Cutscene?.SoundPlayer; + if (sp != null) + { + sp.Stop(); + sp.DisposeAudio(); + } + } private void CutsceneForm_Load(object sender, EventArgs e) @@ -242,6 +316,11 @@ namespace CodeWalker.World } + private void CutsceneForm_FormClosing(object sender, FormClosingEventArgs e) + { + DisposeAudio(); + } + private void CutsceneForm_FormClosed(object sender, FormClosedEventArgs e) { WorldForm?.OnCutsceneFormClosed(); @@ -275,6 +354,31 @@ namespace CodeWalker.World } } + private void SubtitlesCheckBox_CheckedChanged(object sender, EventArgs e) + { + EnableSubtitles = SubtitlesCheckBox.Checked; + if (Cutscene != null) + { + Cutscene.EnableSubtitles = EnableSubtitles; + } + } + + private void AudioCheckBox_CheckedChanged(object sender, EventArgs e) + { + EnableAudio = AudioCheckBox.Checked; + if (!EnableAudio) + { + StopAudio(); + } + else + { + if (Playing && (Cutscene != null)) + { + PlayAudio(Cutscene.PlaybackTime); + } + } + } + private void PlayStopButton_Click(object sender, EventArgs e) { if (Playing) @@ -282,12 +386,14 @@ namespace CodeWalker.World Playing = false; PlayStopButton.Text = "Play"; PlaybackTimer.Enabled = false; + StopAudio(); } else { Playing = true; PlayStopButton.Text = "Stop"; PlaybackTimer.Enabled = true; + PlayAudio(Cutscene.PlaybackTime); } } @@ -309,6 +415,11 @@ namespace CodeWalker.World if (Cutscene != null) { Cutscene.Update(t); + + if (Playing) + { + PlayAudio(t); + } } if (!Playing) @@ -327,11 +438,17 @@ namespace CodeWalker.World PositionScrolled = false; var f = Math.Min(Math.Max((e.X - 13.0f) / (TimeTrackBar.Width - 26.0f), 0.0f), 1.0f); - var v = f * (TimeTrackBar.Maximum / 10.0f); + var t = f * (TimeTrackBar.Maximum / 10.0f); if (Cutscene != null) { - Cutscene.Update(v); + Cutscene.Update(t); + + if (Playing) + { + StopAudio(); + PlayAudio(t); + } } if (!Playing) @@ -340,6 +457,16 @@ namespace CodeWalker.World UpdateTimeLabel(); } } + + private void VolumeTrackBar_Scroll(object sender, EventArgs e) + { + Volume = VolumeTrackBar.Value / 100.0f; + var sp = Cutscene?.SoundPlayer; + if (sp != null) + { + sp.SetVolume(Volume); + } + } } @@ -348,6 +475,7 @@ namespace CodeWalker.World public CutFile CutFile { get; set; } = null; private GameFileCache GameFileCache = null; private WorldForm WorldForm = null; + private AudioDatabase AudioDB = null; public float[] CameraCutList { get; set; } = null; public YcdFile[] Ycds { get; set; } = null; @@ -357,6 +485,8 @@ namespace CodeWalker.World public float PlaybackTime { get; set; } = 0.0f; private bool Seeking = false; + public bool EnableSubtitles { get; set; } = true; + public Dictionary Objects { get; set; } = null; public Dictionary SceneObjects { get; set; } = null; @@ -381,14 +511,17 @@ namespace CodeWalker.World public bool CameraClipUpdate = false;//signal to the form to update the camera clip planes public Quaternion CameraRotationOffset = Quaternion.RotationAxis(Vector3.UnitX, -1.57079632679f) * Quaternion.RotationAxis(Vector3.UnitZ, 3.141592653f); + public AudioPlayer SoundPlayer { get; set; } = null; + public float SoundStartOffset { get; set; } - public void Init(CutFile cutFile, GameFileCache gfc, WorldForm wf) + public void Init(CutFile cutFile, GameFileCache gfc, WorldForm wf, AudioDatabase adb) { CutFile = cutFile; GameFileCache = gfc; WorldForm = wf; + AudioDB = adb; var csf = cutFile?.CutsceneFile2; if (csf == null) return; @@ -766,6 +899,37 @@ namespace CodeWalker.World if (args == null) { return; } + var obje = e as CutObjectIdEvent; + if (obje == null) + { return; } + + var obj = obje.Object as CutAudioObject; + if (obj == null) + { return; } + + if (Seeking) return; + + if (SceneObjects.TryGetValue(obje.iObjectId, out CutsceneObject audobj)) + { + if (audobj.SoundPlayer != null) + { + SoundStartOffset = obj.fOffset; + if (SoundPlayer != audobj.SoundPlayer) + { + if (SoundPlayer != null) + { + SoundPlayer.Stop(); + SoundPlayer.DisposeAudio(); + SoundPlayer = null; + } + SoundPlayer = audobj.SoundPlayer; + } + } + else + { } + } + else + { } } private void LoadModels(CutEvent e) { @@ -962,6 +1126,7 @@ namespace CodeWalker.World if (args == null) { return; } + if (!EnableSubtitles) return; if (Seeking) return; //don't raise subtitle events while seeking backwards... if (WorldForm != null) @@ -1109,7 +1274,7 @@ namespace CodeWalker.World foreach (var obj in Objects.Values) { var sobj = new CutsceneObject(); - sobj.Init(obj, GameFileCache); + sobj.Init(obj, GameFileCache, AudioDB); SceneObjects[sobj.ObjectID] = sobj; if (sobj.AnimHash != 0) @@ -1148,10 +1313,14 @@ namespace CodeWalker.World public MetaHash AnimHash { get; set; } public ClipMapEntry AnimClip { get; set; } + public Dat54Sound SoundInfo { get; set; } + public AwcStream[] SoundStreams { get; set; } + public AudioPlayer SoundPlayer { get; set; } + public bool Enabled { get; set; } = false; - public void Init(CutObject obj, GameFileCache gfc) + public void Init(CutObject obj, GameFileCache gfc, AudioDatabase adb) { CutObject = obj; ObjectID = obj?.iObjectId ?? -1; @@ -1170,6 +1339,10 @@ namespace CodeWalker.World else if (obj is CutCameraObject cam) { } + else if (obj is CutAudioObject aud) + { + InitAudio(aud, gfc, adb); + } else if (obj is CutPedModelObject ped) { InitPed(ped, gfc); @@ -1214,9 +1387,6 @@ namespace CodeWalker.World else if (obj is CutOverlayObject ovr) { } - else if (obj is CutAudioObject aud) - { - } else if (obj is CutSubtitleObject sub) { } @@ -1230,6 +1400,112 @@ namespace CodeWalker.World { } } + private void InitAudio(CutAudioObject aud, GameFileCache gfc, AudioDatabase adb) + { + + //how to know the correct name/hash to use? + //sound name in the format: cutscenes_name_mastered_only + var name = aud.cName.ToCleanString().ToLowerInvariant().Replace(".wav", ""); + var soundname = "cutscenes_" + name + "_mastered"; + var soundname2 = "cutscenes_" + name + "_mastered_only"; + uint soundhash = JenkHash.GenHash(soundname); + uint soundhash2 = JenkHash.GenHash(soundname2); + + if (adb?.SoundsDB != null) + { + if (adb.SoundsDB.TryGetValue(soundhash, out Dat54Sound snd)) + { + SoundInfo = snd; + } + else if (adb.SoundsDB.TryGetValue(soundhash2, out Dat54Sound snd2)) + { + SoundInfo = snd2; + } + } + + + if (SoundInfo is Dat54StreamingSound strsnd) + { + int dur = strsnd.Duration; + MetaHash awchash = 0; + AwcFile awc = null; + + var streaminfs = new List(); + var streamlist = new List(); + + foreach (var chan in strsnd.AudioTracks) + { + if (chan is Dat54SimpleSound chansnd) + { + var chanawchash = chansnd.ContainerName; + if (chanawchash != awchash) + { + awchash = chanawchash; + if (adb.ContainerDB.TryGetValue(awchash, out RpfFileEntry awcentry)) + { + awc = new AwcFile(); + gfc.RpfMan.LoadFile(awc, awcentry); + } + else + { } + } + + if (awc?.StreamDict != null) + { + var chanhash = chansnd.FileName & 0x1FFFFFFF; + if (awc.StreamDict.TryGetValue(chanhash, out AwcStream chanstream)) + { + streaminfs.Add(chansnd); + streamlist.Add(chanstream); + } + else + { } + } + else + { } + } + else + { } + } + + var streams = streamlist.ToArray(); + + SoundPlayer = new AudioPlayer(); + SoundPlayer.LoadAudio(streams); + for (int i = 0; i < streaminfs.Count; i++) + { + var streaminf = streaminfs[i]; + var left = 1.0f; + var right = 1.0f; + switch (streaminf.Header?.Unk06 ?? 0) + { + case 0://center/default + left = 1.0f; + right = 1.0f; + break; + case 0x133: // 307://left channel + left = 1.0f; + right = 0.0f; + break; + case 0x35: // 53://right channel + left = 0.0f; + right = 1.0f; + break; + default: + break; + } + SoundPlayer.SetOutputMatrix(i, left, right); + } + + } + else if (SoundInfo != null) + { } + if (SoundInfo == null) + { } + + + } + private void InitPed(CutPedModelObject ped, GameFileCache gfc) {