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

📄 audioacm.pas

📁 用于CD/DVD烧录的Delphi源码,包括source和demo
💻 PAS
📖 第 1 页 / 共 3 页
字号:
{-----------------------------------------------------------------------------
 Unit Name: AudioACM
 Author:    Dancemammal
 Purpose:   Wave Utils and conversion functions
 History:   First release
-----------------------------------------------------------------------------}


unit AudioACM;

interface

uses
  Windows, Messages, Classes, SysUtils, mmSystem;



const
// addons for extra codecs
  WAVE_FORMAT_MSG723 = 66;
  WAVE_FORMAT_MPEGLAYER3 = 85;
  MPEGLAYER3_WFX_EXTRA_BYTES = 12;

  MPEGLAYER3_ID_UNKNOWN = 0;
  MPEGLAYER3_ID_MPEG = 1;
  MPEGLAYER3_ID_CONSTANTFRAMESIZE = 2;

  MPEGLAYER3_FLAG_PADDING_ISO = $00000000;
  MPEGLAYER3_FLAG_PADDING_ON = $00000001;
  MPEGLAYER3_FLAG_PADDING_OFF = $00000002;

type

  // Milliseconds to string format specifiers
  TMS2StrFormat = (
    msHMSh, // Hour:Minute:Second.Hunderdth
    msHMS,  // Hour:Minute:Second
    msMSh,  // Minute:Second.Hunderdth
    msMS,   // Minute:Second
    msSh,   // Second.Hunderdth
    msS,    // Second
    msAh,   // Best format with hunderdth of second
    msA);   // Best format without hunderdth of second

  // Standard PCM Audio Format
  TPCMChannel = (cMono, cStereo);
  TPCMSamplesPerSec = (ss8000Hz, ss11025Hz, ss22050Hz, ss44100Hz, ss48000Hz);
  TPCMBitsPerSample = (bs8Bit, bs16Bit);

  TPCMFormat = (nonePCM, Mono8Bit8000Hz, Stereo8bit8000Hz, Mono16bit8000Hz,
    Stereo16bit8000Hz, Mono8bit11025Hz, Stereo8bit11025Hz, Mono16bit11025Hz,
    Stereo16bit11025Hz, Mono8bit22050Hz, Stereo8bit22050Hz, Mono16bit22050Hz,
    Stereo16bit22050Hz, Mono8bit44100Hz, Stereo8bit44100Hz, Mono16bit44100Hz,
    Stereo16bit44100Hz, Mono8bit48000Hz, Stereo8bit48000Hz, Mono16bit48000Hz,
    Stereo16bit48000Hz);

 // TMP3Bitrates = (96kBits,112kBits,128kBits,160kBits,192kBits,224kBits,256kBits,320kBits)


  // Wave Device Supported PCM Formats
  TWaveDeviceFormats = set of TPCMFormat;

  // Wave Out Device Supported Features
  TWaveOutDeviceSupport = (dsVolume, dsStereoVolume, dsPitch, dsPlaybackRate, dsPosition, dsAsynchronize, dsDirectSound);
  TWaveOutDeviceSupports = set of TWaveOutDeviceSupport;

  // Wave Out Options
  TWaveOutOption = (woSetVolume, woSetPitch, woSetPlaybackRate);
  TWaveOutOptions = set of TWaveOutOption;

  // Wave Audio Exceptions
  EWaveAudioError = class(Exception);
  EWaveAudioSysError = class(EWaveAudioError);
  EWaveAudioInvalidOperation = class(EWaveAudioError);



function GetWaveAudioInfo(mmIO: HMMIO; out pWaveFormat: PWaveFormatEx;
  out DataSize, DataOffset: DWORD): Boolean;

function CreateWaveAudio(mmIO: HMMIO; const pWaveFormat: PWaveFormatEx;
  out ckRIFF, ckData: TMMCKInfo): Boolean;

procedure CloseWaveAudio(mmIO: HMMIO; var ckRIFF, ckData: TMMCKInfo);

function GetStreamWaveAudioInfo(Stream: TStream; out pWaveFormat: PWaveFormatEx;
  out DataSize, DataOffset: DWORD): Boolean;

function CreateStreamWaveAudio(Stream: TStream; const pWaveFormat: PWaveFormatEx;
  out ckRIFF, ckData: TMMCKInfo): HMMIO;

function OpenStreamWaveAudio(Stream: TStream): HMMIO;

function CalcWaveBufferSize(const pWaveFormat: PWaveFormatEx; Duration: DWORD): DWORD;

function GetWaveAudioFormat(const pWaveFormat: PWaveFormatEx): String;

function GetWaveAudioLength(const pWaveFormat: PWaveFormatEx; DataSize: DWORD): DWORD;

function GetWaveAudioBitRate(const pWaveFormat: PWaveFormatEx): DWORD;

function GetWaveAudioPeakLevel(const Data: Pointer; DataSize: DWORD;
  BitsPerSample: WORD): Integer;

procedure InvertWaveAudio(const Data: Pointer; DataSize: DWORD;
  BitsPerSample: WORD);

procedure SilenceWaveAudio(const Data: Pointer; DataSize: DWORD;
  BitsPerSample: WORD);

procedure ChangeWaveAudioVolume(const Data: Pointer; DataSize: DWORD;
  BitsPerSample: WORD; Percent: Integer);

function ConvertWaveFormat(const srcFormat: PWaveFormatEx; srcData: Pointer; srcDataSize: DWORD;
  const dstFormat: PWaveFormatEx; out dstData: Pointer; out dstDataSize: DWORD): Boolean;

procedure SetPCMAudioFormat(const pWaveFormat: PWaveFormatEx; Channels: TPCMChannel;
  SamplesPerSec: TPCMSamplesPerSec; BitsPerSample: TPCMBitsPerSample);

procedure SetPCMAudioFormatS(const pWaveFormat: PWaveFormatEx; PCMFormat: TPCMFormat);

function GetPCMAudioFormat(const pWaveFormat: PWaveFormatEx): TPCMFormat;

procedure SetMP3AudioFormatS(const pWaveFormat: PWaveFormatEx; PCMFormat: TPCMFormat);

function GetMP3AudioFormat(const pWaveFormat: PWaveFormatEx): TPCMFormat;

function MS2Str(Milliseconds: DWORD; Fmt: TMS2StrFormat): String;

function WaitForSyncObject(SyncObject: THandle; Timeout: DWORD): DWORD;

function mmioStreamProc(lpmmIOInfo: PMMIOInfo; uMsg, lParam1, lParam2: DWORD): LRESULT; stdcall;






implementation

const
  // acmStreamConvert flags
  ACM_STREAMCONVERTF_BLOCKALIGN = $00000004;
  ACM_STREAMCONVERTF_START      = $00000010;
  ACM_STREAMCONVERTF_END        = $00000020;

  // acmStreamOpen flags
  ACM_STREAMOPENF_QUERY         = $00000001;
  ACM_STREAMOPENF_ASYNC         = $00000002;
  ACM_STREAMOPENF_NONREALTIME   = $00000004;

  // acmStreamSize flags
  ACM_STREAMSIZEF_SOURCE        = $00000000;
  ACM_STREAMSIZEF_DESTINATION   = $00000001;

type
  // ACM Driver Handle
  HACMDRIVER = DWORD;

  // ACM Stream Handle
  HACMSTREAM = DWORD;

  // ACM Stream Header
  PACMSTREAMHEADER = ^TACMSTREAMHEADER;
  TACMSTREAMHEADER = packed record
    cbStruct: DWORD;
    fdwStatus: DWORD;
    dwUser: DWORD;
    pbSrc: PBYTE;
    cbSrcLength: DWORD;
    cbSrcLengthUsed: DWORD;
    dwSrcUser: DWORD;
    pbDst: PBYTE;
    cbDstLength: DWORD;
    cbDstLengthUsed: DWORD;
    dwDstUser: DWORD;
    dwReservedDriver: array[0..9] of DWORD;
  end;

  // ACM Wave Filter
  PWAVEFILTER = ^TWAVEFILTER;
  TWAVEFILTER = packed record
    cbStruct: DWORD;
    dwFilterTag: DWORD;
    fdwFilter: DWORD;
    dwReserved: array[0..4] of DWORD;
  end;

function acmStreamOpen(var phas: HACMSTREAM; had: HACMDRIVER;
  pwfxSrc: PWAVEFORMATEX; pwfxDst: PWAVEFORMATEX; pwfltr: PWAVEFILTER;
  dwCallback: DWORD; dwInstance: DWORD; fdwOpen: DWORD): MMRESULT; stdcall;
  external 'msacm32.dll';

function acmStreamClose(has: HACMSTREAM; fdwClose: DWORD): MMRESULT; stdcall;
  external 'msacm32.dll';

function acmStreamPrepareHeader(has: HACMSTREAM; var pash: TACMSTREAMHEADER;
  fdwPrepare: DWORD): MMRESULT; stdcall;
  external 'msacm32.dll';

function acmStreamUnprepareHeader(has: HACMSTREAM; var pash: TACMSTREAMHEADER;
  fdwUnprepare: DWORD): MMRESULT; stdcall;
  external 'msacm32.dll';

function acmStreamConvert(has: HACMSTREAM; var pash: TACMSTREAMHEADER;
  fdwConvert: DWORD): MMRESULT; stdcall;
  external 'msacm32.dll';

function acmStreamSize(has: HACMSTREAM; cbInput: DWORD;
  var pdwOutputBytes: DWORD; fdwSize: DWORD): MMRESULT; stdcall;
  external 'msacm32.dll';

{ Global Procedures }

// To open a stream using mmIO API functions, use the following code sample:
//
//    FillChar(mmioInfo, SizeOf(mmioInfo), 0);
//    mmioInfo.pIOProc := @mmioStreamProc;
//    mmioInfo.adwInfo[0] := DWORD(your_stream_instance);
//    mmIO := mmioOpen(nil, @mmioInfo, dwOpenFlags);
//
// The flags specified by the dwOpenFlags parameter of mmioOpen function can
// be only one of MMIO_READ, MMIO_WRITE, and MMIO_READWRITE flags. If you use
// another flags, simply they will be ignored by this user defined function.

function mmIOStreamProc(lpmmIOInfo: PMMIOInfo; uMsg, lParam1, lParam2: DWORD): LRESULT; stdcall;
var
  Stream: TStream;
begin
  if Assigned(lpmmIOInfo) and (lpmmIOInfo^.adwInfo[0] <> 0) then
  begin
    Stream := TStream(lpmmIOInfo^.adwInfo[0]);
    case uMsg of
      MMIOM_OPEN:
      begin
        if TObject(lpmmIOInfo^.adwInfo[0]) is TStream then
        begin
          Stream.Seek(0, SEEK_SET);
          lpmmIOInfo^.lDiskOffset := 0;
          Result := MMSYSERR_NOERROR;
        end
        else
          Result := -1;
      end;
      MMIOM_CLOSE:
        Result := MMSYSERR_NOERROR;
      MMIOM_SEEK:
        try
          if lParam2 = SEEK_CUR then
            Stream.Seek(lpmmIOInfo^.lDiskOffset, SEEK_SET);
          Result := Stream.Seek(lParam1, lParam2);
          lpmmIOInfo^.lDiskOffset := Result;
        except
          Result := -1;
        end;
      MMIOM_READ:
        try
          Stream.Seek(lpmmIOInfo^.lDiskOffset, SEEK_SET);
          Result := Stream.Read(Pointer(lParam1)^, lParam2);
          lpmmIOInfo^.lDiskOffset := Stream.Seek(0, SEEK_CUR);
        except
          Result := -1;
        end;
      MMIOM_WRITE,
      MMIOM_WRITEFLUSH:
        try
          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;

⌨️ 快捷键说明

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