MMWaveIO.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:80k
- {========================================================================}
- {= (c) 1995-98 SwiftSoft Ronald Dittrich =}
- {========================================================================}
- {= All Rights Reserved =}
- {========================================================================}
- {= D 01099 Dresden = Fax.: +49(0)351-8037944 =}
- {= Loewenstr.7a = info@swiftsoft.de =}
- {========================================================================}
- {= Actual versions on http://www.swiftsoft.de/index.html =}
- {========================================================================}
- {= This code is for reference purposes only and may not be copied or =}
- {= distributed in any format electronic or otherwise except one copy =}
- {= for backup purposes. =}
- {= =}
- {= No Delphi Component Kit or Component individually or in a collection=}
- {= subclassed or otherwise from the code in this unit, or associated =}
- {= .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed =}
- {= without express permission from SwiftSoft. =}
- {= =}
- {= For more licence informations please refer to the associated =}
- {= HelpFile. =}
- {========================================================================}
- {= $Date: 23.11.98 - 13:42:36 $ =}
- {========================================================================}
- unit MMWaveIO;
- {$I COMPILER.INC}
- interface
- uses
- {$IFDEF WIN32}
- Windows,
- {$ELSE}
- WinTypes,
- WinProcs,
- {$ENDIF}
- SysUtils,
- MMSystem,
- MMRegs,
- MMRiff,
- MMUtils,
- MMAbout;
- const
- { file open flags for waveio functions }
- RIFF_FILE = $0001;
- RIFF_RESOURCE = $0002;
- RIFF_MEMORY = $0004;
- { get the extra Info only }
- RIFF_INFO_ONLY = $0008;
- { we have a RAW file }
- RAW_FILE = $0010;
- type
- PWAVEIOCB = ^TWAVEIOCB;
- TWAVEIOCB = packed record { do not change the first items !!!! }
- dwSize : DWORD; { size for the structure }
- dwFlags : DWORD; { flags used to open the file }
- hmmio : THMMIO; { handle to open file }
- ckRIFF,ckDATA : TMMCKINFO; { the current RIFF and data chunk }
- hMem : THandle; { <> 0 if we have a res. file, free it !}
- dwFileSize : DWORD; { the filesize for the actual file }
- dwDataBytes : DWORD; { the data size for the actual file }
- dwDataOffset : DWORD; { offset from data chunk }
- dwDataSamples : DWORD; { how much samples in the file }
- dwFirstSample : DWORD; { the first sample to read }
- dwLastSample : DWORD; { the last Sample to read }
- dwBytesLeft : DWORD; { how many bytes to play }
- dwPosition : DWORD; { the current file position }
- lpFilePath : PChar; { filename from the actual file }
- lpDisp : PDispList; { pointer to display chunk's }
- lpInfo : PInfoChunk; { pointer to info chunk }
- fAvgBytesPerSec : Double;
- { this MUST be the last element in this structure--its length is }
- { not fixed; use ab[] to get at any extra bytes (note! the length }
- { of ab[] is in wfx.cbSize--this CAN be zero!) }
- wfx : TWaveFormatEx;
- ab : array[0..0] of Byte;
- end;
- const
- { error returns from waveio functions }
- WIOERR_BASE = 100;
- WIOERR_NOERROR = 0;
- WIOERR_ERROR = WIOERR_BASE+1;
- WIOERR_BADHANDLE = WIOERR_BASE+2;
- WIOERR_BADFLAGS = WIOERR_BASE+3;
- WIOERR_BADPARAM = WIOERR_BASE+4;
- WIOERR_BADSIZE = WIOERR_BASE+5;
- WIOERR_FILEERROR = WIOERR_BASE+6;
- WIOERR_NOMEM = WIOERR_BASE+7;
- WIOERR_BADFILE = WIOERR_BASE+8;
- WIOERR_NODEVICE = WIOERR_BASE+9;
- WIOERR_BADFORMAT = WIOERR_BASE+10;
- WIOERR_ALLOCATED = WIOERR_BASE+11;
- WIOERR_NOTSUPPORTED = WIOERR_BASE+12;
- function wioBytesPerSample(pwfx: PWaveFormatEx): integer;
- { 32 bit functions }
- function wioBytesToSamples(pwfx: PWaveFormatEx; dwBytes: DWORD): DWORD;
- function wioBytesToTime(pwfx: PWaveFormatEx; dwBytes: DWORD): DWORD;
- function wioSamplesToBytes(pwfx: PWaveFormatEx; dwSamples: DWORD): DWORD;
- function wioSamplesToTime(pwfx: PWaveFormatEx; dwSamples: DWORD): DWORD;
- function wioTimeToSamples(pwfx: PWaveFormatEx; dwTime: DWORD): DWORD;
- function wioTimeToBytes(pwfx: PWaveFormatEx; dwTime: DWORD): DWORD;
- { 64 bit functions }
- function wioBytesToSamples64(pwfx: PWaveFormatEx; dwBytes: int64): int64;
- function wioBytesToTime64(pwfx: PWaveFormatEx; dwBytes: int64): int64;
- function wioSamplesToBytes64(pwfx: PWaveFormatEx; dwSamples: int64): int64;
- function wioSamplesToTime64(pwfx: PWaveFormatEx; dwSamples: int64): int64;
- function wioTimeToSamples64(pwfx: PWaveFormatEx; dwTime: int64): int64;
- function wioTimeToBytes64(pwfx: PWaveFormatEx; dwTime: int64): int64;
- { lpwio functions }
- function wioBytesToSamplesEx(lpwio: PWaveIOCB; dwBytes: DWORD): DWORD;
- function wioBytesToTimeEx(lpwio: PWaveIOCB; dwBytes: DWORD): DWORD;
- function wioSamplesToBytesEx(lpwio: PWaveIOCB; dwSamples: DWORD): DWORD;
- function wioSamplesToTimeEx(lpwio: PWaveIOCB; dwSamples: DWORD): DWORD;
- function wioTimeToSamplesEx(lpwio: PWaveIOCB; dwTime: DWORD): DWORD;
- function wioTimeToBytesEx(lpwio: PWaveIOCB; dwTime: DWORD): DWORD;
- function wioSizeOfWaveFormat(pwfx: PWaveFormatEx): integer;
- function wioCopyWaveFormat(pwfx: PWaveFormatEx): PWaveFormatEx;
- procedure wioGetFormatName(pwfx: PWaveFormatEx; var FormatName: String);
- procedure wioGetFormat(pwfx: PWaveFormatEx; var Format: String);
- function wioIsWaveFile(FilePath: TFileName; dwFlags: DWORD): Boolean;
- function wioGetFullPathName(lpFilePath: PChar): Boolean;
- function wioFileExists(lpFilePath: PChar): Boolean;
- function wioFileDelete(lpFilePath: PChar): Boolean;
- procedure wioExtractPath(lpFilePath: PChar);
- function wioFileCreateTemp(lpFilePath: PChar): Boolean;
- function wioFileOpen(Var hmmio: THMMIO; Var ckRIFF: TMMCKINFO;
- Var HMem: THandle; lpFilePath: PChar;
- fccType: FourCC; dwFlags: DWORD): integer;
- procedure wioFileClose(Var hmmio: THMMIO; Var hMem: THandle);
- function wioCreateFileInfo(Var lpwio: PWAVEIOCB; pwfx: PWaveFormatEx): integer;
- function wioCopyFileInfo(lpwioDst, lpwioSrc: PWAVEIOCB): integer;
- function wioBuildFileInfoFromMem(Var lpwio: PWaveIOCB; Memory: Pointer; MemSize: DWORD): Word;
- function wioBuildFileInfoFromResource(Var lpwio: PWaveIOCB; ResourceName: PChar): Word;
- function wioBuildFileInfoFromRAWEx(Var lpwio: PWaveIOCB; lpFileName: PChar; DataOffset: DWORD;
- pwfx: PWaveFormatEx): integer;
- function wioBuildFileInfoFromRAW(Var lpwio: PWaveIOCB; lpFileName: PChar;
- DataOffset, BitLength, Channels, SampleRate: DWORD): integer;
- function wioReadFileInfo(Var lpwio: PWAVEIOCB; lpFilePath: PChar;
- fccType: FourCC; dwFlags: DWORD): integer;
- function wioWriteFileInfo(Var lpwio: PWAVEIOCB; lpFilePath: PChar): integer;
- function wioFreeFileInfo(Var lpwio: PWAVEIOCB): integer;
- function wioWaveCopyUselessChunks(lpwioSrc, lpwioDst: PWaveIOCB): integer;
- function wioSetIOBufferSize(lpwio: PWaveIOCB; dwSize: integer): integer;
- function wioWaveOpen(lpwio: PWaveIOCB): integer;
- function wioWaveClose(lpwio: PWaveIOCB): integer;
- function wioWaveLoadFile(lpFilePath: PChar; Var pwfx: PWaveFormatEx;
- Var Buffer: PChar; Var Size: DWORD): integer;
- function wioWaveSaveFile(lpFilePath: PChar; pwfx: PWaveFormatEx;
- Buffer: PChar; Size: DWORD): integer;
- function wioWaveSetFirstSample(lpwio: PWaveIOCB; dwSample: DWORD): integer;
- function wioWaveSetLastSample(lpwio: PWaveIOCB; dwSample: DWORD): integer;
- function wioWaveSetPosition(lpwio: PWaveIOCB; dwSample: DWORD): integer;
- function wioWaveReadData(lpwio: PWaveIOCB; Buffer: PChar; nBytes: DWORD): DWORD;
- function wioWaveReadDataDirect(lpwio: PWaveIOCB; Buffer: PChar; nBytes: DWORD): DWORD;
- function wioWaveReadSamples(lpwio: PWaveIOCB; Buffer: PChar; nSamples: DWORD): DWORD;
- function wioWaveWriteData(lpwio: PWaveIOCB; Buffer: PChar; nBytes: DWORD): DWORD;
- function wioWaveWriteDataDirect(lpwio: PWaveIOCB; Buffer: PChar; nBytes: DWORD): DWORD;
- function wioWaveWriteSamples(lpwio: PWaveIOCB; Buffer: PChar; nSamples: DWORD): DWORD;
- implementation
- Uses
- MMMath,
- MMMulDiv,
- MMPCMSup;
- {$DEFINE ROUND_UP}
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* calculate the bytes per sample from the actual settings. *)
- {* *}
- {*************************************************************************}
- function wioBytesPerSample(pwfx: PWaveFormatEx): integer;
- begin
- Result := wioSamplesToBytes(pwfx, 1);
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* convert a byte offset into a sample offset. *}
- {* *}
- {* dwSamples = (dwBytes / nAvgBytesPerSec) * nSamplesPerSec *}
- {* *}
- {*************************************************************************}
- function wioBytesToSamples(pwfx: PWaveFormatEx; dwBytes: DWORD): DWORD;
- begin
- Result := muldiv32RN(dwBytes,
- pwfx^.nSamplesPerSec,
- pwfx^.nAvgBytesPerSec);
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* convert a byte offset into a time offset in milliseconds. *}
- {* *}
- (* dwTime = (dwBytes / nAvgBytesPerSec) * 1000 *)
- {* *}
- {*************************************************************************}
- function wioBytesToTime(pwfx: PWaveFormatEx; dwBytes: DWORD): DWORD;
- begin
- Result := muldiv32RN(dwBytes, 1000, pwfx^.nAvgBytesPerSec);
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* convert a sample offset into a byte offset, with correct alignment*}
- {* to nBlockAlign. *}
- {* *}
- {* dwBytes = (dwSamples / nSamplesPerSec) * nBytesPerSec *}
- {* *}
- {*************************************************************************}
- function wioSamplesToBytes(pwfx: PWaveFormatEx; dwSamples: DWORD): DWORD;
- begin
- Result := muldiv32RN(dwSamples,
- pwfx^.nAvgBytesPerSec,
- pwfx^.nSamplesPerSec);
- { now align the byte offset to nBlockAlign }
- {$IFDEF ROUND_UP}
- Result := ((Result + pwfx^.nBlockAlign-1) div pwfx^.nBlockAlign) * pwfx^.nBlockAlign;
- {$ELSE}
- Result := (Result div pwfx^.nBlockAlign) * pwfx^.nBlockAlign;
- {$ENDIF}
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* convert a sample offset into a time offset in milliseconds. *}
- {* *}
- {* dwTime = (dwSamples / nSamplesPerSec) * 1000 *}
- {* *}
- {*************************************************************************}
- function wioSamplesToTime(pwfx: PWaveFormatEx; dwSamples: DWORD): DWORD;
- begin
- Result := muldiv32RN(dwSamples, 1000, pwfx^.nSamplesPerSec);
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* convert a time index in milliseconds to a sample offset. *}
- {* *}
- {* dwSamples = (dwTime / 1000) * nSamplesPerSec *}
- {* *}
- {*************************************************************************}
- function wioTimeToSamples(pwfx: PWaveFormatEx; dwTime: DWORD): DWORD;
- begin
- Result := muldiv32RN(dwTime, pwfx^.nSamplesPerSec, 1000);
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* convert a time index in milliseconds to a byte offset, with *)
- (* correct alignment to nBlockAlign. . *)
- {* *}
- {* dwBytes = ((dwTime / 1000) * nAvgBytesPerSec) *}
- {* *}
- {*************************************************************************}
- function wioTimeToBytes(pwfx: PWaveFormatEx; dwTime: DWORD): DWORD;
- begin
- Result := muldiv32RN(dwTime, pwfx^.nAvgBytesPerSec, 1000);
- { now align the byte offset to nBlockAlign }
- {$IFDEF ROUND_UP}
- Result := ((Result + pwfx^.nBlockAlign-1) div pwfx^.nBlockAlign) * pwfx^.nBlockAlign;
- {$ELSE}
- Result := (Result div pwfx^.nBlockAlign) * pwfx^.nBlockAlign;
- {$ENDIF}
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* convert a byte offset into a sample offset. (64 bit) *}
- {* *}
- {* dwSamples = (dwBytes / nAvgBytesPerSec) * nSamplesPerSec *}
- {* *}
- {*************************************************************************}
- function wioBytesToSamples64(pwfx: PWaveFormatEx; dwBytes: int64): int64;
- begin
- Result := MulDiv64(dwBytes,
- pwfx^.nSamplesPerSec,
- pwfx^.nAvgBytesPerSec);
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* convert a byte offset into a time offset in milliseconds.(64 bit)*}
- {* *}
- (* dwTime = (dwBytes / nAvgBytesPerSec) * 1000 *)
- {* *}
- {*************************************************************************}
- function wioBytesToTime64(pwfx: PWaveFormatEx; dwBytes: int64): int64;
- begin
- Result := MulDiv64(dwBytes, 1000, pwfx^.nAvgBytesPerSec);
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* convert a sample offset into a byte offset, with correct alignment*}
- {* to nBlockAlign. *}
- {* *}
- {* dwBytes = (dwSamples / nSamplesPerSec) * nBytesPerSec *}
- {* *}
- {*************************************************************************}
- function wioSamplesToBytes64(pwfx: PWaveFormatEx; dwSamples: int64): int64;
- {$IFNDEF DELPHI4}
- var
- Temp: int64;
- {$ENDIF}
- begin
- Result := muldiv64(dwSamples,
- pwfx^.nAvgBytesPerSec,
- pwfx^.nSamplesPerSec);
- { now align the byte offset to nBlockAlign }
- {$IFDEF ROUND_UP}
- {$IFDEF DELPHI4}
- Result := ((Result + pwfx^.nBlockAlign-1) div pwfx^.nBlockAlign) * pwfx^.nBlockAlign;
- {$ELSE}
- Temp := Result + pwfx^.nBlockAlign-1;
- Result := ((Temp/pwfx^.nBlockAlign)-ModR(Temp,pwfx^.nBlockAlign))* pwfx^.nBlockAlign;
- {$ENDIF}
- {$ELSE}
- {$IFDEF DELPHI4}
- Result := (Result div pwfx^.nBlockAlign) * pwfx^.nBlockAlign;
- {$ELSE}
- Result := ((Result / pwfx^.nBlockAlign)-ModR(Result,pwfx^.nBlockAlign)) * pwfx^.nBlockAlign;
- {$ENDIF}
- {$ENDIF}
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* convert a sample offset into a time offset in milliseconds. *}
- {* *}
- {* dwTime = (dwSamples / nSamplesPerSec) * 1000 *}
- {* *}
- {*************************************************************************}
- function wioSamplesToTime64(pwfx: PWaveFormatEx; dwSamples: int64): int64;
- begin
- Result := muldiv64(dwSamples, 1000, pwfx^.nSamplesPerSec);
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* convert a time index in milliseconds to a sample offset. *}
- {* *}
- {* dwSamples = (dwTime / 1000) * nSamplesPerSec *}
- {* *}
- {*************************************************************************}
- function wioTimeToSamples64(pwfx: PWaveFormatEx; dwTime: int64): int64;
- begin
- Result := muldiv64(dwTime, pwfx^.nSamplesPerSec, 1000);
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* convert a time index in milliseconds to a byte offset, with *)
- (* correct alignment to nBlockAlign. . *)
- {* *}
- {* dwBytes = ((dwTime / 1000) * nBytesPerSec) *}
- {* *}
- {*************************************************************************}
- function wioTimeToBytes64(pwfx: PWaveFormatEx; dwTime: int64): int64;
- {$IFNDEF DELPHI4}
- var
- Temp: int64;
- {$ENDIf}
- begin
- Result := muldiv64(dwTime, pwfx^.nAvgBytesPerSec, 1000);
- { now align the byte offset to nBlockAlign }
- {$IFDEF ROUND_UP}
- {$IFDEF DELPHI4}
- Result := ((Result + pwfx^.nBlockAlign-1) div pwfx^.nBlockAlign) * pwfx^.nBlockAlign;
- {$ELSE}
- Temp := Result + pwfx^.nBlockAlign-1;
- Result := ((Temp/pwfx^.nBlockAlign)-ModR(Temp,pwfx^.nBlockAlign)) * pwfx^.nBlockAlign;
- {$ENDIF}
- {$ELSE}
- {$IFDEF DELPHI4}
- Result := (Result div pwfx^.nBlockAlign) * pwfx^.nBlockAlign;
- {$ELSE}
- Result := ((Result/pwfx^.nBlockAlign)-ModR(Result,pwfx^.nBlockAlign)) * pwfx^.nBlockAlign;
- {$ENDIF}
- {$ENDIF}
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* calculate the bytes per sample from the actual settings. *)
- {* *}
- {*************************************************************************}
- function wioBytesPerSampleEx(lpwio: PWaveIOCB): integer;
- begin
- Result := wioSamplesToBytesEx(lpwio, 1);
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* convert a byte offset into a sample offset. *}
- {* *}
- {* dwSamples = (dwBytes / nAvgBytesPerSec) * nSamplesPerSec *}
- {* *}
- {*************************************************************************}
- function wioBytesToSamplesEx(lpwio: PWaveIOCB; dwBytes: DWORD): DWORD;
- begin
- if (lpwio^.fAvgBytesPerSec <> 0) then
- begin
- Result := Round((dwBytes*lpwio^.wfx.nSamplesPerSec)/lpwio^.fAvgBytesPerSec);
- end
- else Result := wioBytesToSamples(@lpwio^.wfx,dwBytes);
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* convert a byte offset into a time offset in milliseconds. *}
- {* *}
- (* dwTime = (dwBytes / nAvgBytesPerSec) * 1000 *)
- {* *}
- {*************************************************************************}
- function wioBytesToTimeEx(lpwio: PWaveIOCB; dwBytes: DWORD): DWORD;
- begin
- if (lpwio^.fAvgBytesPerSec <> 0) then
- begin
- Result := Round((dwBytes*1000)/lpwio^.fAvgBytesPerSec);
- end
- else Result := wioBytesToTime(@lpwio^.wfx,dwBytes);
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* convert a sample offset into a byte offset, with correct alignment*}
- {* to nBlockAlign. *}
- {* *}
- {* dwBytes = (dwSamples / nSamplesPerSec) * nBytesPerSec *}
- {* *}
- {*************************************************************************}
- function wioSamplesToBytesEx(lpwio: PWaveIOCB; dwSamples: DWORD): DWORD;
- begin
- if (lpwio^.fAvgBytesPerSec <> 0) then
- begin
- Result := Round((dwSamples*lpwio^.fAvgBytesPerSec)/lpwio^.wfx.nSamplesPerSec);
- { now align the byte offset to nBlockAlign }
- {$IFDEF ROUND_UP}
- Result := ((Result + lpwio^.wfx.nBlockAlign-1) div lpwio^.wfx.nBlockAlign) * lpwio^.wfx.nBlockAlign;
- {$ELSE}
- Result := (Result div lpwio^.wfx.nBlockAlign) * lpwio^.wfx.nBlockAlign;
- {$ENDIF}
- end
- else Result := wioSamplesToBytes(@lpwio^.wfx,dwSamples);
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* convert a sample offset into a time offset in milliseconds. *}
- {* *}
- {* dwTime = (dwSamples / nSamplesPerSec) * 1000 *}
- {* *}
- {*************************************************************************}
- function wioSamplesToTimeEx(lpwio: PWaveIOCB; dwSamples: DWORD): DWORD;
- begin
- if (lpwio^.fAvgBytesPerSec <> 0) then
- begin
- Result := Round((dwSamples*1000)/lpwio^.wfx.nSamplesPerSec);
- end
- else Result := wioSamplesToTime(@lpwio^.wfx,dwSamples);
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* convert a time index in milliseconds to a sample offset. *}
- {* *}
- {* dwSamples = (dwTime / 1000) * nSamplesPerSec *}
- {* *}
- {*************************************************************************}
- function wioTimeToSamplesEx(lpwio: PWaveIOCB; dwTime: DWORD): DWORD;
- begin
- if (lpwio^.fAvgBytesPerSec <> 0) then
- begin
- Result := Round((dwTime*lpwio^.wfx.nSamplesPerSec)/1000);
- end
- else Result := wioTimeToSamples(@lpwio^.wfx,dwTime);
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* convert a time index in milliseconds to a byte offset, with *)
- (* correct alignment to nBlockAlign. . *)
- {* *}
- {* dwBytes = ((dwTime / 1000) * nAvgBytesPerSec) *}
- {* *}
- {*************************************************************************}
- function wioTimeToBytesEx(lpwio: PWaveIOCB; dwTime: DWORD): DWORD;
- begin
- if (lpwio^.fAvgBytesPerSec <> 0) then
- begin
- Result := Round((dwTime*lpwio^.fAvgBytesPerSec)/1000);
- { now align the byte offset to nBlockAlign }
- {$IFDEF ROUND_UP}
- Result := ((Result + lpwio^.wfx.nBlockAlign-1) div lpwio^.wfx.nBlockAlign) * lpwio^.wfx.nBlockAlign;
- {$ELSE}
- Result := (Result div lpwio^.wfx.nBlockAlign) * lpwio^.wfx.nBlockAlign;
- {$ENDIF}
- end
- else Result := wioTimeToBytes(@lpwio^.wfx, dwTime);
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* returns the size of the wave format structure pwfx *}
- {* *}
- {*************************************************************************}
- function wioSizeOfWaveFormat(pwfx: PWaveFormatEx): integer;
- begin
- if (pwfx <> nil) then
- begin
- if pwfx^.wFormatTag = WAVE_FORMAT_PCM then
- Result := sizeOf(TWaveFormatEx)
- else
- Result := sizeOf(TWaveFormatEx)+pwfx^.cbSize
- end
- else Result := 0;
- end;
- {*************************************************************************}
- {* *}
- {* DESCRIPTION: *}
- {* duplicates the wave format structure pwfx *}
- {* *}
- {*************************************************************************}
- function wioCopyWaveFormat(pwfx: PWaveFormatEx): PWaveFormatEx;
- var
- Size: integer;
- begin
- Result := nil;
- if (pwfx <> nil) then
- begin
- Size := wioSizeOfWaveFormat(pwfx);
- if (Size > 0) then
- begin
- { get the memory }
- Result := GlobalAllocMem(Size);
- { copy the WaveFormatEx struc }
- Move(pwfx^, Result^, Size);
- if (Result^.wFormatTag = 1) then
- Result^.cbSize := 0;
- end;
- end;
- end;
- {*************************************************************************}
- type
- TStrFormat = packed record
- szformat: String;
- wFormat : Word;
- end;
- const
- Formats: array[0..38] of TStrFormat = (
- (szformat:'Unknown' ; wFormat: WAVE_FORMAT_UNKNOWN),
- (szformat:'PCM' ; wFormat: WAVE_FORMAT_PCM),
- (szformat:'PCM 32' ; wFormat: WAVE_FORMAT_PCM32),
- (szformat:'Microsoft ADPCM' ; wFormat: WAVE_FORMAT_ADPCM),
- (szformat:'Mediavision''s ADPCM' ; wFormat: WAVE_FORMAT_MEDIAVISION_ADPCM),
- (szformat:'IBM CVSD' ; wFormat: WAVE_FORMAT_IBM_CVSD),
- (szformat:'CCITT A-Law' ; wFormat: WAVE_FORMAT_ALAW),
- (szformat:'CCITT mu-Law' ; wFormat: WAVE_FORMAT_MULAW),
- (szformat:'OKI ADPCM' ; wFormat: WAVE_FORMAT_OKI_ADPCM),
- (szformat:'IMA ADPCM' ; wFormat: WAVE_FORMAT_IMA_ADPCM),
- (szformat:'DVI ADPCM' ; wFormat: WAVE_FORMAT_DVI_ADPCM),
- (szformat:'Mediaspace''s ADPCM' ; wFormat: WAVE_FORMAT_MEDIASPACE_ADPCM),
- (szformat:'Sierra''s ADPCM' ; wFormat: WAVE_FORMAT_SIERRA_ADPCM),
- (szformat:'CCITT G.723 ADPCM' ; wFormat: WAVE_FORMAT_G723_ADPCM),
- (szformat:'Digisound DIGISTD' ; wFormat: WAVE_FORMAT_DIGISTD),
- (szformat:'Digisound DIGIFIX' ; wFormat: WAVE_FORMAT_DIGIFIX),
- (szformat:'Dialogic OKI ADPCM' ; wFormat: WAVE_FORMAT_DIALOGIC_OKI_ADPCM),
- (szformat:'Yamaha ADPCM' ; wFormat: WAVE_FORMAT_YAMAHA_ADPCM),
- (szformat:'Sonarc' ; wFormat: WAVE_FORMAT_SONARC),
- (szformat:'DSP Group''s Truespeech' ; wFormat: WAVE_FORMAT_DSPGROUP_TRUESPEECH),
- (szformat:'Echo SC1' ; wFormat: WAVE_FORMAT_ECHOSC1),
- (szformat:'Audiofile AF36' ; wFormat: WAVE_FORMAT_AUDIOFILE_AF36),
- (szformat:'Audio Processing Technology'; wFormat: WAVE_FORMAT_APTX),
- (szformat:'Audiofile AF10' ; wFormat: WAVE_FORMAT_AUDIOFILE_AF10),
- (szformat:'Dolby AC2' ; wFormat: WAVE_FORMAT_DOLBY_AC2),
- (szformat:'Dolby AC2' ; wFormat: WAVE_FORMAT_DOLBY_AC2_REVA),
- (szformat:'GSM 6.10' ; wFormat: WAVE_FORMAT_GSM610),
- (szformat:'Antex ADPCME' ; wFormat: WAVE_FORMAT_ANTEX_ADPCME),
- (szformat:'CS IMA ADPCM' ; wFormat: WAVE_FORMAT_CS_IMAADPCM),
- (szformat:'CCITT G.721 ADPCM' ; wFormat: WAVE_FORMAT_G721_ADPCM),
- (szformat:'MPEG 1' ; wFormat: WAVE_FORMAT_MPEG),
- (szformat:'MPEG Layer-3' ; wFormat: WAVE_FORMAT_MPEG_LAYER3),
- (szformat:'Creative''s ADPCM' ; wFormat: WAVE_FORMAT_CREATIVE_ADPCM),
- (szformat:'Olivetti''s ADPCM' ; wFormat: WAVE_FORMAT_OLIADPCM),
- (szFormat:'CDI-C' ; wFormat: WAVE_FORMAT_CDIC),
- (szFormat:'CDI-B' ; wFormat: WAVE_FORMAT_CDIB),
- (szFormat:'Antex-DVI-OKI ADPCME' ; wFormat: WAVE_FORMAT_ADPCME),
- (szformat:'*DEVELOPMENT ONLY TAG*' ; wFormat: WAVE_FORMAT_DEVELOPMENT),
- (szformat:'' ; wFormat: 0));
- {*************************************************************************}
- procedure wioGetFormatName(pwfx: PWaveFormatEx; var FormatName: String);
- Var
- i: integer;
- begin
- if (pwfx <> Nil) then
- begin
- i := 0;
- while (formats[i].szformat <> '') do
- begin
- if (formats[i].wFormat = pwfx^.wFormatTag) then
- begin
- FormatName := formats[i].szformat;
- exit;
- end;
- inc(i);
- end;
- end;
- FormatName := 'Unknown';
- end;
- {*************************************************************************}
- procedure wioGetFormat(pwfx: PWaveFormatEx; var Format: String);
- const
- gszIntl = 'Intl';
- gszIntlList = 'sList';
- gszIntlDecimal = 'sDecimal';
- gchIntlList : char = ',';
- gchIntlDecimal : char = '.';
- var
- aBuf : array[0..255] of char;
- ach : array[0..1] of char;
- Channels: array[0..24] of char;
- Bits : word;
- begin
- if (pwfx <> Nil) then
- begin
- ach[0] := gchIntlList;
- ach[1] := #0;
- GetProfileString(gszIntl, gszIntlList, ach, ach, sizeof(ach));
- gchIntlList := ach[0];
- ach[0] := gchIntlDecimal;
- ach[1] := #0;
- GetProfileString(gszIntl, gszIntlDecimal, ach, ach, sizeof(ach));
- gchIntlDecimal := ach[0];
- { compute the bit depth--this _should_ be the same as }
- { wBitsPerSample, but isn't always... }
- Bits := (pwfx^.nAvgBytesPerSec * 8 div
- pwfx^.nSamplesPerSec div pwfx^.nChannels);
- if (pwfx^.nChannels = 1) or (pwfx^.nChannels = 2) then
- begin
- if (pwfx^.nChannels = 1)then
- StrCopy(Channels, 'Mono')
- else
- StrCopy(Channels, 'Stereo');
- StrFmt(aBuf,'%d%s%.03d kHz%s %d Bit%s %s',
- [pwfx^.nSamplesPerSec div 1000, gchIntlDecimal,
- pwfx^.nSamplesPerSec mod 1000, gchIntlList,
- Bits, gchIntlList, Channels]);
- end
- else
- begin
- StrFmt(aBuf,'%d%s%.03d kHz%s %d Bit%s %d Channels',
- [pwfx^.nSamplesPerSec div 1000, gchIntlDecimal,
- pwfx^.nSamplesPerSec mod 1000, gchIntlList,
- Bits, gchIntlList, pwfx^.nChannels]);
- end;
- Format := StrPas(aBuf);
- end
- else Format := 'Unknown';
- end;
- {**************************************************************************}
- function wioIsWaveFile(FilePath: TFileName; dwFlags: DWORD): Boolean;
- Var
- aBuf: PChar;
- lpwio: PWAVEIOCB;
- begin
- Result := False;
- if FilePath <> '' then
- begin
- aBuf := StrAlloc(Length(FilePath)+1);
- try
- StrPCopy(aBuf, FilePath);
- if wioReadFileInfo(lpwio, aBuf,
- mmioFOURCC('W', 'A', 'V', 'E'),
- dwFlags) = 0 then
- Result := True;
- finally
- wioFreeFileInfo(lpwio);
- StrDispose(aBuf);
- end;
- end;
- end;
- {**************************************************************************}
- function wioGetFullPathName(lpFilePath: PChar): Boolean;
- begin
- { return a full path for this file }
- Result := mmioOpen(lpFilePath, Nil, MMIO_PARSE) <> 0;
- end;
- {**************************************************************************}
- function wioFileExists(lpFilePath: PChar): Boolean;
- begin
- Result := mmioOpen(lpFilePath, Nil, MMIO_EXIST) <> 0;
- end;
- {**************************************************************************}
- function wioFileDelete(lpFilePath: PChar): Boolean;
- begin
- Result := mmioOpen(lpFilePath, Nil, MMIO_DELETE) <> 0;
- end;
- {**************************************************************************}
- procedure wioExtractPath(lpFilePath: PChar);
- var
- i: Integer;
- begin
- i := StrLen(lpFilePath);
- while (i > 0) and not (lpFilePath[i] in ['', ':']) do
- begin
- lpFilePath[i] := #0;
- dec(i);
- end;
- end;
- {**************************************************************************}
- function wioFileCreateTemp(lpFilePath: PChar): Boolean;
- begin
- {$IFDEF WIN32}
- if (lpFilePath = '') or (lpFilePath[0] = #0) then
- begin
- GetTempPath(MAX_PATH-1,lpFilePath);
- end;
- {$ENDIF}
- { make sure we have a full pathname }
- wioGetFullPathName(lpFilePath);
- {$IFDEF WIN32}
- { extract the filename }
- wioExtractPath(lpFilePath);
- { create the temp file }
- Result := GetTempFileName(lpFilePath,
- 'w'#0,
- Random(256)+1,
- lpFilePath) <> 0;
- {$ELSE}
- { get the drive letter }
- StrLCopy(lpFilePath, StrUpper(lpFilePath), 2);
- { create the temp file }
- Result := GetTempFileName(Char(Byte(UpCase(lpFilePath[0]))or TF_FORCEDRIVE),
- 'w'#0, 0, lpFilePath) <> 0;
- {$ENDIF}
- { return a full path for this file }
- if Result then
- begin
- wioGetFullPathName(lpFilePath);
- wioFileDelete(lpFilePath);
- end;
- end;
- {**************************************************************************}
- procedure wioFileClose(Var hmmio: THMMIO; Var hMem: THandle);
- begin
- if (hMem <> 0) then
- begin
- UnlockResource(hMem);
- FreeResource(hMem);
- hMem := 0;
- end;
- if (hmmio <> 0) then mmioClose(hmmio, 0);
- hmmio := 0;
- end;
- (**************************************************************************)
- function wioFileOpen(Var hmmio: THMMIO;
- Var ckRIFF: TMMCKINFO;
- Var HMem: THandle;
- lpFilePath: PChar;
- fccType: FourCC;
- dwFlags: DWORD): integer;
- Label ERROR_OPEN_WAVE;
- Var
- HRsrc: THandle;
- mmioInfo: TMMIOINFO;
- begin
- { default our error return (assume the worst) }
- Result := WIOERR_FILEERROR;
- HMem := 0;
- { first try to open the file, etc.. open the given file for reading }
- { using buffered I/O }
- if (dwFlags AND RIFF_RESOURCE <> 0) then
- begin
- HRsrc := FindResource(HInstance, lpFilePath, 'WAVE');
- HMem := LoadResource(HInstance, HRsrc);
- if HMem = 0 then
- goto ERROR_OPEN_WAVE;
- FillChar(mmioInfo, sizeOf(TMMIOINFO), 0);
- mmioInfo.pchBuffer := LockResource(HMem);
- if mmioInfo.pchBuffer = Nil then
- goto ERROR_OPEN_WAVE;
- {$IFDEF WIN32}
- mmioInfo.cchBuffer := SizeofResource(HInstance,HRsrc);
- {$ELSE}
- mmioInfo.cchBuffer := GlobalSize(HMem);
- {$ENDIF}
- mmioInfo.fccIOProc := FOURCC_MEM;
- mmioInfo.adwInfo[0] := 0;
- hmmio := mmioOpen(Nil, @mmioInfo, MMIO_READ OR MMIO_ALLOCBUF);
- if (hmmio = 0) then
- goto ERROR_OPEN_WAVE;
- end
- else if (dwFlags AND RIFF_MEMORY <> 0) then
- begin
- move(lpFilePath^, mmioInfo, sizeOf(TMMIOINFO));
- mmioInfo.fccIOProc := FOURCC_MEM;
- mmioInfo.adwInfo[0] := 0;
- hmmio := mmioOpen(Nil, @mmioInfo, MMIO_READ OR MMIO_ALLOCBUF);
- if (hmmio = 0) then
- goto ERROR_OPEN_WAVE;
- end
- else { Open the given file for reading using buffered I/O. }
- begin
- if (FileGetAttr(StrPas(lpFilePath)) and faReadOnly = 0) then
- begin
- hmmio := mmioOpen(lpFilePath, Nil, MMIO_READWRITE OR MMIO_ALLOCBUF);
- if (hmmio = 0) then
- hmmio := mmioOpen(lpFilePath, Nil, MMIO_READ OR MMIO_ALLOCBUF);
- end
- else
- hmmio := mmioOpen(lpFilePath, Nil, MMIO_READ OR MMIO_ALLOCBUF);
- if (hmmio = 0) then
- goto ERROR_OPEN_WAVE;
- end;
- if mmioDescend(hmmio, @ckRIFF, Nil, 0) <> 0 then
- goto ERROR_OPEN_WAVE;
- if (ckRIFF.ckid <> FOURCC_RIFF) or (ckRIFF.fccType <> fccType) then
- goto ERROR_OPEN_WAVE;
- Result := WIOERR_NOERROR;
- exit;
- ERROR_OPEN_WAVE:
- wioFileClose(hmmio, hMem);
- end;
- {**************************************************************************}
- function wioReadFileInfo(Var lpwio: PWAVEIOCB; lpFilePath: PChar;
- fccType: FourCC; dwFlags: DWORD): integer;
- Label ERROR_READING_WAVE;
- Var
- hmmio: THMMIO;
- hMem : THandle;
- wio: TWAVEIOCB;
- ck,ckRIFF: TMMCKINFO;
- dw: Longint;
- TempRes: integer;
- CheckDataSize: Boolean;
- NextOffset: DWORD;
- hasFormat,hasData: Boolean;
- begin
- { default our error return (assume the worst) }
- Result := WIOERR_FILEERROR;
- lpwio := Nil;
- { first try to open the file, etc.. open the given file for reading }
- { using buffered I/O }
- if (wioFileOpen(hmmio, ckRIFF, hMem, lpFilePath, fccType, dwFlags) <> 0) OR (hmmio = 0) then
- goto ERROR_READING_WAVE;
- FillChar(wio, sizeof(wio), 0);
- { Save the filename or the memory/resource mmioInfo structure }
- if (dwFlags = RIFF_MEMORY) then
- begin
- wio.lpFilePath := StrAlloc(sizeOf(TMMIOINFO)+1);
- move(lpFilePath^, wio.lpFilePath^, sizeOf(TMMIOINFO));
- end
- else wio.lpFilePath := StrNew(lpFilePath);
- { get the file size }
- wio.dwFileSize := mmioSeek(hmmio, 0, SEEK_END);
- if (wio.dwFileSize = $FFFFFFFF) then
- goto ERROR_READING_WAVE;
- { return to RIFF chunk }
- if mmioSeek(hmmio, ckRIFF.dwDataOffset + sizeOf(FOURCC), SEEK_SET) = -1 then
- goto ERROR_READING_WAVE;
- { quickly check for corrupt RIFF file--don't ascend past end! }
- if (ckRIFF.dwDataOffset + ckRIFF.cksize > wio.dwFileSize) then
- begin
- ckRIFF.ckSize := wio.dwFileSize-ckRIFF.dwDataOffset;
- {goto ERROR_READING_WAVE;}
- end;
- { we found a WAVE chunk--now go through and get all subchunks that }
- { we know how to deal with... }
- wio.dwDataSamples := $FFFFFFFF;
- TempRes := RiffInitINFO(wio.lpInfo);
- if TempRes <> 0 then
- begin
- Result := TempRes;
- goto ERROR_READING_WAVE;
- end;
- TempRes := RiffInitDISP(wio.lpDisp);
- if TempRes <> 0 then
- begin
- Result := TempRes;
- goto ERROR_READING_WAVE;
- end;
- CheckDataSize := False;
- NextOffset := wio.dwFileSize;
- hasFormat := False;
- hasData := False;
- while mmioDescend(hmmio, @ck, @ckRIFF, 0) = 0 do
- begin
- { quickly check for corrupt RIFF file--don't ascend past end! }
- if (ck.dwDataOffset + ck.cksize > ckRIFF.dwDataOffset + ckRIFF.ckSize) then
- begin
- if hasFormat and hasData then
- break
- else if (ck.dwDataOffset + ck.cksize > wio.dwFileSize) then
- begin
- ck.ckSize := wio.dwFileSize-ck.dwDataOffset;
- {goto ERROR_READING_WAVE;}
- end;
- end;
- if CheckDataSize then
- begin
- NextOffset := ck.dwDataOffset-8;
- CheckDataSize := False;
- end;
- if ck.ckid = mmioFOURCC('L', 'I', 'S', 'T') then
- begin
- if (ck.fccType = mmioFOURCC('I', 'N', 'F', 'O')) then
- begin
- TempRes := RiffReadINFO(hmmio, @ck, wio.lpInfo);
- if TempRes <> 0 then
- begin
- Result := TempRes;
- goto ERROR_READING_WAVE;
- end;
- end;
- end
- else if ck.ckid = mmioFOURCC('D', 'I', 'S', 'P') then
- begin
- TempRes := RiffReadDISP(hmmio, @ck, wio.lpDisp);
- if TempRes <> 0 then
- begin
- Result := TempRes;
- goto ERROR_READING_WAVE;
- end;
- end
- else if ck.ckid = mmioFOURCC('f', 'm', 't', ' ') then
- begin
- { !?! another format chunk !?! }
- if (lpwio <> Nil) then break;
- { get size of the format chunk, allocate and lock memory }
- { for it. we always alloc a complete extended format header }
- { (even for PCM headers that do not have the cbSize field }
- { defined--we just set it to zero). }
- dw := ck.cksize;
- if (dw < sizeof(TWAVEFORMATEX)) then
- dw := sizeof(TWAVEFORMATEX);
- inc(dw, sizeof(TWAVEIOCB) - sizeof(TWAVEFORMATEX));
- lpwio := GlobalAllocMem(dw);
- if (lpwio = Nil) then
- begin
- Result := WIOERR_NOMEM;
- goto ERROR_READING_WAVE;
- end;
- lpwio^.dwSize := dw;
- { read the format chunk }
- Result := WIOERR_FILEERROR;
- dw := ck.cksize;
- if mmioRead(hmmio, PChar(@lpwio^.wfx), dw) <> dw then
- goto ERROR_READING_WAVE;
- hasFormat := True;
- end
- else if ck.ckid = mmioFOURCC('d', 'a', 't', 'a') then
- begin
- { !?! multiple data chunks !?! }
- if (wio.dwDataBytes <> 0) then break;
- { just hang on to the total length in bytes of this data }
- { chunk.. }
- wio.dwDataBytes := ck.cksize;
- { offset of data portion of data chunk }
- wio.dwDataOffset:= ck.dwDataOffset;
- CheckDataSize := True;
- hasData := True;
- end
- else if ck.ckid = mmioFOURCC('f', 'a', 'c', 't') then
- begin
- { !?! multiple fact chunks !?! }
- if (wio.dwDataSamples <> $FFFFFFFF) then break;
- { read the first dword in the fact chunk--it's the only }
- { info we need (and is currently the only info defined for }
- { the fact chunk...) }
- { if this fails, dwDataSamples will remain -1 so we will }
- { deal with it later... }
- mmioRead(hmmio, PChar(@wio.dwDataSamples), sizeof(Longint));
- end;
- { step up to prepare for next chunk.. }
- if mmioAscend(hmmio, @ck, 0) <> 0 then
- { bug fix for files with not 4 byte aligned chunks }
- if (wio.dwDataBytes <> 0) then break
- else goto ERROR_READING_WAVE;
- end;
- if (dwFlags and RIFF_INFO_ONLY = 0) then
- begin
- { if no fmt chunk was found, then die! }
- if (lpwio = Nil) then
- begin
- Result := WIOERR_ERROR;
- goto ERROR_READING_WAVE;
- end;
- wio.dwDataBytes := ((NextOffset-wio.dwDataOffset) div lpwio^.wfx.nBlockAlign)*lpwio^.wfx.nBlockAlign;
-
- { some wave files have wrong entrys for AvgBytesPerSecond and }
- { BlockAlign so we calculate them ourself }
- if (lpwio^.wfx.wFormatTag = WAVE_FORMAT_PCM) then
- with lpwio^.wfx do
- begin
- nBlockAlign := (wBitsPerSample * nChannels) div 8;
- nAvgBytesPerSec:= nBlockAlign * nSamplesPerSec;
- end;
- { all wave files other than PCM are _REQUIRED_ to have a fact chunk }
- { telling the number of samples that are contained in the file. it }
- { is optional for PCM (and if not present, we compute it here). }
- { check for corrupt fact chunk and repair }
- if (wio.dwDataSamples <> wioBytesToSamplesEx(lpwio,wio.dwDataBytes)) then
- wio.dwDataSamples := wioBytesToSamplesEX(lpwio,wio.dwDataBytes);
- { cool! no problems... }
- lpwio^.hmmio := 0;
- lpwio^.dwFlags := dwFlags;
- lpwio^.dwFileSize := wio.dwFileSize;
- lpwio^.dwDataBytes := wio.dwDataBytes;
- lpwio^.dwDataSamples := wio.dwDataSamples;
- lpwio^.dwDataOffset := wio.dwDataOffset;
- lpwio^.dwFirstSample := 0;
- lpwio^.dwLastSample := wio.dwDataSamples;
- lpwio^.dwBytesLeft := 0;
- lpwio^.dwPosition := 0;
- lpwio^.lpFilePath := wio.lpFilePath;
- lpwio^.lpDisp := wio.lpDisp;
- lpwio^.lpInfo := wio.lpInfo;
- end
- else
- begin
- dw := sizeof(TWAVEFORMATEX) + sizeof(TWAVEIOCB);
- lpwio := GlobalAllocMem(dw);
- if (lpwio = Nil) then
- begin
- Result := WIOERR_NOMEM;
- goto ERROR_READING_WAVE;
- end;
- FillChar(lpwio^,dw,0);
- lpwio^.dwSize := dw;
- lpwio^.dwFlags := dwFlags;
- lpwio^.lpFilePath := wio.lpFilePath;
- lpwio^.lpDisp := wio.lpDisp;
- lpwio^.lpInfo := wio.lpInfo;
- end;
- wioFileClose(hmmio, hMem);
- Result := WIOERR_NOERROR;
- exit;
- { return error (after minor cleanup) }
- ERROR_READING_WAVE:
- wioFileClose(hmmio, hMem);
- wioFreeFileInfo(lpwio);
- if (lpwio <> Nil) then GlobalFreeMem(Pointer(lpwio));
- lpwio := Nil;
- end;
- {**************************************************************************}
- function wioCreateFileInfo(Var lpwio: PWAVEIOCB; pwfx: PWaveFormatEx): integer;
- Label ERROR_CREATE_INFO;
- Var
- dwSize: Longint;
- TempRes: integer;
- ExtraAlloc: Longint;
- begin
- { default our error return (assume the worst) }
- Result := WIOERR_BADPARAM;
- lpwio := Nil;
- if (pwfx = Nil) then
- goto ERROR_CREATE_INFO;
- { allocate and lock memory for lpwio. we always alloc a complete }
- { extended format header (even for PCM headers that do not have }
- { the cbSize field defined--we just set it to zero). }
- if (pwfx^.wFormatTag = WAVE_FORMAT_PCM) then
- ExtraAlloc := 0
- else
- ExtraAlloc := pwfx^.cbSize;
- dwSize := sizeOf(TWAVEIOCB) + ExtraAlloc;
- lpwio := GlobalAllocMem(dwSize);
- if (lpwio = Nil) then
- begin
- Result := WIOERR_NOMEM;
- goto ERROR_CREATE_INFO;
- end;
- { set the wio struc size }
- lpwio^.dwSize := dwSize;
- { copy the WaveFormatEx struc to lpwio's }
- Move(pwfx^, lpwio^.wfx, sizeOf(TWAVEFORMATEX) + ExtraAlloc);
- { create a new INFO struc }
- TempRes := RiffInitINFO(lpwio^.lpInfo);
- if (TempRes <> 0) then
- begin
- Result := TempRes;
- goto ERROR_CREATE_INFO;
- end;
- { create a new DISP list }
- TempRes := RiffInitDISP(lpwio^.lpDisp);
- if (TempRes <> 0) then
- begin
- Result := TempRes;
- goto ERROR_CREATE_INFO;
- end;
- Result := WIOERR_NOERROR;
- exit;
- { return error (after minor cleanup) }
- ERROR_CREATE_INFO:
- wioFreeFileInfo(lpwio);
- end;
- {**************************************************************************}
- function wioCopyFileInfo(lpwioDst, lpwioSrc: PWAVEIOCB): integer;
- begin
- { default our error return (assume the worst) }
- Result := WIOERR_BADPARAM;
- if (lpwioSrc = Nil) or (lpwioDst = nil) then
- exit;
- Result := WIOERR_ERROR;
- { copy the INFO chunk to the destination }
- if RiffCopyInfo(lpwioDst^.lpInfo, lpwioSrc^.lpInfo) <> 0 then
- exit;
- { copy the DISP chunk to the destination }
- if RiffCopyDISP(lpwioDst^.lpDisp, lpwioSrc^.lpDisp) <> 0 then
- exit;
- Result := WIOERR_NOERROR;
- end;
- {**************************************************************************}
- function wioBuildFileInfoFromMem(Var lpwio: PWaveIOCB; Memory: Pointer; MemSize: DWORD): Word;
- Var
- mmioInfo: TMMIOINFO;
- begin
- Result := WIOERR_FILEERROR;
- lpwio := nil;
- if (Memory <> nil) and (MemSize > 0) then
- begin
- FillChar(mmioInfo, sizeOf(TMMIOINFO),0);
- mmioInfo.pchBuffer := Memory;
- mmioInfo.cchBuffer := MemSize;
- Result := wioReadFileInfo(lpwio, PChar(@mmioInfo),
- mmioFOURCC('W', 'A', 'V', 'E'), RIFF_MEMORY);
- end;
- end;
- {**************************************************************************}
- function wioBuildFileInfoFromResource(Var lpwio: PWaveIOCB; ResourceName: PChar): Word;
- begin
- lpwio := nil;
- Result := wioReadFileInfo(lpwio, ResourceName,
- mmioFOURCC('W', 'A', 'V', 'E'), RIFF_RESOURCE);
- end;
- {**************************************************************************}
- function wioBuildFileInfoFromRAWEx(Var lpwio: PWaveIOCB; lpFileName: PChar; DataOffset: DWORD;
- pwfx: PWaveFormatEx): integer;
- var
- h: THandle;
- begin
- Result := WIOERR_FILEERROR;
- lpwio := nil;
- if wioCreateFileInfo(lpwio, pwfx) = WIOERR_NOERROR then
- begin
- h := FileOpen(StrPas(lpFileName), fmOpenRead or fmShareDenyNone);
- if (h <> $FFFFFFFF) then
- with lpwio^ do
- begin
- dwFlags := RAW_FILE;
- dwFileSize := FileSeek(h, 0, 2);
- dwDataBytes := dwFileSize-DataOffset;
- dwDataOffset := DataOffset;
- dwDataSamples:= wioBytesToSamplesEx(lpwio,dwDataBytes);
- dwFirstSample:= 0;
- dwLastSample := dwDataSamples;
- dwBytesLeft := 0;
- dwPosition := 0;
- lpFilePath := StrNew(lpFileName);
- FileClose(h);
- Result := WIOERR_NOERROR;
- end
- else wioFreeFileInfo(lpwio);
- end;
- end;
- {**************************************************************************}
- function wioBuildFileInfoFromRAW(Var lpwio: PWaveIOCB; lpFileName: PChar;
- DataOffset, BitLength,
- Channels, SampleRate: DWORD): integer;
- var
- wfx: TWaveFormatEx;
- begin
- pcmBuildWaveHeader(@wfx,BitLength,Channels,SampleRate);
- Result := wioBuildFileInfoFromRAWEx(lpwio,lpFileName,DataOffset,@wfx);
- end;
- {**************************************************************************}
- function wioWriteFileInfo(Var lpwio: PWAVEIOCB; lpFilePath: PChar): integer;
- Label ERROR_CANNOT_WRITE;
- Var
- hmmio: THMMIO;
- ckDATA, ckRIFF: TMMCKINFO;
- dw: Longint;
- begin
- { default our error return (assume the worst) }
- Result := WIOERR_FILEERROR;
- hmmio := 0;
- { validate a couple of things }
- if (lpwio = Nil) or (lpFilePath = Nil) then
- begin
- Result := WIOERR_BADPARAM;
- goto ERROR_CANNOT_WRITE;
- end;
- { yes, this is the open... }
- hmmio := mmioOpen(lpFilePath, Nil, MMIO_CREATE or MMIO_READWRITE or MMIO_ALLOCBUF);
- if (hmmio = 0) then
- goto ERROR_CANNOT_WRITE;
- { create the RIFF chunk of form type 'WAVE' }
- ckRIFF.fccType := mmioFOURCC('W', 'A', 'V', 'E');
- ckRIFF.cksize := 0;
- if mmioCreateChunk(hmmio, @ckRIFF, MMIO_CREATERIFF) <> 0 then
- goto ERROR_CANNOT_WRITE;
- { now create the destination fmt and data chunks _in that order_ }
- { hmmio is now descended into the 'RIFF' chunk--create the format chunk}
- { and write the format header into it }
- dw := wioSizeOfWaveFormat(@lpwio^.wfx);
- ckDATA.ckid := mmioFOURCC('f', 'm', 't', ' ');
- ckDATA.cksize := dw;
- if mmioCreateChunk(hmmio, @ckDATA, 0) <> 0 then
- goto ERROR_CANNOT_WRITE;
- { Write the WAVEFORMAT structure to the 'fmt ' chunk. }
- if mmioWrite(hmmio, @lpwio^.wfx, dw) <> dw then
- goto ERROR_CANNOT_WRITE;
- { Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk. }
- if mmioAscend(hmmio, @ckDATA, 0) <> 0 then
- goto ERROR_CANNOT_WRITE;
- { create the data chunk AND STAY DESCENDED... for reasons that }
- { will become apparent later.. }
- ckDATA.ckid := mmioFOURCC('d', 'a', 't', 'a');
- ckDATA.cksize := 0;
- ckData.dwFlags:= MMIO_DIRTY;
- if mmioCreateChunk(hmmio, @ckDATA, 0) <> 0 then
- goto ERROR_CANNOT_WRITE;
- { to close the file do:
- mmioAscend(hmmio, @ckData, 0);
- mmioAscend(hmmio, @ckRIFF, 0);
- mmioClose(hmmio, 0); }
- { cool! no problems.. }
- lpwio^.hmmio := hmmio;
- lpwio^.ckRIFF := ckRIFF;
- lpwio^.ckDATA := ckDATA;
- lpwio^.dwDataOffset := ckDATA.dwDataOffset;
- lpwio^.lpFilePath := StrNew(lpFilePath);
- lpwio^.dwDataSamples := wioBytesToSamplesEx(lpwio, lpwio^.dwDataBytes);
- lpwio^.dwFirstSample := 0;
- lpwio^.dwLastSample := lpwio^.dwDataSamples;
- Result := WIOERR_NOERROR;
- exit;
- { return error (after minor cleanup) }
- ERROR_CANNOT_WRITE:
- if (hmmio <> 0) then
- mmioClose(hmmio, 0); { close the new file }
- { delete the half-written file. }
- wioFileDelete(lpFilePath);
- end;
- {**************************************************************************}
- function wioFreeFileInfo(Var lpwio: PWAVEIOCB): integer;
- begin
- { validate a couple of things... }
- if (lpwio = Nil) then
- begin
- Result := WIOERR_BADPARAM;
- exit;
- end;
- { get rid of stuff... }
- if (lpwio^.hmmio <> 0) then
- begin
- if (lpwio^.dwFlags and RAW_FILE <> 0) then
- FileClose(lpwio^.hmmio)
- else
- mmioClose(lpwio^.hmmio, 0);
- lpwio^.hmmio := 0;
- end;
- if (lpwio^.lpFilePath <> Nil) then
- StrDispose(lpwio^.lpFilePath);
- if (lpwio^.lpInfo <> Nil) then
- RiffFreeINFO(lpwio^.lpInfo);
- if (lpwio^.lpDisp <> Nil) then
- RiffFreeDISP(lpwio^.lpDisp,True);
- GlobalFreeMem(Pointer(lpwio));
- lpwio := Nil;
- Result := WIOERR_NOERROR;
- end;
- (**************************************************************************
- * This routine will copy from a source wave file to a destination wave
- * file all those useless chunks (well, the ones useless to conversions,
- * etc --> apparently people use them!). The source will be seeked to the
- * begining, but the destination has to be at a current pointer to put the
- * new chunks. This will also seek back to the start of the wave riff
- * header at the end of the routine.
- *
- * Both files must be open !!!
- *
- * Returns 0 if successful, else the error code. If this routine fails, it
- * still attemps to seek back to the start of the wave riff header, though
- * this too could be unsuccessful.
- **************************************************************************)
- function wioWaveCopyUselessChunks(lpwioSrc, lpwioDst: PWaveIOCB): integer;
- Label COPY_ERROR;
- begin
- Result := WIOERR_FILEERROR;
- { First seek to the start of the file, not including the riff header }
- with lpwioSrc^ do
- begin
- if mmioSeek(hmmio, ckRIFF.dwDataOffset + sizeOf(FOURCC), SEEK_SET) = -1 then
- goto COPY_ERROR;
- while mmioDescend(hmmio, @ckDATA, @ckRIFF, 0) = 0 do
- begin
- { quickly check for corrupt RIFF file--don't ascend past end! }
- if (ckData.dwDataOffset + ckDATA.cksize > ckRIFF.dwDataOffset + ckRIFF.cksize) then
- goto COPY_ERROR;
- { copy chunks that are OK to copy }
- if ckDATA.ckid = mmioFOURCC('c', 'u', 'e', ' ') then
- { it doesn't make much sense }
- RiffCopyChunk(hmmio, lpwioDst^.hmmio, @ckDATA)
- else if ckDATA.ckid = mmioFOURCC('p', 'l', 's', 't') then
- { although without the 'cue' chunk, it doesn't make much sense }
- RiffCopyChunk(hmmio, lpwioDst^.hmmio, @ckDATA)
- { don't copy unknown chunks }
- else break;
- { step up to prepare for next chunk.. }
- mmioAscend(hmmio, @ckDATA, 0);
- end;
- end;
- Result := WIOERR_NOERROR;
- COPY_ERROR:
- { Seek back to source RIFF header }
- with lpwioSrc^ do
- mmioSeek(hmmio, ckRIFF.dwDataOffset + sizeof(FOURCC), SEEK_SET);
- end;
- {**************************************************************************}
- (* TODO: does not work !? mmioGetInfo returns in cchBuffer bad size !!!???*)
- function wioSetIOBufferSize(lpwio: PWaveIOCB; dwSize: integer): integer;
- begin
- Result := WIOERR_BADPARAM;
- { validate a couple of things... }
- if (lpwio = Nil) then exit;
- Result := WIOERR_ERROR;
- if (lpwio^.dwFlags and RIFF_MEMORY <> 0) or
- (lpwio^.dwFlags and RIFF_RESOURCE <> 0) or
- (lpwio^.dwFlags and RAW_FILE <> 0) then
- Result := WIOERR_NOERROR
- else if (lpwio^.hmmio <> 0) and (dwSize >= 0) then
- Result := mmioSetBuffer(lpwio^.hmmio, Nil, dwSize, 0);
- end;
- {**************************************************************************}
- function wioWaveOpen(lpwio: PWaveIOCB): integer;
- begin
- Result := WIOERR_BADPARAM;
- { validate a couple of things... }
- if (lpwio = Nil) then exit;
- Result := WIOERR_FILEERROR;
- { (re)open the file }
- if (lpwio^.hmmio = 0) then
- with lpwio^ do
- begin
- if (dwFlags and RAW_FILE <> 0) then
- hmmio := FileOpen(StrPas(lpFilePath),fmOpenRead or fmShareDenyNone)
- else wioFileOpen(hmmio, ckRIFF, hMem, lpFilePath,
- mmioFOURCC('W', 'A', 'V', 'E'),dwFlags);
- end;
- { set start position }
- if (lpwio^.hmmio <> 0) then
- if wioWaveSetPosition(lpwio, lpwio^.dwPosition) = 0 then
- Result := WIOERR_NOERROR;
- end;
- {**************************************************************************}
- function wioWaveClose(lpwio: PWaveIOCB): integer;
- Label ERROR_CANNOT_WRITE;
- Var
- mmioInfo: TMMIOINFO;
- begin
- Result := WIOERR_NOERROR;
- if (lpwio = Nil) or (lpwio^.hmmio = 0) then exit;
- with lpwio^ do
- begin
- Result := WIOERR_FILEERROR;
- if (dwFlags and RAW_FILE = 0) and
- (ckData.dwFlags and MMIO_DIRTY <> 0) then
- begin
- if mmioGetInfo(hmmio, @mmioInfo, 0) <> 0 then
- goto ERROR_CANNOT_WRITE;
- if mmioFlush(hmmio,0) <> 0 then
- goto ERROR_CANNOT_WRITE; { cannot write file, probably }
- if mmioInfo.dwFlags and MMIO_CREATE = 0 then
- begin
- { rewrite the size of data chunk }
- ckData.cksize := 0;
- ckData.dwFlags:= ckData.dwFlags or MMIO_DIRTY;
- { seek to the end of the chunk first }
- if mmioSeek(hmmio,dwDataOffset+dwDataBytes,SEEK_SET) = -1 then
- goto ERROR_CANNOT_WRITE; { cannot seek, probably }
- { force the rif chunk to rewrite }
- ckRiff.cksize := 0;
- ckRiff.dwFlags:= ckRiff.dwFlags or MMIO_DIRTY;
- end;
- { Ascend the output file out of the 'data' chunk - this will }
- { cause the chunk size of the 'data' chunk to be written. }
- if mmioAscend(hmmio, @ckDATA, 0) <> 0 then
- goto ERROR_CANNOT_WRITE; { cannot write file, probably }
- { Now create the fact chunk, not required for PCM but nice to have. }
- ckDATA.ckid := mmioFOURCC('f', 'a', 'c', 't');
- ckDATA.cksize := 0;
- if mmioCreateChunk(hmmio, @ckDATA, 0) <> 0 then
- goto ERROR_CANNOT_WRITE;
- { If it didn't fail, write the fact chunk out }
- if mmioWrite(hmmio, @dwDataSamples, sizeOf(Longint)) <> sizeOf(Longint) then
- goto ERROR_CANNOT_WRITE;
- { Now ascend out of the fact chunk... }
- if mmioAscend(hmmio, @ckDATA, 0) <> 0 then
- goto ERROR_CANNOT_WRITE;
- { now write out possibly editted chunks... }
- if RiffWriteDISP(hmmio, lpDisp) <> 0 then
- goto ERROR_CANNOT_WRITE;
- if RiffWriteINFO(hmmio, lpInfo) <> 0 then
- goto ERROR_CANNOT_WRITE;
- { Ascend the output file out of the 'RIFF' chunk - this will }
- { cause the chunk size of the 'RIFF' chunk to be written. }
- if mmioAscend(hmmio, @ckRIFF, 0) <> 0 then
- goto ERROR_CANNOT_WRITE; { cannot write file, probably }
- { Get the file size }
- dwFileSize := mmioSeek(hmmio, 0, SEEK_END);
- if (dwFileSize = $FFFFFFFF) then
- goto ERROR_CANNOT_WRITE;
- { cool! no problems.. }
- dwLastSample := dwDataSamples;
- end;
- Result := WIOERR_NOERROR;
- ERROR_CANNOT_WRITE:
- { finally close the file }
- if (dwFlags and RAW_FILE <> 0) then
- begin
- FileClose(hmmio);
- hmmio := 0;
- end
- else
- wioFileClose(hmmio, hMem);
- dwBytesLeft := 0;
- dwPosition := 0;
- end;
- end;
- (**************************************************************************
- * This routine loads a full wave file into memory. Be careful, wave files
- * can get pretty big these days :).
- *
- * lpFilePath - Filename
- * Size - Size of loaded wave (returned)
- * pwfx - Pointer to waveFormatEx structure. The wfx
- * structure IS ALLOCATED by this routine! Make
- * sure to free it!
- * Buffer - Pointer to a byte pointer (globalalloc) which is
- * allocated by this routine. Make sure to free it!
- *
- * Returns 0 if successful, else the error code.
- **************************************************************************)
- function wioWaveLoadFile(lpFilePath: PChar; { (IN) }
- Var pwfx: PWaveFormatEx; { (OUT) }
- Var Buffer: PChar; { (OUT) }
- Var Size: DWORD): integer; { (OUT) }
- Label ERROR_LOADING, DONE_LOADING;
- Var
- lpwio: PWaveIOCB;
- Res: Longint;
- begin
- pwfx := Nil;
- Buffer := Nil;
- lpwio := Nil;
- Size := 0;
- Result := wioReadFileInfo(lpwio, lpFilePath, mmioFOURCC('W', 'A', 'V', 'E'), RIFF_FILE);
- if (Result <> 0) then
- goto ERROR_LOADING;
- Result := wioWaveOpen(lpwio);
- if (Result <> 0) then
- goto ERROR_LOADING;
- { Ok, size of wave data is in lpwio^.dwDataSize, allocate that buffer. }
- Buffer := GlobalAllocPtr(GMEM_FIXED, lpwio^.dwDataBytes);
- if (Buffer = Nil) then
- begin
- Result := WIOERR_NOMEM;
- goto ERROR_LOADING;
- end;
- Res := wioWaveReadData(lpwio, Buffer, lpwio^.dwDataBytes);
- if (Res <= 0) then
- begin
- Result := WIOERR_FILEERROR;
- goto ERROR_LOADING;
- end;
- pwfx := GlobalAllocPtr(GMEM_FIXED, sizeOf(TWaveFormatEx) + lpwio^.wfx.cbSize);
- if (pwfx = Nil) then
- begin
- Result := WIOERR_NOMEM;
- goto ERROR_LOADING;
- end;
- move(lpwio^.wfx, pwfx^, sizeOf(TWaveFormatEx) + lpwio^.wfx.cbSize);
- Size := lpwio^.dwDataBytes;
- Result := WIOERR_NOERROR;
- goto DONE_LOADING;
- ERROR_LOADING:
- if (Buffer <> Nil) then
- begin
- GlobalFreePtr(Buffer);
- Buffer := Nil;
- end;
- if (pwfx <> Nil) then
- begin
- GlobalFreePtr(pwfx);
- pwfx := Nil;
- end;
- DONE_LOADING:
- { Close the wave file. }
- wioWaveClose(lpwio);
- wioFreeFileInfo(lpwio);
- end;
- (**************************************************************************
- * This routine saves a wave file currently in memory.
- * lpFilePath - FileName to save to. Automatically overwritten, be careful!
- * Size - Size in bytes to write.
- * pwfx - Pointer to waveformatex structure.
- * Buffer - Pointer to the data.
- **************************************************************************)
- function wioWaveSaveFile(lpFilePath: PChar; { (IN) }
- pwfx: PWAVEFORMATEX; { (IN) }
- Buffer: PChar; { (IN) }
- Size: DWORD): integer; { (IN) }
- Label ERROR_SAVING;
- Var
- lpwio: PWaveIOCB;
- begin
- Result := wioCreateFileInfo(lpwio, pwfx);
- if (Result <> 0) then
- goto ERROR_SAVING;
- Result := wioWriteFileInfo(lpwio, lpFilePath);
- if (Result <> 0) then
- goto ERROR_SAVING;
- Result := wioWaveWriteData(lpwio, Buffer, Size);
- if (Result <= 0) then
- begin
- Result := WIOERR_FILEERROR;
- goto ERROR_SAVING;
- end;
- Result := WIOERR_NOERROR;
- ERROR_SAVING:
- { Close the wave file. }
- wioWaveClose(lpwio);
- wioFreeFileInfo(lpwio);
- if Result <> WIOERR_NOERROR then
- { delete the half-written file. }
- wioFileDelete(lpFilePath);
- end;
- {**************************************************************************}
- function wioWaveSetFirstSample(lpwio: PWaveIOCB; dwSample: DWORD): integer;
- begin
- Result := WIOERR_BADPARAM;
- if (lpwio <> Nil) then
- begin
- with lpwio^do
- begin
- if (Longint(dwSample) >= 0) and (dwSample < dwLastSample) then
- begin
- dwFirstSample := dwSample;
- dwBytesLeft := wioSamplesToBytesEx(lpwio, dwLastSample-dwFirstSample);
- Result := WIOERR_NOERROR;
- end;
- end;
- end;
- end;
- {**************************************************************************}
- function wioWaveSetLastSample(lpwio: PWaveIOCB; dwSample: DWORD): integer;
- begin
- Result := WIOERR_BADPARAM;
- if (lpwio <> Nil) then
- begin
- with lpwio^do
- begin
- if (dwSample > dwFirstSample) and (dwSample <= dwDataSamples) then
- begin
- dwLastSample := dwSample;
- { set the bytes to play }
- dwBytesLeft := wioSamplesToBytesEx(lpwio, dwLastSample-dwFirstSample);
- Result := WIOERR_NOERROR;
- end;
- end;
- end;
- end;
- {**************************************************************************}
- function wioWaveSetPosition(lpwio: PWaveIOCB; dwSample: DWORD): integer;
- Var
- dwDataPos: DWORD;
- begin
- Result := WIOERR_FILEERROR;
- if (lpwio <> Nil) and (Longint(dwSample) >= 0) then
- with lpwio^ do
- begin
- { make sure we are in range }
- {$IFDEF BUILD_ACTIVEX}
- dwSample := MinMax(dwSample, 0, dwLastSample-dwFirstSample);
- {$ELSE}
- dwSample := MinMax(dwSample, 0, dwLastSample-dwFirstSample-1);
- {$ENDIF}
- if (hmmio <> 0) then
- begin
- if (dwFlags and RAW_FILE <> 0) then
- begin
- { convert samples to bytes }
- dwDataPos := Min(wioSamplesToBytesEx(lpwio,dwFirstSample+dwSample),dwDataBytes);
- { align to nBlockAlign }
- dwDataPos := (dwDataPos div wfx.nBlockAlign)*wfx.nBlockAlign;
- { set the position }
- if FileSeek(hmmio, dwDataOffset+dwDataPos, 0) <> -1 then
- begin
- { set the bytes to play }
- dwBytesLeft := wioSamplesToBytesEx(lpwio, dwLastSample) - dwDataPos;
- { set the current file position }
- dwPosition := wioBytesToSamplesEx(lpwio, dwDataPos) - dwFirstSample;
- Result := WIOERR_NOERROR;
- end;
- end
- else
- begin
- dwDataPos := dwDataOffset - 2*sizeof(FOURCC);
- { go to the 'data' chunk }
- if mmioSeek(hmmio, dwDataPos, SEEK_SET) = Longint(dwDataPos) then
- begin
- { now we are at start of 'data' chunk, descend into the chunk }
- if mmioDescend(hmmio, @ckDATA, Nil, 0) = 0 then
- begin
- { convert samples to bytes }
- dwDataPos := Min(wioSamplesToBytesEx(lpwio,dwFirstSample+dwSample),dwDataBytes);
- { align to nBlockAlign }
- dwDataPos := (dwDataPos div wfx.nBlockAlign)*wfx.nBlockAlign;
- { set the position }
- if mmioSeek(hmmio, dwDataPos, SEEK_CUR) <> -1 then
- begin
- { set the bytes to play }
- dwBytesLeft := wioSamplesToBytesEx(lpwio, dwLastSample) - dwDataPos;
- { set the current file position }
- dwPosition := wioBytesToSamplesEx(lpwio, dwDataPos) - dwFirstSample;
- Result := WIOERR_NOERROR;
- end;
- end;
- end;
- end;
- end
- else
- begin
- { only set the start position (round to blockalign) }
- dwDataPos := wioSamplesToBytesEx(lpwio, dwFirstSample+dwSample);
- dwPosition := wioBytesToSamplesEx(lpwio,dwDataPos)-dwFirstSample;
- Result := WIOERR_NOERROR;
- end;
- end;
- end;
- {**************************************************************************}
- function wioWaveReadData(lpwio: PWaveIOCB; Buffer: PChar; nBytes: DWORD): DWORD;
- Label Again;
- begin
- Result := $FFFFFFFF;
- if (lpwio <> Nil) AND (lpwio^.hmmio <> 0) then
- begin
- with lpwio^ do
- begin
- if (dwBytesLeft > 0) then
- begin
- { read the data from the file... }
- if (dwFlags and RAW_FILE <> 0) then
- Result := FileRead(hmmio, Buffer^, Min(nBytes,dwBytesLeft))
- else
- Result := mmioRead(hmmio, Buffer, Min(nBytes,dwBytesLeft));
- if (Result < nBytes) then dwBytesLeft := 0;
- end;
- if (Result > 0) then
- begin
- dwBytesLeft := Max(dwBytesLeft-Result,0);
- dwPosition := (dwLastSample-dwFirstSample) - wioBytesToSamplesEx(lpwio, dwBytesLeft);
- { inc(dwPosition,wioBytesToSamples(@wfx, Result));}
- end;
- end;
- end;
- end;
- {**************************************************************************}
- function wioWaveReadDataDirect(lpwio: PWaveIOCB; Buffer: PChar; nBytes: DWORD): DWORD;
- Label ERROR_CANNOT_READ;
- Var
- i: Cardinal;
- CopyLength: DWORD;
- mmioInfo: TMMIOINFO;
- begin
- if (lpwio = Nil) or (lpwio^.hmmio = 0) then
- goto ERROR_CANNOT_READ;
- with lpwio^ do
- begin
- if (dwFlags and RAW_FILE <> 0) then
- goto ERROR_CANNOT_READ;
- { read the data from the file... }
- Result := mmioGetInfo(hmmio, @mmioInfo, 0);
- if (Result <> 0) then
- goto ERROR_CANNOT_READ;
- nBytes := Min(dwBytesLeft, nBytes);
- i := 0;
- while i < nBytes do
- begin
- { Copy the bytes from the io to the buffer. }
- if (mmioInfo.pchNext = mmioInfo.pchEndRead) then
- begin
- if mmioAdvance(hmmio, @mmioInfo, MMIO_READ) <> 0 then
- goto ERROR_CANNOT_READ;
- if (mmioInfo.pchNext = mmioInfo.pchEndRead) then
- goto ERROR_CANNOT_READ;
- end;
- { Actual copy. }
- CopyLength := (mmioInfo.pchEndRead - mmioInfo.pchNext);
- if (nBytes - i < CopyLength) then
- CopyLength := nBytes - i;
- move(PByte(mmioInfo.pchNext)^, PByte(Buffer+i)^, CopyLength);
- inc(i, CopyLength);
- inc(mmioInfo.pchNext, CopyLength);
- end;
- Result := mmioSetInfo(hmmio, @mmioInfo, 0);
- if (Result <> 0) then
- goto ERROR_CANNOT_READ;
- dec(dwBytesLeft, nBytes);
- inc(dwPosition, wioBytesToSamplesEx(lpwio, nBytes));
- Result := nBytes;
- exit;
- end;
- ERROR_CANNOT_READ:
- Result := $FFFFFFFF;
- end;
- {**************************************************************************}
- function wioWaveReadSamples(lpwio: PWaveIOCB; Buffer: PChar; nSamples: DWORD): DWORD;
- Var
- nBytes: Longint;
- begin
- Result := $FFFFFFFF;
- if (lpwio <> Nil) And (nSamples > 0) then
- begin
- { convert samples to bytes }
- nBytes := wioSamplesToBytesEx(lpwio, nSamples);
- { read the data from the file... }
- nBytes := wioWaveReadData(lpwio,Buffer,nBytes);
- if (nBytes > 0) then
- Result := wioBytesToSamplesEx(lpwio, nBytes);
- end;
- end;
- {**************************************************************************}
- function wioWaveWriteData(lpwio: PWaveIOCB; Buffer: PChar; nBytes: DWORD): DWORD;
- var
- dwPos: DWORD;
- begin
- Result := $FFFFFFFF;
- if (lpwio <> Nil) and (lpwio^.hmmio <> 0) and (nBytes > 0) then
- begin
- with lpwio^ do
- begin
- if (dwFlags and RAW_FILE <> 0) then exit;
- { write the data to the file... }
- Result := mmioWrite(hmmio, Buffer, nBytes);
- if (Result > 0) then
- begin
- ckData.dwFlags:= ckData.dwFlags or MMIO_DIRTY;
- dwPos := DWORD(mmioSeek(hmmio,0,SEEK_CUR))-dwDataOffset;
- dwPosition := wioBytesToSamplesEx(lpwio, dwPos);
- if (dwPos > dwDataBytes) then dwDataBytes := dwPos;
- if (dwPosition > dwDataSamples) then
- begin
- dwDataSamples := dwPosition;
- dwLastSample := dwDataSamples;
- end;
- dwBytesLeft := wioSamplesToBytesEx(lpwio, dwLastSample-dwPosition);
- end
- else
- begin
- { What to do here? Well, for now, nothing, just return that }
- { error. maybe delete the file later? }
- end;
- end;
- end;
- end;
- {**************************************************************************}
- function wioWaveWriteDataDirect(lpwio: PWaveIOCB; Buffer: PChar; nBytes: DWORD): DWORD;
- Label ERROR_CANNOT_WRITE;
- Var
- i: Cardinal;
- mmioInfo: TMMIOINFO;
- dwPos: DWORD;
- begin
- if (lpwio = Nil) or (lpwio^.hmmio = 0) then
- goto ERROR_CANNOT_WRITE;
- with lpwio^ do
- begin
- if (dwFlags and RAW_FILE <> 0) then
- goto ERROR_CANNOT_WRITE;
- Result := mmioGetInfo(hmmio, @mmioInfo, 0);
- if (Result <> 0) then
- goto ERROR_CANNOT_WRITE;
- i := 0;
- while i < nBytes do
- begin
- if (mmioInfo.pchNext = mmioInfo.pchEndWrite) then
- begin
- mmioInfo.dwFlags := mmioInfo.dwFlags or MMIO_DIRTY;
- if mmioAdvance(hmmio, @mmioInfo, MMIO_WRITE) <> 0 then
- goto ERROR_CANNOT_WRITE;
- end;
- PByte(mmioInfo.pchNext)^ := PByte(Buffer+i)^;
- inc(mmioInfo.pchNext);
- inc(Result);
- inc(i);
- end;
- mmioInfo.dwFlags := mmioInfo.dwFlags or MMIO_DIRTY;
- if mmioSetInfo(hmmio, @mmioInfo, 0) <> 0 then
- goto ERROR_CANNOT_WRITE; { cannot flush, probably... }
- ckData.dwFlags := ckData.dwFlags or MMIO_DIRTY;
- dwPos := DWORD(mmioSeek(hmmio,0,SEEK_CUR))-dwDataOffset;
- dwPosition := wioBytesToSamplesEx(lpwio, dwPos);
- if (dwPos > dwDataBytes) then dwDataBytes := dwPos;
- if (dwPosition > dwDataSamples) then
- begin
- dwDataSamples := dwPosition;
- dwLastSample := dwDataSamples;
- end;
- end;
- exit;
- ERROR_CANNOT_WRITE:
- { What to do here? Well, for now, nothing, just return that error. }
- { (maybe delete the file later? }
- Result := $FFFFFFFF;
- end;
- {**************************************************************************}
- function wioWaveWriteSamples(lpwio: PWaveIOCB; Buffer: PChar; nSamples: DWORD): DWORD;
- Var
- nBytes: Longint;
- begin
- Result := $FFFFFFFF;
- if (lpwio <> Nil) And (nSamples > 0) then
- begin
- { convert samples to bytes }
- nBytes := wioSamplesToBytesEx(lpwio, nSamples);
- { write the data to the file... }
- nBytes := wioWaveWriteData(lpwio, Buffer, nBytes);
- Result := wioBytesToSamplesEx(lpwio, nBytes);
- end;
- end;
- end.