Converter - wav to raw |
Top Previous Next |
|
Convert Wave format file to Raw data format
Does any body know how to convert a wave format file to raw format. e.g. I want to strip out any header or encoding mechanism/method which may be stored or encode in a wave file. I have a D1/D2 routine that reads WAV files and pulls out raw data, but it doesn't decompress using the various forms of compression.
--------------------------------------------------------------------------------
unit LinearSystem;
interface
{============== WAV Format Coding Type ==================} type WAVHeader = record nChannels : Word; nBitsPerSample : LongInt; nSamplesPerSec : LongInt; nAvgBytesPerSec : LongInt; RIFFSize : LongInt; fmtSize : LongInt; formatTag : Word; nBlockAlign : LongInt; DataSize : LongInt; end;
{============== Sample DataStreams ========================} const MaxN = 300; { max number of sample values } type SampleIndex = 0 .. MaxN+3; type DataStream = array[ SampleIndex ] of Real;
var N : SampleIndex;
{============== Observation Variables ======================} type Observation = record Name : String[40]; {Name of this observation} yyy : DataStream; {Array of data points} WAV : WAVHeader; {WAV specs for observation} Last : SampleIndex;{Last valid index to yyy} MinO, MaxO : Real; {Range values from yyy} end;
var K0R, K1R, K2R, K3R : Observation; K0B, K1B, K2B, K3B : Observation;
{================== File Name Variables ===================} var StandardDatabase : String[ 80 ]; BaseFileName : String[ 80 ]; StandardOutput : String[ 80 ]; StandardInput : String[ 80 ];
{=============== Operations ==================} procedure ReadWAVFile (var Ki, Kj : Observation); procedure WriteWAVFile(var Ki, Kj : Observation); procedure ScaleData (var Kk : Observation); procedure InitAllSignals; procedure InitLinearSystem;
implementation {$R *.DFM} uses VarGraph, SysUtils;
{================== Standard WAV File Format ===================} const MaxDataSize : LongInt = (MaxN+1)*2*2; const MaxRIFFSize : LongInt = (MaxN+1)*2*2+36; const StandardWAV : WAVHeader = ( nChannels : Word(2); nBitsPerSample : LongInt(16); nSamplesPerSec : LongInt(8000); nAvgBytesPerSec : LongInt(32000); RIFFSize : LongInt((MaxN+1)*2*2+36); fmtSize : LongInt(16); formatTag : Word(1); nBlockAlign : LongInt(4); DataSize : LongInt((MaxN+1)*2*2) );
{================== Scale Observation Data ===================}
procedure ScaleData(var Kk : Observation); var I : SampleIndex; begin {Initialize the scale values} Kk.MaxO := Kk.yyy[0]; Kk.MinO := Kk.yyy[0];
{Then scan for any higher or lower values} for I := 1 to Kk.Last do begin if Kk.MaxO < Kk.yyy[I] then Kk.MaxO := Kk.yyy[I]; if Kk.MinO > Kk.yyy[I] then Kk.MinO := Kk.yyy[I]; end; end; { ScaleData }
procedure ScaleAllData; begin ScaleData(K0R); ScaleData(K0B); ScaleData(K1R); ScaleData(K1B); ScaleData(K2R); ScaleData(K2B); ScaleData(K3R); ScaleData(K3B); end; {ScaleAllData}
{================== WAV Data I/O ===================}
VAR InFile, OutFile : file of Byte;
type Tag = (F0, T1, M1); type FudgeNum = record case X:Tag of F0 : (chrs : array[0..3] of Byte); T1 : (lint : LongInt); M1 : (up,dn: Integer); end; var ChunkSize : FudgeNum;
procedure WriteChunkName(Name:String); var i : Integer; MM : Byte; begin for i := 1 to 4 do begin MM := ord(Name[i]); write(OutFile,MM); end; end; {WriteChunkName}
procedure WriteChunkSize(LL:Longint); var I : integer; begin ChunkSize.x:=T1; ChunkSize.lint:=LL; ChunkSize.x:=F0; for I := 0 to 3 do Write(OutFile,ChunkSize.chrs[I]); end;
procedure WriteChunkWord(WW:Word); var I : integer; begin ChunkSize.x:=T1; ChunkSize.up:=WW; ChunkSize.x:=M1; for I := 0 to 1 do Write(OutFile,ChunkSize.chrs[I]); end; {WriteChunkWord}
procedure WriteOneDataBlock(var Ki, Kj : Observation); var I : Integer; begin ChunkSize.x:=M1; with Ki.WAV do begin case nChannels of 1:if nBitsPerSample=16 then begin {1..2 16-bit samples in buffer for one channel} ChunkSize.up := trunc(Ki.yyy[N]+0.5); if N<MaxN then ChunkSize.dn := trunc(Ki.yyy[N+1]+0.5); N := N+2; end else begin {1..4 8-bit samples in buffer for one channel} for I:=0 to 3 do ChunkSize.chrs[I] := trunc(Ki.yyy[N+I]+0.5); N := N+4; end; 2:if nBitsPerSample=16 then begin {2 16-bit samples on two channels} ChunkSize.dn := trunc(Ki.yyy[N]+0.5); ChunkSize.up := trunc(Kj.yyy[N]+0.5); N := N+1; end else begin {4 8-bit samples on two channels} ChunkSize.chrs[1] := trunc(Ki.yyy[N]+0.5); ChunkSize.chrs[3] := trunc(Ki.yyy[N+1]+0.5); ChunkSize.chrs[0] := trunc(Kj.yyy[N]+0.5); ChunkSize.chrs[2] := trunc(Kj.yyy[N+1]+0.5); N := N+2; end; end; {with WAV do begin..} end; {the four-byte variable "ChunkSize" has now been filled}
ChunkSize.x:=T1; WriteChunkSize(ChunkSize.lint);{put 4 bytes of data} end; {WriteOneDataBlock}
procedure WriteWAVFile(var Ki, Kj : Observation); var MM : Byte; I : Integer; OK : Boolean; begin {Prepare to write a file of data} AssignFile(OutFile, StandardOutput); { File selected in dialog } ReWrite( OutFile ); With Ki.WAV do begin DataSize := nChannels*(nBitsPerSample div 8)*(Ki.Last+1); RIFFSize := DataSize+36; fmtSize := 16; end;
{Write ChunkName "RIFF"} WriteChunkName('RIFF');
{Write ChunkSize} WriteChunkSize(Ki.WAV.RIFFSize);
{Write ChunkName "WAVE"} WriteChunkName('WAVE');
{Write tag "fmt_"} WriteChunkName('fmt ');
{Write ChunkSize} Ki.WAV.fmtSize := 16; {should be 16-18} WriteChunkSize(Ki.WAV.fmtSize);
{Write formatTag, nChannels} WriteChunkWord(Ki.WAV.formatTag); WriteChunkWord(Ki.WAV.nChannels);
{Write nSamplesPerSec} WriteChunkSize(Ki.WAV.nSamplesPerSec);
{Write nAvgBytesPerSec} WriteChunkSize(Ki.WAV.nAvgBytesPerSec);
{Write nBlockAlign, nBitsPerSample} WriteChunkWord(Ki.WAV.nBlockAlign); WriteChunkWord(Ki.WAV.nBitsPerSample);
{WriteDataBlock tag "data"} WriteChunkName('data');
{Write DataSize} WriteChunkSize(Ki.WAV.DataSize);
N:=0; {first write-out location} while N<=Ki.Last do WriteOneDataBlock(Ki,Kj); {put 4 bytes & increment N}
{Free the file buffers} CloseFile( OutFile ); end; {WriteWAVFile}
procedure InitSpecs; begin end; { InitSpecs }
procedure InitSignals(var Kk : Observation); var J : Integer; begin for J := 0 to MaxN do Kk.yyy[J] := 0.0; Kk.MinO := 0.0; Kk.MaxO := 0.0; Kk.Last := MaxN; end; {InitSignals}
procedure InitAllSignals; begin InitSignals(K0R); InitSignals(K0B); InitSignals(K1R); InitSignals(K1B); InitSignals(K2R); InitSignals(K2B); InitSignals(K3R); InitSignals(K3B); end; {InitAllSignals}
var ChunkName : string[4];
procedure ReadChunkName; var I : integer; MM : Byte; begin ChunkName[0]:=chr(4); for I := 1 to 4 do begin Read(InFile,MM); ChunkName[I]:=chr(MM); end; end; {ReadChunkName}
procedure ReadChunkSize; var I : integer; MM : Byte; begin ChunkSize.x := F0; ChunkSize.lint := 0; for I := 0 to 3 do begin Read(InFile,MM); ChunkSize.chrs[I]:=MM; end; ChunkSize.x := T1; end; {ReadChunkSize}
procedure ReadOneDataBlock(var Ki,Kj:Observation); var I : Integer; begin if N<=MaxN then begin ReadChunkSize; {get 4 bytes of data} ChunkSize.x:=M1; with Ki.WAV do case nChannels of 1:if nBitsPerSample=16 then begin {1..2 16-bit samples in buffer for one channel} Ki.yyy[N] :=1.0*ChunkSize.up; if N<MaxN then Ki.yyy[N+1]:=1.0*ChunkSize.dn; N := N+2; end else begin {1..4 8-bit samples in buffer for one channel} for I:=0 to 3 do Ki.yyy[N+I]:=1.0*ChunkSize.chrs[I]; N := N+4; end; 2:if nBitsPerSample=16 then begin {2 16-bit samples on two channels} Ki.yyy[N]:=1.0*ChunkSize.dn; Kj.yyy[N]:=1.0*ChunkSize.up; N := N+1; end else begin {4 8-bit samples on two channels} Ki.yyy[N] :=1.0*ChunkSize.chrs[1]; Ki.yyy[N+1]:=1.0*ChunkSize.chrs[3]; Kj.yyy[N] :=1.0*ChunkSize.chrs[0]; Kj.yyy[N+1]:=1.0*ChunkSize.chrs[2]; N := N+2; end; end; if N<=MaxN then begin {LastN := N;} Ki.Last := N; if Ki.WAV.nChannels=2 then Kj.Last := N; end else begin {LastN := MaxN;} Ki.Last := MaxN; if Ki.WAV.nChannels=2 then Kj.Last := MaxN; end; end; end; {ReadOneDataBlock}
procedure ReadWAVFile(var Ki, Kj :Observation); var MM : Byte; I : Integer; OK : Boolean; NoDataYet : Boolean; DataYet : Boolean; nDataBytes : LongInt; begin if FileExists(StandardInput) then with Ki.WAV do begin { Bring up open file dialog } OK := True; {unless changed somewhere below} {Prepare to read a file of data} AssignFile(InFile, StandardInput); { File selected in dialog } Reset( InFile );
{Read ChunkName "RIFF"} ReadChunkName; if ChunkName<>'RIFF' then OK := False;
{Read ChunkSize} ReadChunkSize; RIFFSize := ChunkSize.lint; {should be 18,678}
{Read ChunkName "WAVE"} ReadChunkName; if ChunkName<>'WAVE' then OK := False;
{Read ChunkName "fmt_"} ReadChunkName; if ChunkName<>'fmt ' then OK := False;
{Read ChunkSize} ReadChunkSize; fmtSize := ChunkSize.lint; {should be 18}
{Read formatTag, nChannels} ReadChunkSize; ChunkSize.x := M1; formatTag := ChunkSize.up; nChannels := ChunkSize.dn;
{Read nSamplesPerSec} ReadChunkSize; nSamplesPerSec := ChunkSize.lint;
{Read nAvgBytesPerSec} ReadChunkSize; nAvgBytesPerSec := ChunkSize.lint;
{Read nBlockAlign} ChunkSize.x := F0; ChunkSize.lint := 0; for I := 0 to 3 do begin Read(InFile,MM); ChunkSize.chrs[I]:=MM; end; ChunkSize.x := M1; nBlockAlign := ChunkSize.up;
{Read nBitsPerSample} nBitsPerSample := ChunkSize.dn; for I := 17 to fmtSize do Read(InFile,MM);
NoDataYet := True; while NoDataYet do begin {Read tag "data"} ReadChunkName;
{Read DataSize} ReadChunkSize; DataSize := ChunkSize.lint;
if ChunkName<>'data' then begin for I := 1 to DataSize do {skip over any nondata stuff} Read(InFile,MM); end else NoDataYet := False; end;
nDataBytes := DataSize; {Finally, start reading data for nDataBytes bytes} if nDataBytes>0 then DataYet := True; N:=0; {first read-in location} while DataYet do begin ReadOneDataBlock(Ki,Kj); {get 4 bytes} nDataBytes := nDataBytes-4; if nDataBytes<=4 then DataYet := False; end;
ScaleData(Ki); if Ki.WAV.nChannels=2 then begin Kj.WAV := Ki.WAV; ScaleData(Kj); end; {Free the file buffers} CloseFile( InFile ); end else begin InitSpecs;{file does not exist} InitSignals(Ki);{zero "Ki" array} InitSignals(Kj);{zero "Kj" array} end; end; { ReadWAVFile }
{================= Database Operations ====================}
const MaxNumberOfDataBaseItems = 360; type SignalDirectoryIndex = 0 .. MaxNumberOfDataBaseItems;
VAR DataBaseFile : file of Observation; LastDataBaseItem : LongInt; {Current number of database items} ItemNameS : array[SignalDirectoryIndex] of String[40];
procedure GetDatabaseItem( Kk : Observation; N : LongInt ); begin if N<=LastDataBaseItem then begin Seek(DataBaseFile, N); Read(DataBaseFile, Kk); end else InitSignals(Kk); end; {GetDatabaseItem}
procedure PutDatabaseItem( Kk : Observation; N : LongInt ); begin if N<MaxNumberOfDataBaseItems then if N<=LastDataBaseItem then begin Seek(DataBaseFile, N); Write(DataBaseFile, Kk); LastDataBaseItem := LastDataBaseItem+1; end else while LastDataBaseItem<=N do begin Seek(DataBaseFile, LastDataBaseItem); Write(DataBaseFile, Kk); LastDataBaseItem := LastDataBaseItem+1; end else ReportError(1); {Attempt to read beyond MaxNumberOfDataBaseItems} end; {PutDatabaseItem}
procedure InitDataBase; begin LastDataBaseItem := 0; if FileExists(StandardDataBase) then begin Assign(DataBaseFile,StandardDataBase); Reset(DataBaseFile); while not EOF(DataBaseFile) do begin GetDataBaseItem(K0R, LastDataBaseItem); ItemNameS[LastDataBaseItem] := K0R.Name; LastDataBaseItem := LastDataBaseItem+1; end; if EOF(DataBaseFile) then if LastDataBaseItem>0 then LastDataBaseItem := LastDataBaseItem-1; end; end; {InitDataBase}
function FindDataBaseName( Nstg : String ):LongInt; var ThisOne : LongInt; begin ThisOne := 0; FindDataBaseName := -1; while ThisOne<LastDataBaseItem do begin if Nstg=ItemNameS[ThisOne] then begin FindDataBaseName := ThisOne; Exit; end; ThisOne := ThisOne+1; end; end; {FindDataBaseName}
{======================= Init Unit ========================} procedure InitLinearSystem; begin BaseFileName := '\PROGRA~1\SIGNAL~1\'; StandardOutput := BaseFileName + 'K0.wav'; StandardInput := BaseFileName + 'K0.wav';
StandardDataBase := BaseFileName + 'Radar.sdb';
InitAllSignals; InitDataBase; ReadWAVFile(K0R,K0B); ScaleAllData; end; {InitLinearSystem}
begin {unit initialization code} InitLinearSystem; end. {Unit LinearSystem} |