From 23524c98f37e85f1cea0fb1b05006c3525c5733c Mon Sep 17 00:00:00 2001 From: fhsjxk <3398028530@qq.com> Date: Wed, 10 Dec 2025 15:59:15 +0800 Subject: [PATCH 1/4] Support export adpcm wav and mp3 from awc, export select rel tree --- .../GameFiles/FileTypes/AwcFile.cs | 248 ++++++++++++++++-- CodeWalker/Forms/AwcForm.Designer.cs | 16 +- CodeWalker/Forms/AwcForm.cs | 41 ++- .../Tools/AudioExplorerForm.Designer.cs | 13 + CodeWalker/Tools/AudioExplorerForm.cs | 33 +++ CodeWalker/Utils/AudioUtils.cs | 2 +- 6 files changed, 314 insertions(+), 39 deletions(-) diff --git a/CodeWalker.Core/GameFiles/FileTypes/AwcFile.cs b/CodeWalker.Core/GameFiles/FileTypes/AwcFile.cs index 42a30f522..7112355ff 100644 --- a/CodeWalker.Core/GameFiles/FileTypes/AwcFile.cs +++ b/CodeWalker.Core/GameFiles/FileTypes/AwcFile.cs @@ -790,7 +790,8 @@ public void BuildStreamDict() public enum AwcCodecType { PCM = 0, - ADPCM = 4 + ADPCM = 4, + MP3 = 7 } [TC(typeof(EXP))] public class AwcStreamInfo @@ -996,6 +997,7 @@ public string Type { case AwcCodecType.PCM: case AwcCodecType.ADPCM: + case AwcCodecType.MP3: break; default: codec = "Unknown"; @@ -1115,8 +1117,17 @@ public void WriteXml(StringBuilder sb, int indent, string wavfolder) } else { - fname += ".wav"; - fdata = export ? GetWavFile() : null; + var codec = StreamFormat?.Codec ?? FormatChunk?.Codec ?? AwcCodecType.PCM; + if (codec == AwcCodecType.MP3) + { + fname += ".mp3"; + fdata = export ? GetMp3File() : null; + } + else + { + fname += ".wav"; + fdata = export ? GetWavFile() : null; + } } AwcXml.StringTag(sb, indent, "FileName", AwcXml.XmlEscape(fname)); try @@ -1505,14 +1516,18 @@ public byte[] GetRawData() return DataChunk.Data; } - public byte[] GetPcmData() + public byte[] GetPcmData(bool adpcm=true) { var data = GetRawData(); var codec = StreamFormat?.Codec ?? FormatChunk?.Codec ?? AwcCodecType.PCM; - if (codec == AwcCodecType.ADPCM)//just convert ADPCM to PCM for compatibility reasons + if (codec == AwcCodecType.ADPCM)//no more compatibility { data = ADPCMCodec.DecodeADPCM(data, SampleCount); + if (adpcm) + { + data = ADPCMCodec.EncodeADPCMStandard(data, SampleCount); //SharpDX not work for ADPCM wav + } } return data; @@ -1526,9 +1541,9 @@ public byte[] GetWavFile() return data; } - public Stream GetWavStream() + public Stream GetWavStream(bool adpcm=true) { - byte[] dataPCM = GetPcmData(); + byte[] dataPCM = GetPcmData(adpcm); var bitsPerSample = 16; var channels = 1; short formatcodec = 1; // 1 = WAVE_FORMAT_PCM @@ -1536,17 +1551,21 @@ public Stream GetWavStream() short blockAlign = (short)(channels * bitsPerSample / 8); short samplesPerBlock = 0; bool addextrafmt = false; + int samples_per_block = (blockAlign - 4 * channels) * 2 / channels + 1; + bool fact = false; - //if (codec == AwcCodecFormat.ADPCM)//can't seem to get ADPCM wav files to work :( - //{ - // bitsPerSample = 4; - // formatcodec = 17; - // byteRate = (int)(SamplesPerSecond * 0.50685 * channels); - // blockAlign = 2048;// (short)(256 * (4 * channels));// (short)(36 * channels);//256;// 2048;// - // samplesPerBlock = 4088;// (short)(((blockAlign - (4 * channels)) * 8) / (bitsPerSample * channels) + 1); // 2044;// - // addextrafmt = true; - //} + var codec = StreamFormat?.Codec ?? FormatChunk?.Codec ?? AwcCodecType.PCM; + if (codec == AwcCodecType.ADPCM && adpcm)//yeah I got it work :) + { + bitsPerSample = 4; + formatcodec = 17; + blockAlign = /* (short)(blockAlign / 4);// */2048;// (short)(256 * (4 * channels));// (short)(36 * channels);//256;// 2048;// + byteRate = byteRate / 4 + 41;// SamplesPerSecond * blockAlign / samples_per_block;// (int)(SamplesPerSecond * 0.50685 * channels); + samplesPerBlock = (short)SampleCount;// (short)samples_per_block;// 4088;// (short)(((blockAlign - (4 * channels)) * 8) / (bitsPerSample * channels) + 1); // 2044;// + addextrafmt = true; + fact = true; + } MemoryStream stream = new MemoryStream(); BinaryWriter w = new BinaryWriter(stream); @@ -1576,6 +1595,13 @@ public Stream GetWavStream() w.Write((ushort)samplesPerBlock); } + if (fact) + { + w.Write("fact".ToCharArray()); + w.Write((int)4); + w.Write((int)samplesPerBlock); + } + // data sub-chunk w.Write("data".ToCharArray()); w.Write((int)dataPCM.Length); @@ -1613,20 +1639,27 @@ public void ParseWavFile(byte[] wav) var datalen = r.ReadInt32(); var dataPCM = r.ReadBytes(datalen); + var sampleCount = datalen * 2; //assume 16bits per sample PCM + if (r.Position != r.Length) { } - if (formatcodec != 1) + switch (formatcodec) { - throw new Exception("Only PCM format .wav files supported!"); + case 1: + break; + case 17: + dataPCM = ADPCMCodec.DecodeADPCMStandard(dataPCM, sampleCount); + break; + default: + throw new Exception("Only PCM format .wav files supported!"); } + if (channels != 1) { throw new Exception("Only mono .wav files supported!"); } - var sampleCount = datalen * 2; //assume 16bits per sample PCM - var codec = StreamFormat?.Codec ?? FormatChunk?.Codec ?? AwcCodecType.PCM; if (codec == AwcCodecType.ADPCM)// convert PCM wav to ADPCM where required { @@ -1662,6 +1695,11 @@ public void ParseWavFile(byte[] wav) } + public byte[] GetMp3File() + { + var data = GetRawData(); + return data; + } } @@ -3026,6 +3064,64 @@ void parseNibble(byte nibble) return dataPCM; } + public static byte[] DecodeADPCMStandard(byte[] data, int sampleCount) //not work + { + byte[] dataPCM = new byte[data.Length * 4]; + int predictor = 0, stepIndex = 0; + int readingOffset = 0, writingOffset = 0, bytesInBlock = 0; + + void writePredictorSample() + { + int samplePCM = clip(predictor, -32768, 32767); + dataPCM[writingOffset] = (byte)(samplePCM & 0xFF); + dataPCM[writingOffset + 1] = (byte)((samplePCM >> 8) & 0xFF); + writingOffset += 2; + } + + void parseNibble(byte nibble) + { + var step = ima_step_table[stepIndex]; + int diff = ((((nibble & 7) << 1) + 1) * step) >> 3; + if ((nibble & 8) != 0) diff = -diff; + predictor = predictor + diff; + predictor = clip(predictor, -32768, 32767); + + stepIndex = clip(stepIndex + ima_index_table[nibble & 7], 0, 88); + + int samplePCM = predictor; + dataPCM[writingOffset] = (byte)(samplePCM & 0xFF); + dataPCM[writingOffset + 1] = (byte)((samplePCM >> 8) & 0xFF); + writingOffset += 2; + } + + while ((readingOffset < data.Length) && (sampleCount > 0)) + { + if (bytesInBlock == 0) + { + predictor = BitConverter.ToInt16(data, readingOffset); + stepIndex = clip(data[readingOffset + 2], 0, 88); + + writePredictorSample(); + sampleCount -= 1; + + bytesInBlock = 2044; + readingOffset += 4; + } + else + { + parseNibble((byte)(data[readingOffset] & 0x0F)); + if (sampleCount <= 0) break; + parseNibble((byte)((data[readingOffset] >> 4) & 0x0F)); + + bytesInBlock--; + sampleCount -= 2; + readingOffset++; + } + } + + return dataPCM; + } + public static byte[] EncodeADPCM(byte[] data, int sampleCount) { byte[] dataPCM = new byte[data.Length / 4]; @@ -3112,11 +3208,121 @@ byte encodeNibble(int pcm16) return dataPCM; } - } + public static byte[] EncodeADPCMStandard(byte[] data, int sampleCount) + { + byte[] dataPCM = new byte[data.Length / 4]; + + int predictor = 0, stepIndex = 0; + int readingOffset = 0, writingOffset = 0, bytesInBlock = 0; + + short readSample() + { + var s = BitConverter.ToInt16(data, readingOffset); + readingOffset += 2; + return s; + } + void writeInt16(short v) + { + var ba = BitConverter.GetBytes(v); + dataPCM[writingOffset++] = ba[0]; + dataPCM[writingOffset++] = ba[1]; + } + + void writeByte(byte b) + { + dataPCM[writingOffset++] = b; + } + byte encodeNibble(int pcm16) + { + int delta = pcm16 - predictor; + byte nibble = 0; + if (delta < 0) + { + nibble = 8; + delta = -delta; + } + int step = ima_step_table[stepIndex]; + int diff = step >> 3; + if (delta >= step) + { + nibble |= 4; + delta -= step; + diff += step; + } + if (delta >= (step >> 1)) + { + nibble |= 2; + delta -= (step >> 1); + diff += (step >> 1); + } + if (delta >= (step >> 2)) + { + nibble |= 1; + diff += (step >> 2); + } + + if ((nibble & 8) != 0) + predictor -= diff; + else + predictor += diff; + + if (predictor > short.MaxValue) predictor = short.MaxValue; + if (predictor < short.MinValue) predictor = short.MinValue; + + stepIndex += ima_index_table[nibble & 0x07]; + if (stepIndex < 0) stepIndex = 0; + if (stepIndex > 88) stepIndex = 88; + + return nibble; + } + + while ((writingOffset < dataPCM.Length) && (sampleCount > 0)) + { + if (bytesInBlock == 0) + { + predictor = readSample(); + writeInt16((short)predictor); + writeByte((byte)stepIndex); + writeByte(0); + + sampleCount -= 1; + + bytesInBlock = 2044; + } + else + { + if (sampleCount <= 1) + { + short s0 = readSample(); + short s1 = 0; + var b0 = encodeNibble(s0); + var b1 = encodeNibble(s1); + var b = (byte)((b0 & 0x0F) | ((b1 & 0x0F) << 4)); + dataPCM[writingOffset++] = b; + bytesInBlock--; + sampleCount -= 2; + } + else + { + var s0 = readSample(); + var s1 = readSample(); + var b0 = encodeNibble(s0); + var b1 = encodeNibble(s1); + var b = (byte)((b0 & 0x0F) | ((b1 & 0x0F) << 4)); + dataPCM[writingOffset++] = b; + bytesInBlock--; + sampleCount -= 2; + } + } + } + return dataPCM; + } + + } public class AwcXml : MetaXmlBase { diff --git a/CodeWalker/Forms/AwcForm.Designer.cs b/CodeWalker/Forms/AwcForm.Designer.cs index 3e565e553..0afef2b3e 100644 --- a/CodeWalker/Forms/AwcForm.Designer.cs +++ b/CodeWalker/Forms/AwcForm.Designer.cs @@ -46,7 +46,7 @@ private void InitializeComponent() this.PlaylistLengthHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.PlaylistSizeHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); - this.ExportAsWav = new System.Windows.Forms.ToolStripMenuItem(); + this.ExportAsFile = new System.Windows.Forms.ToolStripMenuItem(); this.VolumeTrackBar = new System.Windows.Forms.TrackBar(); this.PositionTrackBar = new System.Windows.Forms.TrackBar(); this.DetailsTabPage = new System.Windows.Forms.TabPage(); @@ -231,16 +231,16 @@ private void InitializeComponent() // contextMenuStrip // this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.ExportAsWav}); + this.ExportAsFile}); this.contextMenuStrip.Name = "contextMenuStrip1"; this.contextMenuStrip.Size = new System.Drawing.Size(150, 26); // - // ExportAsWav + // ExportAsFile // - this.ExportAsWav.Name = "ExportAsWav"; - this.ExportAsWav.Size = new System.Drawing.Size(149, 22); - this.ExportAsWav.Text = "Export as .wav"; - this.ExportAsWav.Click += new System.EventHandler(this.ExportAsWav_Click); + this.ExportAsFile.Name = "ExportAsFile"; + this.ExportAsFile.Size = new System.Drawing.Size(149, 22); + this.ExportAsFile.Text = "Export as .wav"; + this.ExportAsFile.Click += new System.EventHandler(this.ExportAsFile_Click); // // VolumeTrackBar // @@ -402,7 +402,7 @@ private void InitializeComponent() private System.Windows.Forms.Label LabelTime; private System.Windows.Forms.Label LabelInfo; private System.Windows.Forms.ContextMenuStrip contextMenuStrip; - private System.Windows.Forms.ToolStripMenuItem ExportAsWav; + private System.Windows.Forms.ToolStripMenuItem ExportAsFile; private System.Windows.Forms.SaveFileDialog saveFileDialog; private System.Windows.Forms.ColumnHeader PlaylistSizeHeader; private System.Windows.Forms.TabPage XmlTabPage; diff --git a/CodeWalker/Forms/AwcForm.cs b/CodeWalker/Forms/AwcForm.cs index ccb532724..4ed0c288e 100644 --- a/CodeWalker/Forms/AwcForm.cs +++ b/CodeWalker/Forms/AwcForm.cs @@ -369,7 +369,7 @@ private void AwcForm_FormClosing(object sender, FormClosingEventArgs e) Player.DisposeAudio(); } - private void ExportAsWav_Click(object sender, EventArgs e) + private void ExportAsFile_Click(object sender, EventArgs e) { if (PlayListView.SelectedItems.Count == 1) { @@ -383,7 +383,17 @@ private void ExportAsWav_Click(object sender, EventArgs e) return; } - var ext = ".wav"; + var codec = audio.StreamFormat?.Codec ?? audio.FormatChunk?.Codec ?? AwcCodecType.PCM; + string ext; + + if (codec == AwcCodecType.MP3) + { + ext = ".mp3"; + saveFileDialog.Filter = "Mp3 files (*.mp3)|*.mp3"; + } + else + ext = ".wav"; + if (audio?.MidiChunk != null) { ext = ".midi"; @@ -398,11 +408,19 @@ private void ExportAsWav_Click(object sender, EventArgs e) } else if ((audio?.FormatChunk != null) || (audio?.StreamFormat != null)) { - Stream wavStream = audio.GetWavStream(); - FileStream stream = File.Create(saveFileDialog.FileName); - wavStream.CopyTo(stream); - stream.Close(); - wavStream.Close(); + if (codec == AwcCodecType.MP3) + { + byte[] data = audio.GetMp3File(); + File.WriteAllBytes(saveFileDialog.FileName, data); + } + else + { + Stream wavStream = audio.GetWavStream(); + FileStream stream = File.Create(saveFileDialog.FileName); + wavStream.CopyTo(stream); + stream.Close(); + wavStream.Close(); + } } } @@ -411,14 +429,19 @@ private void ExportAsWav_Click(object sender, EventArgs e) private void PlayListView_SelectedIndexChanged(object sender, EventArgs e) { - ExportAsWav.Text = "Export as .wav"; + ExportAsFile.Text = "Export as .wav"; + if (PlayListView.SelectedItems.Count == 1) { var item = PlayListView.SelectedItems[0]; var audio = item.Tag as AwcStream; + var codec = audio.StreamFormat?.Codec ?? audio.FormatChunk?.Codec ?? AwcCodecType.PCM; + + if (codec == AwcCodecType.MP3) + ExportAsFile.Text = "Export as .mp3"; if (audio?.MidiChunk != null) { - ExportAsWav.Text = "Export as .midi"; + ExportAsFile.Text = "Export as .midi"; } } } diff --git a/CodeWalker/Tools/AudioExplorerForm.Designer.cs b/CodeWalker/Tools/AudioExplorerForm.Designer.cs index c4b7e4ff1..682e37aaa 100644 --- a/CodeWalker/Tools/AudioExplorerForm.Designer.cs +++ b/CodeWalker/Tools/AudioExplorerForm.Designer.cs @@ -40,6 +40,7 @@ private void InitializeComponent() this.XmlTextBox = new FastColoredTextBoxNS.FastColoredTextBox(); this.NameComboBox = new System.Windows.Forms.ComboBox(); this.TypeComboBox = new System.Windows.Forms.ComboBox(); + this.ExportBotton = new System.Windows.Forms.Button(); ((System.ComponentModel.ISupportInitialize)(this.MainSplitContainer)).BeginInit(); this.MainSplitContainer.Panel1.SuspendLayout(); this.MainSplitContainer.Panel2.SuspendLayout(); @@ -188,11 +189,22 @@ private void InitializeComponent() this.TypeComboBox.TabIndex = 2; this.TypeComboBox.TextChanged += new System.EventHandler(this.TypeComboBox_TextChanged); // + // ExportBotton + // + this.ExportBotton.Location = new System.Drawing.Point(670, 8); + this.ExportBotton.Name = "ExportBotton"; + this.ExportBotton.Size = new System.Drawing.Size(93, 21); + this.ExportBotton.TabIndex = 3; + this.ExportBotton.Text = "Export Select"; + this.ExportBotton.UseVisualStyleBackColor = true; + this.ExportBotton.Click += new System.EventHandler(this.ExportBotton_Click); + // // AudioExplorerForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(823, 564); + this.Controls.Add(this.ExportBotton); this.Controls.Add(this.TypeComboBox); this.Controls.Add(this.NameComboBox); this.Controls.Add(this.MainSplitContainer); @@ -221,6 +233,7 @@ private void InitializeComponent() private WinForms.PropertyGridFix DetailsPropertyGrid; private System.Windows.Forms.TabPage XmlTabPage; private FastColoredTextBoxNS.FastColoredTextBox XmlTextBox; + private System.Windows.Forms.Button ExportBotton; private System.Windows.Forms.ComboBox TypeComboBox; } } \ No newline at end of file diff --git a/CodeWalker/Tools/AudioExplorerForm.cs b/CodeWalker/Tools/AudioExplorerForm.cs index 606699406..cca238799 100644 --- a/CodeWalker/Tools/AudioExplorerForm.cs +++ b/CodeWalker/Tools/AudioExplorerForm.cs @@ -8,6 +8,7 @@ using System.Text; using System.Threading.Tasks; using System.Windows.Forms; +using System.IO; namespace CodeWalker.Tools { @@ -312,5 +313,37 @@ private void HierarchyTreeView_AfterSelect(object sender, TreeViewEventArgs e) var item = HierarchyTreeView.SelectedNode?.Tag as RelData; SelectItem(item); } + + private void ExportBotton_Click(object sender, EventArgs e) + { + SaveFileDialog saveFileDialog = new SaveFileDialog(); + saveFileDialog.FileName = HierarchyTreeView.SelectedNode.Text.Replace(" : ", ":").Split(':')[0] + ".xml"; + if (saveFileDialog.ShowDialog() == DialogResult.OK) + { + string fileName = saveFileDialog.FileName; + List sl = new List(); + StringBuilder sb = new StringBuilder(); + sb.Append("\n\n "); + + AppendXmlRecursive(HierarchyTreeView.SelectedNode, sb, sl); + + sb.Append(""); + File.WriteAllText(fileName, sb.ToString()); + } + } + + private void AppendXmlRecursive(TreeNode treeNode, StringBuilder sb, List sl) + { + RelData item = treeNode?.Tag as RelData; + if (!sl.Contains(treeNode.Text)) + { + sb.Append(RelXml.GetXml(item).Replace("\n", "\n ")); + sl.Add(treeNode.Text); + } + foreach (TreeNode tn in treeNode.Nodes) + { + AppendXmlRecursive(tn, sb, sl); + } + } } } diff --git a/CodeWalker/Utils/AudioUtils.cs b/CodeWalker/Utils/AudioUtils.cs index a121c45da..59bbad16d 100644 --- a/CodeWalker/Utils/AudioUtils.cs +++ b/CodeWalker/Utils/AudioUtils.cs @@ -83,7 +83,7 @@ public void LoadAudio(params AwcStream[] audios) voice.audio = audio; voice.trackLength = audio.Length; trackLength = Math.Max(trackLength, voice.trackLength); - var wavStream = audio.GetWavStream(); + var wavStream = audio.GetWavStream(false); var soundStream = new SoundStream(wavStream); voice.soundStream = soundStream; voice.audioBuffer = new AudioBuffer From a16a2a871f3058534679d5f286ce9843348a8971 Mon Sep 17 00:00:00 2001 From: fhsjxk <3398028530@qq.com> Date: Wed, 10 Dec 2025 16:45:11 +0800 Subject: [PATCH 2/4] Support import mp3 awc --- .../GameFiles/FileTypes/AwcFile.cs | 33 +++++++++++++++++-- CodeWalker/Forms/AwcForm.cs | 12 +++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/CodeWalker.Core/GameFiles/FileTypes/AwcFile.cs b/CodeWalker.Core/GameFiles/FileTypes/AwcFile.cs index 7112355ff..567fe0d60 100644 --- a/CodeWalker.Core/GameFiles/FileTypes/AwcFile.cs +++ b/CodeWalker.Core/GameFiles/FileTypes/AwcFile.cs @@ -1207,7 +1207,14 @@ public void ReadXml(XmlNode node, string wavfolder) } else { - ParseWavFile(fdata); + if (filepath.EndsWith(".wav")) + ParseWavFile(fdata); + + else if (filepath.EndsWith(".mp3")) + { + StreamFormat.Codec = AwcCodecType.MP3; + ParseMp3File(fdata); + } } } } @@ -1652,7 +1659,7 @@ public void ParseWavFile(byte[] wav) dataPCM = ADPCMCodec.DecodeADPCMStandard(dataPCM, sampleCount); break; default: - throw new Exception("Only PCM format .wav files supported!"); + throw new Exception("Only PCM and ADPCM format .wav files supported!"); } if (channels != 1) @@ -1701,6 +1708,28 @@ public byte[] GetMp3File() return data; } + public void ParseMp3File(byte[] mp3) + { + if (Awc.MultiChannelFlag) + { + if (StreamFormat != null) + { + DataChunk = new AwcDataChunk(null); + DataChunk.Data = mp3; + } + } + else + { + if (FormatChunk != null) + { + if (DataChunk == null) DataChunk = new AwcDataChunk(new AwcChunkInfo() { Type = AwcChunkType.data }); + + DataChunk.Data = mp3; + } + + } + } + } diff --git a/CodeWalker/Forms/AwcForm.cs b/CodeWalker/Forms/AwcForm.cs index 4ed0c288e..aed0a84ab 100644 --- a/CodeWalker/Forms/AwcForm.cs +++ b/CodeWalker/Forms/AwcForm.cs @@ -8,6 +8,7 @@ using System.Drawing; using System.Linq; using Range = FastColoredTextBoxNS.Range; +using System.Xml.Serialization; namespace CodeWalker.Forms { @@ -174,7 +175,18 @@ private void Play() var item = PlayListView.SelectedItems[0]; var audio = item.Tag as AwcStream; var stereo = (audio?.ChannelStreams?.Length == 2); + AwcCodecType codec; + if (stereo) + codec = audio.ChannelStreams[0].StreamFormat?.Codec ?? audio.ChannelStreams[0].FormatChunk?.Codec ?? AwcCodecType.PCM; + else + codec = audio.StreamFormat?.Codec ?? audio.FormatChunk?.Codec ?? AwcCodecType.PCM; + + if (codec == AwcCodecType.MP3) + { + //todo: play MP3 + } + else if (stereo) { var name0 = audio.ChannelStreams[0].Name; var left0 = name0.EndsWith("left") || name0.EndsWith(".l"); From e5c0f8430994830e4cd1cdd57827b52be400b2a8 Mon Sep 17 00:00:00 2001 From: fhsjxk <3398028530@qq.com> Date: Wed, 10 Dec 2025 17:25:42 +0800 Subject: [PATCH 3/4] Support import adpcm wav, bug fixes --- CodeWalker.Core/GameFiles/FileTypes/AwcFile.cs | 8 +++++--- CodeWalker/Forms/AwcForm.cs | 3 +++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CodeWalker.Core/GameFiles/FileTypes/AwcFile.cs b/CodeWalker.Core/GameFiles/FileTypes/AwcFile.cs index 567fe0d60..5d843f54d 100644 --- a/CodeWalker.Core/GameFiles/FileTypes/AwcFile.cs +++ b/CodeWalker.Core/GameFiles/FileTypes/AwcFile.cs @@ -1567,9 +1567,9 @@ public Stream GetWavStream(bool adpcm=true) { bitsPerSample = 4; formatcodec = 17; - blockAlign = /* (short)(blockAlign / 4);// */2048;// (short)(256 * (4 * channels));// (short)(36 * channels);//256;// 2048;// + blockAlign = 2048; // (short)(blockAlign / 4);// //2048;// (short)(256 * (4 * channels));// (short)(36 * channels);//256;// 2048;// byteRate = byteRate / 4 + 41;// SamplesPerSecond * blockAlign / samples_per_block;// (int)(SamplesPerSecond * 0.50685 * channels); - samplesPerBlock = (short)SampleCount;// (short)samples_per_block;// 4088;// (short)(((blockAlign - (4 * channels)) * 8) / (bitsPerSample * channels) + 1); // 2044;// + samplesPerBlock = 4089; //(short)SampleCount;// (short)samples_per_block;// 4088;// (short)(((blockAlign - (4 * channels)) * 8) / (bitsPerSample * channels) + 1); // 2044;// addextrafmt = true; fact = true; } @@ -1642,7 +1642,9 @@ public void ParseWavFile(byte[] wav) ext2 = r.ReadUInt16(); samplesPerBlock = r.ReadUInt16(); } - var datatag = r.ReadUInt32(); // 0x61746164 + var tag = r.ReadUInt32(); // 0x61746164 + if (tag == 0x74636166) + r.ReadBytes(12); var datalen = r.ReadInt32(); var dataPCM = r.ReadBytes(datalen); diff --git a/CodeWalker/Forms/AwcForm.cs b/CodeWalker/Forms/AwcForm.cs index aed0a84ab..1a156e2d3 100644 --- a/CodeWalker/Forms/AwcForm.cs +++ b/CodeWalker/Forms/AwcForm.cs @@ -112,6 +112,9 @@ public void LoadAwc(AwcFile awc) var name = audio.Name; if (stereo) name = "(Stereo Playback)"; var item = PlayListView.Items.Add(name); + if (stereo) + item.SubItems.Add(audio.ChannelStreams[0].Type); + else item.SubItems.Add(audio.Type); item.SubItems.Add(audio.LengthStr); item.SubItems.Add(TextUtil.GetBytesReadable(audio.ByteLength)); From 689155add20484d3fa4d2f3f2f34e4fb82d2e020 Mon Sep 17 00:00:00 2001 From: fhsjxk <3398028530@qq.com> Date: Wed, 10 Dec 2025 17:26:46 +0800 Subject: [PATCH 4/4] Support import mp3 awc --- CodeWalker.Core/GameFiles/FileTypes/AwcFile.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CodeWalker.Core/GameFiles/FileTypes/AwcFile.cs b/CodeWalker.Core/GameFiles/FileTypes/AwcFile.cs index 5d843f54d..51d392315 100644 --- a/CodeWalker.Core/GameFiles/FileTypes/AwcFile.cs +++ b/CodeWalker.Core/GameFiles/FileTypes/AwcFile.cs @@ -3095,7 +3095,7 @@ void parseNibble(byte nibble) return dataPCM; } - public static byte[] DecodeADPCMStandard(byte[] data, int sampleCount) //not work + public static byte[] DecodeADPCMStandard(byte[] data, int sampleCount) { byte[] dataPCM = new byte[data.Length * 4]; int predictor = 0, stepIndex = 0;