/// <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 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
            }
        }
Exemplo n.º 3
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);
    }
Exemplo n.º 4
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;
    }
Exemplo n.º 5
0
        /*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);
            }
        }
Exemplo n.º 6
0
        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();
        }
Exemplo n.º 7
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));
                    for (Iterator <VsqEvent> itr = track.getNoteEventIterator(); itr.hasNext();)
                    {
                        VsqEvent ve = itr.next();
                        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);
        }