Пример #1
0
        /// <summary>
        /// このインスタンスと指定したアイテムが,歌声合成の観点から等しいかどうかを調べます
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool equalsForSynth(UstEvent item)
        {
            if (item == null)
            {
                return(false);
            }
            bool ret = true;

            // モジュレーション・先行発声・スタート位置・オーバーラップのみチェック.
            // ほかに有効な値でかつ VsqEvent で比較できないものは何かあったか
            if (this.getModuration() != item.getModuration())
            {
                ret = false;
            }
            else if (this.getPreUtterance() != item.getPreUtterance())
            {
                ret = false;
            }
            else if (this.getStartPoint() != item.getStartPoint())
            {
                ret = false;
            }
            else if (this.getVoiceOverlap() != item.getVoiceOverlap())
            {
                ret = false;
            }
            return(ret);
        }
Пример #2
0
        /// <summary>
        /// TempoTableの[*].Timeの部分を更新します
        /// </summary>
        /// <returns></returns>
        public void updateTempoInfo()
        {
            if (m_tempo_table == null)
            {
                m_tempo_table = new List <TempoTableEntry>();
            }
            else
            {
                m_tempo_table.Clear();
            }
            if (m_tracks.Count <= 0)
            {
                return;
            }
            int      clock            = 0;
            double   time             = 0.0;
            int      last_tempo_clock = 0;       //最後にTempo値が代入されていたイベントのクロック
            float    last_tempo       = m_tempo; //最後に代入されていたテンポの値
            UstTrack ust_track        = m_tracks[0];

            for (int i = 0; i < ust_track.getEventCount(); i++)
            {
                UstEvent itemi = ust_track.getEvent(i);
                if (ust_track.getEvent(i).isTempoSpecified())
                {
                    time += (clock - last_tempo_clock) / (8.0 * last_tempo);
                    if (m_tempo_table.Count == 0 && clock != 0)
                    {
                        m_tempo_table.Add(new TempoTableEntry(0, (int)(6e7 / m_tempo), 0.0));
                    }
                    m_tempo_table.Add(new TempoTableEntry(clock, (int)(6e7 / itemi.getTempo()), time));
                    last_tempo       = itemi.getTempo();
                    last_tempo_clock = clock;
                }
                clock += (int)itemi.getLength();
            }
        }
Пример #3
0
        public Object clone()
        {
            UstEvent ret = new UstEvent();

            ret.mLength          = mLength;
            ret.mIsLengthSpec    = mIsLengthSpec;
            ret.mLyric           = mLyric;
            ret.mIsLyricSpec     = mIsLyricSpec;
            ret.mNote            = mNote;
            ret.mIsNoteSpec      = mIsNoteSpec;
            ret.mIntensity       = mIntensity;
            ret.mIsIntensitySpec = mIsIntensitySpec;
            ret.mPBType          = mPBType;
            ret.mIsPBTypeSpec    = mIsPBTypeSpec;
            if (mPitches != null)
            {
                ret.mPitches = new float[mPitches.Length];
                for (int i = 0; i < mPitches.Length; i++)
                {
                    ret.mPitches[i] = mPitches[i];
                }
            }
            ret.mIsPitchesSpec = mIsPitchesSpec;
            ret.mTempo         = mTempo;
            ret.mIsTempoSpec   = mIsTempoSpec;
            if (mVibrato != null)
            {
                ret.mVibrato = (UstVibrato)mVibrato.clone();
            }
            ret.mIsVibratoSpec = mIsVibratoSpec;
            if (mPortamento != null)
            {
                ret.mPortamento = (UstPortamento)mPortamento.clone();
            }
            ret.mIsPortamentoSpec = mIsPortamentoSpec;
            if (mEnvelope != null)
            {
                ret.mEnvelope = (UstEnvelope)mEnvelope.clone();
            }
            ret.mIsEnvelopeSpec     = mIsEnvelopeSpec;
            ret.mPreUtterance       = mPreUtterance;
            ret.mIsPreUtteranceSpec = mIsPreUtteranceSpec;
            ret.mVoiceOverlap       = mVoiceOverlap;
            ret.mIsVoiceOverlapSpec = mIsVoiceOverlapSpec;
            ret.Flags             = Flags;
            ret.mModuration       = mModuration;
            ret.mIsModurationSpec = mIsModurationSpec;
            ret.mStartPoint       = mStartPoint;
            ret.mIsStartPointSpec = mIsStartPointSpec;
            ret.SplitVoiceOverlap = splitVoiceOverlap;
            ret.SplitLength       = splitLength;
            ret.SplitisPercent    = splitispercent;
            ret.MoreOver          = _MoreOver;
            ret.ReplaceNoteID     = ReplaceNoteID;
            ret.LeftLimit         = LeftLimit;
            ret.Tag            = Tag;
            ret.Index          = Index;
            ret.NotePreOverlap = NotePreOverlap;
            ret.SplitSTP       = SplitSTP;
            return(ret);
        }
Пример #4
0
        public UstFile(string path)
        {
            StreamReader sr = null;

            try {
                string ENC = cadencii.utau.GetUSTEncodingValue.getUstEncoding(path);
                if (ENC == "")
                {
                    ENC = "Shift_JIS";
                }

                sr = new StreamReader(path, Encoding.GetEncoding(ENC));
#if DEBUG
                sout.println("UstFile#.ctor; path=" + path);
                sout.println("UstFile#.ctor; (sr==null)=" + (sr == null));
#endif
                string line = sr.ReadLine();

                UstTrack track = new UstTrack();
                int      type  = 0; //0 => reading "SETTING" section
                while (true)
                {
#if DEBUG
                    sout.println("UstFile#.ctor; line=" + line);
#endif
                    UstEvent ue = null;
                    if (type == 1)
                    {
                        ue = new UstEvent();
                    }
                    int index = 0;
                    if (line == "[#TRACKEND]")
                    {
                        break;
                    }
                    else if (line.ToUpper() == "[#NEXT]")
                    {
                        index = NEXT_INDEX;
                    }
                    else if (line.ToUpper() == "[#PREV]")
                    {
                        index = PREV_INDEX;
                    }
                    else if (line.ToUpper() == "[#SETTING]")
                    {
                        type = 0;
                    }
                    else
                    {
                        if (type != 1)
                        {
                            ue   = new UstEvent();
                            type = 1;
                        }
                        string s = line.Replace("[#", "").Replace("]", "").Trim();
                        try {
                            index = int.Parse(s);
                        } catch (Exception ex) {
#if DEBUG
                            sout.println("UstFile#.ctor; ex=" + ex);
#endif
                        }
                    }
#if DEBUG
                    sout.println("UstFile#.ctor; index=" + index);
#endif
                    line = sr.ReadLine(); // "[#" 直下の行
                    if (line == null)
                    {
                        break;
                    }
                    while (!line.StartsWith("[#"))
                    {
#if DEBUG
                        sout.println("line=" + line);
#endif
                        string[] spl = PortUtil.splitString(line, new char[] { '=' }, 2);
                        if (type == 0)
                        {
                            // reading "SETTING" section
                            if (spl[0] == "Tempo")
                            {
                                m_tempo = 125f;
                                float v = 125f;
                                try {
                                    v       = (float)double.Parse(spl[1]);
                                    m_tempo = v;
                                } catch (Exception ex) {
                                }
                            }
                            else if (spl[0] == "ProjectName")
                            {
                                m_project_name = spl[1];
                            }
                            else if (spl[0] == "VoiceDir")
                            {
                                m_voice_dir = spl[1];
                            }
                            else if (spl[0] == "OutFile")
                            {
                                m_out_file = spl[1];
                            }
                            else if (spl[0] == "CacheDir")
                            {
                                m_cache_dir = spl[1];
                            }
                            else if (spl[0] == "Tool1")
                            {
                                m_tool1 = spl[1];
                            }
                            else if (spl[0] == "Tool2")
                            {
                                m_tool2 = spl[1];
                            }
                        }
                        else if (type == 1)
                        {
                            if (spl.Length >= 2)
                            {
                                // readin event section
                                if (spl[0] == "Length")
                                {
                                    ue.setLength(0);
                                    int v = 0;
                                    try {
                                        v = int.Parse(spl[1]);
                                        ue.setLength(v);
                                    } catch (Exception ex) {
                                    }
                                }
                                else if (spl[0] == "Lyric")
                                {
                                    ue.setLyric(spl[1]);
                                }
                                else if (spl[0] == "NoteNum")
                                {
                                    int v = 0;
                                    try {
                                        v = int.Parse(spl[1]);
                                        ue.setNote(v);
                                    } catch (Exception ex) {
                                    }
                                }
                                else if (spl[0] == "Intensity")
                                {
                                    int v = 100;
                                    try {
                                        v = int.Parse(spl[1]);
                                        ue.setIntensity(v);
                                    } catch (Exception ex) {
                                    }
                                }
                                else if (spl[0] == "PBType")
                                {
                                    int v = 5;
                                    try {
                                        v = int.Parse(spl[1]);
                                        ue.setPBType(v);
                                    } catch (Exception ex) {
                                    }
                                }
                                else if (spl[0] == "Piches")
                                {
                                    string[] spl2 = PortUtil.splitString(spl[1], ',');
                                    float[]  t    = new float[spl2.Length];
                                    for (int i = 0; i < spl2.Length; i++)
                                    {
                                        float v = 0;
                                        try {
                                            v    = (float)double.Parse(spl2[i]);
                                            t[i] = v;
                                        } catch (Exception ex) {
                                        }
                                    }
                                    ue.setPitches(t);
                                }
                                else if (spl[0] == "Tempo")
                                {
                                    float v;
                                    try {
                                        v = (float)double.Parse(spl[1]);
                                        ue.setTempo(v);
                                    } catch (Exception ex) {
                                    }
                                }
                                else if (spl[0] == "VBR")
                                {
                                    ue.setVibrato(new UstVibrato(line));

                                    /*
                                     * PBW=50,50,46,48,56,50,50,50,50
                                     * PBS=-87
                                     * PBY=-15.9,-20,-31.5,-26.6
                                     * PBM=,s,r,j,s,s,s,s,s
                                     */
                                }
                                else if (spl[0] == "PBW" || spl[0] == "PBS" || spl[0] == "PBY" || spl[0] == "PBM")
                                {
                                    if (ue.getPortamento() == null)
                                    {
                                        ue.setPortamento(new UstPortamento());
                                    }
                                    ue.getPortamento().parseLine(line);
                                }
                                else if (spl[0] == "Envelope")
                                {
                                    ue.setEnvelope(new UstEnvelope(line));
                                    //PreUtterance=1
                                    //VoiceOverlap=6
                                }
                                else if (spl[0] == "VoiceOverlap")
                                {
                                    if (spl[1] != "")
                                    {
                                        ue.setVoiceOverlap((float)double.Parse(spl[1]));
                                    }
                                }
                                else if (spl[0] == "PreUtterance")
                                {
                                    if (spl[1] != "")
                                    {
                                        ue.setPreUtterance((float)double.Parse(spl[1]));
                                    }
                                }
                                else if (spl[0] == "Flags")
                                {
                                    ue.Flags = line.Substring(6);
                                }
                                else if (spl[0] == "StartPoint")
                                {
                                    try {
                                        float stp = (float)double.Parse(spl[1]);
                                        ue.setStartPoint(stp);
                                    } catch (Exception ex) {
                                    }
                                }
                                else if (spl[0] == "Moduration")
                                {
                                    try {
                                        int moduration = int.Parse(spl[1]);
                                        ue.setModuration(moduration);
                                    } catch (Exception ex) {
                                    }
                                }
                                else
                                {
                                    string name  = spl[0];
                                    string value = spl[1];
                                    if (ue.Properties == null)
                                    {
                                        ue.Properties = new List <UstEventProperty>();
                                    }
                                    ue.Properties.Add(new UstEventProperty(name, value));
                                }
                            }
                        }
                        line = sr.ReadLine();
                        if (line == null)
                        {
                            break;
                        }
                    }
                    if (type == 0)
                    {
                        type = 1;
                    }
                    else if (type == 1)
                    {
                        ue.Index = index;
                        track.addEvent(ue);
                    }
                }
                m_tracks.Add(track);
                updateTempoInfo();
            } catch (Exception ex) {
#if DEBUG
                serr.println("UstFile#.ctor(String); ex=" + ex);
#endif
            } finally {
                if (sr != null)
                {
                    try {
                        sr.Close();
                    } catch (Exception ex2) {
                    }
                }
            }
        }
Пример #5
0
        /// <summary>
        /// vsqの指定したトラックを元に,トラックを1つだけ持つustを構築します
        /// </summary>
        /// <param name="vsq"></param>
        /// <param name="track_index"></param>
        /// <param name="id_map">UstEventのIndexフィールドと、元になったVsqEventのInternalIDを対応付けるマップ。キーがIndex、値がInternalIDを表す</param>
        public UstFile(VsqFile vsq, int track_index, SortedDictionary <int, int> id_map)
        {
            VsqFile work = (VsqFile)vsq.clone();
            //work.removePart( 0, work.getPreMeasureClocks() );

            VsqTrack vsq_track = work.Track[track_index];

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

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

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

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

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

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

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

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

            m_tracks.Add(track_add);
        }
Пример #6
0
 public void addEvent(UstEvent item)
 {
     m_events.Add(item);
 }
Пример #7
0
 public void setEvent(int index, UstEvent item)
 {
     m_events[index] = item;
 }