MIDI声音仅在一个声道(左或右)

时间:2018-04-23 19:28:16

标签: c# wpf naudio

我有一个WPF应用程序,它需要播放MIDI声音,但只能在一个声道中 - 左或右耳机声道。

我有一段播放MIDI音符的代码(在两个频道中),但是我不知道如何修改它以仅在RIGHT或仅在LEFT频道上播放MIDI声音。

这是我的代码:

public static class MidiNote
{
    public static MidiOut MidiOut = new MidiOut(0);
    public static void PlayNote(int key, int duration)
    {
        MidiOut.Volume = 65535;
        MidiOut.Send(MidiMessage.StartNote(key, 127, 1).RawData);
        Thread.Sleep(duration);
        MidiOut.Send(MidiMessage.StopNote(key, 0, 1).RawData);
    }
}

我找到了一些部分答案,但我不知道如何使用它们。我读了这两篇文章:

Play sound on specific channel with NAudio

How to play sound only on the left channel of the headphone and only on the right channel of the headphone in c#?

1 个答案:

答案 0 :(得分:2)

当您使用MIDI时,您必须向MIDI OUT设备发送适当的MIDI信息(控制变更或CC信息),告诉它您要使用的PAN设置。

PAN设置值应在0-127范围内,其中:

  • 0 = PAN HARD LEFT
  • 127 = PAN HARD RIGHT
  • 64 = PAN CENTER

我使用您的代码作为起点,并添加了一些方法来调整MIDI OUT设备的PAN设置。

我的示例调用演示了PANNING,就好像它是一个CONSOLE应用程序,但新方法应该在现有的类/ WPF应用程序中正常工作。

public static class MidiNote
{
    public static MidiOut MidiOut = new MidiOut(0);

    public static void PlayNote(int key, int duration)
    {
        MidiOut.Volume = 65535;
        MidiOut.Send(MidiMessage.StartNote(key, 127, 1).RawData);
        Thread.Sleep(duration);
        MidiOut.Send(MidiMessage.StopNote(key, 0, 1).RawData);
    }

    public static void SetPanHardLeft()
    {
        var panSettingHardLeft = 0;
        var cce = new ControlChangeEvent(0L, 1, MidiController.Pan, panSettingHardLeft);
        MidiOut.Send( cce.GetAsShortMessage() );
    }

    public static void SetPanHardRight()
    {
        var panSettingHardRight = 127;
        var cce = new ControlChangeEvent(0L, 1, MidiController.Pan, panSettingHardRight);
        MidiOut.Send(cce.GetAsShortMessage());
    }

    public static void SetPanCenter()
    {
        var panSettingCenter = 64;
        var cce = new ControlChangeEvent(0L, 1, MidiController.Pan, panSettingCenter);
        MidiOut.Send(cce.GetAsShortMessage());
    }

    public static void PlayNoteRightChannel(int key, int duration)
    {
        var panSettingHardRight = 127;
        var cce = new ControlChangeEvent(0L, 1, MidiController.Pan, panSettingHardRight);
        MidiOut.Send(cce.GetAsShortMessage());

        PlayNote(key, duration);
    }

    static void Main(string[] args)
    {
        // Plays using current setting (probably CENTER)
        Console.WriteLine( "Pan setting unchanged (should be CENTER)");
        PlayNote( 50, 2000 );

        // Set the PAN for the MIDI device to HARD LEFT...
        Console.WriteLine("Pan setting HARD LEFT");
        SetPanHardLeft();
        // ...and play the note again
        PlayNote( 50, 2000);

        // Set the PAN for the MIDI device to HARD RIGHT...
        Console.WriteLine("Pan setting HARD RIGHT");
        SetPanHardRight();
        // ...and play the note again
        PlayNote(50, 2000);

        // Set the PAN for the MIDI device back to CENTER...
        Console.WriteLine("Pan setting CENTER");
        SetPanCenter();
        // ...and play the note one last time
        PlayNote(50, 2000);
    }

}