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

📄 audioacm.pas

📁 用于CD/DVD烧录的Delphi源码,包括source和demo
💻 PAS
📖 第 1 页 / 共 3 页
字号:
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).
procedure ChangeWaveAudioVolume(const Data: Pointer; DataSize: DWORD;
  BitsPerSample: WORD; Percent: Integer);

  procedure ChangeVolume8Bit;
  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);
      Dec(DataSize, SizeOf(Byte));
    end;
  end;

  procedure ChangeVolume16Bit;
  var
    pSample: PSmallInt;
    Value: Integer;
  begin
    pSample := Data;
    while DataSize > 0 do
    begin
      Value := pSample^ + (pSample^ * Percent) div 100;
      if Value > High(SmallInt) then
        Value := High(SmallInt)
      else if Value < -High(SmallInt) then
        Value := -High(SmallInt);
      pSample^ := Value;
      Inc(pSample);
      Dec(DataSize, SizeOf(SmallInt));
    end;
  end;

begin
  case BitsPerSample of
    8: ChangeVolume8Bit;
    16: ChangeVolume16Bit;
  end;
end;

// Converts the wave data to the specified format. The caller is responsible to
// release the memory allocated for the converted wave data buffer.

function ConvertWaveFormat(const srcFormat: PWaveFormatEx; srcData: Pointer; srcDataSize: DWORD;
  const dstFormat: PWaveFormatEx; out dstData: Pointer; out dstDataSize: DWORD): Boolean;
var
  hStream: HACMSTREAM;
  Header: TACMSTREAMHEADER;
begin
  Result := False;
  if acmStreamOpen(hStream, 0, srcFormat, dstFormat, nil, 0, 0, ACM_STREAMOPENF_NONREALTIME) = 0 then
  begin
    try
      if acmStreamSize(hStream, srcDataSize, dstDataSize, ACM_STREAMSIZEF_SOURCE) = 0 then
      begin
        dstData := nil;
        FillChar(Header, SizeOf(Header), 0);
        ReallocMem(dstData, dstDataSize);
        try
          Header.cbStruct := SizeOf(Header);
          Header.pbSrc := srcData;
          Header.cbSrcLength := srcDataSize;
          Header.pbDst := dstData;
          Header.cbDstLength := dstDataSize;
          if acmStreamPrepareHeader(hStream, Header, 0) = 0 then
            try
              Result := (acmStreamConvert(hStream, Header, ACM_STREAMCONVERTF_START or ACM_STREAMCONVERTF_END) = 0);
            finally
              acmStreamUnprepareHeader(hStream, Header, 0);
            end;
        finally
          ReallocMem(dstData, Header.cbDstLengthUsed);
          dstDataSize := Header.cbDstLengthUsed;
        end;
      end;
    finally
      acmStreamClose(hStream, 0);
    end;
  end;
end;





// Initializes a standard MP3 wave format header. The size of memory referenced
// by the pWaveFormat parameter must not be less than the size of TWaveFormatEx
// record.
procedure SetMP3AudioFormat(const pWaveFormat: PWaveFormatEx;
  Channels: TPCMChannel; SamplesPerSec: TPCMSamplesPerSec;
  BitsPerSample: TPCMBitsPerSample);
begin
{
        .nChannels = wfxIN.nChannels
        .nSamplesPerSec = wfxIN.nSamplesPerSec
        .wFormatTag = WAVE_FORMAT_MPEGLAYER3}
  with pWaveFormat^ do
  begin
    wFormatTag := WAVE_FORMAT_MPEGLAYER3;
    case Channels of
      cMono: nChannels := 1;
      cStereo: nChannels := 2;
    end;

⌨️ 快捷键说明

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