ACMWaveIn.pas 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. unit ACMWaveIn;
  2. interface
  3. uses
  4. msacm, Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, mmsystem;
  5. type
  6. TOnData = procedure(data: pointer; size: longint) of object;
  7. TACMWaveIn = class(TWinControl)
  8. private
  9. FOnData: TOnData;
  10. Fbuffersize: Integer;
  11. //FDeviceID: Integer;
  12. procedure WaveInCallback(var msg: TMessage); message MM_WIM_DATA;
  13. procedure Setbuffersize(Value: Integer);
  14. { Private declarations }
  15. protected
  16. procedure TWMPaint(var msg: TWMPaint); message WM_PAINT;
  17. { Protected declarations }
  18. public
  19. constructor Create(AOwner: TComponent); override;
  20. procedure Open(format: PWaveFormatEx; DeviceID: Integer = 0);
  21. procedure Close;
  22. function getsample: int64;
  23. { Public declarations }
  24. published
  25. property BufferSize: Integer read Fbuffersize write Setbuffersize default 160;
  26. property OnData: TOnData read FOnData write FOnData;
  27. { Published declarations }
  28. end;
  29. var
  30. closed: boolean;
  31. sizebuf: integer;
  32. HWaveIn1: PHWaveIn;
  33. procedure Register;
  34. implementation
  35. procedure Register;
  36. begin
  37. RegisterComponents('Milos', [TACMWaveIn]);
  38. end;
  39. procedure TACMWaveIn.TWMPaint(var msg: TWMPaint); //display icon
  40. var
  41. icon: HIcon;
  42. dc: HDC;
  43. begin
  44. if csDesigning in ComponentState then
  45. begin
  46. icon := LoadIcon(HInstance, MAKEINTRESOURCE('TACMWAVEIN'));
  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. constructor TACMWaveIn.Create(AOwner: TComponent);
  57. begin
  58. inherited create(AOwner);
  59. width := 32;
  60. height := 32;
  61. Fbuffersize := 160;
  62. Visible := false;
  63. end;
  64. procedure TACMWaveIn.WaveInCallback(var msg: TMessage); //this is called when is buffer full
  65. var
  66. Header: PWaveHdr;
  67. i, bytesrecorded: integer;
  68. data: PChar;
  69. begin
  70. {block has been recorded}
  71. Header := PWaveHdr(msg.lparam);
  72. if closed = false then
  73. begin
  74. i := waveInUnPrepareHeader(HWaveIn1^, Header, sizeof(TWavehdr));
  75. if i <> 0 then raise Exception.Create('In Un Prepare error');
  76. bytesrecorded := header.dwbytesrecorded;
  77. getmem(data, bytesrecorded); //allocate memory
  78. move(header.lpdata^, data^, bytesrecorded); //copy data
  79. if assigned(FOnData) then
  80. begin
  81. FOnData(data, bytesrecorded);
  82. end;
  83. Freemem(data); //free memory
  84. {reuse a old memory block}
  85. header.dwbufferlength := sizebuf;
  86. header.dwbytesrecorded := 0;
  87. header.dwUser := 0;
  88. header.dwflags := 0;
  89. header.dwloops := 0;
  90. {prepare the old block}
  91. i := waveInPrepareHeader(HWaveIn1^, Header, sizeof(TWavehdr));
  92. if i <> 0 then raise Exception.Create('In Prepare error');
  93. {add it to the buffer}
  94. i := waveInAddBuffer(HWaveIn1^, Header, sizeof(TWaveHdr));
  95. if i <> 0 then raise Exception.Create('Add buffer error');
  96. end
  97. else
  98. begin //free buffers if closed
  99. dispose(header.lpdata);
  100. dispose(header);
  101. end;
  102. end;
  103. procedure TACMWaveIn.Open(format: PWaveFormatEx; DeviceID: Integer = 0);
  104. var
  105. WaveFormat: PWaveFormatEx;
  106. Header: PWaveHdr;
  107. memBlock: PChar;
  108. i, j, maxsizeformat: integer;
  109. begin
  110. if (hwavein1 = nil) and (format <> nil) then
  111. begin
  112. acmMetrics(0, ACM_METRIC_MAX_SIZE_FORMAT, MaxSizeFormat);
  113. getmem(WaveFormat, MaxSizeFormat);
  114. move(format^, waveformat^, maxsizeformat);
  115. //sizebuf := format.nAvgBytesPerSec div 5; //改变此处的大小,可以实现减少延时的作用
  116. sizebuf := 325; //GSM610
  117. //sizebuf := 160; //G729
  118. HWaveIn1 := new(PHWaveIn);
  119. // create record handle with waveformatex structure
  120. i := WaveInOpen(HWaveIn1, DeviceID, waveformat, handle, 0, CALLBACK_WINDOW or WAVE_MAPPED);
  121. if i <> 0 then
  122. begin
  123. raise Exception.Create('Problem creating record handle' + inttostr(i));
  124. exit;
  125. end;
  126. closed := false;
  127. {need to add some buffers to the recording queue}
  128. {in case the messages that blocks have been recorded}
  129. {are delayed}
  130. for j := 1 to 3 do
  131. begin
  132. {make a new block}
  133. //Header := new(PWaveHdr);
  134. //memBlock := new(PChar);
  135. getmem(memblock, sizebuf); //allocate memory
  136. Header := new(PwaveHdr);
  137. header.lpdata := memBlock;
  138. header.dwbufferlength := sizebuf;
  139. header.dwbytesrecorded := 0;
  140. header.dwUser := 0;
  141. header.dwflags := 0;
  142. header.dwloops := 0;
  143. {prepare the new block}
  144. i := waveInPrepareHeader(HWaveIn1^, Header, sizeof(TWavehdr));
  145. if i <> 0 then raise Exception.Create('In Prepare error');
  146. {add it to the buffer}
  147. i := waveInAddBuffer(HWaveIn1^, Header, sizeof(TWaveHdr));
  148. if i <> 0 then raise Exception.Create('Add buffer error');
  149. end; {of loop}
  150. {finally start recording}
  151. i := waveInStart(HwaveIn1^);
  152. if i <> 0 then raise Exception.Create('Start error');
  153. end;
  154. end;
  155. procedure TACMWaveIn.Close;
  156. begin
  157. if HWaveIn1 <> nil then
  158. begin
  159. closed := true;
  160. WaveInReset(HWaveIn1^);
  161. WaveInClose(HWaveIn1^);
  162. dispose(HWaveIn1);
  163. HWaveIn1 := nil;
  164. end;
  165. end;
  166. function TACMWaveIn.getsample: int64;
  167. var
  168. mt: TMMTime;
  169. begin
  170. mt.wType := TIME_SAMPLES;
  171. waveInGetPosition(HWaveIn1^, @mt, sizeof(mt));
  172. Result := mt.sample;
  173. end;
  174. procedure TACMWaveIn.Setbuffersize(Value: Integer);
  175. begin
  176. if Value>0 then
  177. Fbuffersize := Value;
  178. end;
  179. end.