📄 wavout.dpr
字号:
(*
----------------------------------------------
wavOut.dpr
Voice Communicator components version 2.5
Example on how to load and playback the file from memory
----------------------------------------------
This source code cannot be used without
proper permission granted to you as a private
person or an entity by the Lake of Soft, Ltd
Visit http://lakeofsoft.com/ for details.
Copyright (c) 2001, 2005 Lake of Soft, Ltd
All rights reserved
----------------------------------------------
created by:
Lake, 2 Mar 2003
modified by:
Lake, Apr-Jun 2003
Lake, Oct 2005
----------------------------------------------
*)
{$DEFINE CONSOLE } // for some reason not defined by compiler in main project file
// needed for unaDef.inc to work correctly
{$IFDEF CONSOLE}
{$APPTYPE CONSOLE }
{$ENDIF}
{$I unaDef.inc }
program
wavOut;
uses
Windows, unaTypes, unaUtils, unaClasses,
{$IFDEF VCX_DEMO }
Math,
{$ENDIF}
MMSystem, unaWave, unaMsAcmClasses;
{$R *.res }
type
//
// -- wavOutClass --
//
wavOutClass = class
private
f_acm: unaMsAcm;
f_wavRead: unaRiffStream;
f_waveOut: unaWaveOutDevice;
// wndProc
f_data: pointer;
f_dataSize: unsigned;
f_dataPos: unsigned;
f_backChunk: pointer;
f_sampleSize: unsigned;
//
f_isLoop: bool;
f_isBack: bool;
f_loopCount: int;
//
procedure myOnDA(sender: tObject; data: pointer; len: unsigned);
procedure myOnACF(sender: tObject; data: pointer; len: unsigned);
public
procedure beforeDestruction(); override;
//
function init(): bool;
procedure run();
end;
{ wavOutClass }
//
procedure wavOutClass.beforeDestruction();
begin
//
freeAndNil(f_wavRead);
freeAndNil(f_waveOut);
freeAndNil(f_acm);
//
mrealloc(f_data);
mrealloc(f_backChunk);
//
logMessage('Done.');
end;
//
function wavOutClass.init(): bool;
var
i: int;
s: string;
begin
setInfoMessageMode('<none>', nil, 1, 0);
//
result := false;
logMessage('Init.');
//
if (0 < paramCount) then begin
//
s := '';
for i := 1 to paramCount do begin
s := paramStr(i);
if (('' <> s) and (not (s[1] in ['/', '\']))) then
break
else
s := '';
end;
//
if ('' <> s) then begin
//
f_acm := unaMsAcm.create();
f_acm.enumDrivers();
f_wavRead := unaRiffStream.create(s, false, false, f_acm);
//
result := (0 = f_wavRead.status);
//
if (result) then begin
logMessage('Input file: <' + s + '>');
//
f_wavRead.onDataAvailable := myOnDA;
f_wavRead.assignStream(false, nil);
//
f_waveOut := unaWaveOutDevice.create(unsigned(switchValue('d', false, int(WAVE_MAPPER))), false, false, 5);
f_waveOut.onAfterChunkFeed := myOnACF;
f_waveOut.setSampling(f_wavRead.dstFormat^);
//
f_isLoop := hasSwitch('L');
f_isBack := hasSwitch('B');
end;
end;
end
else
logMessage(
' syntax: wavOut <file.wav> [/l] [/b] [/dN]'#13#10#13#10 +
' /l - loop'#13#10 +
' /b - backward direction'#13#10 +
' /dN - use waveOut device #N');
end;
//
procedure wavOutClass.myOnACF(sender: tObject; data: pointer; len: unsigned);
var
size: int;
feed: unsigned;
waveOut: unaWaveOutDevice;
begin
waveOut := unaWaveOutDevice(sender);
//
if ((0 < f_dataSize) and f_isLoop or (not f_isLoop and (1 > f_loopCount))) then begin
//
feed := 0;
repeat
//
if (f_isBack) then begin
//
size := min(len - feed, f_dataPos);
//
if (0 < size) then begin
dec(f_dataPos, size);
move(pArray(f_data)[f_dataPos], f_backChunk^, size);
//
// reverse samples
waveReverse(f_backChunk, size div int(f_sampleSize), waveOut.srcFormat.wBitsPerSample, waveOut.srcFormat.nChannels);
//
waveOut.write(f_backChunk, size);
end;
//
if (1 > f_dataPos) then begin
inc(f_loopCount);
f_dataPos := f_dataSize; // loop
end;
end
else begin
//
size := min(int(len - feed), int(f_dataSize - f_dataPos));
//
if (0 < size) then begin
waveOut.write(@pArray(f_data)[f_dataPos], size);
//
inc(f_dataPos, size);
end;
//
if (f_dataPos >= f_dataSize) then begin
inc(f_loopCount);
f_dataPos := 0; // loop
end;
end;
//
inc(feed, size);
//
until ((not f_isLoop and (0 < f_loopCount)) or (1 > size) or (feed >= len));
end;
end;
//
procedure wavOutClass.myOnDA(sender: tObject; data: pointer; len: unsigned);
var
pos: int;
begin
if ((nil <> data) and (0 < len)) then begin
//
pos := f_dataSize;
inc(f_dataSize, len);
mrealloc(f_data, f_dataSize);
//
move(data^, pArray(f_data)[pos], len);
end;
end;
//
procedure wavOutClass.run();
begin
logMessage('Loading input file...');
f_wavRead.open();
//
while (not f_wavRead.streamIsDone) do begin
// wait until the whole file is loaded
windows.sleep(50);
end;
//
f_wavRead.close(); // no longer needed
//
logMessage('Done, memory taken: ' + int2str(f_dataSize shr 10, 10, 3) + ' KB');
//
logMessage('Starting playback...');
//
if (f_isBack) then begin
//
f_dataPos := f_dataSize;
f_backChunk := malloc(f_waveOut.chunkSize);
f_sampleSize := (f_waveOut.srcFormat.wBitsPerSample shr 3) * f_waveOut.srcFormat.nChannels;
end;
//
f_loopCount := 0;
f_waveOut.open();
f_waveOut.flush(); // start self-feedback process
//
logMessage(#13#10'-------------------------' +
#13#10'Backward direction: ' + bool2strStr(f_isBack) +
#13#10'Looped playback : ' + bool2strStr(f_isLoop) +
#13#10'-------------------------' +
#13#10'Press Esc to terminate' +
#13#10'');
//
repeat
if (0 <> (windows.getKeyState(VK_ESCAPE) and $8000)) then begin
//
break;
end;
//
windows.sleep(50);
{$IFDEF CONSOLE}
// write() is safe in console mode only
write('Playback position: ' + int2str(f_dataPos, 10, 3) + '; Loops: ' + int2str(f_loopCount) + ' '#13);
{$ENDIF}
until (not f_isLoop and (0 < f_loopCount));
//
windows.flushConsoleInputBuffer(windows.getStdHandle(STD_INPUT_HANDLE)); // remove all pressed keys from queue
//
{$IFDEF CONSOLE}
logMessage('');
{$ENDIF}
end;
// -- main --
begin
infoMessage('wavOut, version 1.0 Copyright (c) 2003-2005 Lake of Soft, Ltd');
infoMessage('VC components version 2.5 http://lakeofsoft.com/vc'#13#10);
//
with (wavOutClass.create()) do
try
if (init()) then
run();
finally
free();
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -