Пример #1
0
        /// <summary>
        /// 화음 전이를 일으키면서 새 화음의 음들을 재생합니다.
        /// 확률적으로 연주 속도가 변할 수 있습니다.
        /// </summary>
        /// <returns></returns>
        private static void PlayChordTransition()
        {
            // ChordingCoding에서 공백 문자를 입력할 때 호출됨
            if (!HasStart)
            {
                return;
            }

            int pitch;

            StopPlaying(0);
            chord          = new Chord(SFXTheme.CurrentSFXTheme.ChordTransition, chord);
            pitch          = chord.NextNote();
            syncPlayBuffer = new List <Note>();
            Random r = new Random();

            if (r.Next(0, 27) > 0)
            {
                // TPS 29 기준으로 한 마디에 한 번씩 시도할 때 1분에 한 번 꼴로 발생하는 확률로 채널(staff) 0의 악기를 재생하지 않음
                SFXTheme.InstrumentInfo ii = SFXTheme.CurrentSFXTheme.Instruments[0];
                foreach (int p in chord.NotesInChord())
                {
                    if (p != pitch)
                    {
                        PlayANoteSync(ii.whitespacePitchModulator(p),
                                      ii.whitespaceVolume, ii.whitespaceRhythm, 0);
                    }
                }
            }
            foreach (KeyValuePair <int, SFXTheme.InstrumentInfo> pair in SFXTheme.CurrentSFXTheme.Instruments)
            {
                if (pair.Value.whitespaceVolume > 0 && pair.Key > 1)
                {
                    PlayANoteSync(pair.Value.whitespacePitchModulator(pitch),
                                  pair.Value.whitespaceVolume, pair.Value.whitespaceRhythm, pair.Key);
                }
            }

            // 빠르기 변경
            SetTickPerSecond((int)TICK_PER_SECOND + (int)(1f * Math.Round(Util.GaussianRandom(r), MidpointRounding.AwayFromZero)));

            OnChordTransition?.Invoke(pitch);
        }
Пример #2
0
        /// <summary>
        /// 리듬에 맞게 음표를 재생합니다.
        /// tickDelegate에 의해 1초에 32번씩 자동으로 호출됩니다.
        /// </summary>
        private static void Tick()
        {
            if (!HasStart)
            {
                return;
            }

            //Score.NoteOff(outDevice);
            Score.NoteOff(syn);

            void TickPlay(object[] args)
            {
                // 지속 효과음이 멈추는 것을 대비하여
                if (SFXTheme.CurrentSFXTheme.Instruments.ContainsKey(5) &&
                    SFXTheme.CurrentSFXTheme.Instruments.ContainsKey(6))
                {
                    if (tickNumber % ((int)TICK_PER_SECOND * 10) == 0)
                    {
                        StopPlaying(5);
                        SFXTheme.InstrumentInfo inst = SFXTheme.CurrentSFXTheme.Instruments[5];
                        Note note = new Note(inst.sfxPitchModulator(45), inst.sfxVolume, inst.sfxRhythm * 64 * 60, Measure, Position, 5);   // 음표를 3840배 길게 늘여서 재생
                        //Score.PlayANoteForever(outDevice, note, (int)Math.Round(inst.sfxVolume * (SFXTheme.CurrentSFXTheme.Volume / 100D)));     // 기본 빗소리 (사라지지 않아야 함)
                        Score.PlayANote(syn, note, SFXTheme.CurrentSFXTheme.Volume / 100f);
                    }
                    if (tickNumber % ((int)TICK_PER_SECOND * 10) == (int)TICK_PER_SECOND * 5)
                    {
                        StopPlaying(6);
                        SFXTheme.InstrumentInfo inst = SFXTheme.CurrentSFXTheme.Instruments[6];
                        Note note = new Note(inst.sfxPitchModulator(45), inst.sfxVolume, inst.sfxRhythm * 64 * 60, Measure, Position, 6);   // 음표를 3840배 길게 늘여서 재생
                        //Score.PlayANoteForever(outDevice, note, (int)Math.Round(inst.sfxVolume * (SFXTheme.CurrentSFXTheme.Volume / 100D)));     // 기본 빗소리 (사라지지 않아야 함)
                        Score.PlayANote(syn, note, SFXTheme.CurrentSFXTheme.Volume / 100f);
                    }
                }

                for (int staff = 7; staff <= 8; staff++)
                {
                    if (SFXTheme.CurrentSFXTheme.Instruments.ContainsKey(staff))
                    {
                        if (accompanimentTickNumber[staff] >= Accompaniment.currentPatterns[staff].length)
                        {
                            accompanimentPlayNumber[staff]++;
                            if (accompanimentPlayNumber[staff] >= Accompaniment.currentPatterns[staff].iteration)
                            {
                                Accompaniment.SetNewCurrentPattern(staff);
                                accompanimentPlayNumber[staff] = 0;
                            }
                            else
                            {
                                Score.Play(Accompaniment.currentPatterns[staff].score, "Accompaniment",
                                           SFXTheme.CurrentSFXTheme.Instruments[staff].accompanimentVolume / 127f);
                            }
                            accompanimentTickNumber[staff] = 0;
                        }
                        Score accompaniment = Accompaniment.currentPatterns[staff].score;

                        /*
                         * // 64분음표 단위로 음을 하나씩 재생
                         * long measure = accompanimentTickNumber[staff] / 64;
                         * int position = accompanimentTickNumber[staff] % 64;
                         * if (SFXTheme.CurrentSFXTheme.Instruments.ContainsKey(staff))
                         * {
                         *  accompaniment.PlayEnumerable(syn, measure, position, staff,
                         *      (int)Math.Round(SFXTheme.CurrentSFXTheme.Instruments[staff].accompanimentVolume * (SFXTheme.CurrentSFXTheme.Volume / 100D)));
                         *
                         * }
                         */

                        accompanimentTickNumber[staff]++;
                    }
                    else
                    {
                        accompanimentTickNumber[staff] = 0;
                    }
                }

                // 자동 반주 악보에 대해서만, 자동 반주가 꺼지면 음량이 0이 되도록
                float volumeChanger(string scoreClassName)
                {
                    switch (scoreClassName)
                    {
                    case "Accompaniment":
                        float accompVolume = 1f;
                        if (!SFXTheme.CurrentSFXTheme.hasAccompanied)
                        {
                            accompVolume = 0f;
                        }
                        return(SFXTheme.CurrentSFXTheme.Volume / 100f * accompVolume);

                    default:
                        return(SFXTheme.CurrentSFXTheme.Volume / 100f);
                    }
                }

                // Play()로 재생 목록에 넣은 악보들을 재생
                Score.PlayPerTick(syn, volumeChanger);
            }

            Util.TaskQueue.Add("play", TickPlay);

            if (tickNumber % 64 == 0 && (SFXTheme.CurrentSFXTheme.Instruments.ContainsKey(7) || SFXTheme.CurrentSFXTheme.Instruments.ContainsKey(8)) &&
                SFXTheme.CurrentSFXTheme.hasAccompanied)
            {
                syncTransitionBuffer = false;
                PlayChordTransition();
            }
            else if (syncTransitionBuffer && tickNumber % 32 == 0)
            {
                syncTransitionBuffer = false;
                PlayChordTransition();
            }

            // 동기화된 박자(최소 리듬 단위)에 맞춰 버퍼에 저장되어 있던 음표 재생
            if (NoteResolution > 0 && tickNumber % NoteResolution == 0 && syncPlayBuffer.Count > 0)
            {
                FlushSyncPlayBuffer();
            }
            //SoundPipeline(buffer);

            void IncreaseTick(object[] args)
            {
                tickNumber++;
            }

            Util.TaskQueue.Add("play", IncreaseTick);
        }