如何在Delphi中更改MIDI音符的音高和音量?

时间:2011-07-30 18:30:44

标签: delphi midi

我在我的项目中使用以下代码在按键上播放midi音符(这是与midi相关的部分来源):

uses
MMSystem;

var
hMidi, midimsg, notenum, instrumNum :integer;

procedure TForm1.FormCreate(Sender: TObject);
begin
  midiOutOpen(@hmidi, 0, 0, 0, 0);
  midimsg := $C0+$100*29; // set midi instrument to overdriven guitar (29th in GM midi instrument list)
  midiOutShortMsg (hmidi, midimsg);
end;

procedure playNote(var note:integer);
begin
  midimsg := $90 + (note * $100) + (127 * $10000) + 0;
  midiOutShortMsg (hmidi, midimsg);
end;

procedure stopNote(var note:integer);
begin
  midimsg := $80 + (note * $100) + 0 ;
  midiOutShortMsg (hmidi, midimsg);
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  playNote(60);
end;

procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  stopNote(60);
end;

procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
  midiOutClose(hmidi);
end;

我知道有midi消息可以改变音高和音量。但我在delphi中找不到它们的用法示例。 请帮助我修改 playNote 程序,使声音类似于吉他弯曲效果(半音或全音调播放音符的平滑音高)和类似改变音符的音量(淡入)和淡出效果)。

提前谢谢!

2 个答案:

答案 0 :(得分:3)

我找到了解决方案。

const
  MIDI_NOTE_ON = $90;
  MIDI_NOTE_OFF = $80;
  MIDI_CHANGE_INSTRUMENT = $C0;
  MIDI_PITCH_BEND = $E0;

function MIDIEncodeMessage(Msg, Param1, Param2: byte): integer;
begin
  result := Msg + (Param1 shl 8) + (Param2 shl 16);
end;

procedure TForm4.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  midiOutClose(hMidi);
end;

procedure TForm4.FormCreate(Sender: TObject);
begin
  playing := false;
  midiOutOpen(@hMidi, 0, 0, 0, CALLBACK_NULL);
  midiOutShortMsg(hMidi, MIDIEncodeMessage(MIDI_CHANGE_INSTRUMENT, 19, 0));
end;

procedure TForm4.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if playing then Exit;
  ProgressBar1.Position := $2000;
  midiOutShortMsg(hMidi, MIDIEncodeMessage(MIDI_PITCH_BEND,
    lo(ProgressBar1.Position), hi(ProgressBar1.Position)));
  midiOutShortMsg(hMidi, MIDIEncodeMessage(MIDI_NOTE_ON, 50, 127));
  playing := true;
end;

procedure TForm4.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  midiOutShortMsg(hMidi, MIDIEncodeMessage(MIDI_NOTE_OFF, 50, 127));
  playing := false;
end;

procedure TForm4.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
begin
  ProgressBar1.StepBy(4*WheelDelta);
  midiOutShortMsg(hMidi, MIDIEncodeMessage(MIDI_PITCH_BEND,
    lo(ProgressBar1.Position), hi(ProgressBar1.Position)));
end;

在表单上放置TProgressBar,并将其MinMax分别设置为016383

然后你可以通过滚动鼠标滚轮来“弯曲”音高。 (请注意,处理鼠标滚轮时使用的因子4可能不适合您的鼠标和当前的鼠标设置。)

示例:pitchbend.exe [我从我的网站上删除了EXE文件,因为Google Chrome认为它是恶意软件。虽然这几乎肯定是误报,但我担心它会对我的谷歌排名产生负面影响。]

答案 1 :(得分:0)

您正在寻找pitch bend message

前四位为1110,后四位识别通道。对于14位弯音值,接下来的两个字节是MSB和LSB。 (第一位总是0。)

弯音杆的“中心”值是8192.

例如,通道1上的最低弯曲点:

11100000 00000000 00000000

音高上升和下降完全取决于合成器。许多合成器支持changing this range with an RPN,但不是全部。