Wave Format

  1. Convert Wave format file to Raw data format
  2. Wave File format help[NEW]

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}

Wave File format help[NEW]

From: BerndCordes@t-online.de

Here you go:


        TWaveHeader = record
                Marker1:        Array[0..3] of Char;
                BytesFollowing: LongInt;
                Marker2:        Array[0..3] of Char;
                Marker3:        Array[0..3] of Char;
                Fixed1:         LongInt;
                FormatTag:      Word;
                Channels:       Word;
                SampleRate:     LongInt;
                BytesPerSecond: LongInt;
                BytesPerSample: Word;
                BitsPerSample:  Word;
                Marker4:        Array[0..3] of Char;
                DataBytes:      LongInt;
        end;

To create your own WAV:


        DataBytes := Channels;
        DataBytes := DataBytes * SampleRate;
        DataBytes := DataBytes * Resolution;
        DataBytes := DataBytes div 8;
        DataBytes := DataBytes * Duration;
        DataBytes := DataBytes div 1000;

        WaveHeader.Marker1 := 'RIFF';
        WaveHeader.BytesFollowing := DataBytes + 36;
        WaveHeader.Marker2 := 'WAVE';
        WaveHeader.Marker3 := 'fmt ';
        WaveHeader.Fixed1 := 16;
        WaveHeader.FormatTag := 1;
        WaveHeader.SampleRate := SampleRate;
        WaveHeader.Channels := Channels;
        WaveHeader.BytesPerSecond := Channels;
        WaveHeader.BytesPerSecond := WaveHeader.BytesPerSecond * SampleRate;
        WaveHeader.BytesPerSecond := WaveHeader.BytesPerSecond * Resolution;
        WaveHeader.BytesPerSecond := WaveHeader.BytesPerSecond div 8;
        WaveHeader.BytesPerSample := Channels * Resolution div 8;
        WaveHeader.BitsPerSample := Resolution;
        WaveHeader.Marker4 := 'data';
        WaveHeader.DataBytes := DataBytes;

The rest of the file is the wave data. Order is low-high for left channel, low-high for right channel, and so on. For mono or 8 bit files make the respective changes.


Please email me and tell me if you liked this page.