From 209f39a62fee35b7b1a5d18c996cf3914fd838c4 Mon Sep 17 00:00:00 2001 From: 1987kostya Date: Sun, 20 Dec 2020 10:48:53 +0600 Subject: [PATCH] Add SoundPlayer --- DotNetCTFDumper/DotNetCTFDumper.csproj | 1 + DotNetCTFDumper/GUI/MainForm.Designer.cs | 184 +++++++++++------- DotNetCTFDumper/GUI/MainForm.cs | 143 +++++++++++--- .../MMFParser/EXE/Loaders/Banks/SoundBank.cs | 2 +- DotNetCTFDumper/Utils/WAVReading.cs | 175 +++++++++++++++++ 5 files changed, 405 insertions(+), 100 deletions(-) create mode 100644 DotNetCTFDumper/Utils/WAVReading.cs diff --git a/DotNetCTFDumper/DotNetCTFDumper.csproj b/DotNetCTFDumper/DotNetCTFDumper.csproj index 42c12a0..1de74f2 100644 --- a/DotNetCTFDumper/DotNetCTFDumper.csproj +++ b/DotNetCTFDumper/DotNetCTFDumper.csproj @@ -229,6 +229,7 @@ + diff --git a/DotNetCTFDumper/GUI/MainForm.Designer.cs b/DotNetCTFDumper/GUI/MainForm.Designer.cs index 58e4c82..44c8dbe 100644 --- a/DotNetCTFDumper/GUI/MainForm.Designer.cs +++ b/DotNetCTFDumper/GUI/MainForm.Designer.cs @@ -68,11 +68,14 @@ this.plusCharBtn = new System.Windows.Forms.Button(); this.hexBox1 = new Be.Windows.Forms.HexBox(); this.charBox = new System.Windows.Forms.TextBox(); - this.advDumpTab = new System.Windows.Forms.TabPage(); - this.advancedInfoLabel = new System.Windows.Forms.Label(); - this.advancedPlayAnimation = new System.Windows.Forms.Button(); - this.advancedPictureBox = new System.Windows.Forms.PictureBox(); - this.advancedTreeView = new System.Windows.Forms.TreeView(); + this.imgViewerTab = new System.Windows.Forms.TabPage(); + this.imageViewerInfo = new System.Windows.Forms.Label(); + this.imageViewerPlayAnim = new System.Windows.Forms.Button(); + this.imageViewPictureBox = new System.Windows.Forms.PictureBox(); + this.imagesTreeView = new System.Windows.Forms.TreeView(); + this.soundViewTab = new System.Windows.Forms.TabPage(); + this.soundList = new System.Windows.Forms.TreeView(); + this.playSoundBtn = new System.Windows.Forms.Button(); this.pluginTab = new System.Windows.Forms.TabPage(); this.pluginLogBox = new System.Windows.Forms.TextBox(); this.activatePluginBtn = new System.Windows.Forms.Button(); @@ -84,8 +87,9 @@ this.mfaTab.SuspendLayout(); this.packDataTab.SuspendLayout(); this.cryptKeyTab.SuspendLayout(); - this.advDumpTab.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize) (this.advancedPictureBox)).BeginInit(); + this.imgViewerTab.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize) (this.imageViewPictureBox)).BeginInit(); + this.soundViewTab.SuspendLayout(); this.pluginTab.SuspendLayout(); this.SuspendLayout(); // @@ -386,7 +390,8 @@ this.tabControl1.Controls.Add(this.mfaTab); this.tabControl1.Controls.Add(this.packDataTab); this.tabControl1.Controls.Add(this.cryptKeyTab); - this.tabControl1.Controls.Add(this.advDumpTab); + this.tabControl1.Controls.Add(this.imgViewerTab); + this.tabControl1.Controls.Add(this.soundViewTab); this.tabControl1.Controls.Add(this.pluginTab); this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; this.tabControl1.Font = new System.Drawing.Font("Courier New", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (204))); @@ -590,61 +595,91 @@ this.charBox.Text = "54"; this.charBox.TextChanged += new System.EventHandler(this.charBox_TextChanged); // - // advDumpTab - // - this.advDumpTab.BackColor = System.Drawing.Color.DimGray; - this.advDumpTab.Controls.Add(this.advancedInfoLabel); - this.advDumpTab.Controls.Add(this.advancedPlayAnimation); - this.advDumpTab.Controls.Add(this.advancedPictureBox); - this.advDumpTab.Controls.Add(this.advancedTreeView); - this.advDumpTab.ForeColor = System.Drawing.Color.FromArgb(((int) (((byte) (255)))), ((int) (((byte) (128)))), ((int) (((byte) (0))))); - this.advDumpTab.Location = new System.Drawing.Point(4, 24); - this.advDumpTab.Name = "advDumpTab"; - this.advDumpTab.Padding = new System.Windows.Forms.Padding(3); - this.advDumpTab.Size = new System.Drawing.Size(935, 479); - this.advDumpTab.TabIndex = 1; - this.advDumpTab.Text = "Advanced"; - // - // advancedInfoLabel - // - this.advancedInfoLabel.Anchor = ((System.Windows.Forms.AnchorStyles) ((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.advancedInfoLabel.BackColor = System.Drawing.Color.FromArgb(((int) (((byte) (64)))), ((int) (((byte) (64)))), ((int) (((byte) (64))))); - this.advancedInfoLabel.Location = new System.Drawing.Point(777, 3); - this.advancedInfoLabel.Name = "advancedInfoLabel"; - this.advancedInfoLabel.Size = new System.Drawing.Size(155, 63); - this.advancedInfoLabel.TabIndex = 3; - this.advancedInfoLabel.Text = "DEBUG"; - // - // advancedPlayAnimation - // - this.advancedPlayAnimation.Dock = System.Windows.Forms.DockStyle.Bottom; - this.advancedPlayAnimation.Location = new System.Drawing.Point(170, 441); - this.advancedPlayAnimation.Name = "advancedPlayAnimation"; - this.advancedPlayAnimation.Size = new System.Drawing.Size(762, 35); - this.advancedPlayAnimation.TabIndex = 2; - this.advancedPlayAnimation.Text = "Play Animation"; - this.advancedPlayAnimation.UseVisualStyleBackColor = true; - this.advancedPlayAnimation.Click += new System.EventHandler(this.advancedPlayAnimation_Click); - // - // advancedPictureBox - // - this.advancedPictureBox.BackColor = System.Drawing.Color.FromArgb(((int) (((byte) (64)))), ((int) (((byte) (64)))), ((int) (((byte) (64))))); - this.advancedPictureBox.Dock = System.Windows.Forms.DockStyle.Fill; - this.advancedPictureBox.Location = new System.Drawing.Point(170, 3); - this.advancedPictureBox.Name = "advancedPictureBox"; - this.advancedPictureBox.Size = new System.Drawing.Size(762, 473); - this.advancedPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; - this.advancedPictureBox.TabIndex = 1; - this.advancedPictureBox.TabStop = false; - // - // advancedTreeView - // - this.advancedTreeView.Dock = System.Windows.Forms.DockStyle.Left; - this.advancedTreeView.Location = new System.Drawing.Point(3, 3); - this.advancedTreeView.Name = "advancedTreeView"; - this.advancedTreeView.Size = new System.Drawing.Size(167, 473); - this.advancedTreeView.TabIndex = 0; - this.advancedTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.advancedTreeView_AfterSelect); + // imgViewerTab + // + this.imgViewerTab.BackColor = System.Drawing.Color.DimGray; + this.imgViewerTab.Controls.Add(this.imageViewerInfo); + this.imgViewerTab.Controls.Add(this.imageViewerPlayAnim); + this.imgViewerTab.Controls.Add(this.imageViewPictureBox); + this.imgViewerTab.Controls.Add(this.imagesTreeView); + this.imgViewerTab.ForeColor = System.Drawing.Color.FromArgb(((int) (((byte) (255)))), ((int) (((byte) (128)))), ((int) (((byte) (0))))); + this.imgViewerTab.Location = new System.Drawing.Point(4, 24); + this.imgViewerTab.Name = "imgViewerTab"; + this.imgViewerTab.Padding = new System.Windows.Forms.Padding(3); + this.imgViewerTab.Size = new System.Drawing.Size(935, 479); + this.imgViewerTab.TabIndex = 1; + this.imgViewerTab.Text = "Images"; + // + // imageViewerInfo + // + this.imageViewerInfo.Anchor = ((System.Windows.Forms.AnchorStyles) ((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.imageViewerInfo.BackColor = System.Drawing.Color.FromArgb(((int) (((byte) (64)))), ((int) (((byte) (64)))), ((int) (((byte) (64))))); + this.imageViewerInfo.Location = new System.Drawing.Point(777, 3); + this.imageViewerInfo.Name = "imageViewerInfo"; + this.imageViewerInfo.Size = new System.Drawing.Size(155, 63); + this.imageViewerInfo.TabIndex = 3; + this.imageViewerInfo.Text = "DEBUG"; + // + // imageViewerPlayAnim + // + this.imageViewerPlayAnim.Dock = System.Windows.Forms.DockStyle.Bottom; + this.imageViewerPlayAnim.Location = new System.Drawing.Point(170, 441); + this.imageViewerPlayAnim.Name = "imageViewerPlayAnim"; + this.imageViewerPlayAnim.Size = new System.Drawing.Size(762, 35); + this.imageViewerPlayAnim.TabIndex = 2; + this.imageViewerPlayAnim.Text = "Play Animation"; + this.imageViewerPlayAnim.UseVisualStyleBackColor = true; + this.imageViewerPlayAnim.Click += new System.EventHandler(this.advancedPlayAnimation_Click); + // + // imageViewPictureBox + // + this.imageViewPictureBox.BackColor = System.Drawing.Color.FromArgb(((int) (((byte) (64)))), ((int) (((byte) (64)))), ((int) (((byte) (64))))); + this.imageViewPictureBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.imageViewPictureBox.Location = new System.Drawing.Point(170, 3); + this.imageViewPictureBox.Name = "imageViewPictureBox"; + this.imageViewPictureBox.Size = new System.Drawing.Size(762, 473); + this.imageViewPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; + this.imageViewPictureBox.TabIndex = 1; + this.imageViewPictureBox.TabStop = false; + // + // imagesTreeView + // + this.imagesTreeView.Dock = System.Windows.Forms.DockStyle.Left; + this.imagesTreeView.Location = new System.Drawing.Point(3, 3); + this.imagesTreeView.Name = "imagesTreeView"; + this.imagesTreeView.Size = new System.Drawing.Size(167, 473); + this.imagesTreeView.TabIndex = 0; + this.imagesTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.advancedTreeView_AfterSelect); + // + // soundViewTab + // + this.soundViewTab.BackColor = System.Drawing.Color.Black; + this.soundViewTab.Controls.Add(this.soundList); + this.soundViewTab.Controls.Add(this.playSoundBtn); + this.soundViewTab.Location = new System.Drawing.Point(4, 24); + this.soundViewTab.Name = "soundViewTab"; + this.soundViewTab.Size = new System.Drawing.Size(935, 479); + this.soundViewTab.TabIndex = 6; + this.soundViewTab.Text = "Sounds"; + // + // soundList + // + this.soundList.Dock = System.Windows.Forms.DockStyle.Left; + this.soundList.Location = new System.Drawing.Point(0, 0); + this.soundList.Name = "soundList"; + this.soundList.Size = new System.Drawing.Size(203, 479); + this.soundList.TabIndex = 1; + this.soundList.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.soundList_AfterSelect); + // + // playSoundBtn + // + this.playSoundBtn.Location = new System.Drawing.Point(209, 3); + this.playSoundBtn.Name = "playSoundBtn"; + this.playSoundBtn.Size = new System.Drawing.Size(113, 50); + this.playSoundBtn.TabIndex = 0; + this.playSoundBtn.Text = "Play Sound"; + this.playSoundBtn.UseVisualStyleBackColor = true; + this.playSoundBtn.Click += new System.EventHandler(this.playSoundBtn_Click); // // pluginTab // @@ -717,16 +752,26 @@ this.packDataTab.ResumeLayout(false); this.cryptKeyTab.ResumeLayout(false); this.cryptKeyTab.PerformLayout(); - this.advDumpTab.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize) (this.advancedPictureBox)).EndInit(); + this.imgViewerTab.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize) (this.imageViewPictureBox)).EndInit(); + this.soundViewTab.ResumeLayout(false); this.pluginTab.ResumeLayout(false); this.pluginTab.PerformLayout(); this.ResumeLayout(false); } - private System.Windows.Forms.Label advancedInfoLabel; + private System.Windows.Forms.TreeView soundList; - private System.Windows.Forms.Button advancedPlayAnimation; + private System.Windows.Forms.Button playSoundBtn; + + private System.Windows.Forms.TabPage soundViewTab; + + private System.Windows.Forms.TreeView imagesTreeView; + private System.Windows.Forms.Button imageViewerPlayAnim; + private System.Windows.Forms.PictureBox imageViewPictureBox; + private System.Windows.Forms.TabPage imgViewerTab; + + private System.Windows.Forms.Label imageViewerInfo; public System.Windows.Forms.TextBox pluginLogBox; @@ -735,10 +780,6 @@ private System.Windows.Forms.TabPage pluginTab; - private System.Windows.Forms.PictureBox advancedPictureBox; - - private System.Windows.Forms.TreeView advancedTreeView; - private System.Windows.Forms.Button dumpAllPackButton; private System.Windows.Forms.Button dumpPackButton; private System.Windows.Forms.SaveFileDialog packDataDialog; @@ -746,7 +787,6 @@ private System.Windows.Forms.Label infoLabel; - private System.Windows.Forms.TabPage advDumpTab; private System.Windows.Forms.TabPage mainTab; private System.Windows.Forms.TabPage mfaTab; private System.Windows.Forms.TabPage packDataTab; diff --git a/DotNetCTFDumper/GUI/MainForm.cs b/DotNetCTFDumper/GUI/MainForm.cs index b35e725..91ca13d 100644 --- a/DotNetCTFDumper/GUI/MainForm.cs +++ b/DotNetCTFDumper/GUI/MainForm.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; +using System.Media; using System.Threading; using System.Windows.Forms; using Be.Windows.Forms; @@ -105,6 +106,7 @@ namespace DotNetCTFDumper.GUI if (e.TabPage != mainTab) e.Cancel = true; } + _soundPlayer.Stop(); } @@ -290,7 +292,8 @@ namespace DotNetCTFDumper.GUI Loaded = true; InitKeyTab(); InitPackDataTab(); - InitAdvancedDump(); + InitImages(); + InitSounds(); InitPlugins(); var toLog = ""; toLog += $"Title:{Exe.Instance.GameData.Name}\n"; @@ -604,7 +607,7 @@ namespace DotNetCTFDumper.GUI - public void InitAdvancedDump() + public void InitImages() { var bank = Exe.Instance.GameData.GameChunks.GetChunk(); var items = bank.Images.ToList(); @@ -612,7 +615,7 @@ namespace DotNetCTFDumper.GUI foreach (Frame frame in Exe.Instance.GameData.Frames) { var frameNode = new ChunkNode(frame.Name, frame); - advancedTreeView.Nodes.Add(frameNode); + imagesTreeView.Nodes.Add(frameNode); if (frame.Objects != null) { foreach (ObjectInstance objInst in frame.Objects.Items) @@ -630,40 +633,72 @@ namespace DotNetCTFDumper.GUI objInstNode.Nodes.Add(animNode); foreach (var dir in pair.Value.DirectionDict) { - for (int a = 0; a < dir.Value.Frames.Count; a++) + if (pair.Value.DirectionDict.Count > 1) { - var animFrame = dir.Value.Frames[a]; - bank.Images.TryGetValue(animFrame, out var img); - var animFrameNode = new ChunkNode(a.ToString(), img); - animNode.Nodes.Add(animFrameNode); + var dirNode = new ChunkNode($"Direction {pair.Key}",pair.Value); + animNode.Nodes.Add(dirNode); + for (int a = 0; a < dir.Value.Frames.Count; a++) + { + + var animFrame = dir.Value.Frames[a]; + bank.Images.TryGetValue(animFrame, out var img); + if (img != null) + { + var animFrameNode = new ChunkNode(a.ToString(), img); + dirNode.Nodes.Add(animFrameNode); + } + + } } + else + { + for (int a = 0; a < dir.Value.Frames.Count; a++) + { + + var animFrame = dir.Value.Frames[a]; + bank.Images.TryGetValue(animFrame, out var img); + if (img != null) + { + var animFrameNode = new ChunkNode(a.ToString(), img); + animNode.Nodes.Add(animFrameNode); + } + + } + } + } } } } else if (loader is Backdrop backdrop) { - var backdropNode = new ChunkNode("Image", bank.Images[backdrop.Image]); - objInstNode.Nodes.Add(backdropNode); + bank.Images.TryGetValue(backdrop.Image,out var img); + if (img != null) + { + var backdropNode = new ChunkNode("Image", img); + objInstNode.Nodes.Add(backdropNode); + } } } } } } - private bool breakAnim; - private bool isAnimRunning; + private bool _breakAnim; + private bool _isAnimRunning; + private SoundPlayer _soundPlayer; + private void advancedPlayAnimation_Click(object sender, EventArgs e) { - if (((ChunkNode) advancedTreeView.SelectedNode).loader is Animation anim) + if (((ChunkNode) imagesTreeView.SelectedNode).loader is Animation anim) { - if (isAnimRunning) + if (_isAnimRunning) { - breakAnim = true; + _breakAnim = true; } else { - isAnimRunning = true; + _isAnimRunning = true; var animThread = new Thread(PlayAnimation); List frames = new List(); foreach (var dir in anim.DirectionDict) @@ -673,6 +708,28 @@ namespace DotNetCTFDumper.GUI frames.Add(Exe.Instance.GameData.GameChunks.GetChunk().Images[frame].Bitmap); } animThread.Start(new Tuple,AnimationDirection>(frames,dir.Value)); + break; + } + } + } + else if (((ChunkNode) imagesTreeView.SelectedNode).loader is AnimationDirection dir) + { + if (_isAnimRunning) + { + _breakAnim = true; + } + else + { + _isAnimRunning = true; + var animThread = new Thread(PlayAnimation); + List frames = new List(); + foreach (var frame in dir.Frames) + { + + frames.Add(Exe.Instance.GameData.GameChunks.GetChunk().Images[frame].Bitmap); + + animThread.Start(new Tuple,AnimationDirection>(frames,dir)); + break; } } @@ -692,11 +749,11 @@ namespace DotNetCTFDumper.GUI { foreach (Bitmap frame in frames) { - advancedPictureBox.Image = frame; - advancedInfoLabel.Text = $"Current frame: {frames.IndexOf(frame)}\nAnimation Speed: {fps}"; + imageViewPictureBox.Image = frame; + imageViewerInfo.Text = $"Current frame: {frames.IndexOf(frame)}\nAnimation Speed: {fps}"; Thread.Sleep((int) (delay*1500)); } - isAnimRunning = false; + _isAnimRunning = false; Thread.CurrentThread.Abort(); } else @@ -704,15 +761,15 @@ namespace DotNetCTFDumper.GUI while (true) { var frame = frames[i]; - advancedPictureBox.Image = frame; - advancedInfoLabel.Text = $"Current frame: {i.ToString()}\nAnimation Speed: {fps}"; + imageViewPictureBox.Image = frame; + imageViewerInfo.Text = $"Current frame: {i.ToString()}\nAnimation Speed: {fps}"; Thread.Sleep((int) (delay*1500)); i++; if (i == frames.Count) i = 0; - if (breakAnim) + if (_breakAnim) { - isAnimRunning = false; - breakAnim = false; + _isAnimRunning = false; + _breakAnim = false; Thread.CurrentThread.Abort(); break; @@ -722,7 +779,7 @@ namespace DotNetCTFDumper.GUI } } - //Limited + } @@ -733,7 +790,7 @@ namespace DotNetCTFDumper.GUI if (((ChunkNode) node).loader is ImageItem) { var img = ((ImageItem) ((ChunkNode) node).loader); - advancedPictureBox.Image = img.Bitmap; + imageViewPictureBox.Image = img.Bitmap; } } @@ -756,7 +813,39 @@ namespace DotNetCTFDumper.GUI PluginAPI.PluginAPI.ActivatePlugin(PluginAPI.PluginAPI.Plugins[pluginsList.SelectedIndex]); } - + public void SoundTest() + { + + } + + public void InitSounds() + { + var bank = Exe.Instance.GameData.GameChunks.GetChunk(); + foreach (SoundItem soundItem in bank.Items) + { + soundList.Nodes.Add(new ChunkNode(soundItem.Name,soundItem)); + } + _soundPlayer = new SoundPlayer(new MemoryStream(Exe.Instance.GameData.GameChunks.GetChunk().Items[0].Data)); + + } + + + + private void playSoundBtn_Click(object sender, EventArgs e) + { + _soundPlayer.Stream = new MemoryStream(Exe.Instance.GameData.GameChunks.GetChunk().Items[soundList.SelectedNode.Index].Data); + _soundPlayer.Play(); + + + + + + } + + private void soundList_AfterSelect(object sender, TreeViewEventArgs e) + { + + } } } diff --git a/DotNetCTFDumper/MMFParser/EXE/Loaders/Banks/SoundBank.cs b/DotNetCTFDumper/MMFParser/EXE/Loaders/Banks/SoundBank.cs index 5af39cd..d06bcd2 100644 --- a/DotNetCTFDumper/MMFParser/EXE/Loaders/Banks/SoundBank.cs +++ b/DotNetCTFDumper/MMFParser/EXE/Loaders/Banks/SoundBank.cs @@ -44,7 +44,7 @@ namespace DotNetCTFDumper.MMFParser.EXE.Loaders.Banks Items = new List(); NumOfItems = Reader.ReadInt32(); Logger.Log("Found " + NumOfItems + " sounds"); - if (!Settings.DumpSounds) return; + //if (!Settings.DumpSounds) return; for (int i = 0; i < NumOfItems; i++) { diff --git a/DotNetCTFDumper/Utils/WAVReading.cs b/DotNetCTFDumper/Utils/WAVReading.cs new file mode 100644 index 0000000..7f21a0e --- /dev/null +++ b/DotNetCTFDumper/Utils/WAVReading.cs @@ -0,0 +1,175 @@ +using System; +using System.IO; +using System.Text; +using System.Diagnostics; + +namespace DotNetCTFDumper.Utils +{ + class WavFile + { + public int samplesPerSecond { get; set; } + public int samplesTotalCount { get; set; } + public string wavFilename { get; private set; } + public byte[] metaData { get; set; } + + + public WavFile(string filename) + { + samplesTotalCount = samplesPerSecond = -1; + wavFilename = filename; + metaData = null; + } + + + /// + /// Reading all samples of a 16-bit stereo wav file into arrays. + /// + + public bool readData(ref double[] L, ref double[] R) + { + try + { + BinaryReader reader = new BinaryReader(File.Open(wavFilename, FileMode.Open)); + + // header (8 + 4 bytes): + + byte[] riffId = reader.ReadBytes(4); // "RIFF" + int fileSize = reader.ReadInt32(); // size of entire file + byte[] typeId = reader.ReadBytes(4); // "WAVE" + + if (Encoding.ASCII.GetString(typeId) != "WAVE") return false; + + // chunk 1 (8 + 16 or 18 bytes): + + byte[] fmtId = reader.ReadBytes(4); // "fmt " + int fmtSize = reader.ReadInt32(); // size of chunk in bytes + int fmtCode = reader.ReadInt16(); // 1 - for PCM + int channels = reader.ReadInt16(); // 1 - mono, 2 - stereo + int sampleRate = reader.ReadInt32(); // sample rate per second + int byteRate = reader.ReadInt32(); // bytes per second + int dataAlign = reader.ReadInt16(); // data align + int bitDepth = reader.ReadInt16(); // 8, 16, 24, 32, 64 bits + + if (fmtCode != 1) return false; // not PCM + if (channels != 2) return false; // only Stereo files in this version + if (bitDepth != 16) return false; // only 16-bit in this version + + if (fmtSize == 18) // fmt chunk can be 16 or 18 bytes + { + int fmtExtraSize = reader.ReadInt16(); // read extra bytes size + reader.ReadBytes(fmtExtraSize); // skip over "INFO" chunk + } + + // chunk 2 (8 bytes): + + byte[] dataId = reader.ReadBytes(4); // "data" + int dataSize = reader.ReadInt32(); // size of audio data + + Debug.Assert(Encoding.ASCII.GetString(dataId) == "data", "Data chunk not found!"); + + samplesPerSecond = sampleRate; // sample rate (usually 44100) + samplesTotalCount = dataSize / (bitDepth / 8); // total samples count in audio data + + // audio data: + + L = R = new double[samplesTotalCount / 2]; + + for (int i = 0, s = 0; i < samplesTotalCount; i += 2) + { + L[s] = Convert.ToDouble(reader.ReadInt16()); + R[s] = Convert.ToDouble(reader.ReadInt16()); + s++; + } + + // metadata: + + long moreBytes = reader.BaseStream.Length - reader.BaseStream.Position; + + if (moreBytes > 0) + { + metaData = reader.ReadBytes((int)moreBytes); + } + + reader.Close(); + } + catch + { + Debug.Fail("Failed to read file."); + return false; + } + + return true; + } + + + /// + /// Writing all 16-bit stereo samples from arrays into wav file. + /// + + public bool writeData(double[] L, double[] R) + { + Debug.Assert((samplesTotalCount != -1) && (samplesPerSecond != -1), + "No sample count or sample rate info!"); + + try + { + BinaryWriter writer = new BinaryWriter(File.Create(wavFilename)); + + int fileSize = 44 + samplesTotalCount * 2; + + if (metaData != null) + { + fileSize += metaData.Length; + } + + // header: + + writer.Write(Encoding.ASCII.GetBytes("RIFF")); // "RIFF" + writer.Write((Int32)fileSize); // size of entire file with 16-bit data + writer.Write(Encoding.ASCII.GetBytes("WAVE")); // "WAVE" + + // chunk 1: + + writer.Write(Encoding.ASCII.GetBytes("fmt ")); // "fmt " + writer.Write((Int32)16); // size of chunk in bytes + writer.Write((Int16)1); // 1 - for PCM + writer.Write((Int16)2); // only Stereo files in this version + writer.Write((Int32)samplesPerSecond); // sample rate per second (usually 44100) + writer.Write((Int32)(4 * samplesPerSecond)); // bytes per second (usually 176400) + writer.Write((Int16)4); // data align 4 bytes (2 bytes sample stereo) + writer.Write((Int16)16); // only 16-bit in this version + + // chunk 2: + + writer.Write(Encoding.ASCII.GetBytes("data")); // "data" + writer.Write((Int32)(samplesTotalCount * 2)); // size of audio data 16-bit + + // audio data: + + for (int i = 0, s = 0; i < samplesTotalCount; i += 2) + { + writer.Write(Convert.ToInt16(L[s])); + writer.Write(Convert.ToInt16(R[s])); + s++; + } + + // metadata: + + if (metaData != null) + { + writer.Write(metaData); + } + + writer.Flush(); + writer.Close(); + } + catch + { + Debug.Fail("Failed to write file."); + return false; + } + + return true; + } + } +} \ No newline at end of file