unit LinearSystem;
interface
type WAVHeader = record
nChannels : Word;
nBitsPerSample : LongInt;
nSamplesPerSec : LongInt;
nAvgBytesPerSec : LongInt;
RIFFSize : LongInt;
fmtSize : LongInt;
formatTag : Word;
nBlockAlign : LongInt;
DataSize : LongInt;
end ;
const MaxN = 300 ;
type SampleIndex = 0 .. MaxN+ 3 ;
type DataStream = array [ SampleIndex ] of Real;
var N : SampleIndex;
type Observation = record
Name : String [ 40 ];
yyy : DataStream;
WAV : WAVHeader;
Last : SampleIndex;
MinO, MaxO : Real;
end ;
var K0R, K1R, K2R, K3R : Observation;
K0B, K1B, K2B, K3B : Observation;
var StandardDatabase : String [ 80 ];
BaseFileName : String [ 80 ];
StandardOutput : String [ 80 ];
StandardInput : String [ 80 ];
procedure ReadWAVFile ( var Ki, Kj : Observation);
procedure WriteWAVFile ( var Ki, Kj : Observation);
procedure ScaleData ( var Kk : Observation);
procedure InitAllSignals;
procedure InitLinearSystem;
implementation
uses VarGraph, SysUtils;
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 )
);
procedure ScaleData( var Kk : Observation);
var I : SampleIndex;
begin
Kk.MaxO := Kk.yyy[ 0 ];
Kk.MinO := Kk.yyy[ 0 ];
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 ;
procedure ScaleAllData;
begin
ScaleData(K0R);
ScaleData(K0B);
ScaleData(K1R);
ScaleData(K1B);
ScaleData(K2R);
ScaleData(K2B);
ScaleData(K3R);
ScaleData(K3B);
end ;
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 ;
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 ;
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
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
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
ChunkSize.dn := trunc(Ki.yyy[N]+ 0.5 );
ChunkSize.up := trunc(Kj.yyy[N]+ 0.5 );
N := N+ 1 ;
end
else begin
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 ;
end ;
ChunkSize.x:=T1;
WriteChunkSize(ChunkSize.lint); {помещаем 4 байта данных}
end ;
procedure WriteWAVFile( var Ki, Kj : Observation);
var MM : Byte;
I : Integer;
OK : Boolean;
begin
AssignFile(OutFile, StandardOutput);
ReWrite( OutFile );
With Ki.WAV do
begin DataSize := nChannels*(nBitsPerSample div 8 )*(Ki.Last+ 1 );
RIFFSize := DataSize+ 36 ;
fmtSize := 16 ;
end ;
WriteChunkName( 'RIFF' );
WriteChunkSize(Ki.WAV.RIFFSize);
WriteChunkName( 'WAVE' );
WriteChunkName( 'fmt ' );
Ki.WAV.fmtSize := 16 ;
WriteChunkSize(Ki.WAV.fmtSize);
WriteChunkWord(Ki.WAV.formatTag);
WriteChunkWord(Ki.WAV.nChannels);
WriteChunkSize(Ki.WAV.nSamplesPerSec);
WriteChunkSize(Ki.WAV.nAvgBytesPerSec);
WriteChunkWord(Ki.WAV.nBlockAlign);
WriteChunkWord(Ki.WAV.nBitsPerSample);
WriteChunkName( 'data' );
WriteChunkSize(Ki.WAV.DataSize);
N:= 0 ;
while N<=Ki.Last do WriteOneDataBlock(Ki,Kj);
CloseFile( OutFile );
end ;
procedure InitSpecs;
begin
end ;
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 ;
procedure InitAllSignals;
begin
InitSignals(K0R);
InitSignals(K0B);
InitSignals(K1R);
InitSignals(K1B);
InitSignals(K2R);
InitSignals(K2B);
InitSignals(K3R);
InitSignals(K3B);
end ;
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 ;
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 ;
procedure ReadOneDataBlock( var Ki,Kj:Observation);
var I : Integer;
begin
if N<=MaxN then
begin
ReadChunkSize;
ChunkSize.x:=M1;
with Ki.WAV do
case nChannels of
1 : if nBitsPerSample= 16
then begin
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
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
Ki.yyy[N]:= 1.0 *ChunkSize.dn;
Kj.yyy[N]:= 1.0 *ChunkSize.up;
N := N+ 1 ;
end
else begin
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
Ki.Last := N;
if Ki.WAV.nChannels= 2 then Kj.Last := N;
end
else begin
Ki.Last := MaxN;
if Ki.WAV.nChannels= 2 then Kj.Last := MaxN;
end ;
end ;
end ;
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
OK := True;
AssignFile(InFile, StandardInput);
Reset( InFile );
ReadChunkName;
if ChunkName<> 'RIFF' then OK := False;
ReadChunkSize;
RIFFSize := ChunkSize.lint;
ReadChunkName;
if ChunkName<> 'WAVE' then OK := False;
ReadChunkName;
if ChunkName<> 'fmt ' then OK := False;
ReadChunkSize;
fmtSize := ChunkSize.lint;
ReadChunkSize;
ChunkSize.x := M1;
formatTag := ChunkSize.up;
nChannels := ChunkSize.dn;
ReadChunkSize;
nSamplesPerSec := ChunkSize.lint;
ReadChunkSize;
nAvgBytesPerSec := ChunkSize.lint;
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;
nBitsPerSample := ChunkSize.dn;
for I := 17 to fmtSize do Read(InFile,MM);
NoDataYet := True;
while NoDataYet do
begin
ReadChunkName;
ReadChunkSize;
DataSize := ChunkSize.lint;
if ChunkName<> 'data' then
begin
for I := 1 to DataSize do
Read(InFile,MM);
end
else NoDataYet := False;
end ;
nDataBytes := DataSize;
if nDataBytes> 0 then DataYet := True;
N:= 0 ;
while DataYet do
begin
ReadOneDataBlock(Ki,Kj);
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 ;
CloseFile( InFile );
end
else begin
InitSpecs;
InitSignals(Ki);
InitSignals(Kj);
end ;
end ;
const MaxNumberOfDataBaseItems = 360 ;
type SignalDirectoryIndex = 0 .. MaxNumberOfDataBaseItems;
VAR DataBaseFile : file of Observation;
LastDataBaseItem : LongInt;
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 ;
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 );
end ;
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 ;
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 ;
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 ;
begin
InitLinearSystem;
end . |