Esempio n. 1
0
        public void Send(byte[] msg, int offset, int length, long timestamp)
        {
            if (synth == null)
            {
                throw new InvalidOperationException("The MIDI output is not open.");
            }

            int ch = msg[offset] & 0x0F;

            switch (msg [offset] & 0xF0)
            {
            case 0x80:
                synth.NoteOff(ch, msg [offset + 1]);
                break;

            case 0x90:
                if (msg [offset + 2] == 0)
                {
                    synth.NoteOff(ch, msg [offset + 1]);
                }
                else
                {
                    synth.NoteOn(ch, msg [offset + 1], msg [offset + 2]);
                }
                break;

            case 0xA0:
                synth.KeyPressure(ch, msg [offset + 1], msg [offset + 2]);
                break;

            case 0xB0:
                synth.CC(ch, msg [offset + 1], msg [offset + 2]);
                break;

            case 0xC0:
                synth.ProgramChange(ch, msg [offset + 1]);
                break;

            case 0xD0:
                synth.ChannelPressure(ch, msg [offset + 1]);
                break;

            case 0xE0:
                synth.PitchBend(ch, msg [offset + 1] + msg [offset + 2] * 0x80);
                break;

            case 0xF0:
#if NET472 || NETCOREAPP
                synth.Sysex(new ArraySegment <byte> (msg, offset, length), null);
#else
                unsafe {
                    fixed(byte *ptr = msg)
                    synth.Sysex((IntPtr)(ptr + offset), length, IntPtr.Zero, 0);
                }
                    #endif
                break;
            }
        }
Esempio n. 2
0
        public void Send(byte [] msg, int offset, int length, long timestamp)
        {
            if (synth == null)
            {
                throw new InvalidOperationException("The MIDI output is not open.");
            }

            int ch = msg [offset] & 0x0F;

            switch (msg [offset] & 0xF0)
            {
            case 0x80:
                synth.NoteOff(ch, msg [offset + 1]);
                break;

            case 0x90:
                if (msg [offset + 2] == 0)
                {
                    synth.NoteOff(ch, msg [offset + 1]);
                }
                else
                {
                    synth.NoteOn(ch, msg [offset + 1], msg [offset + 2]);
                }
                break;

            case 0xA0:
                synth.KeyPressure(ch, msg [offset + 1], msg [offset + 2]);
                break;

            case 0xB0:
                synth.CC(ch, msg [offset + 1], msg [offset + 2]);
                break;

            case 0xC0:
                synth.ProgramChange(ch, msg [offset + 1]);
                break;

            case 0xD0:
                synth.ChannelPressure(ch, msg [offset + 1]);
                break;

            case 0xE0:
                synth.PitchBend(ch, msg [offset + 1] + msg [offset + 2] * 0x80);
                break;

            case 0xF0:
                synth.Sysex(new ArraySegment <byte> (msg, offset, length).ToArray(), null);
                break;
            }
        }
        void DoSend(byte[] msg, int offset, int count, long timestamp)
        {
#if MIDI_MANAGER
            output.Send(msg, offset, count, timestamp);
#else
            // FIXME: consider timestamp.

            int ch = msg [offset] & 0x0F;
            switch (msg [offset] & 0xF0)
            {
            case 0x80:
                syn.NoteOff(ch, msg [offset + 1]);
                break;

            case 0x90:
                if (msg [offset + 2] == 0)
                {
                    syn.NoteOff(ch, msg [offset + 1]);
                }
                else
                {
                    syn.NoteOn(ch, msg [offset + 1], msg [offset + 2]);
                }
                break;

            case 0xA0:
                // No PAf in fluidsynth?
                break;

            case 0xB0:
                syn.CC(ch, msg [offset + 1], msg [offset + 2]);
                break;

            case 0xC0:
                syn.ProgramChange(ch, msg [offset + 1]);
                break;

            case 0xD0:
                syn.ChannelPressure(ch, msg [offset + 1]);
                break;

            case 0xE0:
                syn.PitchBend(ch, msg [offset + 1] + msg [offset + 2] * 0x80);
                break;

            case 0xF0:
                syn.Sysex(new ArraySegment <byte> (msg, offset, count).ToArray(), null);
                break;
            }
#endif
        }
Esempio n. 4
0
        private void CheckNoteTrigger(Keys key, int n)
        {
            if (_currentKeyboardState.IsKeyDown(key) && _previousKeyboardState.IsKeyUp(key))
            {
                _synth.NoteOn(n);
                if (n == 0 || n == 2 || n == 4 || n == 5 || n == 7 || n == 9 || n == 11 || n == 12 || n == 14)
                {
                    buttonList[n].Image = whiteKeyPressed;
                }
                else
                {
                    buttonList[n].Image = blackKeyPressed;
                }
            }
            if (_currentKeyboardState.IsKeyUp(key) && _previousKeyboardState.IsKeyDown(key))
            {
                _synth.NoteOff(n);

                if (n == 0 || n == 2 || n == 4 || n == 5 || n == 7 || n == 9 || n == 11 || n == 12 || n == 14)
                {
                    buttonList[n].Image = whiteKey;
                }
                else
                {
                    buttonList[n].Image = blackKey;
                }
            }
        }
Esempio n. 5
0
        /*
         * /// <summary>
         * /// 음표 하나를 음표의 길이와 관계없이 영원히 재생합니다.
         * /// 이미 재생 중인 다른 음표와 동시에 재생할 수 있습니다.
         * /// 재생을 멈추려면 해당 Staff에 Stop()을 호출해야 합니다.
         * /// </summary>
         * /// <param name="outDevice">출력 디바이스</param>
         * /// <param name="note">재생할 음표</param>
         * /// <param name="velocity">연주 세기 (0 ~ 127)</param>
         * // (만약 Unity에서 작업할 경우, 타입을 void 대신 IEnumerator로 바꿔서 Coroutine으로 사용하세요.)
         * public static void PlayANoteForever(OutputDevice outDevice, Note note, int velocity = 127)
         * {
         *  // 이미 재생 중인 악보이면 중복하여 재생하지 않습니다.
         *  if (velocity < 0 || velocity >= 128) return;
         *  //Console.WriteLine("Playing...");
         *
         *  // 악보에 있는 모든 음표를 재생합니다.
         *  KeyValuePair<float, int> p = note.ToMidi()[0];
         *
         *  if (p.Value > 0)
         *  {
         *      // 음표를 재생합니다.
         *      // (Midi message pair를 번역하여 Midi message를 생성합니다.)
         *      try
         *      {
         *          outDevice.Send(new ChannelMessage(ChannelCommand.NoteOn, p.Value >> 16, p.Value & 65535, velocity));
         *      }
         *      catch (ObjectDisposedException) { }
         *      catch (OutputDeviceException) { }
         *  }
         *  //Console.WriteLine("End of note.");
         * }
         */

        /*
         * /// <summary>
         * /// 재생 중인 Staff 하나의 재생을 멈춥니다.
         * /// </summary>
         * /// <param name="outDevice">출력 디바이스</param>
         * // (만약 Unity에서 작업할 경우, 타입을 void 대신 IEnumerator로 바꿔서 Coroutine으로 사용하세요.)
         * public static void Stop(OutputDevice outDevice, int staff = 0)
         * {
         *  // 이미 재생 중인 악보이면 중복하여 재생하지 않습니다.
         *  if (staff < 0 || staff >= 16) return;
         *  //Console.WriteLine("Playing...");
         *
         *  for (int p = 0; p < 128; p++)
         *  {
         *      // 음표의 재생을 멈춥니다.
         *      // (Midi message pair를 번역하여 Midi message를 생성합니다.)
         *      try
         *      {
         *          outDevice.Send(new ChannelMessage(ChannelCommand.NoteOff, staff, p, 32));
         *      }
         *      catch (ObjectDisposedException) { }
         *      catch (OutputDeviceException) { }
         *  }
         *  //Console.WriteLine("End of note.");
         * }
         */
        /// <summary>
        /// 재생 중인 Staff 하나의 재생을 멈춥니다.
        /// </summary>
        /// <param name="syn">신디사이저</param>
        public static void Stop(Synth syn, int staff = 0)
        {
            void noteOffBufferClear(object[] args)
            {
                Dictionary <int, List <Note> > noteOffBuffer_ = args[0] as Dictionary <int, List <Note> >;
                int staff_ = (int)args[1];

                if (!noteOffBuffer_.ContainsKey(staff_))
                {
                    return;
                }

                foreach (Note n in noteOffBuffer_[staff])
                {
                    int p = n.Pitch;
                    try
                    {
                        // 음표의 재생을 멈춥니다.
                        syn.NoteOff(staff, p);
                    }
                    catch (ObjectDisposedException) { }
                    catch (FluidSynthInteropException) { }
                }
                noteOffBuffer_[staff].Clear();
            }

            Util.TaskQueue.Add("noteOffBuffer", noteOffBufferClear, noteOffBuffer, staff);
        }
Esempio n. 6
0
        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
            {
                Exit();
            }

            // Get the current gamepad state.
            GamePadState currentState = GamePad.GetState(PlayerIndex.One);

            // Process input only if connected.
            if (currentState.IsConnected)
            {
                // Increase vibration if the player is tapping the A button.
                // Subtract vibration otherwise, even if the player holds down A
                if (currentState.Buttons.A == ButtonState.Pressed)
                {
                    _synth.NoteOn(0);
                }
                else
                {
                    _synth.NoteOff(0);
                }

                if (currentState.Buttons.B == ButtonState.Pressed &&
                    previousGamePadState.Buttons.B == ButtonState.Released)
                {
                    NextOscillatorType();
                }

                if (currentState.DPad.Up == ButtonState.Pressed)
                {
                    _synth.FadeInDuration = MathHelper.Clamp(_synth.FadeInDuration + 10, 0, 44100);
                }

                if (currentState.DPad.Down == ButtonState.Pressed)
                {
                    _synth.FadeInDuration = MathHelper.Clamp(_synth.FadeInDuration - 10, 0, 44100);
                }

                if (currentState.DPad.Left == ButtonState.Pressed)
                {
                    _synth.FadeOutDuration = MathHelper.Clamp(_synth.FadeOutDuration + 10, 0, 44100);
                }

                if (currentState.DPad.Right == ButtonState.Pressed)
                {
                    _synth.FadeOutDuration = MathHelper.Clamp(_synth.FadeOutDuration - 10, 0, 44100);
                }

                _synth.PitchBend = MathHelper.Clamp(currentState.ThumbSticks.Left.Y, -1.0f, 1.0f);

                // Update previous gamepad state.
                previousGamePadState = currentState;
            }

            _synth.Update(gameTime);

            base.Update(gameTime);
        }
Esempio n. 7
0
 public static void Main(string[] args)
 {
     using (var settings = new Settings())
     {
         // Change this if you don't have pulseaudio or want to change to anything else.
         if (Environment.OSVersion.Platform == PlatformID.Unix)
         {
             settings[ConfigurationKeys.AudioDriver].StringValue = "pulseaudio";
         }
         settings[ConfigurationKeys.SynthAudioChannels].IntValue = 2;
         using (var syn = new Synth(settings))
         {
             foreach (var arg in args)
             {
                 if (SoundFont.IsSoundFont(arg))
                 {
                     syn.LoadSoundFont(arg, true);
                 }
             }
             if (syn.FontCount == 0)
             {
                 syn.LoadSoundFont("/usr/share/sounds/sf2/FluidR3_GM.sf2", true);
             }
             for (int i = 0; i < 16; i++)
             {
                 syn.SoundFontSelect(i, 0);
             }
             var files = args.Where(SoundFont.IsMidiFile);
             if (files.Any())
             {
                 foreach (var arg in files)
                 {
                     using (var player = new Player(syn))
                     {
                         using (var adriver = new AudioDriver(syn.Settings, syn))
                         {
                             player.Add(arg);
                             player.Play();
                             player.Join();
                         }
                     }
                 }
             }
             else
             {
                 using (var adriver = new AudioDriver(syn.Settings, syn))
                 {
                     syn.ProgramChange(0, 1);
                     syn.NoteOn(0, 60, 120);
                     Thread.Sleep(5000);
                     syn.NoteOff(0, 60);
                 }
             }
         }
     }
 }
Esempio n. 8
0
        /*
         * /// <summary>
         * /// 매 64분음표 길이의 시간마다 호출되어, 현재 재생이 멈춰야 할 음표의 재생을 멈춥니다.
         * /// </summary>
         * /// <param name="outDevice"></param>
         * public static void NoteOff(OutputDevice outDevice)
         * {
         *  if (noteOffBuffer.Count <= 0) return;
         *  long measure = Music.Measure;
         *  int position = Music.Position;
         *
         *  void noteOffBufferStop(object[] args)
         *  {
         *      List<Note> noteOffBuffer_ = args[0] as List<Note>;
         *      long measure_ = (long)args[1];
         *      int position_ = (int)args[2];
         *      OutputDevice outDevice_ = args[3] as OutputDevice;
         *
         *      List<Note> deadBuffer = new List<Note>();
         *      for (int i = noteOffBuffer_.Count - 1; i >= 0; i--)
         *      {
         *          Note note = noteOffBuffer_[i];
         *
         *          // 악보에 있는 모든 음표를 재생합니다.
         *          KeyValuePair<float, int> p = note.ToMidi()[1];
         *
         *          if (p.Value <= 0 && p.Key <= measure_ * 64f + position_)
         *          {
         *              // 음표의 재생을 멈춥니다.
         *              // (Midi message pair를 번역하여 Midi message를 생성합니다.)
         *              try
         *              {
         *                  outDevice_.Send(new ChannelMessage(ChannelCommand.NoteOff, -p.Value >> 16, -p.Value & 65535, 10));
         *              }
         *              catch (ObjectDisposedException) { }
         *              catch (OutputDeviceException) { }
         *              finally
         *              {
         *                  deadBuffer.Add(noteOffBuffer_[i]);
         *              }
         *          }
         *      }
         *      noteOffBuffer_.RemoveAll(x => deadBuffer.Contains(x));
         *  }
         *
         *  Util.TaskQueue.Add("noteOffBuffer", noteOffBufferStop, noteOffBuffer, measure, position, outDevice);
         *
         * }
         */
        /// <summary>
        /// 매 64분음표 길이의 시간마다 호출되어, 현재 재생이 멈춰야 할 음표의 재생을 멈춥니다.
        /// </summary>
        /// <param name="syn">신디사이저</param>
        public static void NoteOff(Synth syn)
        {
            //if (noteOffBuffer.Count <= 0) return;
            long measure  = Music.Measure;
            int  position = Music.Position;

            void noteOffBufferStop(object[] args)
            {
                Dictionary <int, List <Note> > noteOffBuffer_ = args[0] as Dictionary <int, List <Note> >;
                long  measure_  = (long)args[1];
                int   position_ = (int)args[2];
                Synth syn_      = args[3] as Synth;

                foreach (List <Note> l in noteOffBuffer_.Values)
                {
                    List <Note> deadBuffer = new List <Note>();
                    for (int i = l.Count - 1; i >= 0; i--)
                    {
                        Note note = l[i];

                        // 악보에 있는 모든 음표를 재생합니다.
                        KeyValuePair <float, int> p = note.ToMidi()[1];

                        if (p.Value <= 0 && p.Key <= measure_ * 64f + position_)
                        {
                            // 음표의 재생을 멈춥니다.
                            // (Midi message pair를 번역하여 Midi message를 생성합니다.)
                            try
                            {
                                syn_.NoteOff(-p.Value >> 16, -p.Value & 65535);
                            }
                            catch (ObjectDisposedException) { }
                            catch (FluidSynthInteropException) { }
                            finally
                            {
                                deadBuffer.Add(l[i]);
                            }
                        }
                    }
                    l.RemoveAll(x => deadBuffer.Contains(x));
                }
            }

            Util.TaskQueue.Add("noteOffBuffer", noteOffBufferStop, noteOffBuffer, measure, position, syn);
        }
Esempio n. 9
0
 public static void Main(string[] args)
 {
     using (var settings = new Settings()) {
         if (Environment.OSVersion.Platform == PlatformID.Unix)
         {
             settings [ConfigurationKeys.AudioDriver].StringValue = "alsa";
         }
         using (var syn = new Synth(settings)) {
             foreach (var arg in args)
             {
                 if (Synth.IsSoundFont(arg))
                 {
                     syn.LoadSoundFont(arg, true);
                 }
             }
             if (syn.FontCount == 0)
             {
                 syn.LoadSoundFont("/usr/share/sounds/sf2/FluidR3_GM.sf2", true);
             }
             var files = args.Where(a => Synth.IsMidiFile(a));
             if (files.Any())
             {
                 foreach (var arg in files)
                 {
                     using (var player = new Player(syn)) {
                         using (var adriver = new AudioDriver(syn.Settings, syn)) {
                             player.Add(arg);
                             player.Play();
                             player.Join();
                         }
                     }
                 }
             }
             else
             {
                 using (var adriver = new AudioDriver(syn.Settings, syn)) {
                     syn.NoteOn(0, 60, 100);
                     Thread.Sleep(5000);
                     syn.NoteOff(0, 60);
                 }
             }
         }
     }
 }
Esempio n. 10
0
        /*
         * /// <summary>
         * /// 음표 하나를 재생합니다.
         * /// 이미 재생 중인 다른 음표와 동시에 재생할 수 있으며
         * /// 음표의 길이만큼 연주하고 음이 사라집니다.
         * /// </summary>
         * /// <param name="outDevice">출력 디바이스</param>
         * /// <param name="note">재생할 음표</param>
         * /// <param name="velocity">연주 세기 (0 ~ 127)</param>
         * // (만약 Unity에서 작업할 경우, 타입을 void 대신 IEnumerator로 바꿔서 Coroutine으로 사용하세요.)
         * public static void PlayANote(OutputDevice outDevice, Note note, int velocity = 127)
         * {
         *  // 이미 재생 중인 악보이면 중복하여 재생하지 않습니다.
         *  if (velocity < 0 || velocity >= 128) return;
         *  //Console.WriteLine("Playing...");
         *
         *  // 악보에 있는 모든 음표를 재생합니다.
         *  KeyValuePair<float, int> p = note.ToMidi()[0];
         *
         *  if (p.Value > 0)
         *  {
         *      // 음표를 재생합니다.
         *      // (Midi message pair를 번역하여 Midi message를 생성합니다.)
         *      try
         *      {
         *          outDevice.Send(new ChannelMessage(ChannelCommand.NoteOn, p.Value >> 16, p.Value & 65535, velocity));
         *      }
         *      catch (ObjectDisposedException) { }
         *      catch (OutputDeviceException) { }
         *  }
         *
         *  void noteOffBufferAdd(object[] args)
         *  {
         *      List<Note> noteOffBuffer_ = args[0] as List<Note>;
         *      Note note_ = args[1] as Note;
         *      noteOffBuffer_.Add(note_);
         *  }
         *
         *  Util.TaskQueue.Add("noteOffBuffer", noteOffBufferAdd, noteOffBuffer, note);
         *  //Console.WriteLine("End of note.");
         * }
         */

        /// <summary>
        /// 음표 하나를 재생합니다.
        /// 이미 재생 중인 다른 음표와 동시에 재생할 수 있으며
        /// 음표의 길이만큼 연주하고 음이 사라집니다.
        /// </summary>
        /// <param name="syn">신디사이저</param>
        /// <param name="note">재생할 음표</param>
        /// <param name="velocityChange">연주 세기를 변화시키기 위해 음 세기에 곱해질 값</param>
        public static void PlayANote(Synth syn, Note note, float velocityChange = 1f)
        {
            // 이미 재생 중인 악보이면 중복하여 재생하지 않습니다.
            if (velocityChange < 0)
            {
                return;
            }
            //Console.WriteLine("Playing...");

            void noteOffBufferCheckAndPlay(object[] args)
            {
                Dictionary <int, List <Note> > noteOffBuffer_ = args[0] as Dictionary <int, List <Note> >;
                Note  note_           = args[1] as Note;
                float velocityChange_ = (float)args[2];
                int   staff           = note_.Staff;
                int   pitch           = note_.Pitch;

                if (noteOffBuffer_.ContainsKey(staff))
                {
                    int i = noteOffBuffer_[staff].FindIndex((n) => (pitch == n.Pitch));
                    if (i != -1)
                    {
                        // 해당 채널에서 같은 음 높이의 음이 이미 재생 중인 경우
                        try
                        {
                            // 재생 중이었던 음표의 재생을 멈춥니다.
                            syn.NoteOff(staff, pitch);
                        }
                        catch (ObjectDisposedException) { }
                        catch (FluidSynthInteropException) { }
                        noteOffBuffer_[staff].RemoveAt(i);
                    }
                }

                KeyValuePair <float, int> p = note.ToMidi()[0];

                if (p.Value > 0)
                {
                    int velocity = Util.RoundAndClamp(note.Velocity * velocityChange_, 0, 127);
                    if (velocity == 0)
                    {
                        return;
                    }

                    // 음표를 재생합니다.
                    // (Midi message pair를 번역하여 Midi message를 생성합니다.)
                    try
                    {
                        syn.NoteOn(p.Value >> 16, p.Value & 65535, velocity);
                        if (!noteOffBuffer_.ContainsKey(staff))
                        {
                            noteOffBuffer_.Add(staff, new List <Note>());
                        }
                        noteOffBuffer_[staff].Add(note_);
                    }
                    catch (ObjectDisposedException) { }
                    catch (FluidSynthInteropException) { }
                }
            }

            Util.TaskQueue.Add("noteOffBuffer", noteOffBufferCheckAndPlay, noteOffBuffer, note, velocityChange);

            //Console.WriteLine("End of note.");
        }
Esempio n. 11
0
 public void Apply(Synth synth)
 {
     synth.NoteOff(Channel, Key);
 }