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

📄 waveutils.pas

📁 一整套声音录制控件
💻 PAS
📖 第 1 页 / 共 3 页
字号:
  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 > 1 then
  begin
    Alignment := Result mod pWaveFormat^.nBlockAlign;
    if Alignment <> 0 then Inc(Result, pWaveFormat^.nBlockAlign - Alignment);
  end;
end;

// Returns the string representation of an audio format tag.
function GetAudioFormat(FormatTag: Word): String;
begin
  case FormatTag of
    WAVE_FORMAT_PCM: Result := 'PCM';
    $0002: Result := 'Microsoft ADPCM';
    $0003: Result := 'PCM IEEE';
    $0004: Result := 'VSELP';
    $0005: Result := 'CSVD';
    $0006: Result := 'A-Law';
    $0007: Result := 'u-Law';
    $0008: Result := 'DTS';
    $0011: Result := 'IMA ADPCM';
    $0031: Result := 'GSM 6.10';
    $0043: Result := 'Microsoft G.723.1';
    $0050: Result := 'MPEG';
    $0055: Result := 'MPEG Layer-3';
  else
    Result := '';
  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');
var
  Fmt: String;
begin
  with pWaveFormat^ do
  begin
    if wBitsPerSample <> 0 then
      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])
    else
      if nChannels in [1..2] then
        Result := Format('%.3f kHz, %s', [nSamplesPerSec / 1000,
          Channels[nChannels]])
      else
        Result := Format('%.3f kHz, %d Ch', [nSamplesPerSec / 1000,
          nChannels]);
    Fmt := GetAudioFormat(wFormatTag);
    if Fmt <> '' then
      Result := Fmt + ': ' + 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;
  const pWaveFormat: PWaveFormatEx): 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
  Result := -1;
  if pWaveFormat^.wFormatTag = WAVE_FORMAT_PCM then
    case pWaveFormat^.wBitsPerSample of
      8: Result := GetAudioPeakLevel8Bit;
      16: Result := GetAudioPeakLevel16Bit;
    end;
end;

// Inverts the wave data (PCM format only).
function InvertWaveAudio(const Data: Pointer; DataSize: DWORD;
  const pWaveFormat: PWaveFormatEx): Boolean;

  function Invert8Bit: Boolean;
  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;
    Result := True;
  end;

  function Invert16Bit: Boolean;
  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;
    Result := True;
  end;

begin
  Result := False;
  if pWaveFormat^.wFormatTag = WAVE_FORMAT_PCM then
    case pWaveFormat^.wBitsPerSample of
      8: Result := Invert8Bit;
      16: Result := Invert16Bit;
    end;
end;

// Fills the wave data with silence
function SilenceWaveAudio(const Data: Pointer; DataSize: DWORD;
  const pWaveFormat: PWaveFormatEx): Boolean;
begin
  Result := False;
  if pWaveFormat^.wFormatTag = WAVE_FORMAT_PCM then
  begin
    Result := True;
    case pWaveFormat^.wBitsPerSample of
      8: FillChar(Data^, DataSize, $7F);
      16: FillChar(Data^, DataSize, 0);
    else
      Result := False;
    end;
  end;
end;

// Increases/Decreases the wave data volume by the specified percentage (PCM format only).
function ChangeWaveAudioVolume(const Data: Pointer; DataSize: DWORD;
  const pWaveFormat: PWaveFormatEx; Percent: Integer): Boolean;

  function ChangeVolume8Bit: Boolean;
  var
    pSample: PByte;
    Value: Integer;
  begin
    pSample := Data;
    while DataSize > 0 do
    begin
      Value := pSample^ + (pSample^ * Percent) div 100;
      if Value > High(Byte) then
        Value := High(Byte)
      else if Value < 0 then
        Value := 0;
      pSample^ := Value;
      Inc(pSample);

⌨️ 快捷键说明

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