喫茶XRAYトップページ

[スレッド全体
]

[10283] Msg.lParamで示されたポインタで配列を操作したい返信 削除
2016/8/10 (水) 20:32:05 taki
マスター、みなさん 助けてください。

ダブルバッファで連続して音データを再生するプログラムの一部です。
MM_WOM_DONEで返されたメッセージのMsg.lParamにwhdr1またはwhdr2の
どちらかのアドレスが格納されて返ってきます。
そのアドレスでabuf1もしくはabuf2の配列を操作したいのです。

以下がソースの一部です。長くてごめんなさい。

type
  Tabuf = array[1..44100] of smallint;

var
  abuf1:Tabuf;   // abuf1:array[1..44100] of smallint;
  abuf2:Tabuf;   // abuf2:array[1..44100] of smallint;
 
  whdr1,whdr2:Twavehdr;

// 再生開始
procedure TForm1.StartPlay;
begin
  // ウェブヘッダーをセット
  with whdr1 do
  begin
    lpdata := @abuf1;
    dwbufferlength := sizeof(abuf1);
    dwbytesrecorded := 0;
    dwUser := 0;
    dwFlags := WHDR_BEGINLOOP or WHDR_ENDLOOP;
    dwloops := 1;
    lpNext := NIL;
    reserved := 0;
  end;

  with whdr2 do
  begin
    lpdata := @abuf2;
    dwbufferlength := sizeof(abuf2);
    dwbytesrecorded := 0;
    dwUser := 0;
    dwFlags := WHDR_BEGINLOOP or WHDR_ENDLOOP;
    dwloops := 1;
    lpNext := NIL;
    reserved := 0;
  end;

  // 出力デバイスを開く
  waveOutOpen(@hwo,WAVE_MAPPER,@wfe,handle,0,CALLBACK_WINDOW);
  // 波形データを準備する
  waveOutPrepareHeader(hwo,@whdr1,sizeof(Twavehdr));
  waveOutPrepareHeader(hwo,@whdr2,sizeof(Twavehdr));
  //
end;

// ここが問題の手続き
procedure SetWaveData(buf:Pointer);  // 引数で受け取る時はPointer型
var
  i:integer;
begin
  for i := 1 to Length(buf) do begin   // 内部では配列として操作したい
    buf[i] := XXX;
  end;
end;

// メッセージ処理
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
  var Handled: Boolean);
begin

  ・・・略・・・

  // MM_WOM_DONE ///////////////////////
  if Msg.message = MM_WOM_DONE then begin

  // Msg.lParam には、出力バッファを表す WAVEHDR 構造体へのポインタが格納されています

  // SetWaveData手続きでabuf1もしくはabuf2にデータをセットする
    SetWaveData(Twavehdr(Pointer(Msg.lParam)^).lpData));  // <-ここで使いたい

 // waveOutWrite(hwo,@whdr1,sizeof(Twavehdr));
    waveOutWrite(hwo,Msg.lParam,sizeof(Twavehdr));  // <-こんな感じでも使えるかも
 
  end;

  ・・・略・・・

end;


Tabuf(buf)とかすると、「正しくない型キャスト」と叱られてしまいました。


[10284] Re: Msg.lParamで示されたポインタで配列を操作したい返信 削除
2016/8/10 (水) 22:16:49 Mr.XRAY
▼ takiさん

> そのアドレスでabuf1もしくはabuf2の配列を操作したいのです。

こういうのは難しいですね.
コーディングの好みもあるかも知れません.
メッセージの処理の部分だけ.例えばです.

動作確認は Windows 7 U64(SP1) + Delphi XE(UP1) Pro です.

implementation

{$R *.dfm}

type
  Tabuf = array[1..44100] of smallint;

var
  abuf1:Tabuf;

procedure TForm1.Button1Click(Sender: TObject);
begin
  abuf1[1] := 100;
//  PostMessage(Handle, MM_WOM_DONE, 0, LPARAM(@abuf1[1]));
  PostMessage(Handle, MM_WOM_DONE, 0, LPARAM(@abuf1));
end;

// 引数の型をTaBufにした方が処理がしやすいかな,と...
procedure SetWaveData(var buf: Tabuf);
begin
  buf[1] := buf[1] + 500;
  buf[3] := 133;
end;

procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
  var Handled: Boolean);
var
  LpBuf : ^Tabuf;
  LText  : string;
begin
  if Msg.message = MM_WOM_DONE then begin
    LpBuf := Pointer(Msg.lParam);
    SetWaveData(LpBuf^);

    LText := IntToStr(LpBuf[1]) + sLineBreak +  IntToStr(LpBuf[3]);
    MessageBox(Handle, PChar(LText), '結果', MB_ICONINFORMATION);
  end;
end;



[10285] Re2: Msg.lParamで示されたポインタで配列を操作したい返信 削除
2016/8/10 (水) 22:39:21 Mr.XRAY
>     LText := IntToStr(LpBuf[1]) + sLineBreak +  IntToStr(LpBuf[3]);

逆参照なので正確には以下ですが,ほとんど^は省略可能でしたよね...

    LText := IntToStr(LpBuf^[1]) + sLineBreak +  IntToStr(LpBuf^[3]);


[▼次のスレッド]
INCM/CMT
Cyclamen v3.82