From 1d2c8bfe0e259f848d8439f437b32d6e1b67d3ac Mon Sep 17 00:00:00 2001 From: Lane Dibello Date: Tue, 9 Mar 2021 12:14:54 -0600 Subject: [PATCH 1/2] Implemented LIP format --- KotOR_IO/File Formats/LIP.cs | 124 +++++++++++++++++++++++++++++++++++ KotOR_IO/KotOR_IO.csproj | 1 + 2 files changed, 125 insertions(+) create mode 100644 KotOR_IO/File Formats/LIP.cs diff --git a/KotOR_IO/File Formats/LIP.cs b/KotOR_IO/File Formats/LIP.cs new file mode 100644 index 0000000..fb3de86 --- /dev/null +++ b/KotOR_IO/File Formats/LIP.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.IO; + +namespace KotOR_IO +{ + /// + /// BioWare 'LIP' data. + /// Tracks Lip movements of speaking NPCs + /// + public class LIP : KFile + { + /// + /// Initiates a new instance of the class from raw byte data. + /// + /// + public LIP(byte[] rawData) + : this(new MemoryStream(rawData)) + { } + + /// + /// Reads the given BioWare LIP File. + /// + /// File path to read. + public LIP(string path) + : this(File.OpenRead(path)) + { } + + protected LIP(Stream s) + { + using (BinaryReader br = new BinaryReader(s)) + { + //Header + FileType = new string(br.ReadChars(4)); + Version = new string(br.ReadChars(4)); + + //Entry Info + SoundLength = br.ReadSingle(); + int EntryCount = br.ReadInt32(); + + for (int i = 0; i < EntryCount; i++) + { + LipEntry le; + le.TimeStamp = br.ReadSingle(); + le.State = (LipState)br.ReadByte(); + Entries.Add(le); + } + } + } + + /// + /// The total length of teh the sound file these lips are synced to + /// + public float SoundLength; + + /// + /// An Entry in the lip table, matching a mouth shape to a timestamp + /// + public struct LipEntry + { + /// + /// The timestamp in seconds from the start of the soundfile + /// + public float TimeStamp; + /// + /// The current mouth shape + /// + public LipState State; + } + + /// + /// The Lip Entries in this file. The first value is a time stamp in seconds from the start of the sound file. + /// The second is the mouth animation from the enum. + /// + public List Entries = new List(); + + /// + /// The current shape of the speaker's mouth. (single byte) + /// + public enum LipState : byte + { + ee = 0x0, // "teeth" + eh = 0x1, // "bet" + a = 0x2, // "sofa" + ah = 0x3, // "cat" + oh = 0x4, // "boat" + oo = 0x5, // "too" + y = 0x6, // "yes" + s = 0x7, // "sick" + f = 0x8, // "fish" + n = 0x9, // "nacho" + th = 0xA, // "think" + m = 0xB, // "moose" + t = 0xC, // "table" + j = 0xD, // "jungle" + l = 0xE, // "lick" + k = 0xF // "catch" + } + + + + + internal override void Write(Stream s) + { + using (BinaryWriter bw = new BinaryWriter(s)) + { + bw.Write(FileType.ToCharArray()); + bw.Write(Version.ToCharArray()); + + bw.Write(SoundLength); + bw.Write(Entries.Count); + + foreach (LipEntry LE in Entries) + { + bw.Write(LE.TimeStamp); + bw.Write((byte)LE.State); + } + } + } + } +} diff --git a/KotOR_IO/KotOR_IO.csproj b/KotOR_IO/KotOR_IO.csproj index 6b26511..c82d62f 100644 --- a/KotOR_IO/KotOR_IO.csproj +++ b/KotOR_IO/KotOR_IO.csproj @@ -68,6 +68,7 @@ + From 7180c4d11adbc580f8deaa9d3141ad608b2a9241 Mon Sep 17 00:00:00 2001 From: laned Date: Tue, 9 Mar 2021 13:36:58 -0600 Subject: [PATCH 2/2] Converted member variables to Properties Moved LipStates Comments into summaries Reorganized Class slightly --- KotOR_IO/File Formats/LIP.cs | 122 ++++++++++++++++++++++------------- 1 file changed, 78 insertions(+), 44 deletions(-) diff --git a/KotOR_IO/File Formats/LIP.cs b/KotOR_IO/File Formats/LIP.cs index fb3de86..16d0cad 100644 --- a/KotOR_IO/File Formats/LIP.cs +++ b/KotOR_IO/File Formats/LIP.cs @@ -13,6 +13,9 @@ namespace KotOR_IO /// public class LIP : KFile { + #region Methods + + //constructors /// /// Initiates a new instance of the class from raw byte data. /// @@ -43,18 +46,39 @@ protected LIP(Stream s) for (int i = 0; i < EntryCount; i++) { - LipEntry le; - le.TimeStamp = br.ReadSingle(); - le.State = (LipState)br.ReadByte(); + LipEntry le = new LipEntry(br.ReadSingle(), (LipState)br.ReadByte()); Entries.Add(le); } } } + //overrides + internal override void Write(Stream s) + { + using (BinaryWriter bw = new BinaryWriter(s)) + { + bw.Write(FileType.ToCharArray()); + bw.Write(Version.ToCharArray()); + + bw.Write(SoundLength); + bw.Write(Entries.Count); + + foreach (LipEntry LE in Entries) + { + bw.Write(LE.TimeStamp); + bw.Write((byte)LE.State); + } + } + } + + #endregion + + #region Properties + /// - /// The total length of teh the sound file these lips are synced to + /// The total length of the the sound file these lips are synced to /// - public float SoundLength; + public float SoundLength { get; set; } /// /// An Entry in the lip table, matching a mouth shape to a timestamp @@ -64,61 +88,71 @@ public struct LipEntry /// /// The timestamp in seconds from the start of the soundfile /// - public float TimeStamp; + public float TimeStamp { get; set; } /// /// The current mouth shape /// - public LipState State; + public LipState State { get; set; } + + /// + /// Constructs a new instance of the LipEntry Struct + /// + /// + /// + public LipEntry(float time_stamp, LipState lip) + { + TimeStamp = time_stamp; + State = lip; + } } /// /// The Lip Entries in this file. The first value is a time stamp in seconds from the start of the sound file. /// The second is the mouth animation from the enum. /// - public List Entries = new List(); + public List Entries { get; set; } = new List(); //migrate to a protected set once we work out entry editing logic + + #endregion /// /// The current shape of the speaker's mouth. (single byte) /// public enum LipState : byte { - ee = 0x0, // "teeth" - eh = 0x1, // "bet" - a = 0x2, // "sofa" - ah = 0x3, // "cat" - oh = 0x4, // "boat" - oo = 0x5, // "too" - y = 0x6, // "yes" - s = 0x7, // "sick" - f = 0x8, // "fish" - n = 0x9, // "nacho" - th = 0xA, // "think" - m = 0xB, // "moose" - t = 0xC, // "table" - j = 0xD, // "jungle" - l = 0xE, // "lick" - k = 0xF // "catch" + /// As in "teeth" or "speed" + ee = 0x0, + /// As in "bet" or "red" + eh = 0x1, + /// Like 'a' in "sofa" + a = 0x2, + /// As in "cat" or "bad " + ah = 0x3, + /// As in "boat" or "toad" + oh = 0x4, + /// As in "Blue", also the 'wh' shape form "wheel" + oo = 0x5, + /// As in "yes" or "yankee" + y = 0x6, + /// As in "sick", also 'ts' from "nets" + s = 0x7, + /// As in "fish", also 'v' from "very" + f = 0x8, + /// As in "nacho", also 'ng' from "running" + n = 0x9, + /// As in "think" or "that" + th = 0xA, + /// As in "moose", also 'p' from "pop" or 'b' from "book" + m = 0xB, + /// As in "table", also 'd' from "door" + t = 0xC, + /// As in "jury", also 'sh' from "shape" + j = 0xD, + /// As in "lick", also 'r' in "run" + l = 0xE, + /// As in "cake", also 'g' from "go" + k = 0xF } - - - - internal override void Write(Stream s) - { - using (BinaryWriter bw = new BinaryWriter(s)) - { - bw.Write(FileType.ToCharArray()); - bw.Write(Version.ToCharArray()); - - bw.Write(SoundLength); - bw.Write(Entries.Count); - - foreach (LipEntry LE in Entries) - { - bw.Write(LE.TimeStamp); - bw.Write((byte)LE.State); - } - } - } + } }