ACMWaveOut.pas 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. unit ACMWaveOut;
  2. interface
  3. uses
  4. msacm, mmsystem, Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
  5. type
  6. TACMWaveOut = class(TWinControl)
  7. private
  8. FOnDone: TNotifyEvent;
  9. procedure WaveOutCallback(var msg: TMessage); message MM_WOM_DONE;
  10. { Private declarations }
  11. protected
  12. procedure TWMPaint(var msg: TWMPaint); message WM_PAINT;
  13. { Protected declarations }
  14. public
  15. { Public declarations }
  16. constructor Create(AOwner: TComponent); override;
  17. //destructor Destroy;
  18. procedure Open(format: PWaveFormatEx; DeviceID: Integer = 0);
  19. procedure PlayBack(data: pointer; size: longint);
  20. procedure Close;
  21. procedure Reset;
  22. function getsample: cardinal;
  23. published
  24. { Published declarations }
  25. property OnDone: TNotifyEvent read FOnDone write FOnDone;
  26. end;
  27. var
  28. HWaveOut1: PHWaveOut;
  29. closed: boolean;
  30. procedure Register;
  31. implementation
  32. constructor TACMWaveOut.create(AOwner: TComponent);
  33. begin
  34. inherited Create(AOWner);
  35. width := 32;
  36. height := 32;
  37. Visible := false;
  38. end;
  39. procedure TACMWaveOut.TWMPaint(var msg: TWMPaint); //draw icon
  40. var
  41. icon: HIcon;
  42. dc: HDC;
  43. begin
  44. if csDesigning in ComponentState then
  45. begin
  46. icon := LoadIcon(HInstance, MAKEINTRESOURCE('TACMWAVEOUT'));
  47. dc := GetDC(Handle);
  48. DrawIcon(dc, 0, 0, icon);
  49. Width := 32;
  50. Height := 32;
  51. ReleaseDC(Handle, dc);
  52. FreeResource(icon);
  53. end;
  54. ValidateRect(Handle, nil);
  55. end;
  56. procedure TACMWaveOut.Open(format: PWaveFormatEx; DeviceID: Integer = 0);
  57. var
  58. waveformat: PWaveFormatEx;
  59. maxsizeformat, i: integer;
  60. begin
  61. if (format <> nil) and (HWaveOut1 = nil) then
  62. begin
  63. acmMetrics(0, ACM_METRIC_MAX_SIZE_FORMAT, MaxSizeFormat);
  64. getmem(WaveFormat, MaxSizeFormat);
  65. move(format^, waveformat^, maxsizeformat);
  66. HWaveOut1 := new(PHWaveOut);
  67. //create playing handle with waveformatex structure
  68. i := WaveOutOpen(HWaveOut1, DeviceID, waveformat, handle, 0, CALLBACK_WINDOW or WAVE_MAPPED);
  69. if i <> 0 then
  70. begin
  71. raise Exception.Create('Problem creating playing handle' + inttostr(i));
  72. //showmessage('Problem creating playing handle' + inttostr(i));
  73. exit;
  74. end;
  75. closed := false;
  76. end;
  77. end;
  78. procedure TACMWaveOut.PlayBack(data: pointer; size: longint);
  79. var
  80. Header: PWaveHdr;
  81. memblock: pointer;
  82. i: integer;
  83. begin
  84. if HWaveOut1 <> nil then
  85. begin
  86. header := new(PWaveHdr);
  87. //memblock := new(pointer);
  88. getmem(memblock, size);
  89. move(data^, memBlock^, size);
  90. header.lpdata := memBlock;
  91. header.dwbufferlength := size;
  92. header.dwbytesrecorded := size;
  93. header.dwUser := 0;
  94. header.dwflags := 0;
  95. header.dwloops := 0;
  96. i := WaveOutPrepareHeader(HWaveOut1^, header, sizeof(TWaveHdr));
  97. if i <> 0 then raise Exception.Create('WaveOutPrepareHeader error');
  98. i := WaveOutWrite(HWaveOut1^, header, sizeof(TWaveHdr));
  99. if i <> 0 then raise Exception.Create('WaveOutWrite error');
  100. end;
  101. end;
  102. procedure TACMWaveOut.WaveOutCallback(var msg: TMessage);
  103. var header: PWaveHdr;
  104. i: integer;
  105. begin
  106. header := PWaveHdr(msg.LParam);
  107. if closed = false then
  108. begin
  109. i := WaveOutUnPrepareHeader(HWaveOut1^, header, sizeof(TWaveHdr));
  110. if i <> 0 then raise Exception.Create('WaveOutPrepareHeader error');
  111. end;
  112. if assigned(FOnDone) then
  113. begin
  114. FOnDone(self);
  115. end;
  116. dispose(Header^.lpData);
  117. dispose(Header);
  118. end;
  119. procedure TACMWaveOut.Close;
  120. begin
  121. if HWaveOut1 <> nil then
  122. begin
  123. closed := TRUE;
  124. WaveOutReset(HWaveOut1^);
  125. WaveOutClose(HWaveOut1^);
  126. HWaveOut1 := nil;
  127. end;
  128. end;
  129. procedure TACMWaveOut.Reset;
  130. begin
  131. if HWaveOut1 <> nil then
  132. begin
  133. WaveOutReset(HWaveOut1^);
  134. end;
  135. end;
  136. procedure Register;
  137. begin
  138. RegisterComponents('Milos', [TACMWaveOut]);
  139. end;
  140. function TACMWaveOut.getsample: cardinal;
  141. var
  142. mt: TMMTime;
  143. begin
  144. Result := 0;
  145. mt.wType := TIME_SAMPLES;
  146. if Closed then exit;
  147. waveOutGetPosition(HWaveout1^, @mt, sizeof(mt));
  148. Result := mt.sample;
  149. end;
  150. end.