📄 wavestorage.pas
字号:
if NeededBytes > DstBufferSize then
begin
DstBufferSize := NeededBytes;
ReallocMem(DstBuffer, DstBufferSize);
end;
FillChar(ACMHeader, SizeOf(TACMSTREAMHEADER), 0);
ACMHeader.cbStruct := SizeOf(TACMSTREAMHEADER);
ACMHeader.pbSrc := SrcBuffer;
ACMHeader.cbSrcLength := BufferOffset;
ACMHeader.pbDst := DstBuffer;
ACMHeader.cbDstLength := NeededBytes;
acmStreamPrepareHeader(ACMStream, ACMHeader, 0);
acmStreamConvert(ACMStream, ACMHeader, ACM_STREAMCONVERTF_END);
acmStreamUnprepareHeader(ACMStream, ACMHeader, 0);
inherited Write(ACMHeader.pbDst^, ACMHeader.cbDstLengthUsed);
end;
acmStreamClose(ACMStream, 0);
Reset;
end;
Result := inherited EndRewrite;
end;
function TWaveStreamConverter.Write(const Buffer; Count: Integer): Integer;
var
NeededBytes: DWORD;
Flags: Integer;
begin
if ACMStream <> 0 then
begin
Result := -1;
Flags := ACM_STREAMCONVERTF_BLOCKALIGN;
if Position = 0 then
Flags := Flags or ACM_STREAMCONVERTF_START;
if BufferOffset > 0 then
begin
if BufferOffset + DWORD(Count) > SrcBufferSize then
begin
SrcBufferSize := BufferOffset + DWORD(Count);
ReallocMem(SrcBuffer, SrcBufferSize);
end;
CopyMemory(Pointer(DWORD(SrcBuffer) + BufferOffset), @Buffer, Count);
end;
acmStreamSize(ACMStream, DWORD(Count) + BufferOffset, NeededBytes, ACM_STREAMSIZEF_SOURCE);
if NeededBytes > DstBufferSize then
begin
DstBufferSize := NeededBytes;
ReallocMem(DstBuffer, DstBufferSize);
end;
FillChar(ACMHeader, SizeOf(TACMSTREAMHEADER), 0);
ACMHeader.cbStruct := SizeOf(TACMSTREAMHEADER);
if BufferOffset <> 0 then
ACMHeader.pbSrc := SrcBuffer
else
ACMHeader.pbSrc := @Buffer;
ACMHeader.cbSrcLength := BufferOffset + DWORD(Count);
ACMHeader.pbDst := DstBuffer;
ACMHeader.cbDstLength := NeededBytes;
acmStreamPrepareHeader(ACMStream, ACMHeader, 0);
acmStreamConvert(ACMStream, ACMHeader, Flags);
acmStreamUnprepareHeader(ACMStream, ACMHeader, 0);
if inherited Write(ACMHeader.pbDst^, ACMHeader.cbDstLengthUsed) >= 0 then
Result := Count;
BufferOffset := 0;
if ACMHeader.cbSrcLength <> ACMHeader.cbSrcLengthUsed then
begin
BufferOffset := ACMHeader.cbSrcLength - ACMHeader.cbSrcLengthUsed;
if BufferOffset > SrcBufferSize then
begin
SrcBufferSize := BufferOffset;
ReallocMem(SrcBuffer, SrcBufferSize);
end;
CopyMemory(SrcBuffer, Pointer(DWORD(ACMHeader.pbSrc) +
ACMHeader.cbSrcLengthUsed), BufferOffset);
end;
end
else
Result := inherited Write(Buffer, Count);
end;
function TWaveStreamConverter.CanRead: Boolean;
var
Dummy: HACMSTREAM;
begin
Result := Valid and (not Assigned(fBufferFormat) or
(acmStreamOpen(Dummy, 0, fWaveFormat, fBufferFormat, nil, 0, 0,
ACM_STREAMOPENF_QUERY) = 0));
end;
function TWaveStreamConverter.BeginRead: Boolean;
begin
Result := False;
if Valid and (not Assigned(fBufferFormat) or
(acmStreamOpen(ACMStream, 0, fWaveFormat, fBufferFormat, nil, 0, 0,
ACM_STREAMOPENF_NONREALTIME) = 0)) then
begin
if not inherited BeginRead then
begin
acmStreamClose(ACMStream, 0);
ACMStream := 0;
end
else
Result := True;
end;
end;
function TWaveStreamConverter.EndRead: Boolean;
begin
if ACMStream <> 0 then
begin
acmStreamClose(ACMStream, 0);
Reset;
end;
Result := inherited EndRead;
end;
function TWaveStreamConverter.Read(var Buffer; Count: Integer): Integer;
var
NeededBytes: DWORD;
ReadBytes: Integer;
Flags: Integer;
begin
if ACMStream <> 0 then
begin
Result := -1;
Flags := 0;
if Position = 0 then
Flags := Flags or ACM_STREAMCONVERTF_START;
acmStreamSize(ACMStream, Count, NeededBytes, ACM_STREAMSIZEF_DESTINATION);
if NeededBytes > SrcBufferSize then
begin
SrcBufferSize := NeededBytes;
ReallocMem(SrcBuffer, SrcBufferSize);
end;
ReadBytes := inherited Read(Pointer(DWORD(SrcBuffer) + BufferOffset)^, NeededBytes - BufferOffset);
if ReadBytes >= 0 then
begin
if DWORD(ReadBytes) + BufferOffset > 0 then
begin
if DWORD(ReadBytes) < NeededBytes - BufferOffset then
Flags := Flags or ACM_STREAMCONVERTF_END
else
Flags := Flags or ACM_STREAMCONVERTF_BLOCKALIGN;
FillChar(ACMHeader, SizeOf(TACMSTREAMHEADER), 0);
ACMHeader.cbStruct := SizeOf(TACMSTREAMHEADER);
ACMHeader.pbSrc := SrcBuffer;
ACMHeader.cbSrcLength := BufferOffset + DWORD(ReadBytes);
ACMHeader.pbDst := @Buffer;
ACMHeader.cbDstLength := Count;
acmStreamPrepareHeader(ACMStream, ACMHeader, 0);
acmStreamConvert(ACMStream, ACMHeader, Flags);
acmStreamUnprepareHeader(ACMStream, ACMHeader, 0);
BufferOffset := 0;
if ACMHeader.cbSrcLength <> ACMHeader.cbSrcLengthUsed then
begin
BufferOffset := ACMHeader.cbSrcLength - ACMHeader.cbSrcLengthUsed;
CopyMemory(SrcBuffer, Pointer(DWORD(SrcBuffer) +
ACMHeader.cbSrcLengthUsed), BufferOffset);
end;
Result := ACMHeader.cbDstLengthUsed;
end
else
Result := 0;
end;
end
else
Result := inherited Read(Buffer, Count);
end;
{ TWave }
constructor TWave.Create;
begin
inherited Create(TMemoryStream.Create, soOwned);
end;
{ TWaveFile }
constructor TWaveFile.Create(const FileName: String; Mode: Word);
begin
inherited Create(TFileStream.Create(FileName, Mode), soOwned);
end;
{ TWaveConverter }
constructor TWaveConverter.Create;
begin
inherited Create(TMemoryStream.Create, soOwned);
end;
{ TWaveFileConverter }
constructor TWaveFileConverter.Create(const FileName: String; Mode: Word);
begin
inherited Create(TFileStream.Create(FileName, Mode), soOwned);
end;
{ TWaveStorage }
constructor TWaveStorage.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
fWave := TWave.Create;
end;
destructor TWaveStorage.Destroy;
begin
fWave.Free;
inherited Destroy;
end;
procedure TWaveStorage.SetWave(Value: TWave);
begin
if Wave <> Value then
begin
if Assigned(Value) then
begin
Value.Stream.Position := 0;
Wave.LoadFromStream(Value.Stream);
end
else
Wave.Clear;
end;
end;
procedure TWaveStorage.ReadData(Stream: TStream);
begin
Wave.LoadFromStream(Stream);
end;
procedure TWaveStorage.WriteData(Stream: TStream);
begin
Wave.SaveToStream(Stream);
end;
procedure TWaveStorage.DefineProperties(Filer: TFiler);
begin
inherited DefineProperties(Filer);
Filer.DefineBinaryProperty('Data', ReadData, WriteData, not Wave.Empty);
end;
procedure TWaveStorage.Assign(Source: TPersistent);
begin
if Source is TWaveStorage then
Wave := TWaveStorage(Source).Wave
else if Source is TWaveItem then
Wave := TWaveItem(Source).Wave
else
inherited Assign(Source);
end;
function TWaveStorage.GetWaveStream(Index: Integer): TStream;
begin
Result := Wave.Stream;
end;
function TWaveStorage.Equals(Another: TCustomWaveStorage): Boolean;
begin
if Another is TWaveStorage then
Result := Wave.Equals(TWaveStorage(Another).Wave)
else
Result := False;
end;
{ TWaveItem }
constructor TWaveItem.Create(Collection: TCollection);
begin
inherited Create(Collection);
fWave := TWave.Create;
end;
destructor TWaveItem.Destroy;
begin
fWave.Free;
inherited Destroy;
end;
procedure TWaveItem.SetWave(Value: TWave);
begin
if Wave <> Value then
begin
if Assigned(Value) then
begin
Value.Stream.Position := 0;
Wave.LoadFromStream(Value.Stream);
end
else
Wave.Clear;
end;
end;
procedure TWaveItem.ReadData(Stream: TStream);
begin
Wave.LoadFromStream(Stream);
end;
procedure TWaveItem.WriteData(Stream: TStream);
begin
Wave.SaveToStream(Stream);
end;
procedure TWaveItem.DefineProperties(Filer: TFiler);
begin
inherited DefineProperties(Filer);
Filer.DefineBinaryProperty('Data', ReadData, WriteData, not Wave.Empty);
end;
procedure TWaveItem.Assign(Source: TPersistent);
begin
if Source is TWaveItem then
begin
Wave := TWaveItem(Source).Wave;
Name := TWaveItem(Source).Name;
Tag := TWaveItem(Source).Tag;
end
else if Source is TWaveStorage then
Wave := TWaveStorage(Source).Wave
else
inherited Assign(Source);
end;
function TWaveItem.GetDisplayName: String;
var
WaveInfo: String;
begin
if (Wave <> nil) and (Wave.Stream.Size <> 0) then
begin
if Wave.Valid then
WaveInfo := Wave.AudioFormat + ', ' +
IntToStr(Wave.BitRate) + ' kbps, ' +
MS2Str(Wave.Length, msAh) + ' sec.'
else
WaveInfo := 'Invalid Content';
end
else
WaveInfo := 'Empty';
Result := Name + ' (' + WaveInfo + ')';
end;
{ TWaveItems }
{$IFDEF COMPILER4_UP}
constructor TWaveItems.Create(AOwner: TPersistent; ItemClass: TWaveItemClass);
{$ELSE}
constructor TWaveItems.Create(AOwner: TPersistent; ItemClass: TWaveItemClass);
{$ENDIF}
begin
inherited Create(ItemClass);
fOwner := AOwner;
end;
function TWaveItems.GetOwner: TPersistent;
begin
Result := fOwner;
end;
function TWaveItems.Add: TWaveItem;
begin
Result := TWaveItem(inherited Add);
end;
{$IFDEF COMPILER4_UP}
function TWaveItems.Insert(Index: Integer): TWaveItem;
begin
Result := TWaveItem(inherited Insert(Index));
end;
{$ENDIF}
function TWaveItems.GetItem(Index: Integer): TWaveItem;
begin
Result := TWaveItem(inherited Items[Index]);
end;
procedure TWaveItems.SetItem(Index: Integer; Value: TWaveItem);
begin
inherited Items[Index] := Value;
end;
{ TWaveCollection }
constructor TWaveCollection.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
fWaves := TWaveItems.Create(Self, TWaveItem);
end;
destructor TWaveCollection.Destroy;
begin
fWaves.Free;
inherited Destroy;
end;
procedure TWaveCollection.SetWaves(const Value: TWaveItems);
begin
if Waves <> Value then
Waves.Assign(Value);
end;
function TWaveCollection.GetWaveStream(Index: Integer): TStream;
begin
Result := Waves[Index].Wave.Stream;
end;
function TWaveCollection.Equals(Another: TCustomWaveStorage): Boolean;
var
I: Integer;
begin
if (Another is TWaveCollection) and
(Waves.Count = TWaveCollection(Another).Waves.Count) then
begin
Result := True;
for I := 0 to Waves.Count - 1 do
if not Waves[I].Wave.Equals(TWaveCollection(Another).Waves[I].Wave) then
begin
Result := False;
Break;
end;
end
else
Result := False;
end;
function TWaveCollection.ExportWaveNames(const List: TStrings): Integer;
var
Index: Integer;
begin
for Index := 0 to Waves.Count - 1 do
List.Add(Waves[Index].Name);
Result := Waves.Count;
end;
function TWaveCollection.IndexOfName(const AName: String): Integer;
var
Index: Integer;
begin
Result := -1;
for Index := 0 to Waves.Count - 1 do
if CompareText(Waves[Index].Name, AName) = 0 then
begin
Result := Index;
Break;
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -