Декомпилляция звукового файла формата Wave и получение звуковых данных Интересно, есть ли технология преобразования Wave-формата в обычный набор звуковых данных? К примеру, мне необходимо удалить заголовок и механизм (метод) сжатия, которые могут компилироваться и сохраняться вместе с Wave-файлами. unit LinearSystem; interface {============== Тип, описывающий формат WAV ==================} 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; {Спецификация WAV для сопровождения} Last : SampleIndex; {Последний доступный индекс yyy} MinO, MaxO : Real; {Диапазон значений yyy} 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 {$R *.DFM} uses VarGraph, SysUtils; {================== Стандартный формат WAV-файла ===================} 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; { ScaleData } procedure ScaleAllData; begin ScaleData(K0R); ScaleData(K0B); ScaleData(K1R); ScaleData(K1B); ScaleData(K2R); ScaleData(K2B); ScaleData(K3R); ScaleData(K3B); end; {ScaleAllData} {================== Считывание/запись WAV-данных ===================} VAR InFile, : 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(,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(,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(,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-битный сэмпл} ChunkSize.up := trunc(Ki.yyy[N]+0.5); if N'RIFF' then OK := False; {Считываем ChunkSize} ReadChunkSize; RIFFSize := ChunkSize.lint; {должно быть 18,678} {Считываем ChunkName "WAVE"} ReadChunkName; if ChunkName<>'WAVE' then OK := False; {Считываем ChunkName "fmt_"} ReadChunkName; if ChunkName<>'fmt ' then OK := False; {Считываем ChunkSize} ReadChunkSize; fmtSize := ChunkSize.lint; {должно быть 18} {Считываем formatTag, nChannels} ReadChunkSize; ChunkSize.x := M1; formatTag := ChunkSize.up; nChannels := ChunkSize.dn; {Считываем nSamplesPerSec} ReadChunkSize; nSamplesPerSec := ChunkSize.lint; {Считываем nAvgBytesPerSec} ReadChunkSize; nAvgBytesPerSec := ChunkSize.lint; {Считываем 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; {Считываем nBitsPerSample} nBitsPerSample := ChunkSize.dn; for I := 17 to fmtSize do Read(InFile,MM); NoDataYet := True; while NoDataYet do begin {Считываем метку блока данных "data"} ReadChunkName; {Считываем DataSize} 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; {Наконец, начинаем считывать данные для байтов nDataBytes} if nDataBytes>0 then DataYet := True; N:=0; {чтение с первой позиции} while DataYet do begin ReadOneDataBlock(Ki,Kj); {получаем 4 байта} 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);{обнуляем массив "Ki"} InitSignals(Kj);{обнуляем массив "Kj"} end; end; { ReadWAVFile } {================= Операции с набором данных ====================} 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; {GetDatabaseItem} procedure PutDatabaseItem( Kk : Observation; N : LongInt ); begin if N0 then LastDataBaseItem := LastDataBaseItem-1; end; end; {InitDataBase} function FindDataBaseName( Nstg : String ):LongInt; var ThisOne : LongInt; begin ThisOne := 0; FindDataBaseName := -1; while ThisOne
|