亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? midicommon.pas

?? Delphi鋼琴源碼
?? PAS
字號:
unit MidiCommon;

interface

uses Classes, WinTypes, Messages, SysUtils, MMSystem;

const
  MIDI_ALLNOTESOFF = $7B;
  MIDI_NOTEON = $90;
  MIDI_NOTEOFF = $80;
  MIDI_KEYAFTERTOUCH = $A0;
  MIDI_CONTROLCHANGE = $B0;
  MIDI_PROGRAMCHANGE = $C0;
  MIDI_CHANAFTERTOUCH = $D0;
  MIDI_PITCHBEND = $E0;
  MIDI_SYSTEMMESSAGE = $F0;
  MIDI_BEGINSYSEX = $F0;
  MIDI_MTCQUARTERFRAME = $F1;
  MIDI_SONGPOSPTR = $F2;
  MIDI_SONGSELECT = $F3;
  MIDI_ENDSYSEX = $F7;
  MIDI_TIMINGCLOCK = $F8;
  MIDI_START = $FA;
  MIDI_CONTINUE = $FB;
  MIDI_STOP = $FC;
  MIDI_ACTIVESENSING = $FE;
  MIDI_SYSTEMRESET = $FF;

  MIM_OVERFLOW = WM_USER; { Input buffer overflow }
  MOM_PLAYBACK_DONE = WM_USER + 1; { Timed playback complete }

type
  { MIDI input event }
  TMidiBufferItem = record
    timestamp: DWORD; { Timestamp in milliseconds after midiInStart }
    data: DWORD; { MIDI message received }
    sysex: PMidiHdr; { Pointer to sysex MIDIHDR, nil if not sysex }
  end;
  PMidiBufferItem = ^TMidiBufferItem;

  { MIDI input buffer }
  TCircularBuffer = record
    RecordHandle: HGLOBAL; { Windows memory handle for this record }
    BufferHandle: HGLOBAL; { Windows memory handle for the buffer }
    pStart: PMidiBufferItem; { ptr to start of buffer }
    pEnd: PMidiBufferItem; { ptr to end of buffer }
    pNextPut: PMidiBufferItem; { next location to fill }
    pNextGet: PMidiBufferItem; { next location to empty }
    Error: Word; { error code from MMSYSTEM functions }
    Capacity: Word; { buffer size (in TMidiBufferItems) }
    EventCount: Word; { Number of events in buffer }
  end;
  PCircularBuffer = ^TCircularBuffer;

  { This is the information about the control that must be accessed by
    the MIDI input callback function in the DLL at interrupt time }
  PMidiCtlInfo = ^TMidiCtlInfo;
  TMidiCtlInfo = record
    hMem: THandle; { Memory handle for this record }
    PBuffer: PCircularBuffer; { Pointer to the MIDI input data buffer }
    hWindow: HWnd; { Control's window handle }
    SysexOnly: Boolean; { Only process System Exclusive input }
  end;

  { Information for the output timer callback function, also required at
    interrupt time. }
  PMidiOutTimerInfo = ^TMidiOutTimerInfo;
  TMidiOutTimerInfo = record
    hMem: THandle; { Memory handle for this record }
    PBuffer: PCircularBuffer; { Pointer to MIDI output data buffer }
    hWindow: HWnd; { Control's window handle }
    TimeToNextEvent: DWORD; { Delay to next event after timer set }
    MIDIHandle: HMidiOut; { MIDI handle to send output to copy of component's FMidiHandle property }
    PeriodMin: Word; { Multimedia timer minimum period supported }
    PeriodMax: Word; { Multimedia timer maximum period supported }
    TimerId: Word; { Multimedia timer ID of current event }
  end;

  { A MIDI input/output event }
  TMyMidiEvent = class(TPersistent)
  public
    MidiMessage: Byte; { MIDI message status byte }
    Data1: Byte; { MIDI message data 1 byte }
    Data2: Byte; { MIDI message data 2 byte }
    Time: DWORD; { Time in ms since midiInOpen }
    SysexLength: Word; { Length of sysex data (0 if none) }
    Sysex: PChar; { Pointer to sysex data buffer }
    destructor Destroy; override; { Frees sysex data buffer if nec. }
  end;
  PMyMidiEvent = ^TMyMidiEvent;

  { Encapsulates the MIDIHDR with its memory handle and sysex buffer }
  PMyMidiHdr = ^TMyMidiHdr;
  TMyMidiHdr = class(TObject)
  public
    hdrHandle: THandle;
    hdrPointer: PMIDIHDR;
    sysexHandle: THandle;
    sysexPointer: Pointer;
    constructor Create(BufferSize: Word);
    destructor Destroy; override;
  end;

{$IFDEF WIN32}
procedure midiHandler(
  hMidiIn: HMidiIn;
  wMsg: UINT;
  dwInstance: DWORD;
  dwParam1: DWORD;
  dwParam2: DWORD); stdcall export;
//function CircbufPutEvent(PBuffer: PCircularBuffer; PTheEvent: PMidiBufferItem): Boolean; stdcall; export;
{$ELSE}
procedure midiHandler(
  hMidiIn: HMidiIn;
  wMsg: Word;
  dwInstance: DWORD;
  dwParam1: DWORD;
  dwParam2: DWORD); export;
//function CircbufPutEvent(PBuffer: PCircularBuffer; PTheEvent: PMidiBufferItem): Boolean; export;
{$ENDIF}

function midiIOErrorString(IO: Boolean; WError: Word): string;

function GlobalSharedLockedAlloc(Capacity: Word; var hMem: HGLOBAL): Pointer;
procedure GlobalSharedLockedFree(hMem: HGLOBAL; ptr: Pointer);

function NoteToStr(note: integer; bzero: Boolean = False): string;
function MyTimeToStr(const Value: Integer): string;
function MyStrToTime(const Value: string): Integer;


implementation

function midiIOErrorString(IO: Boolean; WError: Word): string;
{ Convert the numeric return code from an MMSYSTEM function to a string }
var
  iError: Cardinal;
  errorDesc: PChar;
begin
  errorDesc := nil;
  try
    errorDesc := StrAlloc(MAXERRORLENGTH);
    if IO then
      iError := midiInGetErrorText(WError, errorDesc, MAXERRORLENGTH) else
      iError := midiOutGetErrorText(WError, errorDesc, MAXERRORLENGTH);
    if iError = 0 then
      result := StrPas(errorDesc)
    else
      result := 'Specified error number is out of range';
  finally
    if errorDesc <> nil then StrDispose(errorDesc);
  end;
end;

procedure midiHandler(hMidiIn: HMidiIn; wMsg: UINT; dwInstance: DWORD; dwParam1: DWORD; dwParam2: DWORD);
  function CircbufPutEvent(PBuffer: PCircularBuffer; PTheEvent: PMidiBufferItem): Boolean;
  begin
    if (PBuffer^.EventCount < PBuffer^.Capacity) then
    begin
      Inc(Pbuffer^.EventCount);
      { Todo: better way of copying this record }
      with PBuffer^.PNextput^ do
      begin
        Timestamp := PTheEvent^.Timestamp;
        Data := PTheEvent^.Data;
        Sysex := PTheEvent^.Sysex;
      end;
      { Move to next put location, with wrap }
      Inc(Pbuffer^.PNextPut);
      if (PBuffer^.PNextPut = PBuffer^.PEnd) then
        PBuffer^.PNextPut := PBuffer^.PStart;
      CircbufPutEvent := True;
    end else
      CircbufPutEvent := False;
  end;
var
  thisEvent: TMidiBufferItem;
  thisCtlInfo: PMidiCtlInfo;
  thisBuffer: PCircularBuffer;
begin
  case wMsg of
    mim_Open:
      { nothing};
    mim_Error:
      { TODO: handle (message to trigger exception?) };
    mim_Data, mim_Longdata, mim_Longerror:
      { Note: mim_Longerror included because there's a bug in the Maui
        input driver that sends MIM_LONGERROR for subsequent buffers when
        the input buffer is smaller than the sysex block being received }
      begin
        { TODO: Make filtered messages customisable, I'm sure someone wants
          to do something with MTC! }
        if (dwParam1 <> MIDI_ACTIVESENSING) and (dwParam1 <> MIDI_TIMINGCLOCK) then
        begin
          { The device driver passes us the instance data pointer we
            specified for midiInOpen. Use this to get the buffer address
            and window handle for the MIDI control }
          thisCtlInfo := PMidiCtlInfo(dwInstance);
          thisBuffer := thisCtlInfo^.PBuffer;
          { Screen out short messages if we've been asked to }
          if ((wMsg <> mim_Data) or (thisCtlInfo^.SysexOnly = False))
            and (thisCtlInfo <> nil) and (thisBuffer <> nil) then
          begin
            with thisEvent do
            begin
              Timestamp := dwParam2;
              if (wMsg = mim_Longdata) or (wMsg = mim_Longerror) then
              begin
                data := 0;
                sysex := PMidiHdr(dwParam1);
              end else
              begin
                data := dwParam1;
                sysex := nil;
              end;
            end;
            if CircbufPutEvent(thisBuffer, @thisEvent) then
              { Send a message to the control to say input's arrived }
              PostMessage(thisCtlInfo^.hWindow, mim_Data, 0, 0)
            else
              { Buffer overflow }
              PostMessage(thisCtlInfo^.hWindow, mim_Overflow, 0, 0);
          end;
        end;
      end;
    mom_Done:
      { Sysex output complete, dwParam1 is pointer to MIDIHDR }
      begin
        { Notify the control that its sysex output is finished.
          The control should call midiOutUnprepareHeader before freeing the buffer }
        PostMessage(PMidiCtlInfo(dwInstance)^.hWindow, mom_Done, 0, dwParam1);
      end;
  end; { End Case }
end;

destructor TMyMidiEvent.Destroy;
{ Free any sysex buffer associated with the event }
begin
  if (Sysex <> nil) then
    Freemem(Sysex, SysexLength);
  inherited Destroy;
end;

constructor TMyMidiHdr.Create(BufferSize: Word);
{ Allocate memory for the sysex header and buffer }
begin
  inherited Create;
  if BufferSize > 0 then
  begin
    hdrPointer := GlobalSharedLockedAlloc(sizeof(TMIDIHDR), hdrHandle);
    sysexPointer := GlobalSharedLockedAlloc(BufferSize, sysexHandle);
    hdrPointer^.lpData := sysexPointer;
    hdrPointer^.dwBufferLength := BufferSize;
  end;
end;

destructor TMyMidiHdr.Destroy;
begin
  GlobalSharedLockedFree(hdrHandle, hdrPointer);
  GlobalSharedLockedFree(sysexHandle, sysexPointer);
  inherited Destroy;
end;

function GlobalSharedLockedAlloc(Capacity: Word; var hMem: HGLOBAL): Pointer;
var
  ptr: Pointer;
begin
 { Allocate the buffer memory }
  hMem := GlobalAlloc(GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT, Capacity);
  if (hMem = 0) then
    ptr := nil else
  begin
    ptr := GlobalLock(hMem);
    if (ptr = nil) then
      GlobalFree(hMem);
  end;
{$IFNDEF WIN32}
  if (ptr <> nil) then
    GlobalPageLock(HIWORD(DWORD(ptr)));
{$ENDIF}
  GlobalSharedLockedAlloc := Ptr;
end;

procedure GlobalSharedLockedFree(hMem: HGLOBAL; ptr: Pointer);
begin
{$IFNDEF WIN32}
  if (ptr <> nil) then
    GlobalPageUnlock(HIWORD(DWORD(ptr)));
{$ENDIF}
  if (hMem <> 0) then
  begin
    GlobalUnlock(hMem);
    GlobalFree(hMem);
  end;
end;

function NoteToStr(note: integer; bzero: Boolean = False): string;
  function KeyToStr(key: integer): string;
  var
    n: integer;
    str: string;
  begin
    n := key mod 12;
    case n of
      0: str := 'C';
      1: str := 'C#';
      2: str := 'D';
      3: str := 'D#';
      4: str := 'E';
      5: str := 'F';
      6: str := 'F#';
      7: str := 'G';
      8: str := 'G#';
      9: str := 'A';
      10: str := 'A#';
      11: str := 'B';
    end;
    Result := str;
  end;
var
  n: integer;
  str: string;
begin
  n := note div 12;
  if bzero then // begin from C0 to C8
  begin
    str := KeyToStr(note);
    Result := str + IntToStr(note div 12);
  end else
  begin // begin from C2 to c5
    case n of
      0..1: str := UpperCase(KeyToStr(note)) + IntToStr(2 - n);
      2: str := UpperCase(KeyToStr(note));
      3: str := LowerCase(KeyToStr(note));
      4..8: str := LowerCase(KeyToStr(note)) + IntToStr(n - 3);
    end;
    Result := str;
  end;
end;

function MyStrToTime(const Value: string): Integer;
var
  hour: word;
  min: word;
  sec: word;
  msec: word;
begin //0:01:10.204
  try
    DecodeTime(StrToTime(Value), hour, min, sec, msec);
    Result := hour * 60 * 60 * 1000 + min * 60 * 1000 + sec * 1000 + msec;
  except
    Result := 0;
  end;
end;

function MyTimeToStr(const Value: Integer): string;
  function IntToLenStr(val: Integer; len: Integer): string;
  var
    str: string;
  begin
    str := IntToStr(val);
    while Length(str) < len do
      str := '0' + str;
    Result := str;
  end;
var
  hour: Integer;
  min: Integer;
  sec: Integer;
  msec: Integer;
begin
  msec := Value mod 1000;
  sec := Value div 1000;
  min := sec div 60;
  sec := sec mod 60;
  hour := min div 60;
  min := min mod 60;
  Result := IntToStr(hour) + ':' + IntToLenStr(min, 2) + ':' + IntToLenStr(sec, 2) + '.' + IntToLenStr(msec, 3);
end;

end.

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
一区二区三区.www| 欧美国产成人精品| 91久久线看在观草草青青 | 日韩一区二区三区在线| 婷婷久久综合九色国产成人| 欧美国产日韩在线观看| 国产日韩欧美制服另类| 精品国产凹凸成av人网站| 欧美日韩免费电影| 国产成人精品免费视频网站| 麻豆精品视频在线观看视频| 亚洲成人久久影院| 尤物视频一区二区| 一区二区在线观看av| 亚洲人妖av一区二区| 国产精品嫩草影院av蜜臀| 国产欧美精品日韩区二区麻豆天美 | 国产精品美女久久久久久久网站| 国产亚洲精久久久久久| 国产精品不卡在线观看| 亚洲一卡二卡三卡四卡无卡久久| 亚洲va欧美va天堂v国产综合| 免费精品视频在线| 国产成人午夜精品5599| 色综合网色综合| 日韩无一区二区| 国产精品久久二区二区| 亚洲国产成人porn| 国产一区二区三区久久久| 不卡的av网站| 日韩欧美一级二级| 18欧美乱大交hd1984| 日精品一区二区| 成人av免费观看| 欧美一区二区三区喷汁尤物| 国产日韩欧美一区二区三区综合| 一区二区三区国产精华| 精品亚洲aⅴ乱码一区二区三区| aaa欧美日韩| 精品国产乱码久久久久久久久| 中文字幕中文乱码欧美一区二区| 性感美女极品91精品| 粉嫩av一区二区三区在线播放| 在线观看亚洲一区| 中文字幕精品综合| 免费看日韩精品| 91麻豆成人久久精品二区三区| 精品久久99ma| 亚洲国产裸拍裸体视频在线观看乱了 | 蜜臀久久99精品久久久久宅男 | 日本韩国一区二区三区| 久久综合九色综合97婷婷| 一级精品视频在线观看宜春院| 国产乱码精品1区2区3区| 欧美日本国产视频| 亚洲在线视频一区| 菠萝蜜视频在线观看一区| 亚洲精品一区二区三区福利| 亚洲电影一级黄| 日本韩国精品一区二区在线观看| 国产日韩欧美不卡在线| 激情图片小说一区| 精品日韩在线观看| 美女在线视频一区| 欧美一区二区三区免费在线看| 亚洲综合成人在线视频| 97久久精品人人做人人爽| 亚洲国产精品国自产拍av| 国产呦萝稀缺另类资源| 精品久久久久久久久久久久包黑料| 肉色丝袜一区二区| 欧美一区二区三区播放老司机| 亚洲一区二区三区四区的| 日本精品一区二区三区高清| ...av二区三区久久精品| 成人理论电影网| 最新不卡av在线| 91蜜桃视频在线| 一区二区三区在线免费观看| 在线亚洲一区观看| 午夜免费久久看| 日韩美女主播在线视频一区二区三区| 性做久久久久久久久| 欧美日韩精品高清| 日韩在线播放一区二区| 欧美日韩不卡在线| 蜜桃免费网站一区二区三区| 精品国产区一区| 国产成人啪午夜精品网站男同| 日本一区二区成人| 色av成人天堂桃色av| 亚洲成年人网站在线观看| 欧美日韩国产乱码电影| 久久精品国产久精国产爱| 欧美成人午夜电影| 成人免费av在线| 亚洲视频免费观看| 欧美精品久久久久久久久老牛影院| 日韩电影在线免费观看| 精品日本一线二线三线不卡| 国产精品一区二区你懂的| 国产精品久久久久桃色tv| 欧美亚洲禁片免费| 国产在线一区二区| 亚洲最新在线观看| 日韩欧美亚洲国产精品字幕久久久| 国产成人av电影在线| 一区二区在线观看免费视频播放 | 国产风韵犹存在线视精品| 国产精品福利一区二区三区| 欧美日韩亚洲综合一区| 国产成人福利片| 亚洲成人激情社区| 欧美激情一区二区三区蜜桃视频| 在线亚洲一区二区| 激情都市一区二区| 亚洲午夜免费福利视频| 久久综合九色综合欧美亚洲| 精品视频999| 成人精品小蝌蚪| 乱一区二区av| 一区二区三区国产| 中文一区一区三区高中清不卡| 欧美日韩国产美女| 色综合天天综合给合国产| 紧缚捆绑精品一区二区| 亚洲最快最全在线视频| 中文字幕在线一区免费| 日韩欧美高清dvd碟片| 欧美色精品在线视频| av一本久道久久综合久久鬼色| 毛片一区二区三区| 日韩av不卡在线观看| 亚洲精品免费播放| 国产精品国产馆在线真实露脸| 欧美成人三级在线| 91麻豆精品国产91久久久久久久久 | 国产三区在线成人av| 日韩视频免费直播| 欧美理论电影在线| 欧美三级蜜桃2在线观看| 91在线免费播放| 成人99免费视频| 成人免费视频一区| 国产激情精品久久久第一区二区| 麻豆久久久久久| 美女在线一区二区| 九九国产精品视频| 国产综合色在线视频区| 精品一区二区三区在线播放视频| 午夜在线电影亚洲一区| 伊人婷婷欧美激情| 亚洲影视资源网| 亚洲国产综合视频在线观看| 亚洲男人的天堂av| 亚洲一区二区三区激情| 亚洲午夜精品在线| 亚洲国产日韩av| 日本视频一区二区三区| 蜜臀av性久久久久蜜臀aⅴ| 琪琪久久久久日韩精品| 免费高清在线视频一区·| 久久99精品一区二区三区三区| 麻豆久久一区二区| 国产成人在线视频网站| 成人看片黄a免费看在线| 99久久精品情趣| 日本高清无吗v一区| 9191成人精品久久| 欧美大片一区二区| 国产无一区二区| 亚洲欧美一区二区久久| 亚洲综合久久久| 免费在线观看成人| 国产夫妻精品视频| 99亚偷拍自图区亚洲| 欧美日韩电影在线| 欧美精品一区视频| 一区二区三区在线视频免费观看| 午夜精品一区二区三区三上悠亚| 激情综合色播激情啊| 不卡的av电影在线观看| 欧美日韩国产首页| 亚洲国产激情av| 石原莉奈在线亚洲三区| 国产盗摄一区二区| 欧美在线观看禁18| 2020国产精品| 亚洲最大成人综合| 国产成人av电影在线播放| 欧美视频精品在线| 久久久99精品免费观看| 亚洲一区二区三区美女| 国产成人精品aa毛片| 欧美精品粉嫩高潮一区二区| 日本一区二区三区在线观看| 三级欧美在线一区| 色综合久久综合中文综合网| 精品成人私密视频| 午夜精品免费在线观看|