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; } }
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 }
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; } } }
/* * /// <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); }
/// <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); }
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); } } } } }
/* * /// <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); }
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); } } } } }
/* * /// <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."); }
public void Apply(Synth synth) { synth.NoteOff(Channel, Key); }