Example #1
0
        /// <summary>
        /// vsqファイルのstart_clockクロックからメトロノームを起動する。startは、start_clockをいつから起動したかを指定する。
        /// </summary>
        /// <param name="vsq"></param>
        /// <param name="start_clock"></param>
        /// <param name="start"></param>
        public static void Start(VsqFileEx vsq, int start_clock, double start_time)
        {
            s_queue.clear();
            m_stop_required           = false;
            m_stop_metronome_required = false;
            if (s_device0 == null)
            {
                s_device0 = new MidiDeviceImp(s_metronome_device);
            }
            if (s_metronome_device != s_general_device)
            {
                if (s_device1 == null)
                {
                    s_device1 = new MidiDeviceImp(s_general_device);
                }
            }

            m_vsq         = (VsqFileEx)vsq.clone();
            m_started_sec = m_vsq.getSecFromClock(start_clock);
            ByRef <Integer> bar             = new ByRef <Integer>();
            Timesig         timesig         = m_vsq.getTimesigAt(start_clock, bar);
            int             clock_at_bartop = m_vsq.getClockFromBarCount(bar.value);
            int             clock_step      = 480 * 4 / timesig.denominator;
            int             next_clock      = clock_at_bartop + ((start_clock - clock_at_bartop) / clock_step + 1) * clock_step;

            m_started       = start_time;
            m_started_clock = start_clock;
            m_temp_exit     = false;

            for (int track = 1; track < m_vsq.Track.size(); track++)
            {
#if DEBUG
                AppManager.debugWriteLine("Metronome.Start; track=" + track);
#endif
                for (Iterator <VsqEvent> itr = m_vsq.Track.get(track).getNoteEventIterator(); itr.hasNext();)
                {
                    VsqEvent item = itr.next();
                    if (start_clock <= item.Clock)
                    {
                        MidiQueue q = new MidiQueue();
                        q.Track    = track;
                        q.Channel  = (byte)(track - 1);
                        q.Clock    = item.Clock;
                        q.Note     = (byte)(item.ID.Note);
                        q.Program  = 0;
                        q.Velocity = 0x40;
                        q.Done    += new MidiQueueDoneEventHandler(ReGenerateMidiQueue);
                        s_queue.add(q);
                        break;
                    }
                }
            }

            Collections.sort(s_queue);

            m_thread = new Thread(new ThreadStart(ThreadProc));
            m_thread.IsBackground = true;
            m_thread.Priority     = ThreadPriority.Highest;
            m_thread.Start();
        }
        public void handleCommonMouseDown(Object sender, MouseEventArgs e)
        {
            if (AppManager.getEditMode() != EditMode.NONE)
            {
                return;
            }
            DraggableBButton btn = (DraggableBButton)sender;

            if (mMainWindow != null)
            {
                mMainWindow.BringToFront();
            }

            IconDynamicsHandle handle = btn.getHandle();
            VsqEvent           item   = new VsqEvent();

            item.Clock   = 0;
            item.ID.Note = 60;
            item.ID.type = VsqIDType.Aicon;
            item.ID.IconDynamicsHandle = (IconDynamicsHandle)handle.clone();
            int length = handle.getLength();

            if (length <= 0)
            {
                length = 1;
            }
            item.ID.setLength(length);
            AppManager.mAddingEvent = item;

            btn.DoDragDrop(handle, System.Windows.Forms.DragDropEffects.All);
        }
        /// <summary>
        /// 選択中のアイテムが編集された場合、編集にあわせてオブジェクトを更新する。
        /// </summary>
        public void updateSelectedEventInstance()
        {
            VsqFileEx vsq = AppManager.getVsqFile();

            if (vsq == null)
            {
                return;
            }
            int      selected  = AppManager.getSelected();
            VsqTrack vsq_track = vsq.Track[selected];

            for (int i = 0; i < mEvents.Count; i++)
            {
                SelectedEventEntry item = mEvents[i];
                VsqEvent           ev   = null;
                if (item.track == selected)
                {
                    int internal_id = item.original.InternalID;
                    ev = vsq_track.findEventFromID(internal_id);
                }
                if (ev != null)
                {
                    mEvents[i] = new SelectedEventEntry(selected, ev, (VsqEvent)ev.clone());
                }
                else
                {
                    mEvents.RemoveAt(i);
                    i--;
                }
            }
        }
        private XmlElement createNoteNode(VsqEvent vsq_event, int pre_measure_clock)
        {
            var node = doc_.CreateElement("note");

            node.AppendChild(createNode("posTick", vsq_event.Clock - pre_measure_clock));
            node.AppendChild(createNode("durTick", vsq_event.ID.getLength()));
            node.AppendChild(createNode("noteNum", vsq_event.ID.Note));
            node.AppendChild(createNode("velocity", vsq_event.ID.Dynamics));
            node.AppendChild(createNode("lyric", vsq_event.ID.LyricHandle.getLyricAt(0).Phrase));
            node.AppendChild(createNode("phnms", vsq_event.ID.LyricHandle.getLyricAt(0).getPhoneticSymbol()));
            {
                var style = doc_.CreateElement("noteStyle");
                style.AppendChild(createNode("attr", vsq_event.ID.DEMaccent).Attribute("id", "accent"));
                style.AppendChild(createNode("attr", vsq_event.ID.PMBendDepth).Attribute("id", "bendDep"));
                style.AppendChild(createNode("attr", vsq_event.ID.PMBendLength).Attribute("id", "bendLen"));
                style.AppendChild(createNode("attr", vsq_event.ID.DEMdecGainRate).Attribute("id", "decay"));
                style.AppendChild(createNode("attr", vsq_event.ID.isFallPortamento() ? 1 : 0).Attribute("id", "fallPort"));
                style.AppendChild(createNode("attr", 127).Attribute("id", "opening"));
                style.AppendChild(createNode("attr", vsq_event.ID.isRisePortamento() ? 1 : 0).Attribute("id", "risePort"));
                if (vsq_event.ID.VibratoHandle != null && vsq_event.ID.VibratoDelay < vsq_event.ID.getLength())
                {
                    int vibrato_length = vsq_event.ID.getLength() - vsq_event.ID.VibratoDelay;
                    int percent        = (int)(vibrato_length * 100.0 / vsq_event.ID.getLength());
                    style.AppendChild(createNode("attr", percent).Attribute("id", "vibLen"));
                    style.AppendChild(createNode("attr", vsq_event.ID.VibratoHandle.Index).Attribute("id", "vibType"));
                    style.AppendChild(createVibratoCurveNode(vsq_event.ID.VibratoHandle.getStartDepth(), vsq_event.ID.VibratoHandle.getDepthBP()).Attribute("id", "vibDep"));
                    style.AppendChild(createVibratoCurveNode(vsq_event.ID.VibratoHandle.getStartRate(), vsq_event.ID.VibratoHandle.getRateBP()).Attribute("id", "vibRate"));
                }
                node.AppendChild(style);
            }
            return(node);
        }
        public void propertyGrid_PropertyValueChanged(Object s, PropertyValueChangedEventArgs e)
        {
            AppManager.mMainWindow.setPrograssBarVisible(true);
            AppManager.mMainWindow.setPrograssBarName("应用属性");
            Object[] selobj = propertyGrid.SelectedObjects;
            int      len    = selobj.Length;

            AppManager.mMainWindow.setPrograssBarMaxium(len);
            AppManager.mMainWindow.setPrograssBarValue(0);

            VsqEvent[] items = new VsqEvent[len];
            for (int i = 0; i < len; i++)
            {
                SelectedEventEntry proxy = (SelectedEventEntry)selobj[i];
                items[i] = proxy.editing;
                Application.DoEvents();
            }
            CadenciiCommand run = new CadenciiCommand(VsqCommand.generateCommandEventReplaceRange(m_track, items));

            if (CommandExecuteRequired != null)
            {
                CommandExecuteRequired(this, run);
            }
            for (int i = 0; i < len; i++)
            {
                AppManager.itemSelection.addEvent(items[i].InternalID);
                AppManager.mMainWindow.setPrograssBarValue(i);
                Application.DoEvents();
            }
            propertyGrid.Refresh();
            setEditing(false);
            AppManager.mMainWindow.setPrograssBarVisible(false);
        }
        public void testReflectVibratoPitch()
        {
            var tempoTable = new TempoVector();
            var pitchBend = new VsqBPList( CurveType.PIT.getName(), CurveType.PIT.getDefault(), CurveType.PIT.getMinimum(), CurveType.PIT.getMaximum() );
            var pitchBendSensitivity = new VsqBPList( CurveType.PIT.getName(), CurveType.PIT.getDefault(), CurveType.PIT.getMinimum(), CurveType.PIT.getMaximum() );

            pitchBend.add( 0, 8191 );
            pitchBendSensitivity.add( 0, 2 );

            var generator = new AquesTone2WaveGeneratorStub();
            var item = new VsqEvent( 0, new VsqID() );
            item.ID.type = VsqIDType.Anote;
            item.ID.VibratoHandle = new VibratoHandle();
            item.ID.VibratoHandle.StartRate = 0x40;
            item.ID.VibratoHandle.RateBP.clear();
            item.ID.VibratoHandle.StartDepth = 0x40;
            item.ID.VibratoHandle.DepthBP.clear();
            item.ID.setLength( 480 );
            item.ID.VibratoDelay = 430;
            item.ID.VibratoHandle.setLength( 50 );
            generator.reflectVibratoPitch( item, pitchBend, pitchBendSensitivity, tempoTable );

            {
                var expectedPit = new Dictionary<int, int> {
                    { 0, 8191 },
                    { 430, 5461 }, { 431, 5467 }, { 432, 5484 }, { 433, 5514 }, { 434, 5555 },
                    { 435, 5608 }, { 436, 5672 }, { 437, 5748 }, { 438, 5835 }, { 439, 5932 },
                    { 440, 6041 }, { 441, 6096 }, { 442, 6151 }, { 443, 6205 }, { 444, 6257 },
                    { 445, 6309 }, { 446, 6360 }, { 447, 6410 }, { 448, 6459 }, { 449, 6507 },
                    { 450, 6553 }, { 451, 6598 }, { 452, 6642 }, { 453, 6684 }, { 454, 6725 },
                    { 455, 6764 }, { 456, 6802 }, { 457, 6838 }, { 458, 6873 }, { 459, 6906 },
                    { 460, 6937 }, { 461, 6967 }, { 462, 6994 }, { 463, 7020 }, { 464, 7044 },
                    { 465, 7066 }, { 466, 7087 }, { 467, 7105 }, { 468, 7121 }, { 469, 7136 },
                    { 470, 7148 }, { 471, 6989 }, { 472, 6826 }, { 473, 6660 }, { 474, 6491 },
                    { 475, 6320 }, { 476, 6149 }, { 477, 5976 }, { 478, 5804 }, { 479, 5632 },
                    { 480, 8191 }
                };
                Assert.AreEqual( expectedPit.Count, pitchBend.size() );
                int i = 0;
                foreach ( var pitInfo in expectedPit ) {
                    Assert.AreEqual( pitInfo.Key, pitchBend.getKeyClock( i ) );
                    Assert.AreEqual( pitInfo.Value, pitchBend.getElementA( i ) );
                    ++i;
                }
            }

            {
                var expectedPbs = new Dictionary<int, int> {
                    { 0, 2 }, { 430, 3 }, { 480, 2 }
                };
                Assert.AreEqual( expectedPbs.Count, pitchBendSensitivity.size() );
                int i = 0;
                foreach ( var pbsInfo in expectedPbs ) {
                    Assert.AreEqual( pbsInfo.Key, pitchBendSensitivity.getKeyClock( i ) );
                    Assert.AreEqual( pbsInfo.Value, pitchBendSensitivity.getElementA( i ) );
                    ++i;
                }
            }
        }
        private XmlElement createMusicalPartSingerNode(VsqEvent @event, int pre_measure_clock)
        {
            var node = doc_.CreateElement("singer");

            node.AppendChild(createNode("posTick", @event.Clock - pre_measure_clock));
            node.AppendChild(createNode("vBS", @event.ID.IconHandle.Language));
            node.AppendChild(createNode("vPC", @event.ID.IconHandle.Program));
            return(node);
        }
Example #8
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;
            }
        }
    }
 public UtauSymbolSplitor(VsqFileEx mVsq, VsqEvent curEvent, Dictionary <int, double> PitchBrust, List <VsqEvent> VibstrBrustEvents, cadencii.utau.UtauVoiceDB db)
 {
     oriPitchBrust        = PitchBrust;
     oriVibstrBrustEvents = VibstrBrustEvents;
     oriEvent             = curEvent;
     dstVibstrBrustEvents.Add(oriEvent, oriVibstrBrustEvents);
     dstPitchBrust.Add(oriEvent, oriPitchBrust);
     dstParentTable.Add(oriEvent, oriEvent);
     vdb       = db;
     this.mVsq = mVsq;
 }
Example #10
0
 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 );
         }
     }
 }
Example #11
0
 /// <summary>
 /// Initialize by VsqEvent object.
 /// </summary>
 /// <param name="item"></param>
 /// <param name="timesig_table"></param>
 public TiedEvent(VsqEvent item, TimesigVector timesig_table, TempoVector tempo_table)
 {
     Init(timesig_table, tempo_table, item.Clock, item.ID.getLength(), item.ID.Note, false);
     if (notes_.Count > 0 && item.ID.LyricHandle != null && item.ID.LyricHandle.getCount() > 0)
     {
         var lyric = new lyric();
         lyric.text.Add(new textelementdata());
         lyric.text.First.Value = item.ID.LyricHandle.getLyricAt(0).Phrase;
         notes_[0].lyric        = new lyric[] { lyric };
     }
 }
Example #12
0
        public string __DEBUG__toString()
        {
            string phase = "";

            for (int i = 0; i < track.getEventCount(); i++)
            {
                VsqEvent itemi = track.getEvent(i);
                if (itemi.ID.type == VsqIDType.Anote)
                {
                    phase += itemi.ID.LyricHandle.L0.Phrase;
                }
            }
            return(phase);
        }
        public bool equals(Object obj1, Object obj2)
        {
            if (obj1 == null || obj2 == null)
            {
                return(false);
            }
            if (!(obj1 is VsqEvent) || !(obj2 is VsqEvent))
            {
                return(false);
            }
            VsqEvent item1 = (VsqEvent)obj1;
            VsqEvent item2 = (VsqEvent)obj2;

            return(item1.ID.IconDynamicsHandle.IconID.Equals(item2.ID.IconDynamicsHandle.IconID));
        }
Example #14
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);
 }
Example #15
0
        public bool equals(Object obj1, Object obj2)
        {
            if (obj1 == null || obj2 == null)
            {
                return(false);
            }
            if (!(obj1 is VsqEvent) || !(obj2 is VsqEvent))
            {
                return(false);
            }
            VsqEvent item1 = (VsqEvent)obj1;
            VsqEvent item2 = (VsqEvent)obj2;

            return(item1.ID.IconHandle.Program == item2.ID.IconHandle.Program);
        }
        public void addEventAll(List <int> list)
        {
            clearTempo();
            clearTimesig();
            VsqEvent[] index    = new VsqEvent[list.Count];
            int        count    = 0;
            int        c        = list.Count;
            int        selected = AppManager.getSelected();

            for (Iterator <VsqEvent> itr = AppManager.getVsqFile().Track[selected].getEventIterator(); itr.hasNext();)
            {
                VsqEvent ev   = itr.next();
                int      find = -1;
                for (int i = 0; i < c; i++)
                {
                    if (list[i] == ev.InternalID)
                    {
                        find = i;
                        break;
                    }
                }
                if (0 <= find)
                {
                    index[find] = ev;
                    count++;
                }
                if (count == list.Count)
                {
                    break;
                }
            }
            for (int i = 0; i < index.Length; i++)
            {
                try
                {
                    if (!isEventContains(selected, index[i].InternalID))
                    {
                        mEvents.Add(new SelectedEventEntry(selected, index[i], (VsqEvent)index[i].clone()));
                    }
                }
                catch {; }
            }
#if ENABLE_PROPERTY
            AppManager.propertyPanel.updateValue(selected);
#endif
            checkSelectedItemExistence();
        }
Example #17
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);
    }
Example #18
0
    /// <summary>
    /// スクリプトの本体
    /// </summary>
    /// <param name="vsq"></param>
    /// <returns></returns>
    public static ScriptReturnStatus Edit(VsqFileEx vsq)
    {
        int          selected  = AppManager.getSelected();
        VsqTrack     vsq_track = vsq.Track[selected];
        RendererKind kind      = VsqFileEx.getTrackRendererKind(vsq_track);

        if (kind != RendererKind.UTAU)
        {
            return(ScriptReturnStatus.NOT_EDITED);
        }
        bool edited = false;

        foreach (var item in AppManager.itemSelection.getEventIterator())
        {
            VsqEvent original = item.original;
            if (original.ID.type != VsqIDType.Anote)
            {
                continue;
            }
            VsqEvent     singer = vsq_track.getSingerEventAt(original.Clock);
            SingerConfig sc     = AppManager.getSingerInfoUtau(singer.ID.IconHandle.Language, singer.ID.IconHandle.Program);
            if (sc != null && AppManager.mUtauVoiceDB.ContainsKey(sc.VOICEIDSTR))
            {
                string      phrase    = original.ID.LyricHandle.L0.Phrase;
                UtauVoiceDB db        = AppManager.mUtauVoiceDB[sc.VOICEIDSTR];
                int         CheckNote = original.ID.Note;
                if (original.UstEvent != null)
                {
                    CheckNote = original.UstEvent.ReplaceNoteID > 0 ? original.UstEvent.ReplaceNoteID : original.ID.Note;
                }
                OtoArgs  oa      = db.attachFileNameFromLyric(phrase, CheckNote);
                VsqEvent editing = vsq_track.findEventFromID(original.InternalID);
                if (editing.UstEvent == null)
                {
                    editing.UstEvent = new UstEvent();
                }
                editing.UstEvent.setVoiceOverlap(oa.msOverlap);
                editing.UstEvent.setPreUtterance(oa.msPreUtterance);
                edited = true;
            }
        }

        return(edited ? ScriptReturnStatus.EDITED : ScriptReturnStatus.NOT_EDITED);
    }
        private void addEventCor(int id, bool silent)
        {
            clearTempo();
            clearTimesig();
            int selected = AppManager.getSelected();

            for (Iterator <VsqEvent> itr = AppManager.getVsqFile().Track[selected].getEventIterator(); itr.hasNext();)
            {
                VsqEvent ev = itr.next();
                if (ev.InternalID == id)
                {
                    if (isEventContains(selected, id))
                    {
                        // すでに選択されていた場合
                        int count = mEvents.Count;
                        for (int i = 0; i < count; i++)
                        {
                            SelectedEventEntry item = mEvents[i];
                            if (item.original.InternalID == id)
                            {
                                mEvents.RemoveAt(i);
                                break;
                            }
                        }
                    }

                    mEvents.Add(new SelectedEventEntry(selected, ev, (VsqEvent)ev.clone()));
                    if (!silent)
                    {
                        invokeSelectedEventChangedEvent(false);
                    }
                    break;
                }
            }
            if (!silent)
            {
#if ENABLE_PROPERTY
                AppManager.propertyPanel.updateValue(selected);
#endif
            }
        }
Example #20
0
        public static string FlagGener(VsqTrack track, VsqEvent item)
        {
            string SpecialI = item.UstEvent.Flags;
            int    g        = (track.MetaText.GEN.getValue(item.Clock + (item.ID.getLength() > 10 ? 10 : (item.ID.getLength() / 2))) - 64);
            int    b        = (track.MetaText.BRE.getValue(item.Clock + (item.ID.getLength() > 10 ? 10 : (item.ID.getLength() / 2))) - 64);

            if (SpecialI.IndexOf("g") < 0)
            {
                if (g != 0)
                {
                    SpecialI = SpecialI + "g" + g.ToString();
                }
            }
            if (SpecialI.IndexOf("BRE") < 0)
            {
                if (b != 0)
                {
                    SpecialI = SpecialI + "BRE" + b.ToString();
                }
            }
            return(SpecialI);// SpecialI.Replace("p", "popop") + " p0";
        }
Example #21
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;
            }
        }
    }
 public void setUp()
 {
     fixture = new VsqEventList();
     {
         var item = new VsqEvent( 0, new VsqID() );
         item.ID.type = VsqIDType.Singer;
         fixture.add( item, 0 );
     }
     {
         var item = new VsqEvent( 480, new VsqID() );
         item.ID.type = VsqIDType.Anote;
         fixture.add( item, 1 );
     }
     {
         var item = new VsqEvent( 480, new VsqID() );
         item.ID.type = VsqIDType.Singer;
         fixture.add( item, 2 );
     }
     {
         var item = new VsqEvent( 1920, new VsqID() );
         item.ID.type = VsqIDType.Singer;
         fixture.add( item, 3 );
     }
 }
Example #23
0
 public void setUp()
 {
     fixture = new VsqEventList();
     {
         var item = new VsqEvent(0, new VsqID());
         item.ID.type = VsqIDType.Singer;
         fixture.add(item, 0);
     }
     {
         var item = new VsqEvent(480, new VsqID());
         item.ID.type = VsqIDType.Anote;
         fixture.add(item, 1);
     }
     {
         var item = new VsqEvent(480, new VsqID());
         item.ID.type = VsqIDType.Singer;
         fixture.add(item, 2);
     }
     {
         var item = new VsqEvent(1920, new VsqID());
         item.ID.type = VsqIDType.Singer;
         fixture.add(item, 3);
     }
 }
Example #24
0
        /// <summary>
        /// musicalPartを解釈し、パート内の情報をtrackに追加する
        /// </summary>
        /// <param name="voiceTable">音源情報のテーブル</param>
        /// <param name="track">追加先のトラック</param>
        /// <param name="musicalPart">解釈対象のmusicalPart</param>
        private static void parseMusicalPart(Dictionary <int, Dictionary <int, IconHandle> > voiceTable, VsqTrack track, XmlNode musicalPart)
        {
            int offset = int.Parse(musicalPart["posTick"].InnerText);

            // 歌手切り替え情報をパース
            foreach (XmlNode singer in musicalPart.ChildNodes)
            {
                if (singer.Name != "singer")
                {
                    continue;
                }
                int posTick       = int.Parse(singer["posTick"].InnerText);
                int bankSelect    = int.Parse(singer["vBS"].InnerText);
                int programChange = int.Parse(singer["vPC"].InnerText);
                if (voiceTable.ContainsKey(bankSelect) && voiceTable[bankSelect].ContainsKey(programChange))
                {
                    var iconHandle = voiceTable[bankSelect][programChange];
                    var item       = new VsqEvent();
                    item.ID.IconHandle = (IconHandle)iconHandle.clone();
                    item.ID.type       = VsqIDType.Singer;
                    item.Clock         = offset + posTick;
                    track.addEvent(item);
                }
                else
                {
                    throw new Exception("音源情報のparseに失敗しました。");
                }
            }

            // ノート情報をパース
            foreach (XmlNode note in musicalPart.ChildNodes)
            {
                if (note.Name != "note")
                {
                    continue;
                }
                var item = createNoteEvent(note, offset);
                track.addEvent(item);

                // OPEカーブを更新
                int ope  = getOpening(note);
                var list = track.getCurve("OPE");
                list.add(item.Clock, ope);
            }

            // OPE以外のコントロールカーブをパース
            foreach (XmlNode ctrl in musicalPart.ChildNodes)
            {
                if (ctrl.Name != "mCtrl")
                {
                    continue;
                }
                int    posTick = int.Parse(ctrl["posTick"].InnerText);
                string id      = ctrl["attr"].Attributes["id"].Value;
                int    value   = int.Parse(ctrl["attr"].InnerText);
                var    list    = track.getCurve(id);
                if (list != null)
                {
                    list.add(posTick, value);
                }
            }
        }
        public void begin(long total_samples, WorkerState state)
        {
            var mDriver = getDriver();

#if DEBUG
            sout.println("AquesToneRenderingRunner#begin; (mDriver==null)=" + (mDriver == null));
            String file = System.IO.Path.Combine(System.Windows.Forms.Application.StartupPath, "AquesToneWaveGenerator.txt");
            log           = new System.IO.StreamWriter(file);
            log.AutoFlush = true;
#endif
            if (mDriver == null)
            {
#if DEBUG
                log.WriteLine("mDriver==null");
                log.Close();
#endif
                exitBegin();
                state.reportComplete();
                return;
            }

#if DEBUG
            sout.println("AquesToneRenderingRunner#begin; mDriver.loaded=" + mDriver.loaded);
#endif
            if (!mDriver.loaded)
            {
#if DEBUG
                log.WriteLine("mDriver.loaded=" + mDriver.loaded);
                log.Close();
#endif
                exitBegin();
                state.reportComplete();
                return;
            }

            mRunning = true;
            //mAbortRequired = false;
            mTotalSamples = total_samples;
#if DEBUG
            sout.println("AquesToneWaveGenerator#begin; mTotalSamples=" + mTotalSamples);
            log.WriteLine("mTotalSamples=" + mTotalSamples);
            log.WriteLine("mTrimRemain=" + mTrimRemain);
#endif

            VsqTrack track       = mVsq.Track.get(mTrack);
            int      BUFLEN      = mSampleRate / 10;
            double[] left        = new double[BUFLEN];
            double[] right       = new double[BUFLEN];
            long     saProcessed = 0;
            int      saRemain    = 0;
            int      lastClock   = 0; // 最後に処理されたゲートタイム

            // 最初にダミーの音を鳴らす
            // (最初に入るノイズを回避するためと、前回途中で再生停止した場合に無音から始まるようにするため)
            mDriver.resetAllParameters();
            mDriver.process(left, right, BUFLEN);
            MidiEvent f_noteon = new MidiEvent();
            f_noteon.firstByte = 0x90;
            f_noteon.data      = new int[] { 0x40, 0x40 };
            f_noteon.clock     = 0;
            mDriver.send(new MidiEvent[] { f_noteon });
            mDriver.process(left, right, BUFLEN);
            MidiEvent f_noteoff = new MidiEvent();
            f_noteoff.firstByte = 0x80;
            f_noteoff.data      = new int[] { 0x40, 0x7F };
            mDriver.send(new MidiEvent[] { f_noteoff });
            for (int i = 0; i < 3; i++)
            {
                mDriver.process(left, right, BUFLEN);
            }
#if DEBUG
            log.WriteLine("pre-process done");
            log.WriteLine("-----------------------------------------------------");
            VsqTrack vsq_track = mVsq.Track.get(mTrack);
            for (Iterator <VsqEvent> itr = vsq_track.getNoteEventIterator(); itr.hasNext();)
            {
                VsqEvent item = itr.next();
                log.WriteLine("c" + item.Clock + "; " + item.ID.LyricHandle.L0.Phrase);
            }
#endif

            // レンダリング開始位置での、パラメータの値をセットしておく
            for (Iterator <VsqEvent> itr = track.getNoteEventIterator(); itr.hasNext();)
            {
                VsqEvent item = itr.next();
#if DEBUG
                sout.println("AquesToneWaveGenerator#begin; item.Clock=" + item.Clock);
                log.WriteLine("*********************************************************");
                log.WriteLine("item.Clock=" + item.Clock);
#endif
                long saNoteStart = (long)(mVsq.getSecFromClock(item.Clock) * mSampleRate);
                long saNoteEnd   = (long)(mVsq.getSecFromClock(item.Clock + item.ID.getLength()) * mSampleRate);
#if DEBUG
                log.WriteLine("saNoteStart=" + saNoteStart + "; saNoteEnd=" + saNoteEnd);
#endif

                EventQueueSequence list = generateMidiEvent(mVsq, mTrack, lastClock, item.Clock + item.ID.getLength());
                lastClock = item.Clock + item.ID.Length + 1;
                for (Iterator <Integer> itr2 = list.keyIterator(); itr2.hasNext();)
                {
                    // まず直前までの分を合成
                    Integer clock = itr2.next();
#if DEBUG
                    log.WriteLine("-------------------------------------------------------");
                    sout.println("AquesToneWaveGenerator#begin;     clock=" + clock);
#endif
                    long saStart = (long)(mVsq.getSecFromClock(clock) * mSampleRate);
                    saRemain = (int)(saStart - saProcessed);
#if DEBUG
                    log.WriteLine("saStart=" + saStart);
                    log.WriteLine("saRemain=" + saRemain);
#endif
                    while (saRemain > 0)
                    {
                        if (state.isCancelRequested())
                        {
                            goto heaven;
                        }
                        int len = saRemain > BUFLEN ? BUFLEN : saRemain;
                        mDriver.process(left, right, len);
                        waveIncoming(left, right, len);
                        saRemain    -= len;
                        saProcessed += len;
                        state.reportProgress(saProcessed);
                        //mTotalAppend += len; <- waveIncomingで計算されるので
                    }

                    // MIDiイベントを送信
                    MidiEventQueue queue = list.get(clock);
                    // まずnoteoff
                    boolean noteoff_send = false;
                    if (queue.noteoff.size() > 0)
                    {
#if DEBUG
                        for (int i = 0; i < queue.noteoff.size(); i++)
                        {
                            String    str   = "";
                            MidiEvent itemi = queue.noteoff.get(i);
                            str += "0x" + PortUtil.toHexString(itemi.firstByte, 2) + " ";
                            for (int j = 0; j < itemi.data.Length; j++)
                            {
                                str += "0x" + PortUtil.toHexString(itemi.data[j], 2) + " ";
                            }
                            sout.println(typeof(AquesToneWaveGenerator) + "#begin;         noteoff; " + str);
                        }
#endif
                        mDriver.send(queue.noteoff.toArray(new MidiEvent[] { }));
                        noteoff_send = true;
                    }
                    // parameterの変更
                    if (queue.param.size() > 0)
                    {
                        for (Iterator <ParameterEvent> itr3 = queue.param.iterator(); itr3.hasNext();)
                        {
                            ParameterEvent pe = itr3.next();
#if DEBUG
                            sout.println(typeof(AquesToneWaveGenerator) + "#begin;         param;   index=" + pe.index + "; value=" + pe.value);
#endif
                            mDriver.setParameter(pe.index, pe.value);
                        }
                    }
                    // ついでnoteon
                    if (queue.noteon.size() > 0)
                    {
                        // 同ゲートタイムにピッチベンドも指定されている場合、同時に送信しないと反映されないようだ!
                        if (queue.pit.size() > 0)
                        {
                            queue.noteon.addAll(queue.pit);
                            queue.pit.clear();
                        }
#if DEBUG
                        for (int i = 0; i < queue.noteon.size(); i++)
                        {
                            String    str   = "";
                            MidiEvent itemi = queue.noteon.get(i);
                            str += "0x" + PortUtil.toHexString(itemi.firstByte, 2) + " ";
                            for (int j = 0; j < itemi.data.Length; j++)
                            {
                                str += "0x" + PortUtil.toHexString(itemi.data[j], 2) + " ";
                            }
                            sout.println(typeof(AquesToneWaveGenerator) + "#begin;         noteon;  " + str);
                        }
#endif
                        mDriver.send(queue.noteon.toArray(new MidiEvent[] { }));
                    }
                    // PIT
                    if (queue.pit.size() > 0 && !noteoff_send)
                    {
#if DEBUG
                        for (int i = 0; i < queue.pit.size(); i++)
                        {
                            String    str   = "";
                            MidiEvent itemi = queue.pit.get(i);
                            str += "0x" + PortUtil.toHexString(itemi.firstByte, 2) + " ";
                            for (int j = 0; j < itemi.data.Length; j++)
                            {
                                str += "0x" + PortUtil.toHexString(itemi.data[j], 2) + " ";
                            }
                            sout.println(typeof(AquesToneWaveGenerator) + "#begin;         pit;     " + str);
                        }
#endif
                        mDriver.send(queue.pit.toArray(new MidiEvent[] { }));
                    }
                    if (mDriver.getUi(mMainWindow) != null)
                    {
                        mDriver.getUi(mMainWindow).invalidateUi();
                    }
                }
            }

            // totalSamplesに足りなかったら、追加してレンダリング
            saRemain = (int)(mTotalSamples - mTotalAppend);
#if DEBUG
            sout.println("AquesToneRenderingRunner#run; totalSamples=" + mTotalSamples + "; mTotalAppend=" + mTotalAppend + "; saRemain=" + saRemain);
#endif
            while (saRemain > 0)
            {
                if (state.isCancelRequested())
                {
                    goto heaven;
                }
                int len = saRemain > BUFLEN ? BUFLEN : saRemain;
                mDriver.process(left, right, len);
                waveIncoming(left, right, len);
                saRemain    -= len;
                saProcessed += len;
                state.reportProgress(saProcessed);
                //mTotalAppend += len;
            }
heaven:
#if DEBUG
            log.Close();
#endif
            exitBegin();
            state.reportComplete();
        }
        public static void GenerateSinglePhone(int note, string singer, string file, double amp)
        {
            string renderer = "";

            SingerConfig[] singers1             = VocaloSysUtil.getSingerConfigs(SynthesizerType.VOCALOID1);
            int            c                    = singers1.Length;
            string         first_found_singer   = "";
            string         first_found_renderer = "";

            for (int i = 0; i < c; i++)
            {
                if (first_found_singer.Equals(""))
                {
                    first_found_singer   = singers1[i].VOICENAME;
                    first_found_renderer = VsqFileEx.RENDERER_DSB2;
                }
                if (singers1[i].VOICENAME.Equals(singer))
                {
                    renderer = VsqFileEx.RENDERER_DSB2;
                    break;
                }
            }

            SingerConfig[] singers2 = VocaloSysUtil.getSingerConfigs(SynthesizerType.VOCALOID2);
            c = singers2.Length;
            for (int i = 0; i < c; i++)
            {
                if (first_found_singer.Equals(""))
                {
                    first_found_singer   = singers2[i].VOICENAME;
                    first_found_renderer = VsqFileEx.RENDERER_DSB3;
                }
                if (singers2[i].VOICENAME.Equals(singer))
                {
                    renderer = VsqFileEx.RENDERER_DSB3;
                    break;
                }
            }

            foreach (var sc in AppManager.editorConfig.UtauSingers)
            {
                if (first_found_singer.Equals(""))
                {
                    first_found_singer   = sc.VOICENAME;
                    first_found_renderer = VsqFileEx.RENDERER_UTU0;
                }
                if (sc.VOICENAME.Equals(singer))
                {
                    renderer = VsqFileEx.RENDERER_UTU0;
                    break;
                }
            }

            VsqFileEx vsq = new VsqFileEx(singer, 1, 4, 4, 500000);

            if (renderer.Equals(""))
            {
                singer   = first_found_singer;
                renderer = first_found_renderer;
            }
            vsq.Track[1].getCommon().Version = renderer;
            VsqEvent item = new VsqEvent(1920, new VsqID(0));

            item.ID.LyricHandle = new LyricHandle("あ", "a");
            item.ID.setLength(480);
            item.ID.Note          = note;
            item.ID.VibratoHandle = null;
            item.ID.type          = VsqIDType.Anote;
            vsq.Track[1].addEvent(item);
            vsq.updateTotalClocks();
            int    ms_presend = 500;
            string tempdir    = Path.Combine(AppManager.getCadenciiTempDir(), AppManager.getID());

            if (!Directory.Exists(tempdir))
            {
                try {
                    PortUtil.createDirectory(tempdir);
                } catch (Exception ex) {
                    Logger.write(typeof(FormGenerateKeySound) + ".GenerateSinglePhone; ex=" + ex + "\n");
                    serr.println("Program#GenerateSinglePhone; ex=" + ex);
                    return;
                }
            }
            WaveWriter ww = null;

            try {
                ww = new WaveWriter(file);
                RendererKind     kind        = VsqFileEx.getTrackRendererKind(vsq.Track[1]);
                WaveGenerator    generator   = VSTiDllManager.getWaveGenerator(kind);
                int              sample_rate = vsq.config.SamplingRate;
                FileWaveReceiver receiver    = new FileWaveReceiver(file, 1, 16, sample_rate);
                generator.setReceiver(receiver);
                generator.setGlobalConfig(AppManager.editorConfig);
#if DEBUG
                sout.println("FormGenerateKeySound#GenerateSinglePhone; sample_rate=" + sample_rate);
#endif
                generator.init(vsq, 1, 0, vsq.TotalClocks, sample_rate);
                double         total_sec = vsq.getSecFromClock(vsq.TotalClocks) + 1.0;
                WorkerStateImp state     = new WorkerStateImp();
                generator.begin((long)(total_sec * sample_rate), state);
            } catch (Exception ex) {
                serr.println("FormGenerateKeySound#GenerateSinglePhone; ex=" + ex);
                Logger.write(typeof(FormGenerateKeySound) + ".GenerateSinglePhone; ex=" + ex + "\n");
            } finally {
                if (ww != null)
                {
                    try {
                        ww.close();
                    } catch (Exception ex2) {
                        Logger.write(typeof(FormGenerateKeySound) + ".GenerateSinglePhone; ex=" + ex2 + "\n");
                        serr.println("FormGenerateKeySound#GenerateSinglePhone; ex2=" + ex2);
                    }
                }
            }
        }
    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);
            }
        }
    }
        public void patchWork(WorkerState state, Object arg)
        {
#if DEBUG
            sout.println("SynthesizeWorker#patchWork");
#endif
            VsqFileEx             vsq    = AppManager.getVsqFile();
            Object[]              args   = (Object[])arg;
            List <PatchWorkQueue> queue  = (List <PatchWorkQueue>)args[0];
            List <int>            tracks = (List <int>)args[1];
            int    finished = queue.Count;
            string temppath = AppManager.getTempWaveDir();
            for (int k = 0; k < tracks.Count; k++)
            {
                int        track      = tracks[k];
                string     wavePath   = Path.Combine(temppath, track + ".wav");
                List <int> queueIndex = new List <int>();

                for (int i = 0; i < queue.Count; i++)
                {
                    if (queue[i].track == track)
                    {
                        queueIndex.Add(i);
                    }
                }

                if (queueIndex.Count <= 0)
                {
                    // 第trackトラックに対してパッチワークを行う必要無し
                    continue;
                }

#if DEBUG
                sout.println("AppManager#pathWorkToFreeze; wavePath=" + wavePath + "; queue.get( queueIndex.get( 0 ) ).file=" + queue[queueIndex[0]].file);
                sout.println("AppManager#pathWorkToFreeze; queueIndex.size()=" + queueIndex.Count);
#endif
                if (queueIndex.Count == 1 && wavePath.Equals(queue[queueIndex[0]].file))
                {
                    // 第trackトラック全体の合成を指示するキューだった場合.
                    // このとき,パッチワークを行う必要なし.
                    AppManager.mLastRenderedStatus[track - 1] =
                        new RenderedStatus((VsqTrack)vsq.Track[track].clone(), vsq.TempoTable, (SequenceConfig)vsq.config.clone());
                    AppManager.serializeRenderingStatus(temppath, track);
                    AppManager.invokeWaveViewReloadRequiredEvent(track, wavePath, 1, -1);
                    continue;
                }

                WaveWriter writer = null;
                try {
                    int  sampleRate  = vsq.config.SamplingRate;
                    long totalLength = (long)((vsq.getSecFromClock(vsq.TotalClocks) + 1.0) * sampleRate);
                    writer = new WaveWriter(wavePath, vsq.config.WaveFileOutputChannel, 16, sampleRate);
                    int      BUFLEN = 1024;
                    double[] bufl   = new double[BUFLEN];
                    double[] bufr   = new double[BUFLEN];
                    double   total  = 0.0;
                    for (int m = 0; m < queueIndex.Count; m++)
                    {
                        int i = queueIndex[m];
                        if (finished <= i)
                        {
                            break;
                        }

                        // パッチワークの開始秒時
                        double secStart    = vsq.getSecFromClock(queue[i].clockStart);
                        long   sampleStart = (long)(secStart * sampleRate);

                        // パッチワークの終了秒時
                        int clockEnd = queue[i].clockEnd;
                        if (clockEnd == int.MaxValue)
                        {
                            clockEnd = vsq.TotalClocks + 240;
                        }
                        double secEnd    = vsq.getSecFromClock(clockEnd);
                        long   sampleEnd = (long)(secEnd * sampleRate);

                        WaveReader wr = null;
                        try {
                            wr = new WaveReader(queue[i].file);
                            long remain2 = sampleEnd - sampleStart;
                            long proc    = 0;
                            while (remain2 > 0)
                            {
                                int delta = remain2 > BUFLEN ? BUFLEN : (int)remain2;
                                wr.read(proc, delta, bufl, bufr);
                                writer.replace(sampleStart + proc, delta, bufl, bufr);
                                proc    += delta;
                                remain2 -= delta;
                                total   += delta;
                                state.reportProgress(total);
                            }
                        } catch (Exception ex) {
                            Logger.write(typeof(AppManager) + ".patchWorkToFreeze; ex=" + ex + "\n");
                            serr.println("AppManager#patchWorkToFreeze; ex=" + ex);
                        } finally {
                            if (wr != null)
                            {
                                try {
                                    wr.close();
                                } catch (Exception ex2) {
                                    Logger.write(typeof(AppManager) + ".patchWorkToFreeze; ex=" + ex2 + "\n");
                                    serr.println("AppManager#patchWorkToFreeze; ex2=" + ex2);
                                }
                            }
                        }

                        try {
                            PortUtil.deleteFile(queue[i].file);
                        } catch (Exception ex) {
                            Logger.write(typeof(AppManager) + ".patchWorkToFreeze; ex=" + ex + "\n");
                            serr.println("AppManager#patchWorkToFreeze; ex=" + ex);
                        }
                    }

                    VsqTrack vsq_track = vsq.Track[track];
                    if (queueIndex[queueIndex.Count - 1] <= finished)
                    {
                        // 途中で終了せず,このトラックの全てのパッチワークが完了した.
                        AppManager.mLastRenderedStatus[track - 1] =
                            new RenderedStatus((VsqTrack)vsq_track.clone(), vsq.TempoTable, (SequenceConfig)vsq.config.clone());
                        AppManager.serializeRenderingStatus(temppath, track);
                        AppManager.setRenderRequired(track, false);
                    }
                    else
                    {
                        // パッチワークの作成途中で,キャンセルされた
                        // キャンセルされたやつ以降の範囲に、プログラムチェンジ17の歌手変更イベントを挿入する。→AppManager#detectTrackDifferenceに必ず検出してもらえる。
                        VsqTrack copied = (VsqTrack)vsq_track.clone();
                        VsqEvent dumy   = new VsqEvent();
                        dumy.ID.type               = VsqIDType.Singer;
                        dumy.ID.IconHandle         = new IconHandle();
                        dumy.ID.IconHandle.Program = 17;
                        for (int m = 0; m < queueIndex.Count; m++)
                        {
                            int i = queueIndex[m];
                            if (i < finished)
                            {
                                continue;
                            }
                            int      start       = queue[i].clockStart;
                            int      end         = queue[i].clockEnd;
                            VsqEvent singerAtEnd = vsq_track.getSingerEventAt(end);

                            // startの位置に歌手変更が既に指定されていないかどうかを検査
                            int foundStart = -1;
                            int foundEnd   = -1;
                            for (Iterator <int> itr = copied.indexIterator(IndexIteratorKind.SINGER); itr.hasNext();)
                            {
                                int      j  = itr.next();
                                VsqEvent ve = copied.getEvent(j);
                                if (ve.Clock == start)
                                {
                                    foundStart = j;
                                }
                                if (ve.Clock == end)
                                {
                                    foundEnd = j;
                                }
                                if (end < ve.Clock)
                                {
                                    break;
                                }
                            }

                            VsqEvent dumyStart = (VsqEvent)dumy.clone();
                            dumyStart.Clock = start;
                            if (foundStart >= 0)
                            {
                                copied.setEvent(foundStart, dumyStart);
                            }
                            else
                            {
                                copied.addEvent(dumyStart);
                            }

                            if (end != int.MaxValue)
                            {
                                VsqEvent dumyEnd = (VsqEvent)singerAtEnd.clone();
                                dumyEnd.Clock = end;
                                if (foundEnd >= 0)
                                {
                                    copied.setEvent(foundEnd, dumyEnd);
                                }
                                else
                                {
                                    copied.addEvent(dumyEnd);
                                }
                            }

                            copied.sortEvent();
                        }

                        AppManager.mLastRenderedStatus[track - 1] = new RenderedStatus(copied, vsq.TempoTable, (SequenceConfig)vsq.config.clone());
                        AppManager.serializeRenderingStatus(temppath, track);
                    }

                    state.reportComplete();
                } catch (Exception ex) {
                    Logger.write(typeof(AppManager) + ".patchWorkToFreeze; ex=" + ex + "\n");
                    serr.println("AppManager#patchWorkToFreeze; ex=" + ex);
                } finally {
                    if (writer != null)
                    {
                        try {
                            writer.close();
                        } catch (Exception ex2) {
                            Logger.write(typeof(AppManager) + ".patchWorkToFreeze; ex=" + ex2 + "\n");
                            serr.println("AppManager#patchWorkToFreeze; ex2=" + ex2);
                        }
                    }
                }

                // 波形表示用のWaveDrawContextの内容を更新する。

                /*for ( int j = 0; j < queueIndex.size(); j++ ) {
                 *  int i = queueIndex.get( j );
                 *  if ( i >= finished ) {
                 *      continue;
                 *  }
                 *  double secStart = mVsq.getSecFromClock( queue.get( i ).clockStart );
                 *  int clockEnd = queue.get( i ).clockEnd;
                 *  if ( clockEnd == int.MaxValue ) {
                 *      clockEnd = mVsq.TotalClocks + 240;
                 *  }
                 *  double secEnd = mVsq.getSecFromClock( clockEnd );
                 *
                 *  invokeWaveViewReloadRequiredEvent( tracks.get( k ), wavePath, secStart, secEnd );
                 * }*/
                AppManager.invokeWaveViewReloadRequiredEvent(track, wavePath, 1, -1);
            }
#if DEBUG
            sout.println("SynthesizeWorker#patchWork; done");
#endif
            state.reportComplete();
        }
Example #29
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);
    }
Example #30
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;
    }
        /// <summary>
        /// 音符に付随するピッチベンドの情報を、PIT・PBS カーブに反映する
        /// </summary>
        /// <param name="item">音符</param>
        /// <param name="pitchBend">PIT カーブ</param>
        /// <param name="pitchBendSensitivity">PBS カーブ</param>
        /// <param name="tempoTable">テンポ情報</param>
        protected void reflectNoteEventPitch( VsqEvent item, VsqBPList pitchBend, VsqBPList pitchBendSensitivity, TempoVector tempoTable )
        {
            if ( item.ID.type != VsqIDType.Anote ) return;
            
            // AquesTone2 では、note on と同 clock にピッチベンドイベントを送らないと音程が反映されないので、必ずピッチイベントが送られるようにする
            pitchBend.add( item.Clock, pitchBend.getValue( item.Clock ) );

            if ( item.ID.VibratoHandle == null ) {
                return;
            }

            int startClock = item.Clock + item.ID.VibratoDelay;
            int vibratoLength = item.ID.Length - item.ID.VibratoDelay;

            var iterator = new VibratoPointIteratorByClock( tempoTable,
                                                            item.ID.VibratoHandle.RateBP, item.ID.VibratoHandle.StartRate,
                                                            item.ID.VibratoHandle.DepthBP, item.ID.VibratoHandle.StartDepth,
                                                            startClock, vibratoLength );
            var pitContext = new ByRef<int>( 0 );
            var pbsContext = new ByRef<int>( 0 );

            int pitAtEnd = pitchBend.getValue( startClock + vibratoLength );
            int pbsAtEnd = pitchBendSensitivity.getValue( startClock + vibratoLength );
            var pitBackup = (VsqBPList)pitchBend.Clone();
            var pbsBackup = (VsqBPList)pitchBendSensitivity.Clone();

            bool resetPBS = false;
            double maxNetPitchBendInCent = 0.0;
            for ( int clock = startClock; clock < startClock + vibratoLength && iterator.hasNext(); ++clock ) {
                double vibratoPitchBendInCent = iterator.next() * 100.0;
                int pit = pitchBend.getValue( clock, pitContext );
                int pbs = pitchBendSensitivity.getValue( clock, pbsContext );
                const double pow2_13 = 8192;
                double netPitchBendInCent = (pbs * pit / pow2_13) * 100.0 + vibratoPitchBendInCent;
                maxNetPitchBendInCent = Math.Max( maxNetPitchBendInCent, Math.Abs( netPitchBendInCent ) );
                int draftPitchBend = (int)Math.Round( (netPitchBendInCent / 100.0) * pow2_13 / pbs );

                if ( draftPitchBend < pitchBend.Minimum || pitchBend.Maximum < draftPitchBend ) {
                    // pbs を変更せずにビブラートによるピッチベンドを反映しようとすると、
                    // pit が範囲を超えてしまう。
                    resetPBS = true;
                } else {
                    if ( draftPitchBend != pit ) {
                        pitchBend.add( clock, draftPitchBend );
                    }
                }
            }

            if ( !resetPBS ) {
                return;
            }

            pitchBend.Data = pitBackup.Data;

            // ピッチベンドの最大値を実現するのに必要なPBS
            int requiredPitchbendSensitivity = (int)Math.Ceiling( maxNetPitchBendInCent / 100.0 );
            int pseudoMaxPitchbendSensitivity = 12; // AquesTone2 は最大 12 半音までベンドできる。
            if ( requiredPitchbendSensitivity < pitchBendSensitivity.Minimum ) requiredPitchbendSensitivity = pitchBendSensitivity.Minimum;
            if ( pseudoMaxPitchbendSensitivity < requiredPitchbendSensitivity ) requiredPitchbendSensitivity = pseudoMaxPitchbendSensitivity;

            {
                int i = 0;
                while ( i < pitchBend.size() ) {
                    var clock = pitchBend.getKeyClock( i );
                    if ( startClock <= clock && clock < startClock + vibratoLength ) {
                        pitchBend.removeElementAt( i );
                    } else {
                        ++i;
                    }
                }
            }
            {
                int i = 0;
                while ( i < pitchBendSensitivity.size() ) {
                    var clock = pitchBendSensitivity.getKeyClock( i );
                    if ( startClock <= clock && clock < startClock + vibratoLength ) {
                        pitchBendSensitivity.removeElementAt( i );
                    } else {
                        ++i;
                    }
                }
            }
            if ( pitchBendSensitivity.getValue( startClock ) != requiredPitchbendSensitivity ) {
                pitchBendSensitivity.add( startClock, requiredPitchbendSensitivity );
            }
            pitchBend.add( startClock + vibratoLength, pitAtEnd );
            pitchBendSensitivity.add( startClock + vibratoLength, pbsAtEnd );

            iterator.rewind();
            pitContext.value = 0;
            pbsContext.value = 0;
            int lastPitchBend = pitchBend.getValue( startClock );
            for ( int clock = startClock; clock < startClock + vibratoLength && iterator.hasNext(); ++clock ) {
                double vibratoPitchBendInCent = iterator.next() * 100.0;
                int pit = pitBackup.getValue( clock, pitContext );
                int pbs = pbsBackup.getValue( clock, pbsContext );

                const double pow2_13 = 8192;
                double netPitchBendInCent = (pbs * pit / pow2_13) * 100.0 + vibratoPitchBendInCent;
                maxNetPitchBendInCent = Math.Max( maxNetPitchBendInCent, Math.Abs( netPitchBendInCent ) );
                int draftPitchBend = (int)Math.Round((netPitchBendInCent / 100.0) * pow2_13 / requiredPitchbendSensitivity);
                if ( draftPitchBend < pitchBend.Minimum ) draftPitchBend = pitchBend.Minimum;
                if ( pitchBend.Maximum < draftPitchBend ) draftPitchBend = pitchBend.Maximum;
                if ( draftPitchBend != lastPitchBend ) {
                    pitchBend.add( clock, draftPitchBend );
                    lastPitchBend = draftPitchBend;
                }
            }
        }
Example #32
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;
    }
Example #33
0
        /// <summary>
        /// xml要素から音符イベントを生成する
        /// </summary>
        /// <param name="note">xml要素</param>
        /// <param name="tickOffset">指定したxml要素が所属しているmusicalPartの、オフセットtick数</param>
        /// <returns>生成した音符イベント</returns>
        private static VsqEvent createNoteEvent(XmlNode note, int tickOffset)
        {
            int      posTick = int.Parse(note["posTick"].InnerText);
            VsqEvent item    = new VsqEvent();

            item.Clock   = posTick + tickOffset;
            item.ID      = new VsqID();
            item.ID.type = VsqIDType.Anote;

            item.ID.LyricHandle = new LyricHandle();
            string     lyric            = note["lyric"].InnerText;
            XmlElement phnmsElement     = note["phnms"];
            string     symbols          = phnmsElement.InnerText;
            bool       symbolsProtected = false;

            if (phnmsElement.HasAttribute("lock"))
            {
                int value = int.Parse(phnmsElement.Attributes["lock"].Value);
                symbolsProtected = value == 1;
            }
            item.ID.LyricHandle.L0.PhoneticSymbolProtected = symbolsProtected;

            item.ID.LyricHandle.L0.Phrase = lyric;
            item.ID.LyricHandle.L0.setPhoneticSymbol(symbols);

            item.ID.Note = int.Parse(note["noteNum"].InnerText);
            item.ID.setLength(int.Parse(note["durTick"].InnerText));
            item.ID.Dynamics = int.Parse(note["velocity"].InnerText);

            var attributes = getNoteAttributes(note);

            if (attributes.ContainsKey("accent"))
            {
                item.ID.DEMaccent = attributes["accent"];
            }
            if (attributes.ContainsKey("bendDep"))
            {
                item.ID.PMBendDepth = attributes["bendDep"];
            }
            if (attributes.ContainsKey("bendLen"))
            {
                item.ID.PMBendLength = attributes["bendLen"];
            }
            if (attributes.ContainsKey("decay"))
            {
                item.ID.DEMdecGainRate = attributes["decay"];
            }
            if (attributes.ContainsKey("fallPort"))
            {
                item.ID.setFallPortamento(attributes["fallPort"] == 1);
            }
            if (attributes.ContainsKey("risePort"))
            {
                item.ID.setRisePortamento(attributes["risePort"] == 1);
            }

            // vibrato
            if (attributes.ContainsKey("vibLen") && attributes.ContainsKey("vibType"))
            {
                int lengthPercentage = attributes["vibLen"];
                int vibratoType      = attributes["vibType"] - 1;
                if (lengthPercentage > 0)
                {
                    var vibratoHandle = new VibratoHandle();
                    int length        = item.ID.getLength();
                    int duration      = (int)(length * (lengthPercentage / 100.0));
                    vibratoHandle.setLength(duration);
                    item.ID.VibratoDelay = length - duration;
                    vibratoHandle.IconID = "$0404" + vibratoType.ToString("X4");

                    double delayRatio = (double)(length - duration) / (double)length;
                    // VibDepth
                    vibratoHandle.setDepthBP(getVibratoCurve(note, "vibDep", delayRatio));
                    // VibRate
                    vibratoHandle.setRateBP(getVibratoCurve(note, "vibRate", delayRatio));

                    item.ID.VibratoHandle = vibratoHandle;
                }
            }
            return(item);
        }
        public void testReflectVibratoPitch()
        {
            var tempoTable           = new TempoVector();
            var pitchBend            = new VsqBPList(CurveType.PIT.getName(), CurveType.PIT.getDefault(), CurveType.PIT.getMinimum(), CurveType.PIT.getMaximum());
            var pitchBendSensitivity = new VsqBPList(CurveType.PIT.getName(), CurveType.PIT.getDefault(), CurveType.PIT.getMinimum(), CurveType.PIT.getMaximum());

            pitchBend.add(0, 8191);
            pitchBendSensitivity.add(0, 2);

            var generator = new AquesTone2WaveGeneratorStub();
            var item      = new VsqEvent(0, new VsqID());

            item.ID.type                    = VsqIDType.Anote;
            item.ID.VibratoHandle           = new VibratoHandle();
            item.ID.VibratoHandle.StartRate = 0x40;
            item.ID.VibratoHandle.RateBP.clear();
            item.ID.VibratoHandle.StartDepth = 0x40;
            item.ID.VibratoHandle.DepthBP.clear();
            item.ID.setLength(480);
            item.ID.VibratoDelay = 430;
            item.ID.VibratoHandle.setLength(50);
            generator.reflectVibratoPitch(item, pitchBend, pitchBendSensitivity, tempoTable);

            {
                var expectedPit = new Dictionary <int, int> {
                    { 0, 8191 },
                    { 430, 5461 }, { 431, 5467 }, { 432, 5484 }, { 433, 5514 }, { 434, 5555 },
                    { 435, 5608 }, { 436, 5672 }, { 437, 5748 }, { 438, 5835 }, { 439, 5932 },
                    { 440, 6041 }, { 441, 6096 }, { 442, 6151 }, { 443, 6205 }, { 444, 6257 },
                    { 445, 6309 }, { 446, 6360 }, { 447, 6410 }, { 448, 6459 }, { 449, 6507 },
                    { 450, 6553 }, { 451, 6598 }, { 452, 6642 }, { 453, 6684 }, { 454, 6725 },
                    { 455, 6764 }, { 456, 6802 }, { 457, 6838 }, { 458, 6873 }, { 459, 6906 },
                    { 460, 6937 }, { 461, 6967 }, { 462, 6994 }, { 463, 7020 }, { 464, 7044 },
                    { 465, 7066 }, { 466, 7087 }, { 467, 7105 }, { 468, 7121 }, { 469, 7136 },
                    { 470, 7148 }, { 471, 6989 }, { 472, 6826 }, { 473, 6660 }, { 474, 6491 },
                    { 475, 6320 }, { 476, 6149 }, { 477, 5976 }, { 478, 5804 }, { 479, 5632 },
                    { 480, 8191 }
                };
                Assert.AreEqual(expectedPit.Count, pitchBend.size());
                int i = 0;
                foreach (var pitInfo in expectedPit)
                {
                    Assert.AreEqual(pitInfo.Key, pitchBend.getKeyClock(i));
                    Assert.AreEqual(pitInfo.Value, pitchBend.getElementA(i));
                    ++i;
                }
            }

            {
                var expectedPbs = new Dictionary <int, int> {
                    { 0, 2 }, { 430, 3 }, { 480, 2 }
                };
                Assert.AreEqual(expectedPbs.Count, pitchBendSensitivity.size());
                int i = 0;
                foreach (var pbsInfo in expectedPbs)
                {
                    Assert.AreEqual(pbsInfo.Key, pitchBendSensitivity.getKeyClock(i));
                    Assert.AreEqual(pbsInfo.Value, pitchBendSensitivity.getElementA(i));
                    ++i;
                }
            }
        }
 public void reflectVibratoPitch( VsqEvent item, VsqBPList pitchBend, VsqBPList pitchBendSensitivity, TempoVector tempoTable )
 {
     base.reflectNoteEventPitch( item, pitchBend, pitchBendSensitivity, tempoTable );
 }
Example #36
0
        public bool edit(VsqTrack track, int[] event_internal_ids, MouseButtons button)
        {
            bool edited = false;

            try {
                int divide_threshold = Numerator * 480 * 4 / Denominator;
                Console.WriteLine("s_divide_threshold=" + divide_threshold);
                Keys modifier    = Control.ModifierKeys;
                bool middle_mode = button == MouseButtons.Middle;
                if (getModifier().Equals("Alt"))
                {
                    if ((modifier & Keys.Alt) == Keys.Alt)
                    {
                        middle_mode = true;
                    }
                }
                else if (getModifier().Equals("Control"))
                {
                    if ((modifier & Keys.Control) == Keys.Control)
                    {
                        middle_mode = true;
                    }
                }
                else if (getModifier().Equals("Shift"))
                {
                    if ((modifier & Keys.Shift) == Keys.Shift)
                    {
                        middle_mode = true;
                    }
                }
                Console.WriteLine("DivideNote#edit; (event_internal_ids==null)=" + (event_internal_ids == null));
                foreach (int id in event_internal_ids)
                {
                    Console.WriteLine("DivideNote#edit; (track==null)=" + (track == null));
                    foreach (var ve in track.getNoteEventIterator())
                    {
                        Console.WriteLine("DivideNote#edit; (ve==null)=" + (ve == null));
                        if (ve.InternalID == id)
                        {
                            Console.WriteLine("DivideNote#edit; (ve.ID==null)=" + (ve.ID == null));
                            if (ve.ID.Length >= divide_threshold * 2)
                            {
                                Console.WriteLine("before; clock=" + ve.Clock + "; length=" + ve.ID.Length);
                                VsqEvent      add    = (VsqEvent)ve.clone();
                                int           length = ve.ID.Length;
                                List <string> symbol = ve.ID.LyricHandle.L0.getPhoneticSymbolList();
                                for (int i = 0; i < symbol.Count; i++)
                                {
                                    Console.WriteLine("symbol[" + i + "]=" + symbol[i]);
                                }
                                ve.ID.Length  = divide_threshold;
                                add.Clock     = ve.Clock + divide_threshold;
                                add.ID.Length = length - divide_threshold;
                                if (add.ID.VibratoHandle != null)
                                {
                                    if (add.ID.VibratoDelay >= add.ID.Length)
                                    {
                                        add.ID.VibratoHandle = null;
                                    }
                                }
                                if (ve.ID.VibratoHandle != null)
                                {
                                    if (ve.ID.VibratoDelay >= ve.ID.Length)
                                    {
                                        ve.ID.VibratoHandle = null;
                                    }
                                }
                                if (symbol.Count >= 2)
                                {
                                    if (middle_mode && !VsqPhoneticSymbol.isConsonant(symbol[1]))
                                    {
                                        ve.ID.LyricHandle.L0.setPhoneticSymbol(symbol[0] + " " + symbol[1]);
                                    }
                                    else
                                    {
                                        ve.ID.LyricHandle.L0.setPhoneticSymbol(symbol[0]);
                                    }
                                    string symbol2 = "";
                                    for (int i = 1; i < symbol.Count; i++)
                                    {
                                        symbol2 += ((i == 1) ? "" : " ") + symbol[i];
                                    }
                                    Console.WriteLine("symbol2=" + symbol2);
                                    add.ID.LyricHandle.L0.setPhoneticSymbol(symbol2);
                                }
                                track.addEvent(add);
                                edited = true;
                            }
                            break;
                        }
                    }
                }
            } catch (Exception ex) {
                Console.WriteLine("DivideNote#edit; ex=" + ex);
            }
            return(edited);
        }
        /*private int round5(float X)
         * {
         *  return (int)(Math.Round(X / 5, 0) * 5);
         * }*/
        public void SplitIt()
        {
            dstVibstrBrustEvents.Clear();
            dstPitchBrust.Clear();
            dstParentTable.Clear();
            string PRO = oriEvent.ID.LyricHandle.L0.getPhoneticSymbol();

            if (PRO.IndexOf(',') > 0)
            {
                if (oriEvent.UstEvent.SplitLength > 0)
                {
                    int Len1      = 0;
                    int Len2      = 0;
                    int SplitTime = 0;
                    Len2 = (int)oriEvent.UstEvent.SplitLength;
                    Len1 = oriEvent.ID.getLength() - Len2;

                    /*if (oriEvent.UstEvent.SplitisPercent)
                     * {
                     *  Len2 = (int)(oriEvent.ID.getLength() * (oriEvent.UstEvent.SplitLength / 100.0));
                     *  Len1 = oriEvent.ID.getLength() - Len2;
                     * }
                     * else
                     * {
                     *  Len2 = (int)oriEvent.UstEvent.SplitLength;
                     *  Len1 = oriEvent.ID.getLength() - Len2;
                     * }
                     * if (Len1 <= 0)
                     * {
                     *  Len1 = oriEvent.ID.getLength() / 2;
                     *  Len2 = oriEvent.ID.getLength() - Len1;
                     * }*/

                    /*int PitchCountStartPoint=(int)Math.Round(oriEvent.Clock-oriEvent.UstEvent.getPreUtterance(),0);
                     * Len1 = Cell5(PitchCountStartPoint + Len1) - PitchCountStartPoint;
                     * Len2 = oriEvent.ID.getLength() - Len1;
                     * SplitTime=(Len1 + oriEvent.Clock);
                     */

                    OtoArgs oa = new OtoArgs();
                    if (vdb != null)
                    {
                        int CheckNote = oriEvent.ID.Note;
                        if (oriEvent.UstEvent != null)
                        {
                            CheckNote = oriEvent.UstEvent.ReplaceNoteID > 0 ? oriEvent.UstEvent.ReplaceNoteID : oriEvent.ID.Note;
                        }
                        oa = vdb.attachFileNameFromLyric(PRO.Split(',')[1], CheckNote);
                    }
                    if (oa.fileName == null ||
                        (oa.fileName != null && oa.fileName == ""))
                    {
                        oriEvent.ID.LyricHandle.L0.setPhoneticSymbol(PRO.Split(',')[0]);
                        //oriEvent.UstEvent.setVoiceOverlap(oriEvent.UstEvent.getVoiceOverlap() + preover);
                        dstVibstrBrustEvents.Add(oriEvent, oriVibstrBrustEvents);
                        dstPitchBrust.Add(oriEvent, oriPitchBrust);
                        dstParentTable.Add(oriEvent, oriEvent);
                        return;
                    }
                    int SplitLen = (int)oriEvent.UstEvent.SplitLength;
                    if (oriEvent.UstEvent.SplitisPercent)
                    {
                        SplitLen = (int)(oriEvent.ID.getLength() * SplitLen / 100.0);
                    }

                    float V2PreUttr   = oa.msPreUtterance + oriEvent.UstEvent.SplitSTP;
                    float V1PreUttr   = oriEvent.UstEvent.getPreUtterance() + oriEvent.UstEvent.getStartPoint();
                    int   RealV1Start = (int)mVsq.getClockFromSec(mVsq.getSecFromClock(oriEvent.Clock) - V1PreUttr / 1000.0);
                    int   RealV2Start = (int)mVsq.getClockFromSec(mVsq.getSecFromClock(oriEvent.Clock + Len1) - V2PreUttr / 1000.0);
                    int   R           = Cell5(RealV2Start - RealV1Start);
                    int   Dert        = (RealV2Start - RealV1Start) - R;
                    if (Dert > 3)
                    {
                        Len1 = Len1 + ((5 - Dert) > 0 ? (5 - Dert) : 0);
                    }
                    else
                    {
                        Len1 = Len1 - Dert;
                    }
                    Len2      = oriEvent.ID.getLength() - Len1;
                    SplitTime = (Len1 + oriEvent.Clock);
                    int CrossLen = (int)((oa.msOverlap) + oriEvent.UstEvent.SplitVoiceOverlap);


                    VsqEvent V1 = (VsqEvent)oriEvent.clone();
                    V1.ID.LyricHandle.L0.setPhoneticSymbol(PRO.Split(',')[0]);
                    V1.Clock = oriEvent.Clock;
                    V1.ID.setLength(Len1);
                    V1.UstEvent.setVoiceOverlap(V1.UstEvent.getVoiceOverlap() + V1.UstEvent.NotePreOverlap);
                    UstEnvelope env = oriEvent.UstEvent.getEnvelope();
                    if (env == null)
                    {
                        env = new UstEnvelope();
                    }
                    env.p3 = CrossLen;
                    env.p4 = 0;
                    env.v4 = 0;
                    V1.UstEvent.setEnvelope(env);

                    VsqEvent V2 = (VsqEvent)oriEvent.clone();
                    V2.ID.LyricHandle.L0.setPhoneticSymbol(PRO.Split(',')[1]);
                    V2.Clock = SplitTime;
                    V2.ID.setLength(Len2);
                    V2.UstEvent.setVoiceOverlap(CrossLen);
                    V2.UstEvent.setPreUtterance(oa.msPreUtterance);
                    V2.UstEvent.setStartPoint(V2.UstEvent.SplitSTP);
                    V2.UstEvent.LeftLimit = 0;
                    env = oriEvent.UstEvent.getEnvelope();
                    if (env == null)
                    {
                        env = new UstEnvelope();
                    }
                    env.p2 = CrossLen;
                    env.v2 = env.v2 - V1.UstEvent.MoreOver;
                    if (env.v2 < 0)
                    {
                        env.v2 = 0;
                    }
                    env.p1 = 0;
                    env.v1 = 0;
                    if (env.p5 > 0)
                    {
                        env.p5 = env.p5 - Len1;
                    }
                    V2.UstEvent.setEnvelope(env);


                    dstVibstrBrustEvents.Add(V1, oriVibstrBrustEvents);
                    dstPitchBrust.Add(V1, oriPitchBrust);
                    dstParentTable.Add(V1, oriEvent);
                    dstVibstrBrustEvents.Add(V2, oriVibstrBrustEvents);
                    dstPitchBrust.Add(V2, oriPitchBrust);
                    dstParentTable.Add(V2, oriEvent);
                }
                else
                {
                    if (oriEvent.ID.LyricHandle.L0.getPhoneticSymbol().IndexOf(",") > 0)
                    {
                        oriEvent.ID.LyricHandle.L0.setPhoneticSymbol(PRO.Split(',')[0]);
                    }
                    dstVibstrBrustEvents.Add(oriEvent, oriVibstrBrustEvents);
                    oriEvent.UstEvent.setVoiceOverlap(oriEvent.UstEvent.getVoiceOverlap() + oriEvent.UstEvent.NotePreOverlap);
                    dstPitchBrust.Add(oriEvent, oriPitchBrust);
                    dstParentTable.Add(oriEvent, oriEvent);
                }
            }
            else
            {
                dstVibstrBrustEvents.Add(oriEvent, oriVibstrBrustEvents);
                oriEvent.UstEvent.setVoiceOverlap(oriEvent.UstEvent.getVoiceOverlap() + oriEvent.UstEvent.NotePreOverlap);
                dstPitchBrust.Add(oriEvent, oriPitchBrust);
                dstParentTable.Add(oriEvent, oriEvent);
            }
        }