コード例 #1
0
ファイル: ResoXAmp.cs プロジェクト: cadencii/cadencii
 public static bool edit( VsqFile vsq ) {
     ResoXAmp form = new ResoXAmp();
     if ( form.ShowDialog() != DialogResult.OK ) {
         return false;
     }
     VsqTrack track = vsq.Track[AppManager.Selected];
     VsqBPList source = track.getCurve( CurveType.reso1amp.getName() );
     VsqBPList reso2amp = (VsqBPList)track.getCurve( CurveType.reso2amp.getName() ).clone();
     VsqBPList reso3amp = (VsqBPList)track.getCurve( CurveType.reso3amp.getName() ).clone();
     VsqBPList reso4amp = (VsqBPList)track.getCurve( CurveType.reso4amp.getName() ).clone();
     Console.WriteLine( "AmplifyCoeffReso2=" + AmplifyCoeffReso2 );
     Console.WriteLine( "AmplifyCoeffReso3=" + AmplifyCoeffReso3 );
     Console.WriteLine( "AmplifyCoeffReso4=" + AmplifyCoeffReso4 );
     amplify( source, reso2amp, AmplifyCoeffReso2 );
     amplify( source, reso3amp, AmplifyCoeffReso3 );
     amplify( source, reso4amp, AmplifyCoeffReso4 );
     track.setCurve( CurveType.reso2amp.getName(), reso2amp );
     track.setCurve( CurveType.reso3amp.getName(), reso3amp );
     track.setCurve( CurveType.reso4amp.getName(), reso4amp );
     Console.WriteLine( "reso2amp.getCount()=" + reso2amp.size() );
     Console.WriteLine( "reso3amp.getCount()=" + reso3amp.size() );
     Console.WriteLine( "reso4amp.getCount()=" + reso4amp.size() );
     MessageBox.Show( "done" );
     return true;
 }
コード例 #2
0
ファイル: VsqxWriterTest.cs プロジェクト: cadencii/cadencii
        public void writeSingerTest()
        {
            var sequence = new VsqFile("singer", 1, 4, 4, 500000);
            var premeasaure_clock = sequence.getPreMeasureClocks();

            var temporary = Path.GetTempFileName();
            var writer = new VsqxWriter();
            Assert.DoesNotThrow(() => writer.write(sequence, temporary));

            var text = File.ReadAllText(temporary);
            var document = XElement.Parse(text);
            XNamespace ns = "http://www.yamaha.co.jp/vocaloid/schema/vsq3/";
            var singer =
                document
                    .Descendants(ns + "vsTrack")
                    .First()
                    .Descendants(ns + "musicalPart")
                    .First()
                    .Descendants(ns + "singer")
                    .FirstOrDefault();
            Assert.NotNull(singer);
            var pos_tick = singer.Descendants(ns + "posTick").FirstOrDefault();
            Assert.NotNull(pos_tick);
            Assert.AreEqual("0", pos_tick.Value);
        }
コード例 #3
0
ファイル: ResoXAmp.cs プロジェクト: scskarsper/Cadencii_UTAU
    public static bool edit(VsqFile vsq)
    {
        ResoXAmp form = new ResoXAmp();

        if (form.ShowDialog() != DialogResult.OK)
        {
            return(false);
        }
        VsqTrack  track    = vsq.Track[AppManager.Selected];
        VsqBPList source   = track.getCurve(CurveType.reso1amp.getName());
        VsqBPList reso2amp = (VsqBPList)track.getCurve(CurveType.reso2amp.getName()).clone();
        VsqBPList reso3amp = (VsqBPList)track.getCurve(CurveType.reso3amp.getName()).clone();
        VsqBPList reso4amp = (VsqBPList)track.getCurve(CurveType.reso4amp.getName()).clone();

        Console.WriteLine("AmplifyCoeffReso2=" + AmplifyCoeffReso2);
        Console.WriteLine("AmplifyCoeffReso3=" + AmplifyCoeffReso3);
        Console.WriteLine("AmplifyCoeffReso4=" + AmplifyCoeffReso4);
        amplify(source, reso2amp, AmplifyCoeffReso2);
        amplify(source, reso3amp, AmplifyCoeffReso3);
        amplify(source, reso4amp, AmplifyCoeffReso4);
        track.setCurve(CurveType.reso2amp.getName(), reso2amp);
        track.setCurve(CurveType.reso3amp.getName(), reso3amp);
        track.setCurve(CurveType.reso4amp.getName(), reso4amp);
        Console.WriteLine("reso2amp.getCount()=" + reso2amp.size());
        Console.WriteLine("reso3amp.getCount()=" + reso3amp.size());
        Console.WriteLine("reso4amp.getCount()=" + reso4amp.size());
        MessageBox.Show("done");
        return(true);
    }
コード例 #4
0
ファイル: Time_Shift.cs プロジェクト: cadencii/cadencii
 public static bool Edit( VsqFile vsq ) {
     Time_Shift ts = new Time_Shift();
     if ( ts.ShowDialog() != DialogResult.OK ) {
         return false;
     }
     return true;
 }
コード例 #5
0
        public void writeSingerTest()
        {
            var sequence          = new VsqFile("singer", 1, 4, 4, 500000);
            var premeasaure_clock = sequence.getPreMeasureClocks();

            var temporary = Path.GetTempFileName();
            var writer    = new VsqxWriter();

            Assert.DoesNotThrow(() => writer.write(sequence, temporary));

            var        text     = File.ReadAllText(temporary);
            var        document = XElement.Parse(text);
            XNamespace ns       = "http://www.yamaha.co.jp/vocaloid/schema/vsq3/";
            var        singer   =
                document
                .Descendants(ns + "vsTrack")
                .First()
                .Descendants(ns + "musicalPart")
                .First()
                .Descendants(ns + "singer")
                .FirstOrDefault();

            Assert.NotNull(singer);
            var pos_tick = singer.Descendants(ns + "posTick").FirstOrDefault();

            Assert.NotNull(pos_tick);
            Assert.AreEqual("0", pos_tick.Value);
        }
コード例 #6
0
        public static VsqCommand generateCommandReplace(VsqFile vsq)
        {
            VsqCommand command = new VsqCommand();

            command.Args    = new Object[1];
            command.Type    = VsqCommandType.REPLACE;
            command.Args[0] = (VsqFile)vsq.clone();
            return(command);
        }
コード例 #7
0
    private static void hamori(VsqFile vsq, int basecode, int opt)
    {
        int[][] steps = new int[][] {
            // C Major    C     D     E  F     G     A     B
            // 7度上
            new int[] { 11, 11, 10, 10, 10, 11, 11, 10, 10, 10, 10, 10 },
            // 6度上
            new int[] { 9, 9, 9, 9, 8, 9, 9, 9, 9, 8, 8, 9 },
            // 5度上
            new int[] { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6 },
            // 4度上
            new int[] { 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5 },
            // 3度上
            new int[] { 4, 4, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3 },
            // 2度上
            new int[] { 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 }
        };
        int[] step;
        if (opt == 6)
        {
            return;
        }
        if (opt < 6)
        {
            step = steps[opt];
        }
        else
        {
            step = steps[opt - 7];
            for (int i = 0; i < 12; i++)
            {
                step[i] -= 12;
            }
        }

        int      note, tmp;
        VsqTrack track = vsq.Track[AppManager.Selected];

        for (Iterator <SelectedEventEntry> itr = AppManager.getSelectedEventIterator(); itr.hasNext();)
        {
            VsqEvent item = track.findEventFromID(((SelectedEventEntry)itr.next()).original.InternalID);
            if (item.ID.type == VsqIDType.Anote)
            {
                tmp  = (item.ID.Note + 12 - basecode) % 12;
                note = item.ID.Note + step[tmp];
                if (note < 0)
                {
                    note = 0;
                }
                if (127 < note)
                {
                    note = 127;
                }
                item.ID.Note = note;
            }
        }
    }
コード例 #8
0
 public static void Main( string[] args ){
     int unit = int.Parse( args[0] );
     System.Windows.Forms.OpenFileDialog d = new System.Windows.Forms.OpenFileDialog();
     if ( d.ShowDialog() == System.Windows.Forms.DialogResult.OK ) {
         string f = d.FileName;
         string dir = System.IO.Path.GetDirectoryName( f );
         string name = System.IO.Path.GetFileNameWithoutExtension( f );
         Console.WriteLine( "name=" + name );
         int index = name.IndexOf( "-001" );
         string basename = "";
         if ( index >= 0 ) {
             basename = name.Substring( 0, index );
         }
         int count = 0;
         Dictionary<int, int> dict = new Dictionary<int, int>();
         while ( true ) {
             count++;
             string open = PortUtil.combinePath( dir, basename + "-" + PortUtil.formatDecimal( "000", count ) + ".vsq" );
             Console.WriteLine( "open=" + open );
             if ( !PortUtil.isFileExists( open ) ) {
                 break;
             }
             VsqFile vsq = new VsqFile( open, "Shift_JIS" );
             int i = -1;
             int b = 3840;
             for ( Iterator itr = vsq.Track.get( 1 ).getNoteEventIterator(); itr.hasNext(); ) {
                 i++;
                 VsqEvent item = (VsqEvent)itr.next();
                 if ( i == 0 ){
                     continue;
                 }
                 int ideal_start = b + i * unit;
                 int shift = item.Clock - ideal_start;
                 if( dict.ContainsKey( shift ) ){
                     dict[shift] = dict[shift] + 1;
                 }else{
                     dict.Add( shift, 1 );
                 }
             }
         }
         int max = 0;
         int min = 0;
         foreach( int key in dict.Keys ){
             max = Math.Max( max, key );
             min = Math.Min( min, key );
         }
         using ( System.IO.StreamWriter sw = new System.IO.StreamWriter( PortUtil.combinePath( dir, basename + ".txt" ) ) ) {
             for( int i = min; i <= max; i++ ){
                 if ( dict.ContainsKey( i ) ){
                     sw.WriteLine( i + "\t" + dict[i] );
                 }else{
                     sw.WriteLine( i + "\t0" );
                 }
             }
         }
     }
 }
コード例 #9
0
    public static bool Edit(VsqFile vsq)
    {
        Time_Shift ts = new Time_Shift();

        if (ts.ShowDialog() != DialogResult.OK)
        {
            return(false);
        }
        return(true);
    }
コード例 #10
0
ファイル: Roman2Hiragana.cs プロジェクト: cadencii/cadencii
 public static bool Edit( VsqFile Vsq ) {
   for ( int i = 1; i < Vsq.Track.size(); i++ ) {
     for ( int j = 0; j < Vsq.Track.get( i ).getEventCount(); j++ ) {
       VsqEvent item = Vsq.Track.get( i ).getEvent( j );
       if ( item.ID.type == VsqIDType.Anote ) {
         item.ID.LyricHandle.L0.Phrase = KanaDeRomanization.Attach( item.ID.LyricHandle.L0.Phrase );
       }
     }
   }
   return true;
 }
コード例 #11
0
ファイル: makeMids.cs プロジェクト: kixtarte/cadencii
 public static void Main( string[] args ){
     if( args.Length < 3 ){
         Console.WriteLine( "makeMids [words-list] [singer(ex. Miku)] [DSB(ex. DSB303)] [extension(ex. .vsq)] [start-index]" );
         return;
     }
     string list = args[0];
     string singer = args[1];
     string dsb = args[2];
     string ext = args[3];
     int start_index = 0;
     if( args.Length >= 5 ){
         start_index = int.Parse( args[4] );
     }
     if( !Directory.Exists( singer ) ){
         Directory.CreateDirectory( singer );
     }
     using( StreamReader sr = new StreamReader( list ) ){
         string line = "";
         VsqFile src = new VsqFile( singer, 2, 4, 4, 500000 );
         VsqFile vsq = (VsqFile)src.clone();
         int clock = 480 * 4 * 2;
         int count = 0;
         int numVsqs = start_index;
         while( (line = sr.ReadLine()) != null ){
             VsqEvent item = new VsqEvent();
             item.Clock = clock;
             item.ID = new VsqID();
             item.ID.type = VsqIDType.Anote;
             item.ID.setLength( 240 );
             item.ID.Note = 64;
             item.ID.LyricHandle = new LyricHandle();
             item.ID.LyricHandle.L0 = new Lyric( line, "u:" );
             vsq.Track.get( 1 ).addEvent( item, count + 1 );
             
             clock += 240;
             count++;
             if( count > 5000 ){
                 vsq.Track.get( 1 ).getCommon().Version = dsb;
                 vsq.Track.get( 1 ).sortEvent();
                 vsq.write( singer + "\\" + numVsqs + ext );
                 numVsqs++;
                 vsq = null;
                 vsq = (VsqFile)src.clone();
                 clock = 480 * 4 * 2;
                 count = 0;
             }
         }
         if( count > 0 ){
             vsq.Track.get( 1 ).getCommon().Version = dsb;
             vsq.Track.get( 1 ).sortEvent();
             vsq.write( singer + "\\" + numVsqs + ext );
         }
     }
 }
コード例 #12
0
ファイル: TransposeEx.cs プロジェクト: cadencii/cadencii
 //---------------------------------------------
 public static bool Edit( VsqFile vsq ) {
   using ( TransposeEx d = new TransposeEx() ) {
     if ( d.ShowDialog() != DialogResult.OK ) {
       return false;
     } else {
       int step = (int)d.numUpDown.Value;
       if (step != 0) transpose( vsq, step );
       return true;
     }
   }
 }
コード例 #13
0
 private List <IconHandle> collectAllSingerInfo(VsqFile sequence)
 {
     return
         (sequence.Track
          .Where((track) => track.MetaText != null)
          .SelectMany((track) => track.MetaText.Events.Events)
          .Where((vsq_event) => vsq_event.ID.type == VsqIDType.Singer)
          .Select((vsq_event) => vsq_event.ID.IconHandle)
          .Distinct()
          .OrderBy((handle) => handle.Language * 255 + handle.Program)
          .ToList());
 }
コード例 #14
0
        /// <summary>
        /// Do export to MusicXML file.
        /// </summary>
        /// <param name="sequence">A sequence to be exported.</param>
        /// <param name="file_path">A file path.</param>
        public void write(VsqFile sequence, string file_path)
        {
            var score = new scorepartwise();

            score.version = "2.0";

            score.identification          = new identification();
            score.identification.encoding = new encoding();
            score.identification.encoding.software.Add(this.GetType().FullName);

            score.partlist                          = new partlist();
            score.partlist.scorepart                = new scorepart();
            score.partlist.scorepart.id             = "P1";
            score.partlist.scorepart.partname       = new partname();
            score.partlist.scorepart.partname.Value = sequence.Track[1].getName();
            var partlist = new List <scorepart>();

            for (int i = 2; i < sequence.Track.Count; ++i)
            {
                var track     = sequence.Track[i];
                var scorepart = new scorepart();
                scorepart.id             = "P" + i;
                scorepart.partname       = new partname();
                scorepart.partname.Value = track.getName();
                partlist.Add(scorepart);
            }
            score.partlist.Items = partlist.ToArray();

            var quantized_tempo_table = quantizeTempoTable(sequence.TempoTable);

            score.part =
                sequence.Track.Skip(1).Select((track) => {
                var result = createScorePart(track, sequence.TimesigTable, quantized_tempo_table);
                quantized_tempo_table.Clear();
                return(result);
            }).ToArray();
            for (int i = 0; i < score.part.Length; i++)
            {
                score.part[i].id = "P" + (i + 1);
            }

            var serializer = new System.Xml.Serialization.XmlSerializer(typeof(scorepartwise));

            using (var stream = new FileStream(file_path, FileMode.Create, FileAccess.Write)) {
                var writer = new System.Xml.XmlTextWriter(stream, System.Text.Encoding.UTF8);
                writer.Formatting = System.Xml.Formatting.Indented;
                writer.WriteStartDocument();
                writer.WriteDocType("score-partwise", "-//Recordare//DTD MusicXML 2.0 Partwise//EN", "http://www.musicxml.org/dtds/partwise.dtd", null);
                var ns = new System.Xml.Serialization.XmlSerializerNamespaces();
                ns.Add(string.Empty, string.Empty);
                serializer.Serialize(writer, score, ns);
            }
        }
コード例 #15
0
ファイル: TransposeEx.cs プロジェクト: cadencii/cadencii
 private static void transpose( VsqFile vsq, int step ) {
   int note;
   VsqTrack track = vsq.Track[AppManager.Selected];
   for( Iterator<SelectedEventEntry> itr = AppManager.getSelectedEventIterator(); itr.hasNext(); ) {
     VsqEvent item = track.findEventFromID(((SelectedEventEntry)itr.next()).original.InternalID);
     if ( item.ID.type == VsqIDType.Anote ) {
       note = item.ID.Note + step;
       if ( note < 0 ) note = 0;
       if ( 127 < note ) note = 127;
       item.ID.Note = note;
     }
   }
 }
コード例 #16
0
 public static bool Edit(VsqFile vsq)
 {
     using (Hamori d = new Hamori())
     {
         if (d.ShowDialog() != DialogResult.OK)
         {
             return(false);
         }
         else
         {
             hamori(vsq, d.cbbBaseCode.SelectedIndex, d.cbbSlide.SelectedIndex);
             return(true);
         }
     }
 }
コード例 #17
0
 public static bool Edit(VsqFile Vsq)
 {
     for (int i = 1; i < Vsq.Track.size(); i++)
     {
         for (int j = 0; j < Vsq.Track.get(i).getEventCount(); j++)
         {
             VsqEvent item = Vsq.Track.get(i).getEvent(j);
             if (item.ID.type == VsqIDType.Anote)
             {
                 item.ID.LyricHandle.L0.Phrase = KanaDeRomanization.Attach(item.ID.LyricHandle.L0.Phrase);
             }
         }
     }
     return(true);
 }
コード例 #18
0
ファイル: Hamori.cs プロジェクト: cadencii/cadencii
 public static bool Edit(VsqFile vsq)
 {
     using (Hamori d = new Hamori())
     {
         if (d.ShowDialog() != DialogResult.OK)
         {
             return false;
         }
         else
         {
             hamori(vsq, d.cbbBaseCode.SelectedIndex, d.cbbSlide.SelectedIndex);
             return true;
         }
     }
 }
コード例 #19
0
 public void Redo(int index)
 {
     if (s_current.Child.Count > 0)
     {
         ICommand run = s_current.Child[index];
         ICommand rev = VsqFile.executeCommand(run);
         rev.Parent = s_current;
         for (int i = 0; i < run.Child.Count; i++)
         {
             run.Child[i].Parent = rev;
             rev.Child.Add(run.Child[i]);
         }
         s_current.Child[index] = rev;
         s_current = run;
     }
 }
コード例 #20
0
        private XmlElement createVoiceTableNode(VsqFile sequence)
        {
            var result = doc_.CreateElement("vVoiceTable");
            var all_assigned_singers = collectAllSingerInfo(sequence);

            all_assigned_singers.ForEach((handle) => {
                var node = doc_.CreateElement("vVoice");
                node.AppendChild(createNode("vBS", handle.Language));
                node.AppendChild(createNode("vPC", handle.Program));
                node.AppendChild(createNode("compID", "AAAAAAAAAAAAAAAA"));
                node.AppendChild(createNode("vVoiceName", handle.Caption));
                node.AppendChild(createVoiceParamNode(handle));
                result.AppendChild(node);
            });
            return(result);
        }
コード例 #21
0
    public static bool Edit(VsqFile vsq)
    {
        int      track = 1;
        InputBox ib    = new InputBox("Input target track index");

        ib.setResult(track.ToString());
        if (ib.ShowDialog() != DialogResult.OK)
        {
            return(false);
        }
        if (!int.TryParse(ib.getResult(), out track))
        {
            MessageBox.Show("integer parse error");
            return(false);
        }
        if (track <= 0 || vsq.Track.Count <= track)
        {
            MessageBox.Show("invalid target track");
            return(false);
        }
        using (SaveFileDialog sfd = new SaveFileDialog()) {
            if (sfd.ShowDialog() != DialogResult.OK)
            {
                return(false);
            }
            using (StreamWriter sw = new StreamWriter(sfd.FileName, false, Encoding.GetEncoding(932))) {
                sw.WriteLine("vlf\t2.0");
                sw.WriteLine("vlfpart\tPhrase1\t0\t0");
                for (int i = 0; i < vsq.Track[track].getEventCount(); i++)
                {
                    VsqEvent ve = vsq.Track[track].getEvent(i);
                    if (ve.ID.type == VsqIDType.Anote)
                    {
                        string symbol = "";
                        for (int j = 0; j < ve.ID.LyricHandle.L0.getPhoneticSymbolList().Count; j++)
                        {
                            symbol += (" " + ve.ID.LyricHandle.L0.getPhoneticSymbolList()[j]);
                        }
                        symbol = symbol.Trim();
                        sw.WriteLine(ve.ID.LyricHandle.L0.Phrase + "\t" + symbol + "\t0");
                    }
                }
            }
        }
        return(true);
    }
コード例 #22
0
        /// <summary>
        /// エクスポートを行う。
        /// </summary>
        /// <param name="path">出力先のファイルパス</param>
        /// <param name="sequence">出力するシーケンス</param>
        public void write(VsqFile sequence, string path)
        {
            doc_ = new XmlDocument();
            const string xsi_url = "http://www.w3.org/2001/XMLSchema-instance";
            var          root    = doc_.CreateElement("vsq3");

            {
                var xmlns = doc_.CreateAttribute("xmlns");
                xmlns.Value = "http://www.yamaha.co.jp/vocaloid/schema/vsq3/";
                root.Attributes.Append(xmlns);
            }
            {
                var xsi = doc_.CreateAttribute("xmlns:xsi");
                xsi.Value = xsi_url;
                root.Attributes.Append(xsi);
            }
            {
                var schema = doc_.CreateAttribute("xsi", "schemaLocation", xsi_url);
                schema.Value = "http://www.yamaha.co.jp/vocaloid/schema/vsq3/ vsq3.xsd";
                root.Attributes.Append(schema);
            }
            root.AppendChild(createNode("vender", "Yamaha corporation"));
            root.AppendChild(createNode("version", "3.0.0.11"));
            root.AppendChild(createVoiceTableNode(sequence));
            root.AppendChild(createMixerNode(sequence.Mixer));
            root.AppendChild(createMasterTrackNode(sequence, sequence.Track[0]));

            for (int i = 1; i < sequence.Track.Count; ++i)
            {
                root.AppendChild(createTrackNode(sequence.Track[i],
                                                 i - 1,
                                                 sequence.getPreMeasureClocks(),
                                                 sequence.TotalClocks));
            }

            root.AppendChild(doc_.CreateElement("seTrack"));
            root.AppendChild(doc_.CreateElement("karaokeTrack"));

            doc_.AppendChild(root);
            using (var stream = new System.IO.FileStream(path, System.IO.FileMode.Create, System.IO.FileAccess.Write)) {
                var writer = new XmlTextWriter(stream, Encoding.UTF8);
                writer.Formatting = Formatting.Indented;
                doc_.Save(writer);
            }
        }
コード例 #23
0
 //---------------------------------------------
 public static bool Edit(VsqFile vsq)
 {
     using (TransposeEx d = new TransposeEx()) {
         if (d.ShowDialog() != DialogResult.OK)
         {
             return(false);
         }
         else
         {
             int step = (int)d.numUpDown.Value;
             if (step != 0)
             {
                 transpose(vsq, step);
             }
             return(true);
         }
     }
 }
コード例 #24
0
        public void Undo()
        {
            ICommand run = s_current;
            ICommand rev = VsqFile.executeCommand(run);

            for (int i = 0; i < s_current.Child.Count; i++)
            {
                s_current.Child[i].Parent = rev;
                rev.Child.Add(s_current.Child[i]);
            }
            rev.Parent = s_current.Parent;
            for (int i = 0; i < s_current.Parent.Child.Count; i++)
            {
                if (Object.ReferenceEquals(s_current, s_current.Parent.Child[i]))
                {
                    s_current.Parent.Child[i] = rev;
                    break;
                }
            }
            s_current = s_current.Parent;
        }
コード例 #25
0
        public void readFromVsqxMultiTrack()
        {
            VsqFile vsq = VsqxReader.readFromVsqx("./fixture/track2.vsqx");

            Assert.AreEqual(3, vsq.Track.size());

            // 1トラック目
            var track = vsq.Track.get(1);

            Assert.AreEqual(3, track.getEventCount());
            Assert.AreEqual(VsqIDType.Singer, track.getEvent(1).ID.type);
            Assert.AreEqual("VY1V3", track.getEvent(1).ID.IconHandle.IDS);
            Assert.AreEqual(VsqIDType.Anote, track.getEvent(2).ID.type);
            Assert.AreEqual("ど", track.getEvent(2).ID.LyricHandle.L0.Phrase);

            // 2トラック目
            track = vsq.Track.get(2);
            Assert.AreEqual(3, track.getEventCount());
            Assert.AreEqual(VsqIDType.Singer, track.getEvent(1).ID.type);
            Assert.AreEqual("VY1V3", track.getEvent(1).ID.IconHandle.IDS);
            Assert.AreEqual(VsqIDType.Anote, track.getEvent(2).ID.type);
            Assert.AreEqual("み", track.getEvent(2).ID.LyricHandle.L0.Phrase);
        }
コード例 #26
0
    private static void transpose(VsqFile vsq, int step)
    {
        int      note;
        VsqTrack track = vsq.Track[AppManager.Selected];

        for (Iterator <SelectedEventEntry> itr = AppManager.getSelectedEventIterator(); itr.hasNext();)
        {
            VsqEvent item = track.findEventFromID(((SelectedEventEntry)itr.next()).original.InternalID);
            if (item.ID.type == VsqIDType.Anote)
            {
                note = item.ID.Note + step;
                if (note < 0)
                {
                    note = 0;
                }
                if (127 < note)
                {
                    note = 127;
                }
                item.ID.Note = note;
            }
        }
    }
コード例 #27
0
        private XmlElement createMasterTrackNode(VsqFile sequence, VsqTrack master_track)
        {
            var result = doc_.CreateElement("masterTrack");

            result.AppendChild(createNode("seqName", master_track.getName()));
            result.AppendChild(createNode("comment", ""));
            result.AppendChild(createNode("resolution", sequence.getTickPerQuarter()));
            result.AppendChild(createNode("preMeasure", sequence.getPreMeasure()));
            sequence.TimesigTable.ForEach((time_sig) => {
                var node = doc_.CreateElement("timeSig");
                node.AppendChild(createNode("posMes", time_sig.BarCount));
                node.AppendChild(createNode("nume", time_sig.Numerator));
                node.AppendChild(createNode("denomi", time_sig.Denominator));
                result.AppendChild(node);
            });
            sequence.TempoTable.ForEach((tempo) => {
                var node = doc_.CreateElement("tempo");
                node.AppendChild(createNode("posTick", tempo.Clock));
                node.AppendChild(createNode("bpm", (int)(60e6 / tempo.Tempo * 100)));
                result.AppendChild(node);
            });
            return(result);
        }
コード例 #28
0
ファイル: Generate VLF.cs プロジェクト: cadencii/cadencii
 public static bool Edit( VsqFile vsq ){
     int track = 1;
     InputBox ib = new InputBox( "Input target track index" );
     ib.setResult( track.ToString() );
     if ( ib.ShowDialog() != DialogResult.OK ) {
         return false;
     }
     if ( !int.TryParse( ib.getResult(), out track ) ) {
         MessageBox.Show( "integer parse error" );
         return false;
     }
     if ( track <= 0 || vsq.Track.size() <= track ) {
         MessageBox.Show( "invalid target track" );
         return false;
     }
     using ( SaveFileDialog sfd = new SaveFileDialog() ) {
         if ( sfd.ShowDialog() != DialogResult.OK ) {
             return false;
         }
         using ( StreamWriter sw = new StreamWriter( sfd.FileName, false, Encoding.GetEncoding( 932 ) ) ) {
             sw.WriteLine( "vlf\t2.0" );
             sw.WriteLine( "vlfpart\tPhrase1\t0\t0" );
             for ( int i = 0; i < vsq.Track.get( track ).getEventCount(); i++ ) {
                 VsqEvent ve = vsq.Track.get( track ).getEvent( i );
                 if ( ve.ID.type == VsqIDType.Anote ) {
                     string symbol = "";
                     for ( int j = 0; j < ve.ID.LyricHandle.L0.getPhoneticSymbolList().Count; j++ ) {
                         symbol += (" " + ve.ID.LyricHandle.L0.getPhoneticSymbolList()[j]);
                     }
                     symbol = symbol.Trim();
                     sw.WriteLine( ve.ID.LyricHandle.L0.Phrase + "\t" + symbol + "\t0" );
                 }
             }
         }
     }
     return true;
 }
コード例 #29
0
ファイル: Hamori.cs プロジェクト: cadencii/cadencii
    private static void hamori(VsqFile vsq, int basecode, int opt)
    {
        int[][] steps = new int[][] {
        // C Major    C     D     E  F     G     A     B
        // 7度上
         new int[] { 11,11,10,10,10,11,11,10,10,10,10,10 },
        // 6度上
         new int[] {  9, 9, 9, 9, 8, 9, 9, 9, 9, 8, 8, 9 },
        // 5度上
         new int[] {  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6 },
        // 4度上
         new int[] {  5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5 },
        // 3度上
         new int[] {  4, 4, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3 },
        // 2度上
         new int[] {  2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 }
        };
        int[] step;
        if (opt == 6) return;
        if (opt < 6)
            step = steps[opt];
        else
        {
            step = steps[opt - 7];
            for (int i = 0; i < 12; i++) step[i] -= 12;
        }

        int note, tmp;
        VsqTrack track = vsq.Track[AppManager.Selected];
        for( Iterator<SelectedEventEntry> itr = AppManager.getSelectedEventIterator(); itr.hasNext(); ) {
            VsqEvent item = track.findEventFromID(((SelectedEventEntry)itr.next()).original.InternalID);
            if (item.ID.type == VsqIDType.Anote )
            {
                tmp = (item.ID.Note + 12 - basecode) % 12;
                note = item.ID.Note + step[tmp];
                if (note < 0) note = 0;
                if (127 < note) note = 127;
                item.ID.Note = note;
            }
        }
    }
コード例 #30
0
ファイル: ResoXAmp.cs プロジェクト: scskarsper/Cadencii_UTAU
 public static bool Edit(VsqFile vsq)
 {
     return(edit(vsq));
 }
コード例 #31
0
ファイル: ResoXAmp.cs プロジェクト: cadencii/cadencii
 public static bool Edit( VsqFile vsq ) {
     return edit( vsq );
 }
コード例 #32
0
    public static bool Edit(VsqFile vsq)
    {
        using (RenderAsUtau dlg = new RenderAsUtau()) {
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                Singer    = dlg.txtSinger.Text;
                Resampler = dlg.txtResampler.Text;
                WavTool   = dlg.txtWavtool.Text;
                string script   = Path.Combine(Application.StartupPath, Path.Combine("script", "Render As UTAU.cs"));  //Script.ScriptPath;
                string temp_dir = Path.Combine(Path.GetDirectoryName(script), Path.GetFileNameWithoutExtension(script));

#if DEBUG
                if (!Directory.Exists(temp_dir))
                {
                    Directory.CreateDirectory(temp_dir);
                }
                StreamWriter sw = new StreamWriter(Path.Combine(temp_dir, "log.txt"));
#endif
                // 原音設定を読み込み
                Dictionary <string, OtoArgs> config = new Dictionary <string, OtoArgs>();
                string singer_name = Path.GetFileName(Singer);
                string config_file = Path.Combine(Singer, "oto.ini");
#if DEBUG
                sw.WriteLine("Singer=" + Singer);
                sw.WriteLine("singer_name=" + singer_name);
                sw.WriteLine("config_file=" + config_file);
#endif
                if (File.Exists(config_file))
                {
                    using (cp932reader sr = new cp932reader(config_file)) {
                        string line;
                        while (sr.Peek() >= 0)
                        {
                            try {
                                line = sr.ReadLine();
                                String[] spl       = line.Split('=');
                                String   file_name = spl[0]; // あ.wav
                                String   a2        = spl[1]; // ,0,36,64,0,0
                                String   a1        = Path.GetFileNameWithoutExtension(file_name);
                                spl = a2.Split(',');
                                OtoArgs oa = new OtoArgs();
                                oa.Alias          = spl[0];
                                oa.msOffset       = int.Parse(spl[1]);
                                oa.msConsonant    = int.Parse(spl[2]);
                                oa.msBlank        = int.Parse(spl[3]);
                                oa.msPreUtterance = int.Parse(spl[4]);
                                oa.msOverwrap     = int.Parse(spl[5]);
                                config.Add(a1, oa);
                            } catch {
                            }
                        }
                    }
                }

                int         track = AppManager.getSelected();
                List <Phon> phons = new List <Phon>();
                if (!Directory.Exists(temp_dir))
                {
                    Directory.CreateDirectory(temp_dir);
                }
                int    count       = -1;
                double sec_end     = 0;
                double sec_end_old = 0;
                for (Iterator <VsqEvent> itr = vsq.Track.get(track).getNoteEventIterator(); itr.hasNext();)
                {
                    VsqEvent item = itr.next();
                    count++;
                    double sec_start = vsq.getSecFromClock(item.Clock);
                    sec_end_old = sec_end;
                    sec_end     = vsq.getSecFromClock(item.Clock + item.ID.Length);
                    float t_temp = (float)(item.ID.Length / (sec_end - sec_start) / 8.0);
                    if ((count == 0 && sec_start > 0.0) || (sec_start > sec_end_old))
                    {
                        double sec_start2 = sec_end_old;
                        double sec_end2   = sec_start;
                        float  t_temp2    = (float)(item.Clock / (sec_end2 - sec_start2) / 8.0);
                        phons.Add(new Phon("R", Path.Combine(Singer, "R.wav"), item.Clock, t_temp2, true));
                        count++;
                    }
                    string lyric = item.ID.LyricHandle.L0.Phrase;
                    string note  = NoteStringFromNoteNumber(item.ID.Note);
#if DEBUG
                    sw.WriteLine("note=" + note);
#endif
                    string millisec = ((int)((sec_end - sec_start) * 1000) + 50).ToString();

                    //4_あ_C#4_550.wav
                    string filename = Path.Combine(temp_dir, count + "_" + item.ID.Note + "_" + millisec + ".wav");
#if DEBUG
                    sw.WriteLine("filename=" + filename);
                    sw.WriteLine();
#endif
                    if (File.Exists(filename))
                    {
                        PortUtil.deleteFile(filename);
                    }

                    phons.Add(new Phon(lyric, filename, item.ID.Length, t_temp, false));

                    OtoArgs oa = new OtoArgs();
                    if (config.ContainsKey(lyric))
                    {
                        oa = config[lyric];
                    }
                    int    velocity     = 100;
                    int    moduration   = 100;
                    string flags        = "L";
                    int    time_percent = 100;
                    //                                                                                          C4             100                  L             0                   550              0                      0                  100              100
                    string arg = "\"" + Path.Combine(Singer, lyric + ".wav") + "\" \"" + filename + "\" \"" + note + "\" " + time_percent + " " + flags + " " + oa.msOffset + " " + millisec + " " + oa.msConsonant + " " + oa.msBlank + " " + velocity + " " + moduration;

                    using (System.Diagnostics.Process p = new System.Diagnostics.Process()) {
                        p.StartInfo.FileName         = (InvokeWithWine ? "wine \"" : "\"") + Resampler + "\"";
                        p.StartInfo.Arguments        = arg;
                        p.StartInfo.WorkingDirectory = temp_dir;
                        p.StartInfo.WindowStyle      = System.Diagnostics.ProcessWindowStyle.Hidden;
                        p.Start();
                        p.WaitForExit();
                    }
                }
#if DEBUG
                sw.Close();
#endif

                string filebase = "temp.wav";
                string file     = Path.Combine(temp_dir, filebase);
                if (File.Exists(file))
                {
                    PortUtil.deleteFile(file);
                }
                string file_whd = Path.Combine(temp_dir, filebase + ".whd");
                if (File.Exists(file_whd))
                {
                    PortUtil.deleteFile(file_whd);
                }
                string file_dat = Path.Combine(temp_dir, filebase + ".dat");
                if (File.Exists(file_dat))
                {
                    PortUtil.deleteFile(file_dat);
                }

                // wavtoolを呼び出す
                for (int i = 0; i < phons.Count; i++)
                {
                    OtoArgs oa = new OtoArgs();
                    if (config.ContainsKey(phons[i].Lyric))
                    {
                        oa = config[phons[i].Lyric];
                    }
                    // 次の音符の先行発声とオーバーラップを取得
                    OtoArgs oa_next = new OtoArgs();
                    if (i + 1 < phons.Count)
                    {
                        if (config.ContainsKey(phons[i + 1].Lyric))
                        {
                            oa_next = config[phons[i + 1].Lyric];
                        }
                    }
                    int    mten = oa.msPreUtterance + oa_next.msOverwrap - oa_next.msPreUtterance;
                    string arg  = filebase + " \"" + phons[i].FileName + "\" 0 " + phons[i].ClockLength + "@" + string.Format("{0:f2}", phons[i].Tempo) + mten.ToString("+#;-#;0");
                    if (phons[i].ModeR)
                    {
                        arg += " 0 0";
                    }
                    else
                    {
                        arg += " 0 5 35 0 100 100 100 " + oa.msOverwrap; // エンベロープ
                    }

                    using (System.Diagnostics.Process p = new System.Diagnostics.Process()) {
                        p.StartInfo.FileName         = (InvokeWithWine ? "wine \"" : "\"") + WavTool + "\"";
                        p.StartInfo.Arguments        = arg;
                        p.StartInfo.WorkingDirectory = temp_dir;
                        p.StartInfo.WindowStyle      = System.Diagnostics.ProcessWindowStyle.Hidden;
                        p.Start();
                        p.WaitForExit();
                    }
                }

                // 波形とヘッダを結合
                using (FileStream fs = new FileStream(file, FileMode.Create)) {
                    string[] files  = new string[] { file_whd, file_dat };
                    int      buflen = 512;
                    byte[]   buff   = new byte[buflen];
                    for (int i = 0; i < files.Length; i++)
                    {
                        using (FileStream fs2 = new FileStream(files[i], FileMode.Open)) {
                            int len = fs2.Read(buff, 0, buflen);
                            while (len > 0)
                            {
                                fs.Write(buff, 0, len);
                                len = fs2.Read(buff, 0, buflen);
                            }
                        }
                    }
                }

                // 後片付け
                foreach (Phon ph in phons)
                {
                    if (!ph.ModeR)
                    {
                        if (File.Exists(ph.FileName))
                        {
                            PortUtil.deleteFile(ph.FileName);
                        }
                    }
                }
                if (File.Exists(file_whd))
                {
                    PortUtil.deleteFile(file_whd);
                }
                if (File.Exists(file_dat))
                {
                    PortUtil.deleteFile(file_dat);
                }

                if (saveFileDialog.ShowDialog() == DialogResult.OK)
                {
                    if (File.Exists(saveFileDialog.FileName))
                    {
                        PortUtil.deleteFile(saveFileDialog.FileName);
                    }
                    LastWave = saveFileDialog.FileName;
                    PortUtil.moveFile(file, saveFileDialog.FileName);
                }
                else
                {
                    PortUtil.deleteFile(file);
                }
                return(true);
            }
            else
            {
                return(false);
            }
        }
    }
コード例 #33
0
    public static void Main( string[] args ){
        int count = 0;
        List<string> list = new List<string>();
        while( true ){
            count++;
            string dirname = count + "";
            if( !Directory.Exists( dirname ) ){
                break;
            }
            int i = 0;
            while( true ){
                i++;
                string fname = Path.Combine( dirname, i + ".vsq" );
                if( !File.Exists( fname ) ){
                    break;
                }
                Console.Write( "\r" + fname + "                     " );
                VsqFile vsq = new VsqFile( fname, "Shift_JIS" );
                VsqTrack vsq_track = vsq.Track.get( 1 );
                string cache_phrase = "";
                string cache_symbol = "";
                bool all_symbol_default = true;
                for( Iterator<VsqEvent> itr = vsq_track.getNoteEventIterator(); itr.hasNext(); ){
                    VsqEvent item = itr.next();
                    string phrase = item.ID.LyricHandle.L0.Phrase;
                    string symbol = item.ID.LyricHandle.L0.getPhoneticSymbol();
                    if( symbol != "u:" ){
                        all_symbol_default = false;
                    }
                    if( cache_phrase == "" ){
                        cache_phrase = phrase;
                        cache_symbol = symbol;
                    }else{
                        cache_phrase += "\t" + phrase;
                        cache_symbol += "\t" + symbol;
                    }
                    if( !phrase.EndsWith( "-" ) ){
                        if( cache_phrase != "a" && cache_symbol != "u:" && !all_symbol_default ){
                            list.Add( cache_phrase + "\t\t" + cache_symbol );
                        }
                        all_symbol_default = true;
                        cache_phrase = "";
                        cache_symbol = "";
                    }
                }
            }
        }

        list.Sort();
        string last = "";
        int c = list.Count;
        using( StreamWriter sw = new StreamWriter( "extracted.txt" ) ){
            for( int i = 0; i < c; i++ ){
                string s = list[i];
                if( s != last ){
                    sw.WriteLine( s );
                    last = s;
                }
            }
        }
    }
コード例 #34
0
    public static ScriptReturnStatus Edit(VsqFileEx vsq)
    {
        // 選択状態のアイテムがなければ戻る
        if (AppManager.itemSelection.getEventCount() <= 0)
        {
            return(ScriptReturnStatus.NOT_EDITED);
        }

        // 現在のトラック
        int      selected  = AppManager.getSelected();
        VsqTrack vsq_track = vsq.Track.get(selected);

        vsq_track.sortEvent();

        // プラグイン情報の定義ファイル(plugin.txt)があるかどうかチェック
        string pluginTxtPath = s_plugin_txt_path;

        if (pluginTxtPath == "")
        {
            AppManager.showMessageBox("pluginTxtPath=" + pluginTxtPath);
            return(ScriptReturnStatus.ERROR);
        }
        if (!System.IO.File.Exists(pluginTxtPath))
        {
            AppManager.showMessageBox("'" + pluginTxtPath + "' does not exists");
            return(ScriptReturnStatus.ERROR);
        }

        // plugin.txtがあれば,プラグインの実行ファイルのパスを取得する
        System.Text.Encoding shift_jis = System.Text.Encoding.GetEncoding("Shift_JIS");
        string name     = "";
        string exe_path = "";

        using (StreamReader sr = new StreamReader(pluginTxtPath, shift_jis)) {
            string line = "";
            while ((line = sr.ReadLine()) != null)
            {
                string[] spl = line.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
                if (line.StartsWith("name="))
                {
                    name = spl[1];
                }
                else if (line.StartsWith("execute="))
                {
                    exe_path = Path.Combine(Path.GetDirectoryName(pluginTxtPath), spl[1]);
                }
            }
        }
        if (exe_path == "")
        {
            return(ScriptReturnStatus.ERROR);
        }
        if (!System.IO.File.Exists(exe_path))
        {
            AppManager.showMessageBox("'" + exe_path + "' does not exists");
            return(ScriptReturnStatus.ERROR);
        }

        // 選択状態のアイテムの最初と最後がどこか調べる
        // clock_start, clock_endは,最終的にはPREV, NEXTを含んだ範囲を表すことになる
        // sel_start, sel_endはPREV, NEXTを含まない選択範囲を表す
        int id_start    = -1;
        int clock_start = int.MaxValue;
        int id_end      = -1;
        int clock_end   = int.MinValue;
        int sel_start   = 0;
        int sel_end     = 0;

        for (Iterator <SelectedEventEntry> itr = AppManager.itemSelection.getEventIterator(); itr.hasNext();)
        {
            SelectedEventEntry item = itr.next();
            if (item.original.ID.type != VsqIDType.Anote)
            {
                continue;
            }
            int clock = item.original.Clock;
            if (clock < clock_start)
            {
                id_start    = item.original.InternalID;
                clock_start = clock;
                sel_start   = clock;
            }
            clock += item.original.ID.getLength();
            if (clock_end < clock)
            {
                id_end    = item.original.InternalID;
                clock_end = clock;
                sel_end   = clock;
            }
        }

        // 選択範囲の前後の音符を探す
        VsqEvent ve_prev = null;
        VsqEvent ve_next = null;
        VsqEvent l       = null;

        for (Iterator <VsqEvent> itr = vsq_track.getNoteEventIterator(); itr.hasNext();)
        {
            VsqEvent item = itr.next();
            if (item.InternalID == id_start)
            {
                if (l != null)
                {
                    ve_prev = l;
                }
            }
            if (l != null)
            {
                if (l.InternalID == id_end)
                {
                    ve_next = item;
                }
            }
            l = item;
            if (ve_prev != null && ve_next != null)
            {
                break;
            }
        }
        int  next_rest_clock = -1;
        bool prev_is_rest    = false;

        if (ve_prev != null)
        {
            // 直前の音符がある場合
            if (ve_prev.Clock + ve_prev.ID.getLength() == clock_start)
            {
                // 接続している
                clock_start = ve_prev.Clock;
            }
            else
            {
                // 接続していない
                int new_clock_start = ve_prev.Clock + ve_prev.ID.getLength();
                clock_start = new_clock_start;
            }
        }
        else
        {
            // 無い場合
            if (vsq.getPreMeasureClocks() < clock_start)
            {
                prev_is_rest = true;
            }
            int new_clock_start = vsq.getPreMeasureClocks();
            clock_start = new_clock_start;
        }
        if (ve_next != null)
        {
            // 直後の音符がある場合
            if (ve_next.Clock == clock_end)
            {
                // 接続している
                clock_end = ve_next.Clock + ve_next.ID.getLength();
            }
            else
            {
                // 接続していない
                next_rest_clock = clock_end;
                clock_end       = ve_next.Clock;
            }
        }

        // 作業用のVSQに,選択範囲のアイテムを格納
        VsqFileEx v = (VsqFileEx)vsq.clone();// new VsqFile( "Miku", 1, 4, 4, 500000 );

        // 選択トラックだけ残して他を削る
        for (int i = 1; i < selected; i++)
        {
            v.Track.removeElementAt(1);
        }
        for (int i = selected + 1; i < v.Track.size(); i++)
        {
            v.Track.removeElementAt(selected + 1);
        }
        // 選択トラックの音符を全消去する
        VsqTrack v_track = v.Track.get(1);

        v_track.MetaText.getEventList().clear();
        for (Iterator <VsqEvent> itr = vsq_track.getNoteEventIterator(); itr.hasNext();)
        {
            VsqEvent item = itr.next();
            if (clock_start <= item.Clock && item.Clock + item.ID.getLength() <= clock_end)
            {
                v_track.addEvent((VsqEvent)item.clone(), item.InternalID);
            }
        }
        // 最後のRを手動で追加.これは自動化できない
        if (next_rest_clock != -1)
        {
            VsqEvent item = (VsqEvent)ve_next.clone();
            item.ID.LyricHandle.L0.Phrase = "R";
            item.Clock = next_rest_clock;
            item.ID.setLength(clock_end - next_rest_clock);
            v_track.addEvent(item);
        }
        // 0~選択範囲の開始位置までを削除する
        v.removePart(0, clock_start);

        // vsq -> ustに変換
        // キーがustのIndex, 値がInternalID
        TreeMap <int, int> map = new TreeMap <int, int>();
        UstFile            u   = new UstFile(v, 1, map);

        u.write(Path.Combine(PortUtil.getApplicationStartupPath(), "u.ust"));

        // PREV, NEXTのIndex値を設定する
        if (ve_prev != null || prev_is_rest)
        {
            u.getTrack(0).getEvent(0).Index = UstFile.PREV_INDEX;
        }
        if (ve_next != null)
        {
            u.getTrack(0).getEvent(u.getTrack(0).getEventCount() - 1).Index = UstFile.NEXT_INDEX;
        }

        // ustファイルに出力
        UstFileWriteOptions option = new UstFileWriteOptions();

        option.settingCacheDir    = false;
        option.settingOutFile     = false;
        option.settingProjectName = false;
        option.settingTempo       = true;
        option.settingTool1       = true;
        option.settingTool2       = true;
        option.settingTracks      = false;
        option.settingVoiceDir    = true;
        option.trackEnd           = false;
        string temp = Path.GetTempFileName();

        u.write(temp, option);

        StringBuilder before = new StringBuilder();

        using (StreamReader sr = new StreamReader(temp, System.Text.Encoding.GetEncoding("Shift_JIS"))) {
            string line = "";
            while ((line = sr.ReadLine()) != null)
            {
                before.AppendLine(line);
            }
        }
        String md5_before = PortUtil.getMD5FromString(before.ToString());
        // プラグインの実行ファイルを起動
        Utau_Plugin_Invoker dialog = new Utau_Plugin_Invoker(exe_path, temp);

        dialog.ShowDialog();
        StringBuilder after = new StringBuilder();

        using (StreamReader sr = new StreamReader(temp, System.Text.Encoding.GetEncoding("Shift_JIS"))) {
            string line = "";
            while ((line = sr.ReadLine()) != null)
            {
                after.AppendLine(line);
            }
        }
        String md5_after = PortUtil.getMD5FromString(after.ToString());

        if (md5_before == md5_after)
        {
            // 編集されなかったようだ
            return(ScriptReturnStatus.NOT_EDITED);
        }

        // プラグインの実行結果をustオブジェクトにロード
        UstFile r = new UstFile(temp);

        if (r.getTrackCount() < 1)
        {
            return(ScriptReturnStatus.ERROR);
        }

        // 変更のなかったものについてはプラグインは記録してこないので,
        // 最初の値を代入するようにする
        UstTrack utrack_src = u.getTrack(0);
        UstTrack utrack_dst = r.getTrack(0);

        for (int i = 0; i < utrack_dst.getEventCount(); i++)
        {
            UstEvent ue_dst = utrack_dst.getEvent(i);
            int      index  = ue_dst.Index;
            UstEvent ue_src = utrack_src.findEventFromIndex(index);
            if (ue_src == null)
            {
                continue;
            }
            if (!ue_dst.isEnvelopeSpecified() && ue_src.isEnvelopeSpecified())
            {
                ue_dst.setEnvelope(ue_src.getEnvelope());
            }
            if (!ue_dst.isIntensitySpecified() && ue_src.isIntensitySpecified())
            {
                ue_dst.setIntensity(ue_src.getIntensity());
            }
            if (!ue_dst.isLengthSpecified() && ue_src.isLengthSpecified())
            {
                ue_dst.setLength(ue_src.getLength());
            }
            if (!ue_dst.isLyricSpecified() && ue_src.isLyricSpecified())
            {
                ue_dst.setLyric(ue_src.getLyric());
            }
            if (!ue_dst.isModurationSpecified() && ue_src.isModurationSpecified())
            {
                ue_dst.setModuration(ue_src.getModuration());
            }
            if (!ue_dst.isNoteSpecified() && ue_src.isNoteSpecified())
            {
                ue_dst.setNote(ue_src.getNote());
            }
            if (!ue_dst.isPBTypeSpecified() && ue_src.isPBTypeSpecified())
            {
                ue_dst.setPBType(ue_src.getPBType());
            }
            if (!ue_dst.isPitchesSpecified() && ue_src.isPitchesSpecified())
            {
                ue_dst.setPitches(ue_src.getPitches());
            }
            if (!ue_dst.isPortamentoSpecified() && ue_src.isPortamentoSpecified())
            {
                ue_dst.setPortamento(ue_src.getPortamento());
            }
            if (!ue_dst.isPreUtteranceSpecified() && ue_src.isPreUtteranceSpecified())
            {
                ue_dst.setPreUtterance(ue_src.getPreUtterance());
            }
            if (!ue_dst.isStartPointSpecified() && ue_src.isStartPointSpecified())
            {
                ue_dst.setStartPoint(ue_src.getStartPoint());
            }
            if (!ue_dst.isTempoSpecified() && ue_src.isTempoSpecified())
            {
                ue_dst.setTempo(ue_src.getTempo());
            }
            if (!ue_dst.isVibratoSpecified() && ue_src.isVibratoSpecified())
            {
                ue_dst.setVibrato(ue_src.getVibrato());
            }
            if (!ue_dst.isVoiceOverlapSpecified() && ue_src.isVoiceOverlapSpecified())
            {
                ue_dst.setVoiceOverlap(ue_src.getVoiceOverlap());
            }
        }

        // PREVとNEXT含めて,clock_startからclock_endまでプラグインに渡したけれど,
        // それが伸びて帰ってきたか縮んで帰ってきたか.
        int      ret_length = 0;
        UstTrack r_track    = r.getTrack(0);
        int      size       = r_track.getEventCount();

        for (int i = 0; i < size; i++)
        {
            UstEvent ue = r_track.getEvent(i);
            // 戻りのustには,変更があったものしか記録されていない
            int ue_length = ue.getLength();
            if (!ue.isLengthSpecified() && map.ContainsKey(ue.Index))
            {
                int      internal_id = map[ue.Index];
                VsqEvent found_item  = vsq_track.findEventFromID(internal_id);
                if (found_item != null)
                {
                    ue_length = found_item.ID.getLength();
                }
            }
            // PREV, ENDの場合は長さに加えない
            if (ue.Index != UstFile.NEXT_INDEX &&
                ue.Index != UstFile.PREV_INDEX)
            {
                ret_length += ue_length;
            }
        }

        // 伸び縮みがあった場合
        // 伸ばしたり縮めたりするよ
        int delta = ret_length - (sel_end - sel_start);

        if (delta > 0)
        {
            // のびた
            vsq.insertBlank(selected, sel_end, delta);
        }
        else if (delta < 0)
        {
            // 縮んだ
            vsq.removePart(selected, sel_end + delta, sel_end);
        }

        // r_trackの内容をvsq_trackに転写
        size = r_track.getEventCount();
        int c = clock_start;

        for (int i = 0; i < size; i++)
        {
            UstEvent ue = r_track.getEvent(i);
            if (ue.Index == UstFile.NEXT_INDEX || ue.Index == UstFile.PREV_INDEX)
            {
                // PREVとNEXTは単に無視する
                continue;
            }
            int ue_length = ue.getLength();
            if (map.containsKey(ue.Index))
            {
                // 既存の音符の編集
                VsqEvent target = vsq_track.findEventFromID(map[ue.Index]);
                if (target == null)
                {
                    // そんなばかな・・・
                    continue;
                }
                if (!ue.isLengthSpecified())
                {
                    ue_length = target.ID.getLength();
                }
                if (target.UstEvent == null)
                {
                    target.UstEvent = (UstEvent)ue.clone();
                }
                // utau固有のパラメータを転写
                // pitchは後でやるので無視していい
                // テンポもあとでやるので無視していい
                if (ue.isEnvelopeSpecified())
                {
                    target.UstEvent.setEnvelope(ue.getEnvelope());
                }
                if (ue.isModurationSpecified())
                {
                    target.UstEvent.setModuration(ue.getModuration());
                }
                if (ue.isPBTypeSpecified())
                {
                    target.UstEvent.setPBType(ue.getPBType());
                }
                if (ue.isPortamentoSpecified())
                {
                    target.UstEvent.setPortamento(ue.getPortamento());
                }
                if (ue.isPreUtteranceSpecified())
                {
                    target.UstEvent.setPreUtterance(ue.getPreUtterance());
                }
                if (ue.isStartPointSpecified())
                {
                    target.UstEvent.setStartPoint(ue.getStartPoint());
                }
                if (ue.isVibratoSpecified())
                {
                    target.UstEvent.setVibrato(ue.getVibrato());
                }
                if (ue.isVoiceOverlapSpecified())
                {
                    target.UstEvent.setVoiceOverlap(ue.getVoiceOverlap());
                }
                // vocaloid, utauで同じ意味のパラメータを転写
                if (ue.isIntensitySpecified())
                {
                    target.UstEvent.setIntensity(ue.getIntensity());
                    target.ID.Dynamics = ue.getIntensity();
                }
                if (ue.isLengthSpecified())
                {
                    target.UstEvent.setLength(ue.getLength());
                    target.ID.setLength(ue.getLength());
                }
                if (ue.isLyricSpecified())
                {
                    target.UstEvent.setLyric(ue.getLyric());
                    target.ID.LyricHandle.L0.Phrase = ue.getLyric();
                }
                if (ue.isNoteSpecified())
                {
                    target.UstEvent.setNote(ue.getNote());
                    target.ID.Note = ue.getNote();
                }
            }
            else
            {
                // マップに入っていないので,新しい音符の追加だと思う
                if (ue.getLyric() == "R")
                {
                    // 休符.なにもしない
                }
                else
                {
                    VsqEvent newe = new VsqEvent();
                    newe.Clock    = c;
                    newe.UstEvent = (UstEvent)ue.clone();
                    newe.ID       = new VsqID();
                    AppManager.editorConfig.applyDefaultSingerStyle(newe.ID);
                    if (ue.isIntensitySpecified())
                    {
                        newe.ID.Dynamics = ue.getIntensity();
                    }
                    newe.ID.LyricHandle = new LyricHandle("あ", "a");
                    if (ue.isLyricSpecified())
                    {
                        newe.ID.LyricHandle.L0.Phrase = ue.getLyric();
                    }
                    newe.ID.Note = ue.getNote();
                    newe.ID.setLength(ue.getLength());
                    newe.ID.type = VsqIDType.Anote;
                    // internal id はaddEventメソッドで自動で割り振られる
                    vsq_track.addEvent(newe);
                }
            }

            // テンポの追加がないかチェック
            if (ue.isTempoSpecified())
            {
                insertTempoInto(vsq, c, ue.getTempo());
            }

            c += ue_length;
        }

        // ピッチを転写
        // pitのデータがほしいので,PREV, NEXTを削除して,VsqFileにコンバートする
        UstFile uf = (UstFile)r.clone();
        // prev, nextを削除
        UstTrack uf_track = uf.getTrack(0);

        for (int i = 0; i < uf_track.getEventCount();)
        {
            UstEvent ue = uf_track.getEvent(i);
            if (ue.Index == UstFile.NEXT_INDEX ||
                ue.Index == UstFile.PREV_INDEX)
            {
                uf_track.removeEventAt(i);
            }
            else
            {
                i++;
            }
        }
        uf.updateTempoInfo();
        // VsqFileにコンバート
        VsqFile uf_vsq = new VsqFile(uf);

        // uf_vsqの最初のトラックの0からret_lengthクロックまでが,
        // vsq_trackのsel_startからsel_start+ret_lengthクロックまでに対応する.
        // まずPBSをコピーする
        CurveType[] type = new CurveType[] { CurveType.PBS, CurveType.PIT };
        foreach (CurveType ct in type)
        {
            // コピー元を取得
            VsqBPList src = uf_vsq.Track[1].getCurve(ct.getName());
            if (src != null)
            {
                // コピー先を取得
                VsqBPList dst = vsq_track.getCurve(ct.getName());
                if (dst == null)
                {
                    // コピー先がnullだった場合は作成
                    dst = new VsqBPList(ct.getName(), ct.getDefault(), ct.getMinimum(), ct.getMaximum());
                    vsq_track.setCurve(ct.getName(), dst);
                }
                // あとで復元するので,最終位置での値を保存しておく
                int value_at_end = dst.getValue(sel_start + ret_length);
                // 復元するかどうか.最終位置にそもそもデータ点があれば復帰の必要がないので.
                bool do_revert = (dst.findIndexFromClock(sel_start + ret_length) < 0);
                // [sel_start, sel_start + ret_length)の範囲の値を削除しておく
                size = dst.size();
                for (int i = size - 1; i >= 0; i--)
                {
                    int cl = dst.getKeyClock(i);
                    if (sel_start <= cl && cl < sel_start + ret_length)
                    {
                        dst.removeElementAt(i);
                    }
                }
                // コピーを実行
                size = src.size();
                for (int i = 0; i < size; i++)
                {
                    int cl = src.getKeyClock(i);
                    if (ret_length <= cl)
                    {
                        break;
                    }
                    int value = src.getElementA(i);
                    dst.add(cl + sel_start, value);
                }
                // コピー後,最終位置での値が元と異なる場合,元に戻すようにする
                if (do_revert && dst.getValue(sel_start + ret_length) != value_at_end)
                {
                    dst.add(sel_start + ret_length, value_at_end);
                }
            }
        }

        return(ScriptReturnStatus.EDITED);
    }
コード例 #35
0
ファイル: Render As UTAU.cs プロジェクト: cadencii/cadencii
    public static bool Edit( VsqFile vsq ) {
        using ( RenderAsUtau dlg = new RenderAsUtau() ) {
            if ( dlg.ShowDialog() == DialogResult.OK ) {
                Singer = dlg.txtSinger.Text;
                Resampler = dlg.txtResampler.Text;
                WavTool = dlg.txtWavtool.Text;
                string script = Path.Combine( Application.StartupPath, Path.Combine( "script", "Render As UTAU.cs" ) );//Script.ScriptPath;
                string temp_dir = Path.Combine( Path.GetDirectoryName( script ), Path.GetFileNameWithoutExtension( script ) );

#if DEBUG
                if ( !Directory.Exists( temp_dir ) ) {
                    Directory.CreateDirectory( temp_dir );
                }
                StreamWriter sw = new StreamWriter( Path.Combine( temp_dir, "log.txt" ) );
#endif
                // 原音設定を読み込み
                Dictionary<string, OtoArgs> config = new Dictionary<string, OtoArgs>();
                string singer_name = Path.GetFileName( Singer );
                string config_file = Path.Combine( Singer, "oto.ini" );
#if DEBUG
                sw.WriteLine( "Singer=" + Singer );
                sw.WriteLine( "singer_name=" + singer_name );
                sw.WriteLine( "config_file=" + config_file );
#endif
                if ( File.Exists( config_file ) ) {
                    using ( cp932reader sr = new cp932reader( config_file ) ) {
                        string line;
                        while ( sr.Peek() >= 0 ) {
                            try {
                                line = sr.ReadLine();
                                String[] spl = line.Split( '=' );
                                String file_name = spl[0]; // あ.wav
                                String a2 = spl[1]; // ,0,36,64,0,0
                                String a1 = Path.GetFileNameWithoutExtension( file_name );
                                spl = a2.Split( ',' );
                                OtoArgs oa = new OtoArgs();
                                oa.Alias = spl[0];
                                oa.msOffset = int.Parse( spl[1] );
                                oa.msConsonant = int.Parse( spl[2] );
                                oa.msBlank = int.Parse( spl[3] );
                                oa.msPreUtterance = int.Parse( spl[4] );
                                oa.msOverwrap = int.Parse( spl[5] );
                                config.Add( a1, oa );
                            } catch {
                            }
                        }
                    }
                }

                int track = AppManager.getSelected();
                List<Phon> phons = new List<Phon>();
                if ( !Directory.Exists( temp_dir ) ) {
                    Directory.CreateDirectory( temp_dir );
                }
                int count = -1;
                double sec_end = 0;
                double sec_end_old = 0;
                for ( Iterator<VsqEvent> itr = vsq.Track.get( track ).getNoteEventIterator(); itr.hasNext(); ) {
                    VsqEvent item = itr.next();
                    count++;
                    double sec_start = vsq.getSecFromClock( item.Clock );
                    sec_end_old = sec_end;
                    sec_end = vsq.getSecFromClock( item.Clock + item.ID.Length );
                    float t_temp = (float)(item.ID.Length / (sec_end - sec_start) / 8.0);
                    if ( (count == 0 && sec_start > 0.0) || (sec_start > sec_end_old) ) {
                        double sec_start2 = sec_end_old;
                        double sec_end2 = sec_start;
                        float t_temp2 = (float)(item.Clock / (sec_end2 - sec_start2) / 8.0);
                        phons.Add( new Phon( "R", Path.Combine( Singer, "R.wav" ), item.Clock, t_temp2, true ) );
                        count++;
                    }
                    string lyric = item.ID.LyricHandle.L0.Phrase;
                    string note = NoteStringFromNoteNumber( item.ID.Note );
#if DEBUG
                    sw.WriteLine( "note=" + note );
#endif
                    string millisec = ((int)((sec_end - sec_start) * 1000) + 50).ToString();

                    //4_あ_C#4_550.wav
                    string filename = Path.Combine( temp_dir, count + "_" + item.ID.Note + "_" + millisec + ".wav" );
#if DEBUG
                    sw.WriteLine( "filename=" + filename );
                    sw.WriteLine();
#endif
                    if ( File.Exists( filename ) ) {
                        PortUtil.deleteFile( filename );
                    }

                    phons.Add( new Phon( lyric, filename, item.ID.Length, t_temp, false ) );

                    OtoArgs oa = new OtoArgs();
                    if ( config.ContainsKey( lyric ) ) {
                        oa = config[lyric];
                    }
                    int velocity = 100;
                    int moduration = 100;
                    string flags = "L";
                    int time_percent = 100;
                    //                                                                                          C4             100                  L             0                   550              0                      0                  100              100
                    string arg = "\"" + Path.Combine( Singer, lyric + ".wav" ) + "\" \"" + filename + "\" \"" + note + "\" " + time_percent + " " + flags + " " + oa.msOffset + " " + millisec + " " + oa.msConsonant + " " + oa.msBlank + " " + velocity + " " + moduration;

                    using ( System.Diagnostics.Process p = new System.Diagnostics.Process() ) {
                        p.StartInfo.FileName = (InvokeWithWine ? "wine \"" : "\"") + Resampler + "\"";
                        p.StartInfo.Arguments = arg;
                        p.StartInfo.WorkingDirectory = temp_dir;
                        p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                        p.Start();
                        p.WaitForExit();
                    }
                }
#if DEBUG
                sw.Close();
#endif

                string filebase = "temp.wav";
                string file = Path.Combine( temp_dir, filebase );
                if ( File.Exists( file ) ) {
                    PortUtil.deleteFile( file );
                }
                string file_whd = Path.Combine( temp_dir, filebase + ".whd" );
                if ( File.Exists( file_whd ) ) {
                    PortUtil.deleteFile( file_whd );
                }
                string file_dat = Path.Combine( temp_dir, filebase + ".dat" );
                if ( File.Exists( file_dat ) ) {
                    PortUtil.deleteFile( file_dat );
                }

                // wavtoolを呼び出す
                for ( int i = 0; i < phons.Count; i++ ) {
                    OtoArgs oa = new OtoArgs();
                    if ( config.ContainsKey( phons[i].Lyric ) ) {
                        oa = config[phons[i].Lyric];
                    }
                    // 次の音符の先行発声とオーバーラップを取得
                    OtoArgs oa_next = new OtoArgs();
                    if ( i + 1 < phons.Count ) {
                        if ( config.ContainsKey( phons[i + 1].Lyric ) ) {
                            oa_next = config[phons[i + 1].Lyric];
                        }
                    }
                    int mten = oa.msPreUtterance + oa_next.msOverwrap - oa_next.msPreUtterance;
                    string arg = filebase + " \"" + phons[i].FileName + "\" 0 " + phons[i].ClockLength + "@" + string.Format( "{0:f2}", phons[i].Tempo ) + mten.ToString( "+#;-#;0" );
                    if ( phons[i].ModeR ) {
                        arg += " 0 0";
                    } else {
                        arg += " 0 5 35 0 100 100 100 " + oa.msOverwrap; // エンベロープ
                    }

                    using ( System.Diagnostics.Process p = new System.Diagnostics.Process() ) {
                        p.StartInfo.FileName = (InvokeWithWine ? "wine \"" : "\"") + WavTool + "\"";
                        p.StartInfo.Arguments = arg;
                        p.StartInfo.WorkingDirectory = temp_dir;
                        p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                        p.Start();
                        p.WaitForExit();
                    }
                }

                // 波形とヘッダを結合
                using ( FileStream fs = new FileStream( file, FileMode.Create ) ) {
                    string[] files = new string[] { file_whd, file_dat };
                    int buflen = 512;
                    byte[] buff = new byte[buflen];
                    for ( int i = 0; i < files.Length; i++ ) {
                        using ( FileStream fs2 = new FileStream( files[i], FileMode.Open ) ) {
                            int len = fs2.Read( buff, 0, buflen );
                            while ( len > 0 ) {
                                fs.Write( buff, 0, len );
                                len = fs2.Read( buff, 0, buflen );
                            }
                        }
                    }
                }

                // 後片付け
                foreach ( Phon ph in phons ) {
                    if ( !ph.ModeR ) {
                        if ( File.Exists( ph.FileName ) ) {
                            PortUtil.deleteFile( ph.FileName );
                        }
                    }
                }
                if ( File.Exists( file_whd ) ) {
                    PortUtil.deleteFile( file_whd );
                }
                if ( File.Exists( file_dat ) ) {
                    PortUtil.deleteFile( file_dat );
                }

                if ( saveFileDialog.ShowDialog() == DialogResult.OK ) {
                    if ( File.Exists( saveFileDialog.FileName ) ) {
                        PortUtil.deleteFile( saveFileDialog.FileName );
                    }
                    LastWave = saveFileDialog.FileName;
                    PortUtil.moveFile( file, saveFileDialog.FileName );
                } else {
                    PortUtil.deleteFile( file );
                }
                return true;
            } else {
                return false;
            }
        }
    }
コード例 #36
0
    public static ScriptReturnStatus Edit( VsqFileEx vsq ){
        if( AppManager.getSelectedEventCount() <= 0 ){
            return ScriptReturnStatus.NOT_EDITED;
        }
        string pluginTxtPath = s_plugin_txt_path;
        if( pluginTxtPath == "" ){
            AppManager.showMessageBox( "pluginTxtPath=" + pluginTxtPath );
            return ScriptReturnStatus.ERROR;
        }
        if( !System.IO.File.Exists( pluginTxtPath ) ){
            AppManager.showMessageBox( "'" + pluginTxtPath + "' does not exists" );
            return ScriptReturnStatus.ERROR;
        }
        System.Text.Encoding shift_jis = System.Text.Encoding.GetEncoding( "Shift_JIS" );
        string name = "";
        string exe_path = "";
        using( StreamReader sr = new StreamReader( pluginTxtPath, shift_jis ) ){
            string line = "";
            while( (line = sr.ReadLine()) != null ){
                string[] spl = line.Split( new char[]{ '=' }, StringSplitOptions.RemoveEmptyEntries );
                if( line.StartsWith( "name=" ) ){
                    name = spl[1];
                }else if( line.StartsWith( "execute=" ) ){
                    exe_path = Path.Combine( Path.GetDirectoryName( pluginTxtPath ), spl[1] );
                }
            }
        }
        if( exe_path == "" ){
            return ScriptReturnStatus.ERROR;
        }
        if( !System.IO.File.Exists( exe_path ) ){
            AppManager.showMessageBox( "'" + exe_path + "' does not exists" );
            return ScriptReturnStatus.ERROR;
        }

        // ustを用意 ------------------------------------------------------------------------
        // 方針は,一度VsqFileに音符を格納->UstFile#.ctor( VsqFile )を使って一括変換
        // メイン画面で選択されているアイテムを列挙
        List<VsqEvent> items = new List<VsqEvent>();
        for( Iterator itr = AppManager.getSelectedEventIterator(); itr.hasNext(); ){
            SelectedEventEntry item_itr = (SelectedEventEntry)itr.next();
            if( item_itr.original.ID.type == VsqIDType.Anote ){
                items.Add( (VsqEvent)item_itr.original.clone() );
            }
        }
        items.Sort();

        // R用音符のテンプレート
        VsqEvent template = new VsqEvent();
        template.ID.type = VsqIDType.Anote;
        template.ID.LyricHandle = new LyricHandle( "R", "" );

        int count = items.Count;
        // アイテムが2個以上の場合は、間にRを挿入する必要があるかどうか判定
        if( count > 1 ){
            List<VsqEvent> add = new List<VsqEvent>(); // 追加するR
            VsqEvent last_event = items[0];
            for( int i = 1; i < count; i++ ){
                VsqEvent item = items[i];
                if( last_event.Clock + last_event.ID.Length < item.Clock ){
                    VsqEvent add_temp = (VsqEvent)template.clone();
                    add_temp.Clock = last_event.Clock + last_event.ID.Length;
                    add_temp.ID.Length = item.Clock - add_temp.Clock;
                    add.Add( add_temp );
                }
                last_event = item;
            }
            foreach( VsqEvent v in add ){
                items.Add( v );
            }
            items.Sort();
        }

        // ヘッダ
        int TEMPO = 120;

        // 選択アイテムの直前直後に未選択アイテムがあるかどうかを判定
        int clock_begin = items[0].Clock;
        int clock_end = items[items.Count - 1].Clock;
        VsqTrack vsq_track = vsq.Track.get( AppManager.getSelected() );
        VsqEvent tlast_event = null;
        VsqEvent prev = null;
        VsqEvent next = null;

        // VsqFile -> UstFileのコンバート
        VsqFile conv = new VsqFile( "Miku", 2, 4, 4, (int)(6e7 / TEMPO) );
        VsqTrack conv_track = conv.Track.get( 1 );
        for( Iterator itr = vsq_track.getNoteEventIterator(); itr.hasNext(); ){
            VsqEvent item_itr = (VsqEvent)itr.next();
            if( item_itr.Clock == clock_begin ){
                if( tlast_event != null ){
                    // アイテムあり
                    if( tlast_event.Clock + tlast_event.ID.Length == clock_begin ){
                        // ゲートタイム差0で接続
                        prev = (VsqEvent)tlast_event.clone();
                    }else{
                        // 時間差アリで接続
                        prev = (VsqEvent)template.clone();
                        prev.Clock = tlast_event.Clock + tlast_event.ID.Length;
                        prev.ID.Length = clock_begin - (tlast_event.Clock + tlast_event.ID.Length);
                    }
                }
            }
            tlast_event = item_itr;
            if( item_itr.Clock == clock_end ){
                if( itr.hasNext() ){
                    VsqEvent foo = (VsqEvent)itr.next();
                    int clock_end_end = clock_end + items[items.Count - 1].ID.Length;
                    if( foo.Clock == clock_end_end ){
                        // ゲートタイム差0で接続
                        next = (VsqEvent)foo.clone();
                    }else{
                        // 時間差アリで接続
                        next = (VsqEvent)template.clone();
                        next.Clock = clock_end_end;
                        next.ID.Length = foo.Clock - clock_end_end;
                    }
                }
                break;
            }

        }

        // [#PREV]を追加
        if( prev != null ){
            prev.Clock -= clock_begin;
            conv_track.addEvent( prev );
        }

        // ゲートタイムを計算しながら追加
        count = items.Count;
        for( int i = 0; i < count; i++ ){
            VsqEvent itemi = items[i];
            itemi.Clock -= clock_begin;
            conv_track.addEvent( itemi );
        }

        // [#NEXT]を追加
        if( next != null ){
            next.Clock -= clock_begin;
            conv_track.addEvent( next );
        }
        
        // PIT, PBSを追加
        copyCurve( vsq_track.getCurve( "pit" ), conv_track.getCurve( "pit" ), clock_begin );
        copyCurve( vsq_track.getCurve( "pbs" ), conv_track.getCurve( "pbs" ), clock_begin );

        string temp = Path.GetTempFileName();
        UstFile tust = new UstFile( conv, 1 );
        if( prev != null ){
            tust.getTrack( 0 ).getEvent( 0 ).Index = int.MinValue;
        }
        if( next != null ){
            tust.getTrack( 0 ).getEvent( tust.getTrack( 0 ).getEventCount() - 1 ).Index = int.MaxValue;
        }
        tust.write( temp );

        // 起動 -----------------------------------------------------------------------------
        StartPluginArgs arg = new StartPluginArgs();
        arg.exePath = exe_path;
        arg.tmpFile = temp;
        System.Threading.Thread t = new System.Threading.Thread( new System.Threading.ParameterizedThreadStart( runPlugin ) );
        s_finished = false;
        t.Start( arg );
        while( !s_finished ){
            Application.DoEvents();
        }
        
        // 結果を反映 -----------------------------------------------------------------------
        UstFile ust = null;
        try{
            ust = new UstFile( temp );
        }catch( Exception ex ){
            AppManager.showMessageBox( "invalid ust file; ex=" + ex );
            return ScriptReturnStatus.ERROR;
        }
        int track_count = ust.getTrackCount();
        for( int i = 0; i < track_count; i++ ){
            UstTrack track = ust.getTrack( i );
            int event_count = track.getEventCount();
            for( int j = 0; j < event_count; j++ ){
                UstEvent itemj = track.getEvent( j );
                if( itemj.Index == int.MinValue ){
                    AppManager.showMessageBox( "[#PREV]" );
                }else if( itemj.Index == int.MaxValue ){
                    AppManager.showMessageBox( "[#NEXT]" );
                }else{
                    AppManager.showMessageBox( itemj.Index + "" );
                }
            }
        }

        try{
            System.IO.File.Delete( temp );
        }catch( Exception ex ){
        }
        return ScriptReturnStatus.ERROR;
    }
コード例 #37
0
    public static ScriptReturnStatus Edit( VsqFileEx vsq )
    {
        // 選択状態のアイテムがなければ戻る
        if ( AppManager.itemSelection.getEventCount() <= 0 ) {
            return ScriptReturnStatus.NOT_EDITED;
        }

        // 現在のトラック
        int selected = AppManager.getSelected();
        VsqTrack vsq_track = vsq.Track.get( selected );
        vsq_track.sortEvent();

        // プラグイン情報の定義ファイル(plugin.txt)があるかどうかチェック
        string pluginTxtPath = s_plugin_txt_path;
        if ( pluginTxtPath == "" ) {
            AppManager.showMessageBox( "pluginTxtPath=" + pluginTxtPath );
            return ScriptReturnStatus.ERROR;
        }
        if ( !System.IO.File.Exists( pluginTxtPath ) ) {
            AppManager.showMessageBox( "'" + pluginTxtPath + "' does not exists" );
            return ScriptReturnStatus.ERROR;
        }

        // plugin.txtがあれば,プラグインの実行ファイルのパスを取得する
        System.Text.Encoding shift_jis = System.Text.Encoding.GetEncoding( "Shift_JIS" );
        string name = "";
        string exe_path = "";
        using ( StreamReader sr = new StreamReader( pluginTxtPath, shift_jis ) ) {
            string line = "";
            while ( (line = sr.ReadLine()) != null ) {
                string[] spl = line.Split( new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries );
                if ( line.StartsWith( "name=" ) ) {
                    name = spl[1];
                } else if ( line.StartsWith( "execute=" ) ) {
                    exe_path = Path.Combine( Path.GetDirectoryName( pluginTxtPath ), spl[1] );
                }
            }
        }
        if ( exe_path == "" ) {
            return ScriptReturnStatus.ERROR;
        }
        if ( !System.IO.File.Exists( exe_path ) ) {
            AppManager.showMessageBox( "'" + exe_path + "' does not exists" );
            return ScriptReturnStatus.ERROR;
        }

        // 選択状態のアイテムの最初と最後がどこか調べる
        // clock_start, clock_endは,最終的にはPREV, NEXTを含んだ範囲を表すことになる
        // sel_start, sel_endはPREV, NEXTを含まない選択範囲を表す
        int id_start = -1;
        int clock_start = int.MaxValue;
        int id_end = -1;
        int clock_end = int.MinValue;
        int sel_start = 0;
        int sel_end = 0;
        for ( Iterator<SelectedEventEntry> itr = AppManager.itemSelection.getEventIterator(); itr.hasNext(); ) {
            SelectedEventEntry item = itr.next();
            if ( item.original.ID.type != VsqIDType.Anote ) {
                continue;
            }
            int clock = item.original.Clock;
            if ( clock < clock_start ) {
                id_start = item.original.InternalID;
                clock_start = clock;
                sel_start = clock;
            }
            clock += item.original.ID.getLength();
            if ( clock_end < clock ) {
                id_end = item.original.InternalID;
                clock_end = clock;
                sel_end = clock;
            }
        }

        // 選択範囲の前後の音符を探す
        VsqEvent ve_prev = null;
        VsqEvent ve_next = null;
        VsqEvent l = null;
        for ( Iterator<VsqEvent> itr = vsq_track.getNoteEventIterator(); itr.hasNext(); ) {
            VsqEvent item = itr.next();
            if ( item.InternalID == id_start ) {
                if ( l != null ) {
                    ve_prev = l;
                }
            }
            if ( l != null ) {
                if ( l.InternalID == id_end ) {
                    ve_next = item;
                }
            }
            l = item;
            if ( ve_prev != null && ve_next != null ) {
                break;
            }
        }
        int next_rest_clock = -1;
        bool prev_is_rest = false;
        if ( ve_prev != null ) {
            // 直前の音符がある場合
            if ( ve_prev.Clock + ve_prev.ID.getLength() == clock_start ) {
                // 接続している
                clock_start = ve_prev.Clock;
            } else {
                // 接続していない
                int new_clock_start = ve_prev.Clock + ve_prev.ID.getLength();
                clock_start = new_clock_start;
            }
        } else {
            // 無い場合
            if ( vsq.getPreMeasureClocks() < clock_start ) {
                prev_is_rest = true;
            }
            int new_clock_start = vsq.getPreMeasureClocks();
            clock_start = new_clock_start;
        }
        if ( ve_next != null ) {
            // 直後の音符がある場合
            if ( ve_next.Clock == clock_end ) {
                // 接続している
                clock_end = ve_next.Clock + ve_next.ID.getLength();
            } else {
                // 接続していない
                next_rest_clock = clock_end;
                clock_end = ve_next.Clock;
            }
        }

        // 作業用のVSQに,選択範囲のアイテムを格納
        VsqFileEx v = (VsqFileEx)vsq.clone();// new VsqFile( "Miku", 1, 4, 4, 500000 );
        // 選択トラックだけ残して他を削る
        for ( int i = 1; i < selected; i++ ) {
            v.Track.removeElementAt( 1 );
        }
        for ( int i = selected + 1; i < v.Track.size(); i++ ) {
            v.Track.removeElementAt( selected + 1 );
        }
        // 選択トラックの音符を全消去する
        VsqTrack v_track = v.Track.get( 1 );
        v_track.MetaText.getEventList().clear();
        for ( Iterator<VsqEvent> itr = vsq_track.getNoteEventIterator(); itr.hasNext(); ) {
            VsqEvent item = itr.next();
            if ( clock_start <= item.Clock && item.Clock + item.ID.getLength() <= clock_end ) {
                v_track.addEvent( (VsqEvent)item.clone(), item.InternalID );
            }
        }
        // 最後のRを手動で追加.これは自動化できない
        if ( next_rest_clock != -1 ) {
            VsqEvent item = (VsqEvent)ve_next.clone();
            item.ID.LyricHandle.L0.Phrase = "R";
            item.Clock = next_rest_clock;
            item.ID.setLength( clock_end - next_rest_clock );
            v_track.addEvent( item );
        }
        // 0~選択範囲の開始位置までを削除する
        v.removePart( 0, clock_start );

        // vsq -> ustに変換
        // キーがustのIndex, 値がInternalID
        TreeMap<int, int> map = new TreeMap<int, int>();
        UstFile u = new UstFile( v, 1, map );

        u.write( Path.Combine( PortUtil.getApplicationStartupPath(), "u.ust" ) );

        // PREV, NEXTのIndex値を設定する
        if ( ve_prev != null || prev_is_rest ) {
            u.getTrack( 0 ).getEvent( 0 ).Index = UstFile.PREV_INDEX;
        }
        if ( ve_next != null ) {
            u.getTrack( 0 ).getEvent( u.getTrack( 0 ).getEventCount() - 1 ).Index = UstFile.NEXT_INDEX;
        }

        // ustファイルに出力
        UstFileWriteOptions option = new UstFileWriteOptions();
        option.settingCacheDir = false;
        option.settingOutFile = false;
        option.settingProjectName = false;
        option.settingTempo = true;
        option.settingTool1 = true;
        option.settingTool2 = true;
        option.settingTracks = false;
        option.settingVoiceDir = true;
        option.trackEnd = false;
        string temp = Path.GetTempFileName();
        u.write( temp, option );

        StringBuilder before = new StringBuilder();
        using ( StreamReader sr = new StreamReader( temp, System.Text.Encoding.GetEncoding( "Shift_JIS" ) ) ) {
            string line = "";
            while ( (line = sr.ReadLine()) != null ) {
                before.AppendLine( line );
            }
        }
        String md5_before = PortUtil.getMD5FromString( before.ToString() );
        // プラグインの実行ファイルを起動
        Utau_Plugin_Invoker dialog = new Utau_Plugin_Invoker( exe_path, temp );
        dialog.ShowDialog();
        StringBuilder after = new StringBuilder();
        using ( StreamReader sr = new StreamReader( temp, System.Text.Encoding.GetEncoding( "Shift_JIS" ) ) ) {
            string line = "";
            while ( (line = sr.ReadLine()) != null ) {
                after.AppendLine( line );
            }
        }
        String md5_after = PortUtil.getMD5FromString( after.ToString() );
        if ( md5_before == md5_after ) {
            // 編集されなかったようだ
            return ScriptReturnStatus.NOT_EDITED;
        }

        // プラグインの実行結果をustオブジェクトにロード
        UstFile r = new UstFile( temp );
        if ( r.getTrackCount() < 1 ) {
            return ScriptReturnStatus.ERROR;
        }

        // 変更のなかったものについてはプラグインは記録してこないので,
        // 最初の値を代入するようにする
        UstTrack utrack_src = u.getTrack( 0 );
        UstTrack utrack_dst = r.getTrack( 0 );
        for ( int i = 0; i < utrack_dst.getEventCount(); i++ ) {
            UstEvent ue_dst = utrack_dst.getEvent( i );
            int index = ue_dst.Index;
            UstEvent ue_src = utrack_src.findEventFromIndex( index );
            if ( ue_src == null ) {
                continue;
            }
            if ( !ue_dst.isEnvelopeSpecified() && ue_src.isEnvelopeSpecified() ) {
                ue_dst.setEnvelope( ue_src.getEnvelope() );
            }
            if ( !ue_dst.isIntensitySpecified() && ue_src.isIntensitySpecified() ) {
                ue_dst.setIntensity( ue_src.getIntensity() );
            }
            if ( !ue_dst.isLengthSpecified() && ue_src.isLengthSpecified() ) {
                ue_dst.setLength( ue_src.getLength() );
            }
            if ( !ue_dst.isLyricSpecified() && ue_src.isLyricSpecified() ) {
                ue_dst.setLyric( ue_src.getLyric() );
            }
            if ( !ue_dst.isModurationSpecified() && ue_src.isModurationSpecified() ) {
                ue_dst.setModuration( ue_src.getModuration() );
            }
            if ( !ue_dst.isNoteSpecified() && ue_src.isNoteSpecified() ) {
                ue_dst.setNote( ue_src.getNote() );
            }
            if ( !ue_dst.isPBTypeSpecified() && ue_src.isPBTypeSpecified() ) {
                ue_dst.setPBType( ue_src.getPBType() );
            }
            if ( !ue_dst.isPitchesSpecified() && ue_src.isPitchesSpecified() ) {
                ue_dst.setPitches( ue_src.getPitches() );
            }
            if ( !ue_dst.isPortamentoSpecified() && ue_src.isPortamentoSpecified() ) {
                ue_dst.setPortamento( ue_src.getPortamento() );
            }
            if ( !ue_dst.isPreUtteranceSpecified() && ue_src.isPreUtteranceSpecified() ) {
                ue_dst.setPreUtterance( ue_src.getPreUtterance() );
            }
            if ( !ue_dst.isStartPointSpecified() && ue_src.isStartPointSpecified() ) {
                ue_dst.setStartPoint( ue_src.getStartPoint() );
            }
            if ( !ue_dst.isTempoSpecified() && ue_src.isTempoSpecified() ) {
                ue_dst.setTempo( ue_src.getTempo() );
            }
            if ( !ue_dst.isVibratoSpecified() && ue_src.isVibratoSpecified() ) {
                ue_dst.setVibrato( ue_src.getVibrato() );
            }
            if ( !ue_dst.isVoiceOverlapSpecified() && ue_src.isVoiceOverlapSpecified() ) {
                ue_dst.setVoiceOverlap( ue_src.getVoiceOverlap() );
            }
        }

        // PREVとNEXT含めて,clock_startからclock_endまでプラグインに渡したけれど,
        // それが伸びて帰ってきたか縮んで帰ってきたか.
        int ret_length = 0;
        UstTrack r_track = r.getTrack( 0 );
        int size = r_track.getEventCount();
        for ( int i = 0; i < size; i++ ) {
            UstEvent ue = r_track.getEvent( i );
            // 戻りのustには,変更があったものしか記録されていない
            int ue_length = ue.getLength();
            if ( !ue.isLengthSpecified() && map.ContainsKey( ue.Index ) ) {
                int internal_id = map[ue.Index];
                VsqEvent found_item = vsq_track.findEventFromID( internal_id );
                if ( found_item != null ) {
                    ue_length = found_item.ID.getLength();
                }
            }
            // PREV, ENDの場合は長さに加えない
            if ( ue.Index != UstFile.NEXT_INDEX &&
                 ue.Index != UstFile.PREV_INDEX ) {
                ret_length += ue_length;
            }
        }

        // 伸び縮みがあった場合
        // 伸ばしたり縮めたりするよ
        int delta = ret_length - (sel_end - sel_start);
        if ( delta > 0 ) {
            // のびた
            vsq.insertBlank( selected, sel_end, delta );
        } else if ( delta < 0 ) {
            // 縮んだ
            vsq.removePart( selected, sel_end + delta, sel_end );
        }

        // r_trackの内容をvsq_trackに転写
        size = r_track.getEventCount();
        int c = clock_start;
        for ( int i = 0; i < size; i++ ) {
            UstEvent ue = r_track.getEvent( i );
            if ( ue.Index == UstFile.NEXT_INDEX || ue.Index == UstFile.PREV_INDEX ) {
                // PREVとNEXTは単に無視する
                continue;
            }
            int ue_length = ue.getLength();
            if ( map.containsKey( ue.Index ) ) {
                // 既存の音符の編集
                VsqEvent target = vsq_track.findEventFromID( map[ue.Index] );
                if ( target == null ) {
                    // そんなばかな・・・
                    continue;
                }
                if ( !ue.isLengthSpecified() ) {
                    ue_length = target.ID.getLength();
                }
                if ( target.UstEvent == null ) {
                    target.UstEvent = (UstEvent)ue.clone();
                }
                // utau固有のパラメータを転写
                // pitchは後でやるので無視していい
                // テンポもあとでやるので無視していい
                if ( ue.isEnvelopeSpecified() ) {
                    target.UstEvent.setEnvelope( ue.getEnvelope() );
                }
                if ( ue.isModurationSpecified() ) {
                    target.UstEvent.setModuration( ue.getModuration() );
                }
                if ( ue.isPBTypeSpecified() ) {
                    target.UstEvent.setPBType( ue.getPBType() );
                }
                if ( ue.isPortamentoSpecified() ) {
                    target.UstEvent.setPortamento( ue.getPortamento() );
                }
                if ( ue.isPreUtteranceSpecified() ) {
                    target.UstEvent.setPreUtterance( ue.getPreUtterance() );
                }
                if ( ue.isStartPointSpecified() ) {
                    target.UstEvent.setStartPoint( ue.getStartPoint() );
                }
                if ( ue.isVibratoSpecified() ) {
                    target.UstEvent.setVibrato( ue.getVibrato() );
                }
                if ( ue.isVoiceOverlapSpecified() ) {
                    target.UstEvent.setVoiceOverlap( ue.getVoiceOverlap() );
                }
                // vocaloid, utauで同じ意味のパラメータを転写
                if ( ue.isIntensitySpecified() ) {
                    target.UstEvent.setIntensity( ue.getIntensity() );
                    target.ID.Dynamics = ue.getIntensity();
                }
                if ( ue.isLengthSpecified() ) {
                    target.UstEvent.setLength( ue.getLength() );
                    target.ID.setLength( ue.getLength() );
                }
                if ( ue.isLyricSpecified() ) {
                    target.UstEvent.setLyric( ue.getLyric() );
                    target.ID.LyricHandle.L0.Phrase = ue.getLyric();
                }
                if ( ue.isNoteSpecified() ) {
                    target.UstEvent.setNote( ue.getNote() );
                    target.ID.Note = ue.getNote();
                }
            } else {
                // マップに入っていないので,新しい音符の追加だと思う
                if ( ue.getLyric() == "R" ) {
                    // 休符.なにもしない
                } else {
                    VsqEvent newe = new VsqEvent();
                    newe.Clock = c;
                    newe.UstEvent = (UstEvent)ue.clone();
                    newe.ID = new VsqID();
                    AppManager.editorConfig.applyDefaultSingerStyle( newe.ID );
                    if ( ue.isIntensitySpecified() ) {
                        newe.ID.Dynamics = ue.getIntensity();
                    }
                    newe.ID.LyricHandle = new LyricHandle( "あ", "a" );
                    if ( ue.isLyricSpecified() ) {
                        newe.ID.LyricHandle.L0.Phrase = ue.getLyric();
                    }
                    newe.ID.Note = ue.getNote();
                    newe.ID.setLength( ue.getLength() );
                    newe.ID.type = VsqIDType.Anote;
                    // internal id はaddEventメソッドで自動で割り振られる
                    vsq_track.addEvent( newe );
                }
            }

            // テンポの追加がないかチェック
            if ( ue.isTempoSpecified() ) {
                insertTempoInto( vsq, c, ue.getTempo() );
            }

            c += ue_length;
        }

        // ピッチを転写
        // pitのデータがほしいので,PREV, NEXTを削除して,VsqFileにコンバートする
        UstFile uf = (UstFile)r.clone();
        // prev, nextを削除
        UstTrack uf_track = uf.getTrack( 0 );
        for ( int i = 0; i < uf_track.getEventCount(); ) {
            UstEvent ue = uf_track.getEvent( i );
            if ( ue.Index == UstFile.NEXT_INDEX ||
                 ue.Index == UstFile.PREV_INDEX ) {
                uf_track.removeEventAt( i );
            } else {
                i++;
            }
        }
        uf.updateTempoInfo();
        // VsqFileにコンバート
        VsqFile uf_vsq = new VsqFile( uf );
        // uf_vsqの最初のトラックの0からret_lengthクロックまでが,
        // vsq_trackのsel_startからsel_start+ret_lengthクロックまでに対応する.
        // まずPBSをコピーする
        CurveType[] type = new CurveType[] { CurveType.PBS, CurveType.PIT };
        foreach ( CurveType ct in type ) {
            // コピー元を取得
            VsqBPList src = uf_vsq.Track[1].getCurve( ct.getName() );
            if ( src != null ) {
                // コピー先を取得
                VsqBPList dst = vsq_track.getCurve( ct.getName() );
                if ( dst == null ) {
                    // コピー先がnullだった場合は作成
                    dst = new VsqBPList( ct.getName(), ct.getDefault(), ct.getMinimum(), ct.getMaximum() );
                    vsq_track.setCurve( ct.getName(), dst );
                }
                // あとで復元するので,最終位置での値を保存しておく
                int value_at_end = dst.getValue( sel_start + ret_length );
                // 復元するかどうか.最終位置にそもそもデータ点があれば復帰の必要がないので.
                bool do_revert = (dst.findIndexFromClock( sel_start + ret_length ) < 0);
                // [sel_start, sel_start + ret_length)の範囲の値を削除しておく
                size = dst.size();
                for ( int i = size - 1; i >= 0; i-- ) {
                    int cl = dst.getKeyClock( i );
                    if ( sel_start <= cl && cl < sel_start + ret_length ) {
                        dst.removeElementAt( i );
                    }
                }
                // コピーを実行
                size = src.size();
                for ( int i = 0; i < size; i++ ) {
                    int cl = src.getKeyClock( i );
                    if ( ret_length <= cl ) {
                        break;
                    }
                    int value = src.getElementA( i );
                    dst.add( cl + sel_start, value );
                }
                // コピー後,最終位置での値が元と異なる場合,元に戻すようにする
                if ( do_revert && dst.getValue( sel_start + ret_length ) != value_at_end ) {
                    dst.add( sel_start + ret_length, value_at_end );
                }
            }
        }

        return ScriptReturnStatus.EDITED;
    }
コード例 #38
0
        /// <summary>
        /// vsqxファイルを読み込み,新しいシーケンスオブジェクトを生成する
        /// </summary>
        /// <param name="filePath">ファイルパス</param>
        /// <exception cref="System.Exception">読み込みに失敗した時スローされる</exception>
        /// <returns>生成したシーケンスオブジェクト</returns>
        public static VsqFile readFromVsqx(string filePath)
        {
            if (filePath == null)
            {
                throw new ArgumentNullException("filePath");
            }

            if (false == File.Exists(filePath))
            {
                throw new Exception("file not found");
            }

            var xml = new XmlDocument();

            xml.Load(filePath);

            // 音源テーブルを解釈
            var voiceTable = getVoiceTable(xml);

            // マスタートラックを解釈
            XmlElement masterTrack = xml.DocumentElement["masterTrack"];
            int        preMeasure  = int.Parse(masterTrack["preMeasure"].InnerText);
            VsqFile    result      = new VsqFile("", preMeasure, 4, 4, 500000);

            // テンポ変更を読み取る
            result.TempoTable.Clear();
            foreach (XmlNode node in masterTrack.GetElementsByTagName("tempo"))
            {
                int             posTick    = int.Parse(node["posTick"].InnerText);
                int             bpm        = int.Parse(node["bpm"].InnerText);
                int             tempo      = (int)(6000000000L / bpm);
                TempoTableEntry tempoEntry = new TempoTableEntry(posTick, tempo, 0.0);
                result.TempoTable.Add(tempoEntry);
            }
            result.TempoTable.updateTempoInfo();
            // 拍子変更を読み取る
            result.TimesigTable.Clear();
            foreach (XmlNode node in masterTrack.GetElementsByTagName("timeSig"))
            {
                int posMes      = int.Parse(node["posMes"].InnerText);
                int numerator   = int.Parse(node["nume"].InnerText);
                int denominator = int.Parse(node["denomi"].InnerText);
                TimeSigTableEntry timesigEntry = new TimeSigTableEntry(0, numerator, denominator, posMes);
                result.TimesigTable.Add(timesigEntry);
            }
            result.TimesigTable.updateTimesigInfo();

            // マスター以外のトラックを解釈
            foreach (XmlNode node in xml.DocumentElement.GetElementsByTagName("vsTrack"))
            {
                int      trackIndex = int.Parse(node["vsTrackNo"].InnerText) + 1;
                VsqTrack track      = null;
                if (result.Track.Count <= trackIndex)
                {
                    int amount = trackIndex + 1 - result.Track.Count;
                    for (int i = 0; i < amount; i++)
                    {
                        result.Track.Add(new VsqTrack("", ""));
                    }
                }
                track = result.Track[trackIndex];
                track.setName(node["trackName"].InnerText);

                foreach (XmlNode child in node.ChildNodes)
                {
                    if (child.Name == "musicalPart")
                    {
                        parseMusicalPart(voiceTable, track, child);
                    }
                }
            }

            // MasterMixerをパース
            var mixer      = xml.DocumentElement["mixer"];
            var masterUnit = mixer["masterUnit"];

            result.Mixer.MasterFeder  = int.Parse(masterUnit["vol"].InnerText);
            result.Mixer.MasterMute   = 0;
            result.Mixer.MasterPanpot = 0;

            // SlaveMixerをパース
            result.Mixer.Slave.Clear();
            for (int i = 1; i < result.Track.Count; i++)
            {
                result.Mixer.Slave.Add(null);
            }
            foreach (XmlNode vsUnit in mixer.GetElementsByTagName("vsUnit"))
            {
                int vsTrackNo = int.Parse(vsUnit["vsTrackNo"].InnerText);
                int mute      = int.Parse(vsUnit["mute"].InnerText);
                int solo      = int.Parse(vsUnit["solo"].InnerText);
                int pan       = int.Parse(vsUnit["pan"].InnerText);
                int vol       = int.Parse(vsUnit["vol"].InnerText);
                var slave     = new VsqMixerEntry(vol, pan, mute, solo);
                result.Mixer.Slave[vsTrackNo] = slave;
            }

            return(result);
        }
コード例 #39
0
ファイル: UstFile.cs プロジェクト: scskarsper/Cadencii_UTAU
 public UstFile(VsqFile vsq, int track_index)
     :
     this(vsq, track_index, new SortedDictionary <int, int>())
 {
 }
コード例 #40
0
ファイル: UstFile.cs プロジェクト: scskarsper/Cadencii_UTAU
        /// <summary>
        /// vsqの指定したトラックを元に,トラックを1つだけ持つustを構築します
        /// </summary>
        /// <param name="vsq"></param>
        /// <param name="track_index"></param>
        /// <param name="id_map">UstEventのIndexフィールドと、元になったVsqEventのInternalIDを対応付けるマップ。キーがIndex、値がInternalIDを表す</param>
        public UstFile(VsqFile vsq, int track_index, SortedDictionary <int, int> id_map)
        {
            VsqFile work = (VsqFile)vsq.clone();
            //work.removePart( 0, work.getPreMeasureClocks() );

            VsqTrack vsq_track = work.Track[track_index];

            // デフォルトのテンポ
            if (work.TempoTable.Count <= 0)
            {
                m_tempo = 120.0f;
            }
            else
            {
                m_tempo = (float)(60e6 / (double)work.TempoTable[0].Tempo);
            }
            m_tempo_table = new List <TempoTableEntry>();
            m_tempo_table.Clear();
            // ustには、テンポチェンジを音符の先頭にしか入れられない
            // あとで音符に反映させるためのテンプレートを作っておく
            TempoVector tempo      = new TempoVector();
            int         last_clock = 0;
            int         itempo     = (int)(60e6 / m_tempo);

            foreach (var item in vsq_track.getNoteEventIterator())
            {
                if (last_clock < item.Clock)
                {
                    // 休符Rの分
                    tempo.Add(new TempoTableEntry(last_clock, itempo, work.getSecFromClock(last_clock)));
                }
                tempo.Add(new TempoTableEntry(item.Clock, itempo, work.getSecFromClock(item.Clock)));
                last_clock = item.Clock + item.ID.getLength();
            }
            if (tempo.Count == 0)
            {
                tempo.Add(new TempoTableEntry(0, (int)(60e6 / m_tempo), 0.0));
            }
            // tempoの中の各要素の時刻が、vsq.TempoTableから計算した時刻と合致するよう調節
#if DEBUG
            sout.println("UstFile#.ctor; before; list=");
            for (int i = 0; i < tempo.Count; i++)
            {
                TempoTableEntry item = tempo[i];
                sout.println("    #" + i + "; c" + item.Clock + "; T" + item.Tempo + "; t" + (60e6 / item.Tempo) + "; sec" + item.Time);
            }
#endif
            TempoTableEntry prev = tempo[0];
            for (int i = 1; i < tempo.Count; i++)
            {
                TempoTableEntry item  = tempo[i];
                double          sec   = item.Time - prev.Time;
                int             delta = item.Clock - prev.Clock;
                // deltaクロックでsecを表現するにはテンポをいくらにすればいいか?
                int draft = (int)(480.0 * sec * 1e6 / (double)delta);
                // 丸め誤差が入るので、Timeを更新
                // ustに実際に記録されるテンポはいくらか?
                float act_tempo   = (float)double.Parse(PortUtil.formatDecimal("0.00", 60e6 / draft));
                int   i_act_tempo = (int)(60e6 / act_tempo);
                prev.Tempo = i_act_tempo;
                item.Time  = prev.Time + 1e-6 * delta * prev.Tempo / 480.0;
                prev       = item;
            }
#if DEBUG
            sout.println("UstFile#.ctor; after; list=");
            for (int i = 0; i < tempo.Count; i++)
            {
                TempoTableEntry item = tempo[i];
                sout.println("    #" + i + "; c" + item.Clock + "; T" + item.Tempo + "; t" + (60e6 / item.Tempo) + "; sec" + item.Time);
            }
            sout.println("UstFile#.ctor; vsq.TempoTable=");
            for (int i = 0; i < work.TempoTable.Count; i++)
            {
                TempoTableEntry item = work.TempoTable[i];
                sout.println("    #" + i + "; c" + item.Clock + "; T" + item.Tempo + "; t" + (60e6 / item.Tempo) + "; sec" + item.Time);
            }
#endif

            // R用音符のテンプレート
            int      PBTYPE   = 5;
            UstEvent template = new UstEvent();
            template.setLyric("R");
            template.setNote(60);
            template.setPreUtterance(0);
            template.setVoiceOverlap(0);
            template.setIntensity(100);
            template.setModuration(0);

            // 再生秒時をとりあえず無視して,ゲートタイム基準で音符を追加
            UstTrack track_add = new UstTrack();
            last_clock = 0;
            int index = 0;
            foreach (var item in vsq_track.getNoteEventIterator())
            {
                if (last_clock < item.Clock)
                {
                    // ゲートタイム差あり,Rを追加
                    UstEvent itemust = (UstEvent)template.clone();
                    itemust.setLength(item.Clock - last_clock);
                    itemust.Index = index;
                    index++;
                    id_map[itemust.Index] = -1;
                    track_add.addEvent(itemust);
                }
                UstEvent item_add = (UstEvent)item.UstEvent.clone();
                item_add.setLength(item.ID.getLength());
                item_add.setLyric(item.ID.LyricHandle.L0.Phrase);
                item_add.setNote(item.ID.Note);
                item_add.Index         = index;
                id_map[item_add.Index] = item.InternalID;
                if (item.UstEvent.getEnvelope() != null)
                {
                    item_add.setEnvelope((UstEnvelope)item.UstEvent.getEnvelope().clone());
                }
                index++;
                track_add.addEvent(item_add);
                last_clock = item.Clock + item.ID.getLength();
            }

            // テンポを格納(イベント数はあっているはず)
            if (track_add.getEventCount() > 0)
            {
                int size      = track_add.getEventCount();
                int lasttempo = -1; // ありえない値にしておく
                for (int i = 0; i < size; i++)
                {
                    TempoTableEntry item = tempo[i];
                    if (lasttempo != item.Tempo)
                    {
                        // テンポ値が変わっているもののみ追加
                        UstEvent ue = track_add.getEvent(i);
                        ue.setTempo((float)(60e6 / item.Tempo));
                        lasttempo = item.Tempo;
                        m_tempo_table.Add(item);
                    }
                }
            }
            else
            {
                // tempoはどうせ破棄されるのでクローンしなくていい
                m_tempo_table.Add(tempo[0]);
            }

            // ピッチを反映
            // まず絶対ピッチを取得
            VsqBPList abs_pit     = new VsqBPList("", 600000, 0, 1280000);
            VsqBPList cpit        = vsq_track.getCurve("pit");
            int       clock       = 0;
            int       search_indx = 0;
            int       pit_size    = cpit.size();
            foreach (var item in track_add.getNoteEventIterator())
            {
                int c   = clock;
                int len = item.getLength();
                clock += len;
                if (item.getLyric() == "R")
                {
                    continue;
                }
                // 音符の先頭のpitは必ず入れる
                abs_pit.add(c, (int)(item.getNote() * 10000 + vsq_track.getPitchAt(c) * 100));

                // c~c+lenまで
                for (int i = search_indx; i < pit_size; i++)
                {
                    int c2 = cpit.getKeyClock(i);
                    if (c < c2 && c2 < clock)
                    {
                        abs_pit.add(c2, (int)(item.getNote() * 10000 + vsq_track.getPitchAt(c2) * 100));
                        search_indx = i;
                    }
                    else if (clock <= c2)
                    {
                        break;
                    }
                }
            }

            // ピッチをピッチベンドに変換しながら反映
            clock = 0;
            foreach (var item in track_add.getNoteEventIterator())
            {
                double sec_at_clock = tempo.getSecFromClock(clock);
                double sec_pre      = item.getPreUtterance() / 1000.0;
                double sec_stp      = item.getStartPoint() / 1000.0;
                double sec_at_begin = sec_at_clock - sec_pre - sec_stp;
                int    clock_begin  = (int)tempo.getClockFromSec(sec_at_begin);
                // 音符先頭との距離がPBTYPEの倍数になるようにする
                clock_begin -= (clock < clock_begin) ? ((clock_begin - clock) % PBTYPE)
                                                     : ((clock - clock_begin) % PBTYPE);
                // clock_beginがsec_at_beginより前方になるとNGなので修正する
                double sec_at_clock_begin = tempo.getSecFromClock(clock_begin);
                while (sec_at_clock_begin < sec_at_begin)
                {
                    clock_begin       += PBTYPE;
                    sec_at_clock_begin = tempo.getSecFromClock(clock_begin);
                }
                int          clock_end = clock + item.getLength();
                List <float> pitch     = new List <float>();
                bool         allzero   = true;
                ByRef <int>  ref_indx  = new ByRef <int>(0);
                for (int cl = clock_begin; cl < clock_end; cl += PBTYPE)
                {
                    int   abs = abs_pit.getValue(cl, ref_indx);
                    float pit = (float)(abs / 100.0) - item.getNote() * 100;
                    if (pit != 0.0)
                    {
                        allzero = false;
                    }
                    pitch.Add(pit);
                }
                if (!allzero)
                {
                    item.setPitches(PortUtil.convertFloatArray(pitch.ToArray()));
                    item.setPBType(PBTYPE);
                }
                else
                {
                    item.setPBType(-1);
                }
                clock += item.getLength();
            }

            m_tracks.Add(track_add);
        }
コード例 #41
0
        public void readFromVsqx()
        {
            VsqFile vsq = VsqxReader.readFromVsqx("./fixture/track1.vsqx");

            // トラック数
            Assert.AreEqual(2, vsq.Track.size());

            // プリメジャー
            Assert.AreEqual(4, vsq.getPreMeasure());

            // イベント数
            // 最初のmusicalPartには歌手変更1個と音符2個
            // 2つ目のmusicalPartには歌手変更1個と音符1個が入っているはず
            VsqTrack track = vsq.Track.get(1);

            Assert.AreEqual(6, track.getEventCount());

            // 歌手変更が正しく読み込まれているか
            // 1個目はデフォルトの歌手変更なのでスルー
            var singerChange = track.getEvent(1);

            Assert.AreEqual(7680, singerChange.Clock);
            Assert.Null(singerChange.ID.IconDynamicsHandle);
            Assert.Null(singerChange.ID.LyricHandle);
            Assert.Null(singerChange.ID.NoteHeadHandle);
            Assert.Null(singerChange.ID.VibratoHandle);
            Assert.AreEqual("VY1V3", singerChange.ID.IconHandle.IDS);
            Assert.AreEqual("$07010000", singerChange.ID.IconHandle.IconID);
            Assert.AreEqual(0, singerChange.ID.IconHandle.Language);
            Assert.AreEqual(0, singerChange.ID.IconHandle.Program);

            // 1つめの音符イベントが正しく読み込まれているか
            var firstEvent = track.getEvent(2);

            Assert.AreEqual(7680 + 0, firstEvent.Clock);
            Assert.AreEqual(48, firstEvent.ID.Note);
            Assert.AreEqual(480, firstEvent.ID.getLength());

            Assert.AreEqual(62, firstEvent.ID.Dynamics);
            Assert.AreEqual(50, firstEvent.ID.DEMaccent);
            Assert.AreEqual(8, firstEvent.ID.PMBendDepth);
            Assert.AreEqual(0, firstEvent.ID.PMBendLength);
            Assert.AreEqual(50, firstEvent.ID.DEMdecGainRate);
            Assert.AreEqual(false, firstEvent.ID.isFallPortamento());
            Assert.AreEqual(false, firstEvent.ID.isRisePortamento());

            Assert.Null(firstEvent.ID.IconDynamicsHandle);

            Assert.AreEqual("わ", firstEvent.ID.LyricHandle.L0.Phrase);
            Assert.AreEqual("w a", firstEvent.ID.LyricHandle.L0.getPhoneticSymbol());
            Assert.AreEqual(true, firstEvent.ID.LyricHandle.L0.PhoneticSymbolProtected);
            Assert.Null(firstEvent.ID.NoteHeadHandle);

            Assert.AreEqual("$04040000", firstEvent.ID.VibratoHandle.IconID);
            Assert.AreEqual(316, firstEvent.ID.VibratoHandle.getLength());
            var depthBP = firstEvent.ID.VibratoHandle.getDepthBP();

            Assert.AreEqual(1, depthBP.getCount());
            Assert.AreEqual(0.0f, depthBP.getElement(0).X);
            Assert.AreEqual(64, depthBP.getElement(0).Y);
            var rateBP = firstEvent.ID.VibratoHandle.getRateBP();

            Assert.AreEqual(1, rateBP.getCount());
            Assert.AreEqual(0.0f, rateBP.getElement(0).X);
            Assert.AreEqual(50, rateBP.getElement(0).Y);
            Assert.AreEqual(164, firstEvent.ID.VibratoDelay);

            Assert.Null(firstEvent.ID.IconHandle);

            // 2つめの音符イベントが正しく読み込まれているか
            var secondEvent = track.getEvent(3);

            Assert.AreEqual(7680 + 480, secondEvent.Clock);
            Assert.AreEqual(50, secondEvent.ID.Note);
            Assert.AreEqual(960, secondEvent.ID.getLength());
            Assert.AreEqual(63, secondEvent.ID.Dynamics);
            Assert.AreEqual(50, secondEvent.ID.DEMaccent);
            Assert.AreEqual(8, secondEvent.ID.PMBendDepth);
            Assert.AreEqual(0, secondEvent.ID.PMBendLength);
            Assert.AreEqual(50, secondEvent.ID.DEMdecGainRate);
            Assert.AreEqual(true, secondEvent.ID.isFallPortamento());
            Assert.AreEqual(false, secondEvent.ID.isRisePortamento());

            Assert.Null(secondEvent.ID.IconDynamicsHandle);
            Assert.AreEqual("は", secondEvent.ID.LyricHandle.L0.Phrase);
            Assert.AreEqual("h a", secondEvent.ID.LyricHandle.L0.getPhoneticSymbol());
            Assert.AreEqual(false, secondEvent.ID.LyricHandle.L0.PhoneticSymbolProtected);
            Assert.Null(secondEvent.ID.NoteHeadHandle);

            Assert.AreEqual("$04040004", secondEvent.ID.VibratoHandle.IconID);
            Assert.AreEqual(624, secondEvent.ID.VibratoHandle.getLength());
            depthBP = secondEvent.ID.VibratoHandle.getDepthBP();
            Assert.AreEqual(1, depthBP.getCount());
            Assert.AreEqual(0.0f, depthBP.getElement(0).X);
            Assert.AreEqual(64, depthBP.getElement(0).Y);
            rateBP = secondEvent.ID.VibratoHandle.getRateBP();
            Assert.AreEqual(1, secondEvent.ID.VibratoHandle.getRateBP().getCount());
            Assert.AreEqual(0.0f, rateBP.getElement(0).X);
            Assert.AreEqual(64, rateBP.getElement(0).Y);
            Assert.AreEqual(336, secondEvent.ID.VibratoDelay);

            Assert.Null(secondEvent.ID.IconHandle);

            // 2つ目の歌手変更
            var singerChange2 = track.getEvent(4);

            Assert.AreEqual(10560, singerChange2.Clock);
            Assert.Null(singerChange2.ID.IconDynamicsHandle);
            Assert.Null(singerChange2.ID.LyricHandle);
            Assert.Null(singerChange2.ID.NoteHeadHandle);
            Assert.Null(singerChange2.ID.VibratoHandle);
            Assert.AreEqual("Miku(V2)", singerChange2.ID.IconHandle.IDS);
            Assert.AreEqual("$07010001", singerChange2.ID.IconHandle.IconID);
            Assert.AreEqual(0, singerChange2.ID.IconHandle.Language);
            Assert.AreEqual(1, singerChange2.ID.IconHandle.Program);

            // 3つめの音符イベントが正しく読み込まれているか
            var thirdEvent = track.getEvent(5);

            Assert.AreEqual(10560 + 665, thirdEvent.Clock);
            Assert.AreEqual(60, thirdEvent.ID.Note);
            Assert.AreEqual(480, thirdEvent.ID.getLength());
            Assert.AreEqual(64, thirdEvent.ID.Dynamics);
            Assert.AreEqual(50, thirdEvent.ID.DEMaccent);
            Assert.AreEqual(8, thirdEvent.ID.PMBendDepth);
            Assert.AreEqual(0, thirdEvent.ID.PMBendLength);
            Assert.AreEqual(50, thirdEvent.ID.DEMdecGainRate);
            Assert.AreEqual(false, thirdEvent.ID.isFallPortamento());
            Assert.AreEqual(false, thirdEvent.ID.isRisePortamento());

            Assert.Null(thirdEvent.ID.IconDynamicsHandle);
            Assert.AreEqual("a", thirdEvent.ID.LyricHandle.L0.Phrase);
            Assert.AreEqual("a", thirdEvent.ID.LyricHandle.L0.getPhoneticSymbol());
            Assert.AreEqual(false, thirdEvent.ID.LyricHandle.L0.PhoneticSymbolProtected);
            Assert.Null(thirdEvent.ID.NoteHeadHandle);

            Assert.AreEqual("$04040000", thirdEvent.ID.VibratoHandle.IconID);
            Assert.AreEqual(316, thirdEvent.ID.VibratoHandle.getLength());
            depthBP = thirdEvent.ID.VibratoHandle.getDepthBP();
            Assert.AreEqual(1, depthBP.getCount());
            Assert.AreEqual(0.0f, depthBP.getElement(0).X);
            Assert.AreEqual(64, depthBP.getElement(0).Y);
            rateBP = thirdEvent.ID.VibratoHandle.getRateBP();
            Assert.AreEqual(1, thirdEvent.ID.VibratoHandle.getRateBP().getCount());
            Assert.AreEqual(0.0f, rateBP.getElement(0).X);
            Assert.AreEqual(50, rateBP.getElement(0).Y);
            Assert.AreEqual(164, thirdEvent.ID.VibratoDelay);

            Assert.Null(thirdEvent.ID.IconHandle);

            // トラック名
            Assert.AreEqual("Track", track.getName());

            // テンポ変更
            Assert.AreEqual(2, vsq.TempoTable.size());
            Assert.AreEqual(0, vsq.TempoTable.get(0).Clock);
            Assert.AreEqual(500000, vsq.TempoTable.get(0).Tempo);
            Assert.AreEqual(8640, vsq.TempoTable.get(1).Clock);
            Assert.AreEqual(1199760, vsq.TempoTable.get(1).Tempo);

            // 拍子変更
            Assert.AreEqual(2, vsq.TimesigTable.size());
            Assert.AreEqual(0, vsq.TimesigTable.get(0).Clock);
            Assert.AreEqual(4, vsq.TimesigTable.get(0).Numerator);
            Assert.AreEqual(4, vsq.TimesigTable.get(0).Denominator);
            Assert.AreEqual(9600, vsq.TimesigTable.get(1).Clock);
            Assert.AreEqual(3, vsq.TimesigTable.get(1).Numerator);
            Assert.AreEqual(4, vsq.TimesigTable.get(1).Denominator);

            // コントロールカーブ
            // DYN
            var dyn = track.getCurve("DYN");

            Assert.AreEqual(1, dyn.size());
            Assert.AreEqual(720, dyn.getKeyClock(0));
            Assert.AreEqual(96, dyn.getElement(0));

            // BRE
            var bre = track.getCurve("BRE");

            Assert.AreEqual(1, bre.size());
            Assert.AreEqual(720, bre.getKeyClock(0));
            Assert.AreEqual(102, bre.getElement(0));

            // BRI

            // CLE

            // OPE
            var ope = track.getCurve("OPE");

            Assert.AreEqual(3, ope.size());
            Assert.AreEqual(7680 + 0, ope.getKeyClock(0));
            Assert.AreEqual(127, ope.getElement(0));
            Assert.AreEqual(7680 + 480, ope.getKeyClock(1));
            Assert.AreEqual(127, ope.getElement(1));
            Assert.AreEqual(10560 + 665, ope.getKeyClock(2));
            Assert.AreEqual(127, ope.getElement(2));

            // GEN

            // POR

            // PIT

            // PBS

            // Mixerが正しく読み込まれているか
            Assert.AreEqual(2, vsq.Mixer.MasterFeder);

            Assert.AreEqual(1, vsq.Mixer.Slave.size());
            Assert.AreEqual(1, vsq.Mixer.Slave.get(0).Solo);
            Assert.AreEqual(0, vsq.Mixer.Slave.get(0).Mute);
            Assert.AreEqual(64, vsq.Mixer.Slave.get(0).Panpot);
            Assert.AreEqual(1, vsq.Mixer.Slave.get(0).Feder);
        }