⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 waveutils.pas

📁 用于CD/DVD烧录的Delphi源码,包括source和demo
💻 PAS
📖 第 1 页 / 共 3 页
字号:
          Stream.Seek(lpmmIOInfo^.lDiskOffset, SEEK_SET);
          Result := Stream.Write(Pointer(lParam1)^, lParam2);
          lpmmIOInfo^.lDiskOffset := Stream.Seek(0, SEEK_CUR);
        except
          Result := -1;
        end
    else
      Result := MMSYSERR_NOERROR;
    end;
  end
  else
    Result := -1;
end;

// Retrieves format, size, and offset of the wave audio for an open mmIO
// handle. On success when the the function returns true, it is the caller
// responsibility to free the memory allocated for the Wave Format structure.
function GetWaveAudioInfo(mmIO: HMMIO; out pWaveFormat: PWaveFormatEx;
  out DataSize, DataOffset: DWORD): Boolean;

  function GetWaveFormat(const ckRIFF: TMMCKInfo): Boolean;
  var
    ckFormat: TMMCKInfo;
  begin
    Result := False;
    ckFormat.ckid := mmioStringToFOURCC('fmt', 0);
    if (mmioDescend(mmIO, @ckFormat, @ckRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) and
       (ckFormat.cksize >= SizeOf(TWaveFormat)) then
    begin
      if ckFormat.cksize < SizeOf(TWaveFormatEx) then
      begin
        GetMem(pWaveFormat, SizeOf(TWaveFormatEx));
        FillChar(pWaveFormat^, SizeOf(TWaveFormatEx), 0);
      end
      else
        GetMem(pWaveFormat, ckFormat.cksize);
      Result := (mmioRead(mmIO, PChar(pWaveFormat), ckFormat.cksize) = Integer(ckFormat.cksize));
    end;
  end;

  function GetWaveData(const ckRIFF: TMMCKInfo): Boolean;
  var
    ckData: TMMCKInfo;
  begin
    Result := False;
    ckData.ckid := mmioStringToFOURCC('data', 0);
    if (mmioDescend(mmIO, @ckData, @ckRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) then
    begin
      DataSize := ckData.cksize;
      DataOffset := ckData.dwDataOffset;
      Result := True;
    end;
  end;

var
  ckRIFF: TMMCKInfo;
  OrgPos: Integer;
begin
  Result := False;
  OrgPos := mmioSeek(mmIO, 0, SEEK_CUR);
  try
    mmioSeek(mmIO, 0, SEEK_SET);
    ckRIFF.fccType := mmioStringToFOURCC('WAVE', 0);
    if (mmioDescend(mmIO, @ckRIFF, nil, MMIO_FINDRIFF) = MMSYSERR_NOERROR) then
    begin
      pWaveFormat := nil;
      if GetWaveFormat(ckRIFF) and GetWaveData(ckRIFF) then
        Result := True
      else if Assigned(pWaveFormat) then
        ReallocMem(pWaveFormat, 0);
    end
  finally
    mmioSeek(mmIO, OrgPos, SEEK_SET);
  end;
end;

// Initializes a new wave RIFF format in an open mmIO handle. The previous
// content of mmIO will be lost.
function CreateWaveAudio(mmIO: HMMIO; const pWaveFormat: PWaveFormatEx;
  out ckRIFF, ckData: TMMCKInfo): Boolean;
var
  ckFormat: TMMCKInfo;
  FormatSize: Integer;
begin
  Result := False;
  FormatSize := SizeOf(TWaveFormatEx) + pWaveFormat^.cbSize;
  mmIOSeek(mmIO, 0, SEEK_SET);
  FillChar(ckRIFF, SizeOf(TMMCKInfo), 0);
  ckRIFF.fccType := mmioStringToFOURCC('WAVE', 0);
  if mmioCreateChunk(mmIO, @ckRIFF, MMIO_CREATERIFF) = MMSYSERR_NOERROR then
  begin
    FillChar(ckFormat, SizeOf(TMMCKInfo), 0);
    ckFormat.ckid := mmioStringToFOURCC('fmt', 0);
    if (mmioCreateChunk(mmIO, @ckFormat, 0) = MMSYSERR_NOERROR) and
       (mmioWrite(mmIO, PChar(pWaveFormat), FormatSize) = FormatSize) and
       (mmioAscend(mmIO, @ckFormat, 0) = MMSYSERR_NOERROR) then
    begin
      FillChar(ckData, SizeOf(TMMCKInfo), 0);
      ckData.ckid := mmioStringToFOURCC('data', 0);
      Result := (mmioCreateChunk(mmIO, @ckData, 0) = MMSYSERR_NOERROR);
    end;
  end;
end;

// Updates the chunks and closes an mmIO handle.
procedure CloseWaveAudio(mmIO: HMMIO; var ckRIFF, ckData: TMMCKInfo);
begin
  mmioAscend(mmIO, @ckData, 0);
  mmioAscend(mmIO, @ckRIFF, 0);
  mmioClose(mmIO, 0);
end;

// Retrieves format, size, and offset of the wave audio for a stream. On
// success when the the function returns true, it is the caller responsibility
// to free the memory allocated for the Wave Format structure.
function GetStreamWaveAudioInfo(Stream: TStream; out pWaveFormat: PWaveFormatEx;
  out DataSize, DataOffset: DWORD): Boolean;
var
  mmIO: HMMIO;
begin
  Result := False;
  if Stream.Size <> 0 then
  begin
    mmIO := OpenStreamWaveAudio(Stream);
    if mmIO <> 0 then
      try
        Result := GetWaveAudioInfo(mmIO, pWaveFormat, DataSize, DataOffset);
      finally
        mmioClose(mmIO, MMIO_FHOPEN);
      end;
  end;
end;

// Initializes wave RIFF format in a stream and returns the mmIO handle.
// After calling this function, the previous content of the stream will be lost.
function CreateStreamWaveAudio(Stream: TStream; const pWaveFormat: PWaveFormatEx;
 out ckRIFF, ckData: TMMCKInfo): HMMIO;
begin
  Result := OpenStreamWaveAudio(Stream);
  if Result <> 0 then
  begin
    Stream.Size := 0;
    if not CreateWaveAudio(Result, pWaveFormat, ckRIFF, ckData) then
    begin
      mmioClose(Result, MMIO_FHOPEN);
      Result := 0;
    end;
  end;
end;

// Opens wave RIFF format in a stream for read and write operations and returns
// the mmIO handle.
function OpenStreamWaveAudio(Stream: TStream): HMMIO;
var
  mmIOInfo: TMMIOINFO;
begin
  FillChar(mmIOInfo, SizeOf(mmIOInfo), 0);
  mmIOInfo.pIOProc := @mmIOStreamProc;
  mmIOInfo.adwInfo[0] := DWORD(Stream);
  Result := mmioOpen(nil, @mmIOInfo, MMIO_READ or MMIO_WRITE);
end;

// Claculates the wave buffer size for the specified duration.
function CalcWaveBufferSize(const pWaveFormat: PWaveFormatEx; Duration: DWORD): DWORD;
var
  Alignment: DWORD;
begin
  Result := MulDiv(Duration, pWaveFormat^.nAvgBytesPerSec, 1000);
  if pWaveFormat^.nBlockAlign <> 0 then
  begin
    Alignment := Result mod pWaveFormat^.nBlockAlign;
    if Alignment <> 0 then Inc(Result, pWaveFormat^.nBlockAlign - Alignment);
  end;
end;

// Returns the string representation of a wave audio format.
function GetWaveAudioFormat(const pWaveFormat: PWaveFormatEx): String;
const
  Channels: array[1..2] of String = ('Mono', 'Stereo');
begin
  with pWaveFormat^ do
  begin
    if nChannels in [1..2] then
      Result := Format('%.3f kHz, %d Bit, %s', [nSamplesPerSec / 1000,
        wBitsPerSample, Channels[nChannels]])
    else
      Result := Format('%.3f kHz, %d Bit, %d Ch', [nSamplesPerSec / 1000,
        wBitsPerSample, nChannels]);
    if wFormatTag = WAVE_FORMAT_PCM then
      Result := 'PCM ' + Result;
  end;
end;

// Returns the wave's length in milliseconds.
function GetWaveAudioLength(const pWaveFormat: PWaveFormatEx; DataSize: DWORD): DWORD;
begin
  with pWaveFormat^ do
    if nAvgBytesPerSec <> 0 then
      Result := MulDiv(1000, DataSize, nAvgBytesPerSec)
    else
      Result := 0;
end;

// Returns the wave's bit rate in kbps (kilo bits per second).
function GetWaveAudioBitRate(const pWaveFormat: PWaveFormatEx): DWORD;
begin
  with pWaveFormat^ do
    Result := MulDiv(nSamplesPerSec, nChannels * wBitsPerSample, 1000);
end;

// Returns the wave data peak level in percent (PCM format only).
function GetWaveAudioPeakLevel(const Data: Pointer; DataSize: DWORD;
  BitsPerSample: WORD): Integer;

  function GetAudioPeakLevel8Bit: Integer;
  var
    pSample: PByte;
    Max: Byte;
  begin
    Max := 0;
    pSample := Data;
    while DataSize > 0 do
    begin
      if pSample^ > Max then
        Max := pSample^;
      Inc(pSample);
      Dec(DataSize);
    end;
    if ByteBool(Max and $80) then
      Max := Max and $7F
    else
      Max := 0;
    Result := (100 * Max) div $7F;
  end;

  function GetAudioPeakLevel16Bit: Integer;
  var
    pSample: PSmallInt;
    Max: SmallInt;
  begin
    Max := 0;
    pSample := Data;
    while DataSize > 0 do
    begin
      if pSample^ > Max then
        Max := pSample^;
      Inc(pSample);
      Dec(DataSize, 2);
    end;
    Result := (100 * Max) div $7FFF;
  end;

begin
  case BitsPerSample of
    8: Result := GetAudioPeakLevel8Bit;
    16: Result := GetAudioPeakLevel16Bit;
  else
    Result := -1;
  end;
end;

// Inverts the wave data (PCM format only).
procedure InvertWaveAudio(const Data: Pointer; DataSize: DWORD;
  BitsPerSample: WORD);

  procedure Invert8Bit;
  var
    pStart, pEnd: PByte;
  begin
    pStart := Data;
    pEnd := PByte(DWORD(pStart) + DataSize - SizeOf(Byte));
    while DWORD(pStart) < DWORD(pEnd) do
    begin
      pStart^ := pStart^ xor pEnd^;
      pEnd^ := pStart^ xor pEnd^;
      pStart^ := pStart^ xor pEnd^;
      Inc(pStart);
      Dec(pEnd);
    end;
  end;

  procedure Invert16Bit;
  var
    pStart, pEnd: PSmallInt;
  begin
    pStart := Data;
    pEnd := PSmallInt(DWORD(pStart) + DataSize - SizeOf(SmallInt));
    while DWORD(pStart) < DWORD(pEnd) do
    begin
      pStart^ := pStart^ xor pEnd^;
      pEnd^ := pStart^ xor pEnd^;
      pStart^ := pStart^ xor pEnd^;
      Inc(pStart);
      Dec(pEnd);
    end;
  end;

begin
  case BitsPerSample of
    8: Invert8Bit;
    16: Invert16Bit;
  end;
end;

// Fills the wave data with silence
procedure SilenceWaveAudio(const Data: Pointer; DataSize: DWORD;
  BitsPerSample: WORD);
begin
  case BitsPerSample of
    8: FillChar(Data^, DataSize, $7F);
    16: FillChar(Data^, DataSize, 0);
  end;
end;

// Increases/Decreases the wave data volume by the specified percentage (PCM format only).

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -