<NME> SingerViewDialog.xaml.cs
<BEF> ADDFILE
<MSG> UTAU Soundbank loading.

<DFF> @@ -0,0 +1,39 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+using OpenUtau.UI.Controls;
+using OpenUtau.Core.USTx;
+
+namespace OpenUtau.UI.Dialogs
+{
+    /// <summary>
+    /// Interaction logic for SingerViewDialog.xaml
+    /// </summary>
+    public partial class SingerViewDialog : Window
+    {
+        public SingerViewDialog()
+        {
+            InitializeComponent();
+        }
+
+        public void SetSinger(USinger singer)
+        {
+            this.Title = this.name.Text = singer.Name;
+            this.avatar.Source = singer.Avatar;
+            this.info.Text = "Author: " + singer.Author + "\nWebsite: " + singer.Website + "\nPath: " + singer.ActualPath;
+            this.otoview.Items.Clear();
+            foreach (var pair in singer.AliasMap) this.otoview.Items.Add(pair.Value);
+        }
+    }
+}

{'commit': 'diff --git a/OpenUtau/Core/Formats/Ust.cs b/OpenUtau/Core/Formats/Ust.cs\nindex d507aeb..4a9ffd8 100644\n--- a/OpenUtau/Core/Formats/Ust.cs\n+++ b/OpenUtau/Core/Formats/Ust.cs\n@@ -6,10 +6,11 @@\n using System.IO;\n \n using OpenUtau.Core.USTx;\n+using OpenUtau.Core.Lib;\n \n namespace OpenUtau.Core.Formats\n {\n-    static class Ust\n+    public static class Ust\n     {\n         private enum UstBlock { Version, Setting, Note, Trackend, None };\n \n@@ -62,7 +63,7 @@ static public void Load(string[] files)\n             if (uproject != null) DocManager.Inst.ExecuteCmd(new LoadProjectNotification(uproject));\n         }\n \n-        static public UProject Load(string file)\n+        static public UProject Load(string file, string encoding = "")\n         {\n             int currentNote = 0;\n             UstBlock currentBlock = UstBlock.None;\n@@ -70,7 +71,8 @@ static public UProject Load(string file)\n \n             try\n             {\n-                lines = File.ReadAllLines(file);\n+                if (encoding == "") lines = File.ReadAllLines(file, EncodingUtil.DetectFileEncoding(file));\n+                else lines = File.ReadAllLines(file, Encoding.GetEncoding(encoding));\n             }\n             catch (Exception e)\n             {\n@@ -79,6 +81,11 @@ static public UProject Load(string file)\n             }\n \n             UProject uproject = new UProject() { Resolution = 480 };\n+            uproject.RegisterExpression(new CCExpression(null, "velocity") { Data = 64f });\n+            uproject.RegisterExpression(new CCExpression(null, "opening") { Data = 127f });\n+            uproject.RegisterExpression(new FloatExpression(null, "accent") { Data = 50f, Min = 0f, Max = 100f });\n+            uproject.RegisterExpression(new FloatExpression(null, "decay") { Data = 50f, Min = 0f, Max = 100f });\n+\n             uproject.Tracks.Add(new UTrack());\n             uproject.Tracks.First().TrackNo = 0;\n             UVoicePart upart = new UVoicePart() { TrackNo = 0, PosTick = 0 };\n@@ -98,7 +105,7 @@ static public UProject Load(string file)\n                         try { currentNote = int.Parse(line.Replace("[#", "").Replace("]", "")); }\n                         catch { System.Windows.MessageBox.Show("Unknown ust format"); return null; }\n                         currentBlock = UstBlock.Note;\n-                        if (currNote != null && !currNote.Lyric.Replace("R", "").Equals("")) upart.Notes.Add(currNote);\n+                        if (currNote != null && !currNote.Lyric.Replace("R", "").Replace("r", "").Equals("")) upart.Notes.Add(currNote);\n                         currNote = uproject.CreateNote();\n                         currNote.Lyric = "R";\n                         currNote.PosTick = currTick;\n@@ -110,6 +117,13 @@ static public UProject Load(string file)\n                     {\n                         if (line.StartsWith("Tempo=")) uproject.BPM = double.Parse(line.Trim().Replace("Tempo=", ""));\n                         if (line.StartsWith("ProjectName=")) uproject.Name = line.Trim().Replace("ProjectName=", "");\n+                        if (line.StartsWith("VoiceDir="))\n+                        {\n+                            string singerpath = line.Trim().Replace("VoiceDir=", "").Replace("%VOICE%", "");\n+                            //if (singerpath.StartsWith("%VOICE%"))\n+                            //    singerpath = Path.Combine(@"E:\\Utau\\voice", singerpath.Replace("%VOICE%", ""));\n+                            uproject.Singers.Add(UtauSoundbank.LoadSinger(singerpath, EncodingUtil.DetectFileEncoding(file)));\n+                        }\n                     }\n                     else if (currentBlock == UstBlock.Note)\n                     {\ndiff --git a/OpenUtau/Core/Formats/UtauSoundbank.cs b/OpenUtau/Core/Formats/UtauSoundbank.cs\nnew file mode 100644\nindex 0000000..1239f22\n--- /dev/null\n+++ b/OpenUtau/Core/Formats/UtauSoundbank.cs\n@@ -0,0 +1,134 @@\n+\ufeffusing System;\n+using System.Collections.Generic;\n+using System.Linq;\n+using System.Text;\n+using System.IO;\n+using System.Threading.Tasks;\n+\n+using OpenUtau.Core.USTx;\n+using OpenUtau.Core.Lib;\n+\n+namespace OpenUtau.Core.Formats\n+{\n+    public static class UtauSoundbank\n+    {\n+        public static USinger LoadSinger(string path, Encoding ustEncoding)\n+        {\n+            USinger singer = new USinger();\n+            singer.HomePath = @"I:\\Utau\\voice";\n+            singer.SoundbankPath = path;\n+            singer.PathEncoding = GetPathEncoding(ustEncoding, singer.HomePath, singer.SoundbankPath);\n+            if (singer.PathEncoding == null) return null;\n+            singer.FileEncoding = ustEncoding;\n+\n+            if (!Directory.Exists(singer.ActualPath)) return null;\n+            if (!File.Exists(Path.Combine(singer.ActualPath, "character.txt"))) return null;\n+            if (!File.Exists(Path.Combine(singer.ActualPath, "oto.ini"))) return null;\n+\n+            singer.FileEncoding = EncodingUtil.DetectFileEncoding(Path.Combine(singer.ActualPath, "oto.ini"));\n+            singer.SoundbankPath = EncodingUtil.ConvertEncoding(ustEncoding, singer.FileEncoding, singer.SoundbankPath);\n+            LoadOtos(singer);\n+\n+            string[] lines;\n+            try\n+            {\n+                lines = File.ReadAllLines(Path.Combine(singer.ActualPath, "character.txt"), singer.FileEncoding);\n+            }\n+            catch { return null; }\n+\n+            foreach (var line in lines){\n+                if (line.StartsWith("name=")) singer.Name = line.Trim().Replace("name=", "");\n+                if (line.StartsWith("image=")) singer.ImagePath = line.Trim().Replace("image=", "");\n+                if (line.StartsWith("author=")) singer.Author = line.Trim().Replace("author=", "");\n+                if (line.StartsWith("web=")) singer.Website = line.Trim().Replace("web=", "");\n+            }\n+\n+            if (singer.ImagePath != null)\n+            {\n+                Uri imagepath = new Uri(Path.Combine(singer.ActualPath, singer.ImagePath));\n+                singer.Avatar = new System.Windows.Media.Imaging.BitmapImage(imagepath);\n+            }\n+\n+            LoadPrefixMap(singer);\n+\n+            return singer;\n+        }\n+\n+        static Encoding GetPathEncoding(Encoding pathEncoding, string homepath, string path)\n+        {\n+            if (Directory.Exists(Path.Combine(homepath, EncodingUtil.ConvertEncoding(pathEncoding, Encoding.GetEncoding("shift_jis"), path))))\n+                return Encoding.GetEncoding("shift_jis");\n+            else if (Directory.Exists(Path.Combine(homepath, EncodingUtil.ConvertEncoding(pathEncoding, Encoding.GetEncoding("gbk"), path))))\n+                return Encoding.GetEncoding("gbk");\n+            else if (Directory.Exists(Path.Combine(homepath, EncodingUtil.ConvertEncoding(pathEncoding, Encoding.UTF8, path))))\n+                return Encoding.UTF8;\n+            else\n+                return null;\n+        }\n+\n+        static void LoadOtos(USinger singer)\n+        {\n+            string path = singer.ActualPath;\n+            var otopaths = new List<string>();\n+            if (File.Exists(Path.Combine(path, "oto.ini"))) otopaths.Add(Path.Combine(path, "oto.ini"));\n+            foreach (var dirpath in Directory.EnumerateDirectories(path))\n+                if (File.Exists(Path.Combine(dirpath, "oto.ini"))) otopaths.Add(Path.Combine(dirpath, "oto.ini"));\n+            foreach (var otopath in otopaths) LoadOto(otopath, singer);\n+        }\n+        \n+        static void LoadOto(string file, USinger singer)\n+        {\n+            string[] lines = File.ReadAllLines(file, singer.FileEncoding);\n+            foreach (var line in lines)\n+            {\n+                var s = line.Split(new[] { \'=\' });\n+                if (s.Count() == 2)\n+                {\n+                    string wavfile = s[0];\n+                    var args = s[1].Split(new[] { \',\' });\n+                    if (singer.AliasMap.ContainsKey(args[0])) continue;\n+                    singer.AliasMap.Add(args[0], new UOto()\n+                    {\n+                        File = wavfile,\n+                        Alias = args[0],\n+                        Offset = int.Parse(args[1]),\n+                        Consonant = int.Parse(args[2]),\n+                        Cutoff = int.Parse(args[3]),\n+                        Preutter = int.Parse(args[4]),\n+                        Overlap = int.Parse(args[5])\n+                    });\n+                }\n+            }\n+        }\n+\n+        static void LoadPrefixMap(USinger singer)\n+        {\n+            string path = singer.ActualPath;\n+            if (File.Exists(Path.Combine(path, "prefix.map"))) \n+            {\n+                singer.MultiPitch = true;\n+                string[] lines;\n+                \n+                try\n+                {\n+                    lines = File.ReadAllLines(Path.Combine(path, "prefix.map"));\n+                }\n+                catch\n+                {\n+                    throw new Exception("Prefix map exists but cannot be opened for read.");\n+                }\n+\n+                foreach (string line in lines)\n+                {\n+                    var s = line.Trim().Split(new char[0], StringSplitOptions.RemoveEmptyEntries);\n+                    if (s.Count() == 2)\n+                    {\n+                        string source = s[0];\n+                        string target = s[1];\n+                        singer.PitchMap.Add(source, target);\n+                    }\n+                }\n+            }\n+        }\n+    }\n+}\ndiff --git a/OpenUtau/Core/USTx/Deque.cs b/OpenUtau/Core/Lib/Deque.cs\nsimilarity index 99%\nrename from OpenUtau/Core/USTx/Deque.cs\nrename to OpenUtau/Core/Lib/Deque.cs\nindex 3116e84..3ab1a9f 100644\n--- a/OpenUtau/Core/USTx/Deque.cs\n+++ b/OpenUtau/Core/Lib/Deque.cs\n@@ -4,7 +4,7 @@\n using System.Linq;\n using System.Text;\n \n-namespace OpenUtau.Core.USTx\n+namespace OpenUtau.Core.Lib\n {\n     /// <summary>\n     /// A double-ended queue (deque), which provides O(1) indexed access, O(1) removals from the front and back, amortized O(1) insertions to the front and back, and O(N) insertions and removals anywhere else (with the operations getting slower as the index approaches the middle).\ndiff --git a/OpenUtau/Core/Lib/EncodingUtil.cs b/OpenUtau/Core/Lib/EncodingUtil.cs\nnew file mode 100644\nindex 0000000..c15614f\n--- /dev/null\n+++ b/OpenUtau/Core/Lib/EncodingUtil.cs\n@@ -0,0 +1,331 @@\n+#region *   License     *\n+/*\n+    SimpleHelpers - FileEncoding   \n+\n+    Copyright © 2014 Khalid Salomão\n+\n+    Permission is hereby granted, free of charge, to any person\n+    obtaining a copy of this software and associated documentation\n+    files (the “Software”), to deal in the Software without\n+    restriction, including without limitation the rights to use,\n+    copy, modify, merge, publish, distribute, sublicense, and/or sell\n+    copies of the Software, and to permit persons to whom the\n+    Software is furnished to do so, subject to the following\n+    conditions:\n+\n+    The above copyright notice and this permission notice shall be\n+    included in all copies or substantial portions of the Software.\n+\n+    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,\n+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n+    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n+    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n+    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n+    OTHER DEALINGS IN THE SOFTWARE. \n+\n+    License: http://www.opensource.org/licenses/mit-license.php\n+    Website: https://github.com/khalidsalomao/SimpleHelpers.Net\n+ */\n+#endregion\n+\n+using System;\n+using System.IO;\n+using System.Collections.Generic;\n+using System.Linq;\n+using System.Text;\n+\n+namespace OpenUtau.Core.Lib\n+{\n+    public class EncodingUtil\n+    {\n+        const int DEFAULT_BUFFER_SIZE = 128 * 1024;\n+\n+        /// <summary>\n+        /// Tries to detect the file encoding.\n+        /// </summary>\n+        /// <param name="inputFilename">The input filename.</param>\n+        /// <param name="defaultIfNotDetected">The default encoding if none was detected.</param>\n+        /// <returns></returns>\n+        public static Encoding DetectFileEncoding (string inputFilename, Encoding defaultIfNotDetected = null)\n+        {\n+            using (var stream = new System.IO.FileStream (inputFilename, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite | System.IO.FileShare.Delete, DEFAULT_BUFFER_SIZE))\n+            {\n+                return DetectFileEncoding (stream) ?? defaultIfNotDetected;\n+            }\n+        }\n+\n+        /// <summary>\n+        /// Tries to detect the file encoding.\n+        /// </summary>\n+        /// <param name="inputStream">The input stream.</param>\n+        /// <param name="defaultIfNotDetected">The default encoding if none was detected.</param>\n+        /// <returns></returns>\n+        public static Encoding DetectFileEncoding (Stream inputStream, Encoding defaultIfNotDetected = null)\n+        {\n+            var det = new EncodingUtil ();\n+            det.Detect (inputStream);\n+            return det.Complete () ?? defaultIfNotDetected;\n+        }\n+\n+        /// <summary>\n+        /// Tries to detect the file encoding.\n+        /// </summary>\n+        /// <param name="inputData">The input data.</param>\n+        /// <param name="start">The start.</param>\n+        /// <param name="count">The count.</param>\n+        /// <param name="defaultIfNotDetected">The default encoding if none was detected.</param>\n+        /// <returns></returns>\n+        public static Encoding DetectFileEncoding (byte[] inputData, int start, int count, Encoding defaultIfNotDetected = null)\n+        {\n+            var det = new EncodingUtil ();\n+            det.Detect (inputData, start, count);\n+            return det.Complete () ?? defaultIfNotDetected;            \n+        }\n+\n+        /// <summary>\n+        /// Detects if contains textual data.\n+        /// </summary>\n+        /// <param name="rawData">The raw data.</param>\n+        public static bool CheckForTextualData (byte[] rawData)\n+        {\n+            return CheckForTextualData (rawData, 0, rawData.Length);\n+        }\n+\n+        /// <summary>\n+        /// Detects if contains textual data.\n+        /// </summary>\n+        /// <param name="rawData">The raw data.</param>\n+        /// <param name="start">The start.</param>\n+        /// <param name="count">The count.</param>\n+        public static bool CheckForTextualData (byte[] rawData, int start, int count)\n+        {\n+            if (rawData.Length < count || count < 4 || start + 1 >= count)\n+                return true;\n+                        \n+            if (CheckForByteOrderMark (rawData, start))\n+            {\n+                return true;\n+            }\n+\n+            // http://stackoverflow.com/questions/910873/how-can-i-determine-if-a-file-is-binary-or-text-in-c\n+            // http://www.gnu.org/software/diffutils/manual/html_node/Binary.html\n+            // count the number od null bytes sequences\n+            // considering only sequeces of 2 0s: "\\0\\0" or control characters below 10\n+            int nullSequences = 0;\n+            int controlSequences = 0;\n+            for (var i = start + 1; i < count; i++)\n+            {\n+                if (rawData[i - 1] == 0 && rawData[i] == 0)\n+                {\n+                    if (++nullSequences > 1)\n+                        break;\n+                }\n+                else if (rawData[i - 1] == 0 && rawData[i] < 10)\n+                {\n+                    ++controlSequences;\n+                }\n+            }\n+\n+            // is text if there is no null byte sequences or less than 10% of the buffer has control caracteres\n+            return nullSequences == 0 && (controlSequences <= (rawData.Length / 10));\n+        }\n+  \n+        /// <summary>\n+        /// Detects if data has bytes order mark to indicate its encoding for textual data.\n+        /// </summary>\n+        /// <param name="rawData">The raw data.</param>\n+        /// <param name="start">The start.</param>\n+        /// <returns></returns>\n+        private static bool CheckForByteOrderMark (byte[] rawData, int start = 0)\n+        {\n+            if (rawData.Length - start < 4)\n+                return false;\n+            // Detect encoding correctly (from Rick Strahl\'s blog)\n+            // http://www.west-wind.com/weblog/posts/2007/Nov/28/Detecting-Text-Encoding-for-StreamReader\n+            if (rawData[start] == 0xef && rawData[start + 1] == 0xbb && rawData[start + 2] == 0xbf)\n+            {\n+                // Encoding.UTF8;\n+                return true;\n+            }\n+            else if (rawData[start] == 0xfe && rawData[start + 1] == 0xff)\n+            {\n+                // Encoding.Unicode;\n+                return true;\n+            }\n+            else if (rawData[start] == 0 && rawData[start + 1] == 0 && rawData[start + 2] == 0xfe && rawData[start + 3] == 0xff)\n+            {\n+                // Encoding.UTF32;\n+                return true;\n+            }\n+            else if (rawData[start] == 0x2b && rawData[start + 1] == 0x2f && rawData[start + 2] == 0x76)\n+            {\n+                // Encoding.UTF7;\n+                return true;\n+            }\n+            return false;\n+        }\n+\n+        Ude.CharsetDetector ude = new Ude.CharsetDetector ();\n+        bool _started = false;\n+        \n+\n+        /// <summary>\n+        /// If the detection has reached a decision.\n+        /// </summary>\n+        /// <value>The done.</value>\n+        public bool Done { get; set; }\n+\n+        /// <summary>\n+        /// Detected encoding name.\n+        /// </summary>\n+        public string EncodingName { get; set; }\n+\n+        /// <summary>\n+        /// If the data contains textual data.\n+        /// </summary>\n+        public bool IsText { get; set; }\n+\n+        /// <summary>\n+        /// If the file or data has any mark indicating encoding information (byte order mark).\n+        /// </summary>\n+        public bool HasByteOrderMark { get; set; }\n+\n+        List<string> singleEncodings = new List<string> ();\n+\n+        /// <summary>\n+        /// Resets this instance.\n+        /// </summary>\n+        public void Reset ()\n+        {\n+            _started = false;\n+            Done = false;\n+            HasByteOrderMark = false;\n+            singleEncodings.Clear ();\n+            ude.Reset ();\n+            EncodingName = null;\n+        }\n+\n+        /// <summary>\n+        /// Detects the encoding of textual data of the specified input data.\n+        /// </summary>\n+        /// <param name="inputData">The input data.</param>\n+        /// <returns>Detected encoding name</returns>\n+        public string Detect (Stream inputData)\n+        {\n+            const int bufferSize = 16 * 1024;\n+            const int maxIterations = (20 * 1024 * 1024) / bufferSize;\n+            int i = 0;\n+            byte[] buffer = new byte[bufferSize];\n+            while (i++ < maxIterations)\n+            {\n+                int sz = inputData.Read (buffer, 0, (int)buffer.Length);\n+                if (sz <= 0)\n+                {\n+                    break;\n+                }\n+                Detect (buffer, 0, sz);\n+                if (Done)\n+                    break;\n+            }\n+            Complete ();\n+            return EncodingName;\n+        }\n+\n+        /// <summary>\n+        /// Detects the encoding of textual data of the specified input data.\n+        /// </summary>\n+        /// <param name="inputData">The input data.</param>\n+        /// <param name="start">The start.</param>\n+        /// <param name="count">The count.</param>\n+        /// <returns>Detected encoding name</returns>\n+        public string Detect (byte[] inputData, int start, int count)\n+        {\n+            if (Done)\n+                return EncodingName;\n+            if (!_started)\n+            {\n+                Reset ();\n+                _started = true;\n+                if (!CheckForTextualData (inputData, start, count))\n+                {\n+                    IsText = false;\n+                    Done = true;\n+                    return EncodingName;\n+                }\n+                HasByteOrderMark = CheckForByteOrderMark (inputData, start);\n+                IsText = true;\n+            }\n+\n+            // execute charset detector                \n+            ude.Feed (inputData, start, count);\n+            ude.DataEnd ();\n+            if (ude.IsDone () && !String.IsNullOrEmpty (ude.Charset))\n+            {\n+                Done = true;\n+                return EncodingName;\n+            }\n+\n+            const int bufferSize = 4 * 1024;\n+\n+            // singular buffer detection\n+            if (singleEncodings.Count < 2000)\n+            {\n+                var u = new Ude.CharsetDetector ();\n+                int step = (count - start) < bufferSize ? (count - start) : bufferSize;\n+                for (var i = start; i < count; i += step)\n+                {\n+                    u.Reset ();\n+                    if (i + step > count)\n+                        u.Feed (inputData, i, count - i);\n+                    else\n+                        u.Feed (inputData, i, step);\n+                    u.DataEnd ();\n+                    if (u.Confidence > 0.3 && !String.IsNullOrEmpty (u.Charset))\n+                        singleEncodings.Add (u.Charset);\n+                }\n+            }\n+            return EncodingName;\n+        }\n+\n+        /// <summary>\n+        /// Finalize detection phase and gets detected encoding name.\n+        /// </summary>\n+        /// <returns></returns>\n+        public Encoding Complete ()\n+        {\n+            Done = true;\n+            ude.DataEnd ();\n+            if (ude.IsDone () && !String.IsNullOrEmpty (ude.Charset))\n+            {\n+                EncodingName = ude.Charset;\n+            }\n+            else if (singleEncodings.Count > 0)\n+            {\n+                // vote for best encoding\n+                EncodingName = singleEncodings.GroupBy (i => i)\n+                    .OrderByDescending (i => i.Count () * \n+                    (i.Key.StartsWith ("UTF-32") ? 2 :\n+                    i.Key.StartsWith ("UTF-16") ? 1.8 :\n+                    i.Key.StartsWith ("UTF-8") ? 1.5 :\n+                    i.Key.StartsWith ("UTF-7") ? 1.3 :\n+                    i.Key != ("ASCII") ? 1 : 0.2))\n+                    .Select (i => i.Key).FirstOrDefault ();\n+            }\n+            if (!String.IsNullOrEmpty (EncodingName))\n+                return Encoding.GetEncoding (EncodingName);\n+            return null;\n+        }\n+\n+        public static string ConvertEncoding(string sourceEncoding, string targetEncoding, string text)\n+        {\n+            return ConvertEncoding(Encoding.GetEncoding(sourceEncoding), Encoding.GetEncoding(targetEncoding), text);\n+        }\n+\n+        public static string ConvertEncoding(Encoding source, Encoding target, string text)\n+        {\n+            return target.GetString(source.GetBytes(text));\n+        }\n+    }\n+}\ndiff --git a/OpenUtau/Core/Lib/xxHash.cs b/OpenUtau/Core/Lib/xxHash.cs\nnew file mode 100644\nindex 0000000..70da2ef\n--- /dev/null\n+++ b/OpenUtau/Core/Lib/xxHash.cs\n@@ -0,0 +1,261 @@\n+\ufeff/*\n+xxHashSharp - A pure C# implementation of xxhash\n+Copyright (C) 2014, Seok-Ju, Yun. (https://github.com/noricube/xxHashSharp)\n+Original C Implementation Copyright (C) 2012-2014, Yann Collet. (https://code.google.com/p/xxhash/)\n+BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n+\n+Redistribution and use in source and binary forms, with or without\n+modification, are permitted provided that the following conditions are\n+met:\n+\n+    * Redistributions of source code must retain the above copyright\n+      notice, this list of conditions and the following disclaimer.\n+    * Redistributions in binary form must reproduce the above\n+      copyright notice, this list of conditions and the following\n+      disclaimer in the documentation and/or other materials provided\n+      with the distribution.\n+\n+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+*/\n+\n+using System;\n+using System.Collections.Generic;\n+using System.Linq;\n+using System.Text;\n+using System.Threading.Tasks;\n+\n+namespace OpenUtau.Core.Lib\n+{\n+    public class xxHash\n+    {\n+        public struct XXH_State\n+        {\n+            public ulong total_len;\n+            public uint seed;\n+            public uint v1;\n+            public uint v2;\n+            public uint v3;\n+            public uint v4;\n+            public int memsize;\n+            public byte[] memory;\n+        };\n+\n+        const uint PRIME32_1 = 2654435761U;\n+        const uint PRIME32_2 = 2246822519U;\n+        const uint PRIME32_3 = 3266489917U;\n+        const uint PRIME32_4 = 668265263U;\n+        const uint PRIME32_5 = 374761393U;\n+\n+        protected XXH_State _state;\n+        public xxHash()\n+        {\n+\n+        }\n+\n+        public static uint CalculateHash(byte[] buf, int len = -1, uint seed = 0)\n+        {\n+            uint h32;\n+            int index = 0;\n+            if (len == -1)\n+            {\n+                len = buf.Length;\n+            }\n+\n+\n+            if (len >= 16)\n+            {\n+                int limit = len - 16;\n+                uint v1 = seed + PRIME32_1 + PRIME32_2;\n+                uint v2 = seed + PRIME32_2;\n+                uint v3 = seed + 0;\n+                uint v4 = seed - PRIME32_1;\n+\n+                do\n+                {\n+                    v1 = CalcSubHash(v1, buf, index);\n+                    index += 4;\n+                    v2 = CalcSubHash(v2, buf, index);\n+                    index += 4;\n+                    v3 = CalcSubHash(v3, buf, index);\n+                    index += 4;\n+                    v4 = CalcSubHash(v4, buf, index);\n+                    index += 4;\n+                } while (index <= limit);\n+\n+                h32 = RotateLeft(v1, 1) + RotateLeft(v2, 7) + RotateLeft(v3, 12) + RotateLeft(v4, 18);\n+            }\n+            else\n+            {\n+                h32 = seed + PRIME32_5;\n+            }\n+\n+            h32 += (uint)len;\n+\n+            while (index <= len - 4)\n+            {\n+                h32 += BitConverter.ToUInt32(buf, index) * PRIME32_3;\n+                h32 = RotateLeft(h32, 17) * PRIME32_4;\n+                index += 4;\n+            }\n+\n+            while(index<len)\n+            {\n+                h32 += buf[index] * PRIME32_5;\n+                h32 = RotateLeft(h32, 11) * PRIME32_1;\n+                index++;\n+            }\n+\n+            h32 ^= h32 >> 15;\n+            h32 *= PRIME32_2;\n+            h32 ^= h32 >> 13;\n+            h32 *= PRIME32_3;\n+            h32 ^= h32 >> 16;\n+\n+            return h32;\n+        }\n+\n+        public void Init(uint seed = 0)\n+        {\n+            _state.seed = seed;\n+            _state.v1 = seed + PRIME32_1 + PRIME32_2;\n+            _state.v2 = seed + PRIME32_2;\n+            _state.v3 = seed + 0;\n+            _state.v4 = seed - PRIME32_1;\n+            _state.total_len = 0;\n+            _state.memsize = 0;\n+            _state.memory = new byte[16];\n+        }\n+\n+        public bool Update(byte[] input, int len)\n+        {\n+            int index = 0;\n+\n+            _state.total_len += (uint)len;\n+\n+            if (_state.memsize + len < 16) // 버퍼 + 입력길이가 16바이트 이하일경우 버퍼에 저장만 해둔다\n+            {\n+                Array.Copy(input, 0, _state.memory, _state.memsize, len);\n+                _state.memsize += len;\n+\n+                return true;\n+            }\n+\n+            if (_state.memsize > 0) // 이전데이터가 남아있을경우 먼저 처리한다.\n+            {\n+                Array.Copy(input, 0, _state.memory, _state.memsize, 16 - _state.memsize);\n+\n+                _state.v1 = CalcSubHash(_state.v1, _state.memory, index);\n+                index += 4;\n+                _state.v2 = CalcSubHash(_state.v2, _state.memory, index);\n+                index += 4;\n+                _state.v3 = CalcSubHash(_state.v3, _state.memory, index);\n+                index += 4;\n+                _state.v4 = CalcSubHash(_state.v4, _state.memory, index);\n+                index += 4;\n+\n+                index = 0;\n+                _state.memsize = 0;\n+            }\n+\n+            if (index <= len - 16)\n+            {\n+                int limit = len - 16;\n+                uint v1 = _state.v1;\n+                uint v2 = _state.v2;\n+                uint v3 = _state.v3;\n+                uint v4 = _state.v4;\n+\n+                do\n+                {\n+                    v1 = CalcSubHash(v1, input, index);\n+                    index += 4;\n+                    v2 = CalcSubHash(v2, input, index);\n+                    index += 4;\n+                    v3 = CalcSubHash(v3, input, index);\n+                    index += 4;\n+                    v4 = CalcSubHash(v4, input, index);\n+                    index += 4;\n+                } while (index <= limit);\n+\n+                _state.v1 = v1;\n+                _state.v2 = v2;\n+                _state.v3 = v3;\n+                _state.v4 = v4;\n+            }\n+\n+            if (index < len)\n+            {\n+                Array.Copy(input, index, _state.memory, 0, len - index);\n+                _state.memsize = len - index;\n+            }\n+            return true;\n+        }\n+\n+        public uint Digest()\n+        {\n+            uint h32;\n+            int index = 0;\n+            if (_state.total_len >= 16)\n+            {\n+                h32 = RotateLeft(_state.v1, 1) + RotateLeft(_state.v2, 7) + RotateLeft(_state.v3, 12) + RotateLeft(_state.v4, 18);\n+            }\n+            else\n+            {\n+                h32 = _state.seed + PRIME32_5;\n+            }\n+\n+            h32 += (UInt32)_state.total_len;\n+\n+            while (index <= _state.memsize - 4)\n+            {\n+                h32 += BitConverter.ToUInt32(_state.memory, index) * PRIME32_3;\n+                h32 = RotateLeft(h32, 17) * PRIME32_4;\n+                index += 4;\n+            }\n+\n+            while (index < _state.memsize)\n+            {\n+                h32 += _state.memory[index] * PRIME32_5;\n+                h32 = RotateLeft(h32, 11) * PRIME32_1;\n+                index++;\n+            }\n+\n+            h32 ^= h32 >> 15;\n+            h32 *= PRIME32_2;\n+            h32 ^= h32 >> 13;\n+            h32 *= PRIME32_3;\n+            h32 ^= h32 >> 16;\n+\n+            return h32;\n+        }\n+        private static uint CalcSubHash(uint value, byte[] buf, int index)\n+        {\n+            uint read_value = BitConverter.ToUInt32(buf, index);\n+            value += read_value * PRIME32_2;\n+            value = RotateLeft(value, 13);\n+            value *= PRIME32_1;\n+            return value;\n+        }\n+\n+        private static uint RotateLeft(uint value, int count)\n+        {\n+            return (value << count) | (value >> (32 - count));\n+        }\n+\n+        public static uint CalcStringHash(string str)\n+        {\n+            byte[] data = Encoding.UTF8.GetBytes(str);\n+            return CalculateHash(data);\n+        }\n+    }\n+}\ndiff --git a/OpenUtau/Core/MusicMath.cs b/OpenUtau/Core/MusicMath.cs\nindex e3eb1ec..bf36944 100644\n--- a/OpenUtau/Core/MusicMath.cs\n+++ b/OpenUtau/Core/MusicMath.cs\n@@ -10,7 +10,7 @@ public static class MusicMath\n     {\n         public static string[] noteStrings = new String[12] { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };\n \n-        public static string GetKeyString(int keyNo) { return keyNo < 0 ? "" : noteStrings[keyNo % 12] + (keyNo / 12 - 2).ToString(); }\n+        public static string GetNoteString(int noteNum) { return noteNum < 0 ? "" : noteStrings[noteNum % 12] + (noteNum / 12 - 1).ToString(); }\n \n         public static double TickToNote(int tick, int resolution) { return tick / resolution; }\n \ndiff --git a/OpenUtau/Core/USTx/DocManager.cs b/OpenUtau/Core/USTx/DocManager.cs\nindex 697f7d5..7592af8 100644\n--- a/OpenUtau/Core/USTx/DocManager.cs\n+++ b/OpenUtau/Core/USTx/DocManager.cs\n@@ -4,6 +4,8 @@\n using System.Text;\n using System.Threading.Tasks;\n \n+using OpenUtau.Core.Lib;\n+\n namespace OpenUtau.Core.USTx\n {\n     class DocManager : ICmdPublisher\ndiff --git a/OpenUtau/Core/USTx/UProject.cs b/OpenUtau/Core/USTx/UProject.cs\nindex 4b668df..4b05abd 100644\n--- a/OpenUtau/Core/USTx/UProject.cs\n+++ b/OpenUtau/Core/USTx/UProject.cs\n@@ -20,6 +20,7 @@ public class UProject\n \n         public List<UTrack> Tracks = new List<UTrack>();\n         public List<UPart> Parts = new List<UPart>();\n+        public List<USinger> Singers = new List<USinger>();\n \n         public Dictionary<string, UExpression> ExpressionTable = new Dictionary<string, UExpression>();\n         public void RegisterExpression(UExpression exp) { if (!ExpressionTable.ContainsKey(exp.Name)) ExpressionTable.Add(exp.Name, exp); }\ndiff --git a/OpenUtau/Core/USTx/USinger.cs b/OpenUtau/Core/USTx/USinger.cs\nnew file mode 100644\nindex 0000000..2335e45\n--- /dev/null\n+++ b/OpenUtau/Core/USTx/USinger.cs\n@@ -0,0 +1,41 @@\n+\ufeffusing System;\n+using System.Collections.Generic;\n+using System.Linq;\n+using System.Text;\n+using System.Threading.Tasks;\n+\n+namespace OpenUtau.Core.USTx\n+{\n+    public struct UOto\n+    {\n+        public string Alias { set; get; }\n+        public string File { set; get; }\n+        public int Offset { set; get; }\n+        public int Consonant { set; get; }\n+        public int Cutoff { set; get; }\n+        public int Preutter { set; get; }\n+        public int Overlap { set; get; }\n+    }\n+\n+    public class USinger\n+    {\n+        public string Name;\n+        public string HomePath;\n+        public string SoundbankPath;\n+        public string ImagePath;\n+        public string Author;\n+        public string Website;\n+\n+        public System.Windows.Media.Imaging.BitmapImage Avatar;\n+\n+        public Encoding FileEncoding;\n+        public Encoding PathEncoding;\n+\n+        public bool MultiPitch;\n+        public Dictionary<string, string> PitchMap = new Dictionary<string, string>();\n+        public Dictionary<string, UOto> AliasMap = new Dictionary<string, UOto>();\n+\n+        public string ActualPath { get { return System.IO.Path.Combine(HomePath,\n+            Lib.EncodingUtil.ConvertEncoding(FileEncoding, PathEncoding, SoundbankPath)); } }\n+    }\n+}\ndiff --git a/OpenUtau/Core/USTx/UTrack.cs b/OpenUtau/Core/USTx/UTrack.cs\nindex cc6ebe3..8976fd0 100644\n--- a/OpenUtau/Core/USTx/UTrack.cs\n+++ b/OpenUtau/Core/USTx/UTrack.cs\n@@ -10,6 +10,7 @@ public class UTrack\n     {\n         public string Name = "New Track";\n         public string Comment = "";\n+        public USinger Singer;\n \n         public int TrackNo;\n \ndiff --git a/OpenUtau/OpenUtau.csproj b/OpenUtau/OpenUtau.csproj\nindex 4243ae6..b998feb 100644\n--- a/OpenUtau/OpenUtau.csproj\n+++ b/OpenUtau/OpenUtau.csproj\n@@ -70,20 +70,27 @@\n     <Reference Include="System.Xaml">\n       <RequiredTargetFramework>4.0</RequiredTargetFramework>\n     </Reference>\n+    <Reference Include="Ude">\n+      <HintPath>..\\packages\\UDE.CSharp.1.1.0\\lib\\Ude.dll</HintPath>\n+    </Reference>\n     <Reference Include="WindowsBase" />\n     <Reference Include="PresentationCore" />\n     <Reference Include="PresentationFramework" />\n   </ItemGroup>\n   <ItemGroup>\n     <Compile Include="Core\\Formats\\USTx.cs" />\n+    <Compile Include="Core\\Formats\\UtauSoundbank.cs" />\n+    <Compile Include="Core\\Lib\\xxHash.cs" />\n     <Compile Include="Core\\USTx\\ExpCommands.cs" />\n     <Compile Include="Core\\USTx\\Expressions.cs" />\n     <Compile Include="Core\\USTx\\NoteCommands.cs" />\n-    <Compile Include="Core\\USTx\\Deque.cs" />\n+    <Compile Include="Core\\Lib\\Deque.cs" />\n     <Compile Include="Core\\USTx\\DocManager.cs" />\n     <Compile Include="Core\\USTx\\Notifications.cs" />\n     <Compile Include="Core\\USTx\\PartCommands.cs" />\n     <Compile Include="Core\\USTx\\UCommand.cs" />\n+    <Compile Include="Core\\USTx\\USinger.cs" />\n+    <Compile Include="Core\\Lib\\EncodingUtil.cs" />\n     <Compile Include="UI\\Controls\\ExpComboBox.xaml.cs">\n       <DependentUpon>ExpComboBox.xaml</DependentUpon>\n     </Compile>\n@@ -115,6 +122,9 @@\n       <DependentUpon>ViewScaler.xaml</DependentUpon>\n       <SubType>Code</SubType>\n     </Compile>\n+    <Compile Include="UI\\Dialogs\\SingerViewDialog.xaml.cs">\n+      <DependentUpon>SingerViewDialog.xaml</DependentUpon>\n+    </Compile>\n     <Compile Include="UI\\MainWindow.xaml.cs">\n       <DependentUpon>MainWindow.xaml</DependentUpon>\n     </Compile>\n@@ -140,6 +150,10 @@\n       <SubType>Designer</SubType>\n       <Generator>MSBuild:Compile</Generator>\n     </Page>\n+    <Page Include="UI\\Dialogs\\SingerViewDialog.xaml">\n+      <SubType>Designer</SubType>\n+      <Generator>MSBuild:Compile</Generator>\n+    </Page>\n     <Page Include="UI\\MainWindow.xaml">\n       <SubType>Designer</SubType>\n       <Generator>MSBuild:Compile</Generator>\n@@ -226,6 +240,7 @@\n       <Install>false</Install>\n     </BootstrapperPackage>\n   </ItemGroup>\n+  <ItemGroup />\n   <Import Project="$(MSBuildToolsPath)\\Microsoft.CSharp.targets" />\n   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \n        Other similar extension points exist, see Microsoft.Common.targets.\ndiff --git a/OpenUtau/UI/Controls/BackgroundElements.cs b/OpenUtau/UI/Controls/BackgroundElements.cs\nindex 324a941..23285c0 100644\n--- a/OpenUtau/UI/Controls/BackgroundElements.cs\n+++ b/OpenUtau/UI/Controls/BackgroundElements.cs\n@@ -110,7 +110,7 @@ protected override void OnRender(DrawingContext drawingContext)\n                 if (TrackHeight >= 12)\n                 {\n                     FormattedText text = new FormattedText(\n-                        MusicMath.GetKeyString(UIConstants.MaxNoteNum - alt - 1),\n+                        MusicMath.GetNoteString(UIConstants.MaxNoteNum - alt - 1),\n                         System.Threading.Thread.CurrentThread.CurrentUICulture,\n                         FlowDirection.LeftToRight,\n                         SystemFonts.CaptionFontFamily.GetTypefaces().First(),\ndiff --git a/OpenUtau/UI/Dialogs/SingerViewDialog.xaml b/OpenUtau/UI/Dialogs/SingerViewDialog.xaml\nnew file mode 100644\nindex 0000000..d938deb\n--- /dev/null\n+++ b/OpenUtau/UI/Dialogs/SingerViewDialog.xaml\n@@ -0,0 +1,23 @@\n+\ufeff<Window x:Class="OpenUtau.UI.Dialogs.SingerViewDialog"\n+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\n+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\n+        Title="SingerViewDialog" Height="600" Width="500" Background="White">\n+    <Grid>\n+        <Image x:Name="avatar" Width="100" Height="100" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,10,0,0"/>\n+        <TextBlock x:Name="name" FontSize="24" HorizontalAlignment="Stretch" Margin="120,10,10,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="30"/>\n+        <TextBlock x:Name="info" HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="120,50,10,0" Height="60"/>\n+        <ListView x:Name="otoview" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10,120,10,10">\n+            <ListView.View>\n+                <GridView AllowsColumnReorder="False">\n+                    <GridViewColumn Header="Alias" DisplayMemberBinding="{Binding Alias}"/>\n+                    <GridViewColumn Header="File" DisplayMemberBinding="{Binding File}"/>\n+                    <GridViewColumn Header="Offset" DisplayMemberBinding="{Binding Offset}"/>\n+                    <GridViewColumn Header="Consonant" DisplayMemberBinding="{Binding Consonant}"/>\n+                    <GridViewColumn Header="Cutoff" DisplayMemberBinding="{Binding Cutoff}"/>\n+                    <GridViewColumn Header="Preutter" DisplayMemberBinding="{Binding Preutter}"/>\n+                    <GridViewColumn Header="Overlap" DisplayMemberBinding="{Binding Overlap}"/>\n+                </GridView>\n+            </ListView.View>\n+        </ListView>\n+    </Grid>\n+</Window>\ndiff --git a/OpenUtau/UI/Dialogs/SingerViewDialog.xaml.cs b/OpenUtau/UI/Dialogs/SingerViewDialog.xaml.cs\nnew file mode 100644\nindex 0000000..971e585\n--- /dev/null\n+++ b/OpenUtau/UI/Dialogs/SingerViewDialog.xaml.cs\n@@ -0,0 +1,39 @@\n+\ufeffusing System;\n+using System.Collections.Generic;\n+using System.Linq;\n+using System.Text;\n+using System.Threading.Tasks;\n+using System.Windows;\n+using System.Windows.Controls;\n+using System.Windows.Data;\n+using System.Windows.Documents;\n+using System.Windows.Input;\n+using System.Windows.Media;\n+using System.Windows.Media.Imaging;\n+using System.Windows.Shapes;\n+\n+using OpenUtau.UI.Controls;\n+using OpenUtau.Core.USTx;\n+\n+namespace OpenUtau.UI.Dialogs\n+{\n+    /// <summary>\n+    /// Interaction logic for SingerViewDialog.xaml\n+    /// </summary>\n+    public partial class SingerViewDialog : Window\n+    {\n+        public SingerViewDialog()\n+        {\n+            InitializeComponent();\n+        }\n+\n+        public void SetSinger(USinger singer)\n+        {\n+            this.Title = this.name.Text = singer.Name;\n+            this.avatar.Source = singer.Avatar;\n+            this.info.Text = "Author: " + singer.Author + "\\nWebsite: " + singer.Website + "\\nPath: " + singer.ActualPath;\n+            this.otoview.Items.Clear();\n+            foreach (var pair in singer.AliasMap) this.otoview.Items.Add(pair.Value);\n+        }\n+    }\n+}\ndiff --git a/OpenUtau/UI/MainWindow.xaml b/OpenUtau/UI/MainWindow.xaml\nindex 787d767..b864853 100644\n--- a/OpenUtau/UI/MainWindow.xaml\n+++ b/OpenUtau/UI/MainWindow.xaml\n@@ -49,6 +49,7 @@\n                 <MenuItem Header="Midi Editor" Click="Menu_OpenMidiEditor"/>\n             </MenuItem>\n             <MenuItem Header="_Tools">\n+                <MenuItem Header="Singers..." Click="MenuSingers_Click"/>\n                 <MenuItem Header="Refresh Plugins"/>\n             </MenuItem>\n             <MenuItem Header="_Help">\ndiff --git a/OpenUtau/UI/MainWindow.xaml.cs b/OpenUtau/UI/MainWindow.xaml.cs\nindex a58a7e9..524e595 100644\n--- a/OpenUtau/UI/MainWindow.xaml.cs\n+++ b/OpenUtau/UI/MainWindow.xaml.cs\n@@ -538,5 +538,11 @@ private void MenuSave_Click(object sender, RoutedEventArgs e)\n             }\n         }\n \n+        private void MenuSingers_Click(object sender, RoutedEventArgs e)\n+        {\n+            var w = new Dialogs.SingerViewDialog();\n+            w.SetSinger(DocManager.Inst.Project.Singers[0]);\n+            w.ShowDialog();\n+        }\n     }\n }\ndiff --git a/OpenUtau/packages.config b/OpenUtau/packages.config\nindex 4ef1e14..3ab62b5 100644\n--- a/OpenUtau/packages.config\n+++ b/OpenUtau/packages.config\n@@ -3,4 +3,6 @@\n   <package id="Blend.Interctivity.WPF.v4.0" version="1.0.3" targetFramework="net45" />\n   <package id="Expression.Blend.Sdk" version="1.0.2" targetFramework="net45" />\n   <package id="NAudio" version="1.7.3" targetFramework="net45" />\n+  <package id="SimpleHelpers.FileEncoding" version="1.3.1" targetFramework="net45" />\n+  <package id="UDE.CSharp" version="1.1.0" targetFramework="net45" />\n </packages>\n\\ No newline at end of file\n', 'commit_subject': 'UTAU Soundbank loading.', 'repo_name': 'stakira/OpenUtau', 'committer': {'name': 'Sugita Akira', 'email': 'e6f2f86183fc5c676252cbff8b1c024e9c991343@gmail.com', 'time_sec': '1429760471', 'tz_offset': '-420', 'date': {'seconds': '1429760471'}}, 'commit_tree': 'da36d18f33e2137513665eaa34047c37ca4979f9', 'commit_message': 'UTAU Soundbank loading.\n', 'language_name': 'C#', 'license': 'mit', 'hunks': '@@ -0,0 +1,39 @@\n+\ufeffusing System;\n+using System.Collections.Generic;\n+using System.Linq;\n+using System.Text;\n+using System.Threading.Tasks;\n+using System.Windows;\n+using System.Windows.Controls;\n+using System.Windows.Data;\n+using System.Windows.Documents;\n+using System.Windows.Input;\n+using System.Windows.Media;\n+using System.Windows.Media.Imaging;\n+using System.Windows.Shapes;\n+\n+using OpenUtau.UI.Controls;\n+using OpenUtau.Core.USTx;\n+\n+namespace OpenUtau.UI.Dialogs\n+{\n+    /// <summary>\n+    /// Interaction logic for SingerViewDialog.xaml\n+    /// </summary>\n+    public partial class SingerViewDialog : Window\n+    {\n+        public SingerViewDialog()\n+        {\n+            InitializeComponent();\n+        }\n+\n+        public void SetSinger(USinger singer)\n+        {\n+            this.Title = this.name.Text = singer.Name;\n+            this.avatar.Source = singer.Avatar;\n+            this.info.Text = "Author: " + singer.Author + "\\nWebsite: " + singer.Website + "\\nPath: " + singer.ActualPath;\n+            this.otoview.Items.Clear();\n+            foreach (var pair in singer.AliasMap) this.otoview.Items.Add(pair.Value);\n+        }\n+    }\n+}\n', 'addition_count': 39, 'deletion_count': 0, 'src_file': '/dev/null', 'tgt_file': 'b/OpenUtau/UI/Dialogs/SingerViewDialog.xaml.cs', 'file_extension': '.cs', 'before_file': 'ADDFILE', 'message': 'UTAU Soundbank loading.\n', 'author_name': 'Sugita Akira', 'lang': 'xaml'}