示例#1
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);
        }
示例#2
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);
    }
示例#3
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;
 }
示例#4
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 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();
        }