예제 #1
0
 public SingerEventComparisonContext(VsqTrack track1, VsqTrack track2)
 {
     this.track1 = track1;
     this.track2 = track2;
     it1         = this.track1.indexIterator(IndexIteratorKind.SINGER);
     it2         = this.track2.indexIterator(IndexIteratorKind.SINGER);
 }
 /// <summary>
 /// 音符の note on/off のためのイベントを作成し、イベントキューに追加する
 /// </summary>
 /// <param name="track">生成元のトラック</param>
 /// <param name="result">生成したイベントの追加先</param>
 private void appendNoteEvent(VsqTrack track, EventQueueSequence result)
 {
     foreach (var item in track.MetaText.Events.Events)
     {
         if (item.ID.type != VsqIDType.Anote)
         {
             continue;
         }
         var note = item.ID.Note;
         {
             var clock  = item.Clock;
             var queue  = result.get(clock);
             var noteOn = driver_.createNoteOnEvent(item.ID.Note,
                                                    item.ID.Dynamics,
                                                    item.ID.LyricHandle.L0.Phrase);
             queue.noteon.AddRange(noteOn);
         }
         {
             var clock   = item.Clock + item.ID.Length;
             var queue   = result.get(clock);
             var noteOff = createNoteOffEvent(clock, item.ID.Note);
             queue.noteoff.add(noteOff);
         }
     }
 }
예제 #3
0
 /// <summary>
 /// パレットツールを実行します
 /// </summary>
 /// <param name="id">実行するパレットツールのID</param>
 /// <param name="track">編集対象のトラック番号</param>
 /// <param name="vsq_event_intrenal_ids">編集対象のInternalIDのリスト</param>
 /// <param name="button">パレットツールが押し下げられた時のマウスボタンの種類</param>
 /// <returns>パレットツールによって編集が加えられた場合true。そうでなければfalse(パレットツールがエラーを起こした場合も含む)。</returns>
 public static boolean invokePaletteTool( String id, int track, int[] vsq_event_intrenal_ids, MouseButtons button ) {
     if ( loadedTools.containsKey( id ) ) {
         VsqFileEx vsq = AppManager.getVsqFile();
         VsqTrack item = (VsqTrack)vsq.Track.get( track ).clone();
         Object objPal = loadedTools.get( id );
         if ( objPal == null ) {
             return false;
         }
         if ( !(objPal is IPaletteTool) ) {
             return false;
         }
         IPaletteTool pal = (IPaletteTool)objPal;
         boolean edited = false;
         try {
             edited = pal.edit( item, vsq_event_intrenal_ids, button );
         } catch ( Exception ex ) {
             AppManager.showMessageBox(
                 PortUtil.formatMessage( _( "Palette tool '{0}' reported an error.\nPlease copy the exception text and report it to developper." ), id ),
                 "Error",
                 cadencii.windows.forms.Utility.MSGBOX_DEFAULT_OPTION,
                 cadencii.windows.forms.Utility.MSGBOX_ERROR_MESSAGE );
             serr.println( typeof( PaletteToolServer ) + ".invokePaletteTool; ex=" + ex );
             edited = false;
         }
         if ( edited ) {
             CadenciiCommand run = VsqFileEx.generateCommandTrackReplace( track, item, vsq.AttachedCurves.get( track - 1 ) );
             AppManager.editHistory.register( vsq.executeCommand( run ) );
         }
         return edited;
     } else {
         return false;
     }
 }
        /// <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--;
                }
            }
        }
예제 #5
0
    public static bool edit(VsqFile vsq)
    {
        ResoXAmp form = new ResoXAmp();

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

        Console.WriteLine("AmplifyCoeffReso2=" + AmplifyCoeffReso2);
        Console.WriteLine("AmplifyCoeffReso3=" + AmplifyCoeffReso3);
        Console.WriteLine("AmplifyCoeffReso4=" + AmplifyCoeffReso4);
        amplify(source, reso2amp, AmplifyCoeffReso2);
        amplify(source, reso3amp, AmplifyCoeffReso3);
        amplify(source, reso4amp, AmplifyCoeffReso4);
        track.setCurve(CurveType.reso2amp.getName(), reso2amp);
        track.setCurve(CurveType.reso3amp.getName(), reso3amp);
        track.setCurve(CurveType.reso4amp.getName(), reso4amp);
        Console.WriteLine("reso2amp.getCount()=" + reso2amp.size());
        Console.WriteLine("reso3amp.getCount()=" + reso3amp.size());
        Console.WriteLine("reso4amp.getCount()=" + reso4amp.size());
        MessageBox.Show("done");
        return(true);
    }
예제 #6
0
    private static void hamori(VsqFile vsq, int basecode, int opt)
    {
        int[][] steps = new int[][] {
            // C Major    C     D     E  F     G     A     B
            // 7度上
            new int[] { 11, 11, 10, 10, 10, 11, 11, 10, 10, 10, 10, 10 },
            // 6度上
            new int[] { 9, 9, 9, 9, 8, 9, 9, 9, 9, 8, 8, 9 },
            // 5度上
            new int[] { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6 },
            // 4度上
            new int[] { 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5 },
            // 3度上
            new int[] { 4, 4, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3 },
            // 2度上
            new int[] { 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 }
        };
        int[] step;
        if (opt == 6)
        {
            return;
        }
        if (opt < 6)
        {
            step = steps[opt];
        }
        else
        {
            step = steps[opt - 7];
            for (int i = 0; i < 12; i++)
            {
                step[i] -= 12;
            }
        }

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

        for (Iterator <SelectedEventEntry> itr = AppManager.getSelectedEventIterator(); itr.hasNext();)
        {
            VsqEvent item = track.findEventFromID(((SelectedEventEntry)itr.next()).original.InternalID);
            if (item.ID.type == VsqIDType.Anote)
            {
                tmp  = (item.ID.Note + 12 - basecode) % 12;
                note = item.ID.Note + step[tmp];
                if (note < 0)
                {
                    note = 0;
                }
                if (127 < note)
                {
                    note = 127;
                }
                item.ID.Note = note;
            }
        }
    }
예제 #7
0
 /// <summary>
 /// コンストラクタ。trackはcloneされないが、tempoはcloneされる。
 /// </summary>
 /// <param name="track"></param>
 /// <param name="tempo"></param>
 public RenderedStatus(VsqTrack track, TempoVector tempo, SequenceConfig config)
 {
     this.track = track;
     this.tempo = new TempoVector();
     foreach (var entry in tempo)
     {
         this.tempo.Add((TempoTableEntry)entry.clone());
     }
     this.config = config;
 }
예제 #8
0
        private XmlElement createTrackNode(VsqTrack track, int index, int pre_measure_clock, int sequence_length)
        {
            var result = doc_.CreateElement("vsTrack");

            result.AppendChild(createNode("vsTrackNo", index));
            result.AppendChild(createNode("trackName", track.getName()));
            result.AppendChild(createNode("comment", ""));
            result.AppendChild(createMusicalPartNode(track, pre_measure_clock, sequence_length));
            return(result);
        }
        /// <summary>
        /// ピッチとピッチベンドセンシティビティをイベントキューに追加する
        /// </summary>
        /// <param name="track"></param>
        /// <param name="sequence"></param>
        private void appendPitchEvent(VsqTrack track, EventQueueSequence sequence)
        {
            // 実際に AquesTone2 に送信する pbs の値と、pbs カーブに入っている値とのマップ
            const int maxPitchBendSensitivity = 23;

            int[] map = new int[maxPitchBendSensitivity + 1] {
                0, 5, 15, 35, 44, 54, 64, 74, 84, 93, 103, 113,
                127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
            };
            var pbs = track.MetaText.PBS;

            for (int i = 0; i < pbs.size(); ++i)
            {
                var clock = pbs.getKeyClock(i);
                {
                    // RPN MSB = 0x00
                    var e = new MidiEvent();
                    e.firstByte = 0xB0;
                    e.data      = new int[] { 0x65, 0x00 };
                    e.clock     = clock;
                    sequence.get(clock).pit.add(e);
                }
                {
                    // RPN LSB = 0x00
                    var e = new MidiEvent();
                    e.firstByte = 0xB0;
                    e.data      = new int[] { 0x64, 0x00 };
                    e.clock     = clock;
                    sequence.get(clock).pit.add(e);
                }
                {
                    // RPN data MSB
                    var e = new MidiEvent();
                    e.firstByte = 0xB0;
                    int value = Math.Max(0, Math.Min(maxPitchBendSensitivity, pbs.getElementA(i)));
                    e.data  = new int[] { 0x06, map[value] };
                    e.clock = clock;
                    sequence.get(clock).pit.add(e);
                }
            }

            var pit = track.MetaText.PIT;

            for (int i = 0; i < pit.size(); ++i)
            {
                var clock = pit.getKeyClock(i);
                var e     = new MidiEvent();
                e.firstByte = 0xE0;
                var value = pit.getElementA(i) + 8192;
                var msb   = 0x7F & value;
                var lsb   = 0x7F & (value >> 7);
                e.data = new int[] { msb, lsb };
                sequence.get(clock).pit.add(e);
            }
        }
예제 #10
0
        private List <TiedEvent> quantizeTrack(VsqTrack track, TimesigVector timesig_table, TempoVector tempo_table)
        {
            var result = new List <TiedEvent>();

            if (track.MetaText == null)
            {
                return(result);
            }

            track.MetaText.Events.Events
            .AsParallel()
            .ForAll((item) => {
                if (item.ID != null)
                {
                    var start_clock = quantize(item.Clock);
                    var end_clock   = quantize(item.Clock + item.ID.getLength());
                    item.Clock      = start_clock;
                    item.ID.setLength(end_clock - start_clock);
                }
            });

            track.MetaText.Events.Events
            .RemoveAll((item) => {
                if (item.ID == null)
                {
                    return(false);
                }
                return(item.ID.getLength() <= 0);
            });

            int count = track.MetaText.Events.Events.Count;
            int clock = 0;

            for (int i = 0; i < count; ++i)
            {
                var item = track.MetaText.Events.Events[i];
                if (item.ID.type == VsqIDType.Anote)
                {
                    int rest_length = item.Clock - clock;
                    if (rest_length > 0)
                    {
                        result.Add(new TiedEvent(clock, rest_length, timesig_table, tempo_table));
                    }
                    result.Add(new TiedEvent(item, timesig_table, tempo_table));
                    clock = item.Clock + item.ID.getLength();
                }
            }
            return(result);
        }
예제 #11
0
    /// <summary>
    /// スクリプトの本体
    /// </summary>
    /// <param name="vsq"></param>
    /// <returns></returns>
    public static ScriptReturnStatus Edit(VsqFileEx vsq)
    {
        int          selected  = AppManager.getSelected();
        VsqTrack     vsq_track = vsq.Track[selected];
        RendererKind kind      = VsqFileEx.getTrackRendererKind(vsq_track);

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

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

        return(edited ? ScriptReturnStatus.EDITED : ScriptReturnStatus.NOT_EDITED);
    }
        /// <summary>
        /// 歌手変更イベントを、イベントキューに追加する
        /// </summary>
        /// <param name="queueSequence">追加対象のイベントキュー</param>
        /// <param name="track">歌手変更イベントを取り出すトラック</param>
        /// <param name="start">時間区間の開始位置</param>
        /// <param name="end">時間区間の終了位置</param>
        private void addSingerEvents(EventQueueSequence queueSequence, VsqTrack track, int start, int end)
        {
            var iterator = track.getSingerEventIterator(start, end);

            while (iterator.hasNext())
            {
                var item = iterator.next();
                if (item.ID.IconHandle == null)
                {
                    continue;
                }
                int program = item.ID.IconHandle.Program;
                var singer  = mDriver.createSingerEvent(program);
                if (0 < singer.Length)
                {
                    var queue = queueSequence.get(item.Clock);
                    queue.param.addAll(Arrays.asList(singer));
                }
            }
        }
예제 #13
0
        private XmlElement createMusicalPartNode(VsqTrack track, int pre_measure_clock, int sequence_length)
        {
            var result = doc_.CreateElement("musicalPart");

            result.AppendChild(createNode("posTick", pre_measure_clock));
            result.AppendChild(createNode("playTime", sequence_length - pre_measure_clock));
            result.AppendChild(createNode("partName", track.getName()));
            result.AppendChild(createNode("comment", ""));
            {
                var stylePlugin = doc_.CreateElement("stylePlugin");
                stylePlugin.AppendChild(createNode("stylePluginID", "ACA9C502-A04B-42b5-B2EB-5CEA36D16FCE"));
                stylePlugin.AppendChild(createNode("stylePluginName", "VOCALOID2 Compatible Style"));
                stylePlugin.AppendChild(createNode("version", "3.0.0.1"));
                result.AppendChild(stylePlugin);
            }
            {
                result.AppendChild(createPartStyleNode());
            }

            // Set first singer
            var first_singer = (VsqEvent)track.getSingerEventAt(pre_measure_clock).Clone();

            first_singer.Clock = pre_measure_clock;
            result.AppendChild(createMusicalPartSingerNode(first_singer, pre_measure_clock));

            track.MetaText.Events.Events
            .Where((@event) => (@event.ID.type == VsqIDType.Singer ? @event.Clock > pre_measure_clock : @event.Clock >= pre_measure_clock))
            .ToList()
            .ForEach((@event) => {
                if (@event.ID.type == VsqIDType.Singer)
                {
                    var node = createMusicalPartSingerNode(@event, pre_measure_clock);
                    result.AppendChild(node);
                }
                else if (@event.ID.type == VsqIDType.Anote)
                {
                    result.AppendChild(createNoteNode(@event, pre_measure_clock));
                }
            });
            return(result);
        }
예제 #14
0
        public static string FlagGener(VsqTrack track, VsqEvent item)
        {
            string SpecialI = item.UstEvent.Flags;
            int    g        = (track.MetaText.GEN.getValue(item.Clock + (item.ID.getLength() > 10 ? 10 : (item.ID.getLength() / 2))) - 64);
            int    b        = (track.MetaText.BRE.getValue(item.Clock + (item.ID.getLength() > 10 ? 10 : (item.ID.getLength() / 2))) - 64);

            if (SpecialI.IndexOf("g") < 0)
            {
                if (g != 0)
                {
                    SpecialI = SpecialI + "g" + g.ToString();
                }
            }
            if (SpecialI.IndexOf("BRE") < 0)
            {
                if (b != 0)
                {
                    SpecialI = SpecialI + "BRE" + b.ToString();
                }
            }
            return(SpecialI);// SpecialI.Replace("p", "popop") + " p0";
        }
예제 #15
0
    private static void transpose(VsqFile vsq, int step)
    {
        int      note;
        VsqTrack track = vsq.Track[AppManager.Selected];

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

            result.AppendChild(createNode("seqName", master_track.getName()));
            result.AppendChild(createNode("comment", ""));
            result.AppendChild(createNode("resolution", sequence.getTickPerQuarter()));
            result.AppendChild(createNode("preMeasure", sequence.getPreMeasure()));
            sequence.TimesigTable.ForEach((time_sig) => {
                var node = doc_.CreateElement("timeSig");
                node.AppendChild(createNode("posMes", time_sig.BarCount));
                node.AppendChild(createNode("nume", time_sig.Numerator));
                node.AppendChild(createNode("denomi", time_sig.Denominator));
                result.AppendChild(node);
            });
            sequence.TempoTable.ForEach((tempo) => {
                var node = doc_.CreateElement("tempo");
                node.AppendChild(createNode("posTick", tempo.Clock));
                node.AppendChild(createNode("bpm", (int)(60e6 / tempo.Tempo * 100)));
                result.AppendChild(node);
            });
            return(result);
        }
예제 #17
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);
    }
예제 #18
0
        /// <summary>
        /// vsqxファイルを読み込み,新しいシーケンスオブジェクトを生成する
        /// </summary>
        /// <param name="filePath">ファイルパス</param>
        /// <exception cref="System.Exception">読み込みに失敗した時スローされる</exception>
        /// <returns>生成したシーケンスオブジェクト</returns>
        public static VsqFile readFromVsqx(string filePath)
        {
            if (filePath == null)
            {
                throw new ArgumentNullException("filePath");
            }

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

            var xml = new XmlDocument();

            xml.Load(filePath);

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

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

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

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

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

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

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

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

            return(result);
        }
예제 #19
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);
                }
            }
        }
예제 #20
0
        private void applyValue(bool mode_clock)
        {
            if (!m_changed)
            {
                return;
            }
            int value = m_curve.getDefault();

            try {
                value = int.Parse(txtDataPointValue.Text);
            } catch (Exception ex) {
                Logger.write(typeof(FormCurvePointEdit) + ".applyValue; ex=" + ex + "\n");
                return;
            }
            if (value < m_curve.getMinimum())
            {
                value = m_curve.getMinimum();
            }
            else if (m_curve.getMaximum() < value)
            {
                value = m_curve.getMaximum();
            }

            int clock = 0;

            try {
                clock = int.Parse(txtDataPointClock.Text);
            } catch (Exception ex) {
                Logger.write(typeof(FormCurvePointEdit) + ".applyValue; ex=" + ex + "\n");
                return;
            }

            int       selected  = AppManager.getSelected();
            VsqTrack  vsq_track = AppManager.getVsqFile().Track[selected];
            VsqBPList src       = vsq_track.getCurve(m_curve.getName());
            VsqBPList list      = (VsqBPList)src.clone();

            VsqBPPairSearchContext context = list.findElement(m_editing_id);

            list.move(context.clock, clock, value);
            CadenciiCommand run = new CadenciiCommand(VsqCommand.generateCommandTrackCurveReplace(selected,
                                                                                                  m_curve.getName(),
                                                                                                  list));
            EditedZone zone = new EditedZone();

            Utility.compareList(zone, new VsqBPListComparisonContext(list, src));
            List <EditedZoneUnit> zoneUnits = new List <EditedZoneUnit>();

            foreach (var item in zone.iterator())
            {
                zoneUnits.Add(item);
            }
            AppManager.editHistory.register(AppManager.getVsqFile().executeCommand(run));

            txtDataPointClock.Text = clock + "";
            txtDataPointValue.Text = value + "";

            if (mMainWindow != null)
            {
                mMainWindow.setEdited(true);
                mMainWindow.ensureVisible(clock);
                mMainWindow.refreshScreen();
            }

            if (mode_clock)
            {
                txtDataPointClock.SelectAll();
            }
            else
            {
                txtDataPointValue.SelectAll();
            }

            btnUndo.Enabled = AppManager.editHistory.hasUndoHistory();
            btnRedo.Enabled = AppManager.editHistory.hasRedoHistory();
            m_changed       = false;
        }
예제 #21
0
 /// <summary>
 /// 音符の note on/off のためのイベントを作成し、イベントキューに追加する
 /// </summary>
 /// <param name="track">生成元のトラック</param>
 /// <param name="result">生成したイベントの追加先</param>
 private void appendNoteEvent( VsqTrack track, EventQueueSequence result )
 {
     foreach ( var item in track.MetaText.Events.Events ) {
         if ( item.ID.type != VsqIDType.Anote ) continue;
         var note = item.ID.Note;
         {
             var clock = item.Clock;
             var queue = result.get( clock );
             var noteOn = driver_.createNoteOnEvent( item.ID.Note,
                                                     item.ID.Dynamics,
                                                     item.ID.LyricHandle.L0.Phrase );
             queue.noteon.AddRange( noteOn );
         }
         {
             var clock = item.Clock + item.ID.Length;
             var queue = result.get( clock );
             var noteOff = createNoteOffEvent( clock, item.ID.Note );
             queue.noteoff.add( noteOff );
         }
     }
 }
예제 #22
0
        public void readFromVsqx()
        {
            VsqFile vsq = VsqxReader.readFromVsqx("./fixture/track1.vsqx");

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

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

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

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

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

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

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

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

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

            Assert.Null(firstEvent.ID.IconDynamicsHandle);

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

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

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

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

            Assert.Null(firstEvent.ID.IconHandle);

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

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

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

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

            Assert.Null(secondEvent.ID.IconHandle);

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

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

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

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

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

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

            Assert.Null(thirdEvent.ID.IconHandle);

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

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

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

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

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

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

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

            // BRI

            // CLE

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

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

            // GEN

            // POR

            // PIT

            // PBS

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

            Assert.AreEqual(1, vsq.Mixer.Slave.size());
            Assert.AreEqual(1, vsq.Mixer.Slave.get(0).Solo);
            Assert.AreEqual(0, vsq.Mixer.Slave.get(0).Mute);
            Assert.AreEqual(64, vsq.Mixer.Slave.get(0).Panpot);
            Assert.AreEqual(1, vsq.Mixer.Slave.get(0).Feder);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="vsq"></param>
        /// <param name="track"></param>
        /// <param name="clock_start"></param>
        /// <param name="clock_end"></param>
        /// <returns></returns>
        protected override EventQueueSequence generateMidiEvent(VsqFileEx vsq, int track, int clock_start, int clock_end)
        {
            EventQueueSequence list = new EventQueueSequence();
            VsqTrack           t    = vsq.Track.get(track);

            addSingerEvents(list, t, clock_start, clock_end);

            // ノートon, off
            Vector <Point> pit_send = new Vector <Point>(); // PITが追加されたゲートタイム。音符先頭の分を重複して送信するのを回避するために必要。
            VsqBPList      pit      = t.getCurve("pit");
            VsqBPList      pbs      = t.getCurve("pbs");
            VsqBPList      dyn      = t.getCurve("dyn");
            VsqBPList      bre      = t.getCurve("bre");
            VsqBPList      cle      = t.getCurve("cle");
            VsqBPList      por      = t.getCurve("por");

            for (Iterator <VsqEvent> itr = t.getNoteEventIterator(); itr.hasNext();)
            {
                VsqEvent item           = itr.next();
                int      endclock       = item.Clock + item.ID.getLength();
                boolean  contains_start = clock_start <= item.Clock && item.Clock <= clock_end;
                boolean  contains_end   = clock_start <= endclock && endclock <= clock_end;
                if (contains_start || contains_end)
                {
                    if (contains_start)
                    {
                        #region contains_start
                        // noteonのゲートタイムが,範囲に入っている
                        // noteon MIDIイベントを作成

                        MidiEvent[] noteOnEvents = mDriver.createNoteOnEvent(item.ID.Note, item.ID.Dynamics, item.ID.LyricHandle.L0.Phrase);
                        if (noteOnEvents.Length > 0)
                        {
                            MidiEventQueue queue = list.get(item.Clock);

                            Vector <MidiEvent> add = Arrays.asList(noteOnEvents);
                            queue.noteon.addAll(add);
                            pit_send.add(new Point(item.Clock, item.Clock));
                        }

                        /* 音符頭で設定するパラメータ */
                        // Release
                        MidiEventQueue q = list.get(item.Clock);

                        String strRelease = VsqFileEx.getEventTag(item, VsqFileEx.TAG_VSQEVENT_AQUESTONE_RELEASE);
                        int    release    = 64;
                        try {
                            release = int.Parse(strRelease);
                        } catch (Exception ex) {
                            Logger.write(typeof(AquesToneWaveGenerator) + ".generateMidiEvent; ex=" + ex + "\n");
                            release = 64;
                        }
                        ParameterEvent pe = new ParameterEvent();
                        pe.index = mDriver.releaseParameterIndex;
                        pe.value = release / 127.0f;
                        q.param.add(pe);

                        // dyn
                        int            dynAtStart = dyn.getValue(item.Clock);
                        ParameterEvent peDyn      = new ParameterEvent();
                        peDyn.index = mDriver.volumeParameterIndex;
                        peDyn.value = (float)(dynAtStart - dyn.getMinimum()) / (float)(dyn.getMaximum() - dyn.getMinimum());
                        q.param.add(peDyn);

                        // bre
                        int            breAtStart = bre.getValue(item.Clock);
                        ParameterEvent peBre      = new ParameterEvent();
                        peBre.index = mDriver.haskyParameterIndex;
                        peBre.value = (float)(breAtStart - bre.getMinimum()) / (float)(bre.getMaximum() - bre.getMinimum());
                        q.param.add(peBre);

                        // cle
                        int            cleAtStart = cle.getValue(item.Clock);
                        ParameterEvent peCle      = new ParameterEvent();
                        peCle.index = mDriver.resonancParameterIndex;
                        peCle.value = (float)(cleAtStart - cle.getMinimum()) / (float)(cle.getMaximum() - cle.getMinimum());
                        q.param.add(peCle);

                        // por
                        int            porAtStart = por.getValue(item.Clock);
                        ParameterEvent pePor      = new ParameterEvent();
                        pePor.index = mDriver.portaTimeParameterIndex;
                        pePor.value = (float)(porAtStart - por.getMinimum()) / (float)(por.getMaximum() - por.getMinimum());
                        q.param.add(pePor);
                        #endregion
                    }

                    // ビブラート
                    // ビブラートが存在する場合、PBSは勝手に変更する。
                    if (item.ID.VibratoHandle == null)
                    {
                        if (contains_start)
                        {
                            // 音符頭のPIT, PBSを強制的に指定
                            int            notehead_pit = pit.getValue(item.Clock);
                            MidiEvent      pit0         = getPitMidiEvent(notehead_pit);
                            MidiEventQueue queue        = list.get(item.Clock);
                            queue.pit.clear();
                            queue.pit.add(pit0);
                            int            notehead_pbs = pbs.getValue(item.Clock);
                            ParameterEvent pe           = new ParameterEvent();
                            pe.index = mDriver.bendLblParameterIndex;
                            pe.value = notehead_pbs / 13.0f;
                            queue.param.add(pe);
                        }
                    }
                    else
                    {
                        int    delta_clock   = 5; //ピッチを取得するクロック間隔
                        int    tempo         = 120;
                        double sec_start_act = vsq.getSecFromClock(item.Clock);
                        double sec_end_act   = vsq.getSecFromClock(item.Clock + item.ID.getLength());
                        double delta_sec     = delta_clock / (8.0 * tempo); //ピッチを取得する時間間隔
                        float  pitmax        = 0.0f;
                        int    st            = item.Clock;
                        if (st < clock_start)
                        {
                            st = clock_start;
                        }
                        int end = item.Clock + item.ID.getLength();
                        if (clock_end < end)
                        {
                            end = clock_end;
                        }
                        pit_send.add(new Point(st, end));
                        // ビブラートが始まるまでのピッチを取得
                        double sec_vibstart = vsq.getSecFromClock(item.Clock + item.ID.VibratoDelay);
                        int    pit_count    = (int)((sec_vibstart - sec_start_act) / delta_sec);
                        TreeMap <Integer, Float> pit_change = new TreeMap <Integer, Float>();
                        for (int i = 0; i < pit_count; i++)
                        {
                            double gtime  = sec_start_act + delta_sec * i;
                            int    clock  = (int)vsq.getClockFromSec(gtime);
                            float  pvalue = (float)t.getPitchAt(clock);
                            pitmax = Math.Max(pitmax, Math.Abs(pvalue));
                            pit_change.put(clock, pvalue);
                        }
                        // ビブラート部分のピッチを取得
                        Vector <PointD>   ret  = new Vector <PointD>();
                        Iterator <PointD> itr2 = new VibratoPointIteratorBySec(
                            vsq,
                            item.ID.VibratoHandle.getRateBP(),
                            item.ID.VibratoHandle.getStartRate(),
                            item.ID.VibratoHandle.getDepthBP(),
                            item.ID.VibratoHandle.getStartDepth(),
                            item.Clock + item.ID.VibratoDelay,
                            item.ID.getLength() - item.ID.VibratoDelay,
                            (float)delta_sec);
                        for ( ; itr2.hasNext();)
                        {
                            PointD p      = itr2.next();
                            float  gtime  = (float)p.getX();
                            int    clock  = (int)vsq.getClockFromSec(gtime);
                            float  pvalue = (float)(t.getPitchAt(clock) + p.getY() * 100.0);
                            pitmax = Math.Max(pitmax, Math.Abs(pvalue));
                            pit_change.put(clock, pvalue);
                        }

                        // ピッチベンドの最大値を実現するのに必要なPBS
                        int required_pbs = (int)Math.Ceiling(pitmax / 100.0);
#if DEBUG
                        sout.println("AquesToneRenderingRunner#generateMidiEvent; required_pbs=" + required_pbs);
#endif
                        if (required_pbs > 13)
                        {
                            required_pbs = 13;
                        }
                        MidiEventQueue queue = list.get(item.Clock);
                        ParameterEvent pe    = new ParameterEvent();
                        pe.index = mDriver.bendLblParameterIndex;
                        pe.value = required_pbs / 13.0f;
                        queue.param.add(pe);

                        // PITを順次追加
                        for (Iterator <Integer> itr3 = pit_change.keySet().iterator(); itr3.hasNext();)
                        {
                            Integer clock = itr3.next();
                            if (clock_start <= clock && clock <= clock_end)
                            {
                                float          pvalue    = pit_change.get(clock);
                                int            pit_value = (int)(8192.0 / (double)required_pbs * pvalue / 100.0);
                                MidiEventQueue q         = list.get(clock);
                                MidiEvent      me        = getPitMidiEvent(pit_value);
                                q.pit.clear();
                                q.pit.add(me);
                            }
                            else if (clock_end < clock)
                            {
                                break;
                            }
                        }
                    }

                    //pit_send.add( pit_send_p );

                    // noteoff MIDIイベントを作成
                    if (contains_end)
                    {
                        MidiEvent noteoff = new MidiEvent();
                        noteoff.firstByte = 0x80;
                        noteoff.data      = new int[] { item.ID.Note, 0x40 }; // ここのvel
                        Vector <MidiEvent> a_noteoff = Arrays.asList(new MidiEvent[] { noteoff });
                        MidiEventQueue     q         = list.get(endclock);
                        q.noteoff.addAll(a_noteoff);
                        pit_send.add(new Point(endclock, endclock));     // PITの送信を抑制するために必要
                    }
                }

                if (clock_end < item.Clock)
                {
                    break;
                }
            }

            // pitch bend sensitivity
            // RPNで送信するのが上手くいかないので、parameterを直接いぢる
            if (pbs != null)
            {
                int keycount = pbs.size();
                for (int i = 0; i < keycount; i++)
                {
                    int clock = pbs.getKeyClock(i);
                    if (clock_start <= clock && clock <= clock_end)
                    {
                        int            value = pbs.getElementA(i);
                        ParameterEvent pbse  = new ParameterEvent();
                        pbse.index = mDriver.bendLblParameterIndex;
                        pbse.value = value / 13.0f;
                        MidiEventQueue queue = list.get(clock);
                        queue.param.add(pbse);
                    }
                    else if (clock_end < clock)
                    {
                        break;
                    }
                }
            }

            // pitch bend
            if (pit != null)
            {
                int keycount = pit.size();
                for (int i = 0; i < keycount; i++)
                {
                    int clock = pit.getKeyClock(i);
                    if (clock_start <= clock && clock <= clock_end)
                    {
                        boolean contains = false;
                        for (Iterator <Point> itr = pit_send.iterator(); itr.hasNext();)
                        {
                            Point p = itr.next();
                            if (p.x <= clock && clock <= p.y)
                            {
                                contains = true;
                                break;
                            }
                        }
                        if (contains)
                        {
                            continue;
                        }
                        int            value = pit.getElementA(i);
                        MidiEvent      pbs0  = getPitMidiEvent(value);
                        MidiEventQueue queue = list.get(clock);
                        queue.pit.clear();
                        queue.pit.add(pbs0);
                    }
                    else if (clock_end < clock)
                    {
                        break;
                    }
                }
            }

            appendParameterEvents(list, dyn, mDriver.volumeParameterIndex, clock_start, clock_end);
            appendParameterEvents(list, bre, mDriver.haskyParameterIndex, clock_start, clock_end);
            appendParameterEvents(list, cle, mDriver.resonancParameterIndex, clock_start, clock_end);
            appendParameterEvents(list, por, mDriver.portaTimeParameterIndex, clock_start, clock_end);

            return(list);
        }
예제 #24
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;
 }
예제 #25
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();
        }
예제 #26
0
 public RenderedStatus()
 {
     track  = new VsqTrack(0, 0, 0);
     tempo  = new TempoVector();
     config = new SequenceConfig();
 }
        public void begin(long total_samples, WorkerState state)
        {
            var mDriver = getDriver();

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

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

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

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

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

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

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

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

            // totalSamplesに足りなかったら、追加してレンダリング
            saRemain = (int)(mTotalSamples - mTotalAppend);
#if DEBUG
            sout.println("AquesToneRenderingRunner#run; totalSamples=" + mTotalSamples + "; mTotalAppend=" + mTotalAppend + "; saRemain=" + saRemain);
#endif
            while (saRemain > 0)
            {
                if (state.isCancelRequested())
                {
                    goto heaven;
                }
                int len = saRemain > BUFLEN ? BUFLEN : saRemain;
                mDriver.process(left, right, len);
                waveIncoming(left, right, len);
                saRemain    -= len;
                saProcessed += len;
                state.reportProgress(saProcessed);
                //mTotalAppend += len;
            }
heaven:
#if DEBUG
            log.Close();
#endif
            exitBegin();
            state.reportComplete();
        }
예제 #28
0
        /// <summary>
        /// Create MusicXML.scorepartwisePart object by VsqTrack instance.
        /// </summary>
        /// <param name="track"></param>
        /// <param name="timesig_table"></param>
        /// <returns></returns>
        private scorepartwisePart createScorePart(VsqTrack track, TimesigVector timesig_table, TempoVector tempo_table)
        {
            var     part      = new scorepartwisePart();
            var     note_list = quantizeTrack(track, timesig_table, tempo_table);
            var     measures  = new List <scorepartwisePartMeasure>();
            int     measure   = 0;
            Timesig timesig   = new Timesig(0, 0);

            while (0 < note_list.Count)
            {
                int measure_start_clock = timesig_table.getClockFromBarCount(measure);
                int measure_end_clock   = timesig_table.getClockFromBarCount(measure + 1);

                var tempo_change_in_measure = new TempoVector();
                tempo_change_in_measure.AddRange(
                    tempo_table
                    .Where((tempo) => measure_start_clock <= tempo.Clock && tempo.Clock < measure_end_clock)
                    .Select((tempo) => (TempoTableEntry)tempo.Clone()));

                // get the list of TiedEvent, contained in target measure.
                var in_measure_tied_note_list =
                    note_list
                    .Where((tied_event) => {
                    int tied_event_start = tied_event.Clock;
                    int tied_event_end   = tied_event.Clock + tied_event.Length;
                    return
                    ((measure_start_clock <= tied_event_start && tied_event_start < measure_end_clock) ||
                     (measure_start_clock <= tied_event_end && tied_event_end < measure_end_clock) ||
                     (tied_event_start <= measure_start_clock && measure_end_clock <= tied_event_end));
                });

                // get the list of MusicXML.note.
                var in_measure_note_list =
                    in_measure_tied_note_list
                    .SelectMany((tied_event) => {
                    var result = new List <object>();
                    int clock  = tied_event.Clock;
                    foreach (var note in tied_event)
                    {
                        int length = (int)note.duration.First;
                        if (measure_start_clock <= clock && clock + length <= measure_end_clock)
                        {
                            var tempo_change =
                                tempo_change_in_measure
                                .FirstOrDefault((tempo) => tempo.Clock == clock);
                            if (tempo_change != null)
                            {
                                var direction                = new direction();
                                direction.placement          = abovebelow.above;
                                direction.placementSpecified = true;
                                direction.directiontype      = new directiontype[] { new directiontype() };
                                direction.directiontype[0].metronome.Add(new metronome());
                                var perminute   = new perminute();
                                perminute.Value = getTempo(tempo_change).ToString();
                                direction.directiontype[0].metronome[0].Items = new object[] { notetypevalue.quarter, perminute };
                                direction.sound                = new sound();
                                direction.sound.tempo          = getTempo(tempo_change);
                                direction.sound.tempoSpecified = true;
                                result.Add(direction);
                            }
                            result.Add(note);
                        }
                        clock += length;
                    }
                    return(result);
                });

                var partwise_measure = new scorepartwisePartMeasure();
                partwise_measure.number = (measure + 1).ToString();
                var items = new List <object>();

                var measure_timesig = timesig_table.getTimesigAt(measure_start_clock);
                if (!measure_timesig.Equals(timesig))
                {
                    var attributes = new MusicXML.attributes();
                    attributes.divisions          = 480;
                    attributes.divisionsSpecified = true;
                    attributes.time = new time[] { new time() };
                    attributes.time[0].beats.Add(measure_timesig.numerator.ToString());
                    attributes.time[0].beattype.Add(measure_timesig.denominator.ToString());
                    attributes.time[0].symbol          = timesymbol.common;
                    attributes.time[0].symbolSpecified = true;
                    items.Add(attributes);
                }
                timesig = measure_timesig;

                items.AddRange(in_measure_note_list);
                partwise_measure.Items = items.ToArray();
                measures.Add(partwise_measure);

                note_list.RemoveAll((tied_event) => tied_event.Clock + tied_event.Length <= measure_end_clock);

                measure++;
            }

            part.measure = measures.ToArray();
            return(part);
        }
예제 #29
0
        /// <summary>
        /// ピッチとピッチベンドセンシティビティをイベントキューに追加する
        /// </summary>
        /// <param name="track"></param>
        /// <param name="sequence"></param>
        private void appendPitchEvent( VsqTrack track, EventQueueSequence sequence )
        {
            // 実際に AquesTone2 に送信する pbs の値と、pbs カーブに入っている値とのマップ
            const int maxPitchBendSensitivity = 23;
            int[] map = new int[maxPitchBendSensitivity + 1] {
                0, 5, 15, 35, 44, 54, 64, 74, 84, 93, 103, 113,
                127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
            };
            var pbs = track.MetaText.PBS;
            for ( int i = 0; i < pbs.size(); ++i ) {
                var clock = pbs.getKeyClock( i );
                {
                    // RPN MSB = 0x00
                    var e = new MidiEvent();
                    e.firstByte = 0xB0;
                    e.data = new int[] { 0x65, 0x00 };
                    e.clock = clock;
                    sequence.get( clock ).pit.add( e );
                }
                {
                    // RPN LSB = 0x00
                    var e = new MidiEvent();
                    e.firstByte = 0xB0;
                    e.data = new int[] { 0x64, 0x00 };
                    e.clock = clock;
                    sequence.get( clock ).pit.add( e );
                }
                {
                    // RPN data MSB
                    var e = new MidiEvent();
                    e.firstByte = 0xB0;
                    int value = Math.Max( 0, Math.Min( maxPitchBendSensitivity, pbs.getElementA( i ) ) );
                    e.data = new int[] { 0x06, map[value] };
                    e.clock = clock;
                    sequence.get( clock ).pit.add( e );
                }
            }

            var pit = track.MetaText.PIT;
            for ( int i = 0; i < pit.size(); ++i ) {
                var clock = pit.getKeyClock( i );
                var e = new MidiEvent();
                e.firstByte = 0xE0;
                var value = pit.getElementA( i ) + 8192;
                var msb = 0x7F & value;
                var lsb = 0x7F & (value >> 7);
                e.data = new int[] { msb, lsb };
                sequence.get( clock ).pit.add( e );
            }
        }
예제 #30
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);
        }
예제 #31
0
        public void processQueue(WorkerState state, Object arg)
        {
#if DEBUG
            sout.println("SynthesizeWorker#processQueue");
#endif
            PatchWorkQueue q                = (PatchWorkQueue)arg;
            VsqFileEx      vsq              = q.vsq;
            int            channel          = vsq.config.WaveFileOutputChannel == 1 ? 1 : 2;
            double         amp_master       = VocaloSysUtil.getAmplifyCoeffFromFeder(vsq.Mixer.MasterFeder);
            double         pan_left_master  = VocaloSysUtil.getAmplifyCoeffFromPanLeft(vsq.Mixer.MasterPanpot);
            double         pan_right_master = VocaloSysUtil.getAmplifyCoeffFromPanRight(vsq.Mixer.MasterPanpot);
            int            numTrack         = vsq.Track.Count;
            string         tmppath          = AppManager.getTempWaveDir();
            int            track            = q.track;

            VsqTrack vsq_track = vsq.Track[track];
            int      count     = vsq_track.getEventCount();
            if (count <= 0)
            {
                return;// false;
            }
            double amp_track       = VocaloSysUtil.getAmplifyCoeffFromFeder(vsq.Mixer.Slave[track - 1].Feder);
            double pan_left_track  = VocaloSysUtil.getAmplifyCoeffFromPanLeft(vsq.Mixer.Slave[track - 1].Panpot);
            double pan_right_track = VocaloSysUtil.getAmplifyCoeffFromPanRight(vsq.Mixer.Slave[track - 1].Panpot);
            double amp_left        = amp_track * pan_left_track;
            double amp_right       = amp_track * pan_right_track;
            int    total_clocks    = vsq.TotalClocks;
            double total_sec       = vsq.getSecFromClock(total_clocks);

            RendererKind kind = VsqFileEx.getTrackRendererKind(vsq_track);
            mGenerator = VSTiDllManager.getWaveGenerator(kind);
            Amplifier amp = new Amplifier();
            amp.setRoot(mGenerator);
            if (q.renderAll)
            {
                amp.setAmplify(amp_left, amp_right);
            }
            mGenerator.setReceiver(amp);
            mGenerator.setGlobalConfig(AppManager.editorConfig);
            mGenerator.setMainWindow(mMainWindow);

            Mixer mixer = new Mixer();
            mixer.setRoot(mGenerator);
            mixer.setGlobalConfig(AppManager.editorConfig);
            amp.setReceiver(mixer);

            if (q.renderAll && vsq.config.WaveFileOutputFromMasterTrack)
            {
                // トラック全体を合成するモードで,かつ,他トラックを合成して出力するよう指示された場合
                if (numTrack > 2)
                {
                    for (int i = 1; i < numTrack; i++)
                    {
                        if (i == track)
                        {
                            continue;
                        }
                        string file = Path.Combine(tmppath, i + ".wav");
                        if (!File.Exists(file))
                        {
                            // mixするべきファイルが揃っていないのでbailout
                            return;// true;
                        }
                        WaveReader r = null;
                        try {
                            r = new WaveReader(file);
                        } catch (Exception ex) {
                            Logger.write(typeof(SynthesizeWorker) + ".processQueue; ex=" + ex + "\n");
                            r = null;
                        }
                        if (r == null)
                        {
                            return;// true;
                        }
                        double end_sec = vsq.getSecFromClock(q.clockStart);
                        r.setOffsetSeconds(end_sec);
                        Amplifier amp_i_unit = new Amplifier();
                        amp_i_unit.setRoot(mGenerator);
                        double amp_i       = VocaloSysUtil.getAmplifyCoeffFromFeder(vsq.Mixer.Slave[i - 1].Feder);
                        double pan_left_i  = VocaloSysUtil.getAmplifyCoeffFromPanLeft(vsq.Mixer.Slave[i - 1].Panpot);
                        double pan_right_i = VocaloSysUtil.getAmplifyCoeffFromPanRight(vsq.Mixer.Slave[i - 1].Panpot);
                        double amp_left_i  = amp_i * pan_left_i;
                        double amp_right_i = amp_i * pan_right_i;
#if DEBUG
                        sout.println("FormSynthesize#bgWork_DoWork; #" + i + "; amp_left_i=" + amp_left_i + "; amp_right_i=" + amp_right_i);
#endif
                        amp_i_unit.setAmplify(amp_left_i, amp_right_i);
                        FileWaveSender wave_sender = new FileWaveSender(r);
                        wave_sender.setRoot(mGenerator);
                        wave_sender.setGlobalConfig(AppManager.editorConfig);

                        amp_i_unit.setSender(wave_sender);
                        mixer.addSender(amp_i_unit);
                    }
                }
            }

            PortUtil.deleteFile(q.file);
            int sample_rate = vsq.config.SamplingRate;
#if DEBUG
            sout.println("FormSynthesize#bgWork_DoWork; q.file=" + q.file);
#endif
            FileWaveReceiver wave_receiver = new FileWaveReceiver(q.file, channel, 16, sample_rate);
            wave_receiver.setRoot(mGenerator);
            wave_receiver.setGlobalConfig(AppManager.editorConfig);
            Amplifier amp_unit_master = new Amplifier();
            amp_unit_master.setRoot(mGenerator);
            if (q.renderAll)
            {
                double l = amp_master * pan_left_master;
                double r = amp_master * pan_right_master;
                amp_unit_master.setAmplify(l, r);
            }
            mixer.setReceiver(amp_unit_master);
            amp_unit_master.setReceiver(wave_receiver);

            int end = q.clockEnd;
            if (end == int.MaxValue)
            {
                end = vsq.TotalClocks + 240;
            }
            mGenerator.init(vsq, track, q.clockStart, end, sample_rate);

            double sec_start = vsq.getSecFromClock(q.clockStart);
            double sec_end   = vsq.getSecFromClock(end);
            long   samples   = (long)((sec_end - sec_start) * sample_rate);
            mGenerator.begin(samples, state);

            return;// false;
        }