Смекни!
smekni.com

Система обработки аудиоинформации Подсистема фильтрации и обработки сигнала (стр. 21 из 24)

procedure AddBrainWave(var AudioData: TAudioData; Start, Count, Freq1, Freq2: Integer);

procedure SetSpeedOfAudio(var AudioData: TAudioData; Start, Count: Cardinal; Speed: Real);

function ChangeSpeedOfAudio(var AudioData: TAudioData; Start, Count: Cardinal; Speed: Real): Cardinal;

procedure SetnSamplesPerSec(var AudioData: TAudioData; Value: Cardinal);

procedure SetnBitsPerSample(var AudioData: TAudioData; Value: Cardinal);

procedure SetnChannels(var AudioData: TAudioData; Value: Cardinal);

procedure SetVolumeOfAudio(var AudioData: TAudioData; Start, Count: Cardinal; Volume: Real);

procedure Echo(var AudioData: TAudioData; Start, Count, Number, Delay: Cardinal; Volume: Real);

procedure Reverberation(var AudioData: TAudioData; Start, Count, Number, Delay: Cardinal; Volume: Real);

procedure ChangeVolumeOfAudio(var AudioData: TAudioData; Start, Count: Cardinal; Volume: Real);

procedure ReChangeVolumeOfAudio(var AudioData: TAudioData; Start, Count: Cardinal; Volume: Real);

procedure Normalize(var AudioData: TAudioData; Start, Count: Cardinal);

implementation

constructor TAudioData.Create;

var

TempDir, FileName: String;

i: Word;

begin

inherited Create;

TempDir := GetEnvironmentVariable('TEMP')+'\';

i := 0;

FileName := TempDir + '\' + '0.TAD';

while FileExists(FileName) do

begin

Inc(i);

Str(i, FileName);

FileName := TempDir + '\' + FileName + '.TAD';

end;

Name := FileName;

Data := TFile.Create(FileName);

end;

procedure TAudioData.Calculate_nBlockAlign;

begin

nBlockAlign := nBitsPerSample div 8;

if nBitsPerSample mod 8 <> 0 then Inc(nBlockAlign);

nBlockAlign := nBlockAlign*nChannels;

end;

procedure TAudioData.ReadSample(Number, Channel: LongInt; var Value: Integer);

var

i: Byte;

Mult, AbsValue: LongWord;

begin

Calculate_nBlockAlign;

Data.Position := Number*nBlockAlign + Channel*(nBlockAlign div nChannels);

AbsValue := 0;

Data.Read(AbsValue, nBlockAlign div nChannels);

Mult := 1;

for i := 1 to nBlockAlign div nChannels do

Mult := Mult*256;

if nBitsPerSample>8 then

if AbsValue >= Trunc(Mult/2) then Value := AbsValue - Mult else Value := AbsValue

else Value := AbsValue-128;

end;

procedure TAudioData.WriteSample(Number, Channel: LongInt; Value: Integer);

var

K: Byte;

N: Cardinal;

begin

Calculate_nBlockAlign;

Data.Position := Number*nBlockAlign + Channel*(nBlockAlign div nChannels);

if Data.Position>Data.Size then

begin

K := 0;

N := Data.Position + nBlockAlign div nChannels;

Data.Position := Data.Size;

while Data.Position<=N do Data.Write(K, 1);

Data.Position := Number*nBlockAlign + Channel*(nBlockAlign div nChannels);

end;

if nBitsPerSample<=8 then Value := Value+128;

Data.Write(Value, nBlockAlign div nChannels);

end;

function TAudioData.Extremum(Number, Channel: LongInt): Boolean;

var

Smp1, Smp, Smp2: Integer;

begin

if (Number = 0) or (Number + 1 = Data.Size div nBlockAlign) then

begin

Extremum := True;

Exit;

end;

ReadSample(Number-1, Channel, Smp1);

ReadSample(Number, Channel, Smp);

ReadSample(Number+1, Channel, Smp2);

if (Smp1<Smp)and(Smp>Smp2) or (Smp1>Smp)and(Smp<Smp2) then

Extremum := True

else

Extremum := False;

end;

destructor TAudioData.Destroy;

begin

Data.Destroy;

DeleteFile(Name);

inherited Destroy;

end;

procedure CopyAudio(var AudioSource, AudioGeter: TAudioData; Start, Finish: Cardinal);

var

i: Cardinal;

Buf: array[0..63] of Byte;

begin

AudioGeter.Data.Clear;

AudioGeter.nChannels := AudioSource.nChannels;

AudioGeter.nSamplesPerSec := AudioSource.nSamplesPerSec;

AudioGeter.nBitsPerSample := AudioSource.nBitsPerSample;

AudioGeter.Calculate_nBlockAlign;

AudioSource.Data.Position := Start*AudioSource.nBlockAlign;

for i := 1 to Abs(Finish-Start) do

begin

AudioSource.Data.Read(Buf, AudioSource.nBlockAlign);

AudioGeter.Data.Write(Buf, AudioSource.nBlockAlign);

end;

AudioGeter.nChannels := AudioSource.nChannels;

AudioGeter.nSamplesPerSec := AudioSource.nSamplesPerSec;

AudioGeter.nBitsPerSample := AudioSource.nBitsPerSample;

end;

procedure InsertAudio(var AudioSource, AudioGeter: TAudioData; Start: Cardinal);

var

i: Cardinal;

Buf: Byte;

begin

if AudioSource.Data.Size = 0 then Exit;

AudioGeter.Data.Insert(Start*AudioGeter.nBlockAlign, AudioSource.Data.Size);

AudioSource.Data.Position := 0;

AudioGeter.Data.Position := Start*AudioGeter.nBlockAlign;

for i := 1 to AudioSource.Data.Size do

begin

AudioSource.Data.Read(Buf, 1);

AudioGeter.Data.Write(Buf, 1);

end;

end;

procedure DeleteAudio(var AudioData: TAudioData; Start, Finish: Cardinal);

begin

AudioData.Data.Delete(Start*AudioData.nBlockAlign, Abs(Finish-Start)*AudioData.nBlockAlign);

end;

procedure OverwriteAudio(var AudioSource, AudioGeter: TAudioData; Start: Cardinal);

var

i: Cardinal;

Buf: Byte;

begin

if AudioSource.Data.Size = 0 then Exit;

AudioSource.Data.Position := 0;

AudioGeter.Data.Position := Start*AudioGeter.nBlockAlign;

for i := 1 to AudioSource.Data.Size do

begin

AudioSource.Data.Read(Buf, 1);

AudioGeter.Data.Write(Buf, 1);

end;

end;

procedure MixAudio(var AudioSource, AudioGeter: TAudioData; Start: Cardinal);

var

i, Channel, AudioSize: Cardinal;

Value, MaxValue: Int64;

Samp1, Samp2: Integer;

begin

if AudioSource.Data.Size = 0 then Exit;

AudioSize := AudioGeter.Data.Size div AudioGeter.nBlockAlign;

MaxValue := 1; for i := 1 to AudioGeter.nBitsPerSample-1 do MaxValue := MaxValue*2;

for i := 0 to AudioSource.Data.Size div AudioGeter.nBlockAlign - 1 do

for Channel := 0 to AudioGeter.nChannels-1 do

begin

AudioSource.ReadSample(i, Channel, Samp1);

if Start+i<AudioSize then

AudioGeter.ReadSample(Start+i, Channel, Samp2)

else

Samp2 := 0;

Value := Samp1 + Samp2;

if (Value < -MaxValue)or(Value >= MaxValue) then

Value := Trunc((Value)/2);

AudioGeter.WriteSample(Start+i, Channel, Value);

end;

end;

procedure ReverseAudio(var AudioData: TAudioData; Start, Count: Cardinal);

var

i, AbsStart, AbsFinish, AbsCount: Cardinal;

BufferStart: Cardinal;

Buf: Int64;

TempAudio: TAudioData;

begin

TempAudio := TAudioData.Create;

AbsStart := Start*AudioData.nBlockAlign;

AbsCount := Count*AudioData.nBlockAlign;

AbsFinish := AbsStart+AbsCount;

i := AbsFinish;

repeat

if i-AbsStart>=MaxSizeOfBuffer then

BufferStart := i - MaxSizeOfBuffer

else

BufferStart := AbsStart;

AudioData.Data.Position := BufferStart;

AudioData.Data.Read(Buf, 1);

while i>BufferStart do

begin

i := i - AudioData.nBlockAlign;

AudioData.Data.Position := i;

AudioData.Data.Read(Buf, AudioData.nBlockAlign);

TempAudio.Data.Write(Buf, AudioData.nBlockAlign);

end;

until i=AbsStart;

AudioData.Data.Position := AbsStart;

TempAudio.Data.Position := 0;

for i := 1 to Count do

begin

TempAudio.Data.Read(Buf, AudioData.nBlockAlign);

AudioData.Data.Write(Buf, AudioData.nBlockAlign);

end;

TempAudio.Destroy;

end;

procedure AddBrainWave(var AudioData: TAudioData; Start, Count, Freq1, Freq2: Integer);

var

i, MaxAmplitude: Cardinal;

T, TL, TR: Real;

Freq: Integer;

SampL, SampR: Integer;

begin

if AudioData.nChannels = 1 then Exit;

MaxAmplitude := 1;

for i := 1 to AudioData.nBitsPerSample-1 do

MaxAmplitude := MaxAmplitude*2;

for i := Start to Start+Count-1 do

begin

Freq := Freq1 + Round((i-Start)*(Freq2-Freq1)/Count);

T := 2*Pi/(AudioData.nSamplesPerSec/(Freq/100));

TL := 2*Pi/(AudioData.nSamplesPerSec/(50+50*Freq/100));

TR := 2*Pi/(AudioData.nSamplesPerSec/(50+50*Freq/100+Freq/100));

AudioData.ReadSample(i, 0, SampL);

AudioData.ReadSample(i, 1, SampR);

SampL := Trunc(0.6*SampL+0.4*MaxAmplitude*Sin(i*TL));

SampR := Trunc(0.6*SampR+0.4*MaxAmplitude*Sin(i*TR));

AudioData.WriteSample(i, 0, SampL);

AudioData.WriteSample(i, 1, SampR);

end;

end;

procedure Normalize(var AudioData: TAudioData; Start, Count: Cardinal);

var

i, MaxAmplitude, MaxVolume: Cardinal;

Volume: Integer;

K: Real;

Channel: Word;

begin

MaxAmplitude := 1;

for i := 1 to AudioData.nBitsPerSample-1 do

MaxAmplitude := MaxAmplitude*2;

for Channel := 0 to AudioData.nChannels-1 do

begin

MaxVolume := 0;

for i := Start to Start+Count-1 do

begin

AudioData.ReadSample(i, Channel, Volume);

if Abs(Volume) > MaxVolume then MaxVolume := Abs(Volume);

end;

K := MaxAmplitude/MaxVolume;

for i := Start to Start+Count-1 do

begin

AudioData.ReadSample(i, Channel, Volume);

Volume := Round(Volume*K);

AudioData.WriteSample(i, Channel, Volume);

end;

end;

end;

procedure SetSpeedOfAudio(var AudioData: TAudioData; Start, Count: Cardinal; Speed: Real);

var

i, j, k, n, NewCount: Cardinal;

Channel: Byte;

Smp1, Smp2: Integer;

Interval: Real;

TempAudio: TAudioData;

Buf: Int64;

begin

if (Speed = 1) or (Speed = 0) then Exit;

TempAudio := TAudioData.Create;

TempAudio.nChannels := AudioData.nChannels;

TempAudio.nSamplesPerSec := AudioData.nSamplesPerSec;

TempAudio.nBitsPerSample := AudioData.nBitsPerSample;

TempAudio.nBlockAlign := AudioData.nBlockAlign;

NewCount := Round(Count/Speed);

if Speed > 1 then

begin

i := NewCount;

Interval := Speed;

AudioData.Data.Position := Start*AudioData.nBlockAlign;

while i<>0 do

begin

AudioData.Data.Read(Buf, AudioData.nBlockAlign);

TempAudio.Data.Write(Buf, AudioData.nBlockAlign);

AudioData.Data.Position := AudioData.Data.Position - AudioData.nBlockAlign + Trunc(Interval)*AudioData.nBlockAlign;

Interval := Interval-Trunc(Interval)+Speed;

Dec(i);

end;

end

else

begin

Speed := 1/Speed;

for Channel := 0 to AudioData.nChannels-1 do

begin

i := 0;

j := 0;

Interval := Speed;

while i<>Count do

begin

AudioData.ReadSample(Start+i, Channel, Smp1);

if i+1<>Count then

AudioData.ReadSample(Start+i+1, Channel, Smp2)

else

Smp2 := Smp1;

k := Trunc(Interval);

for n := 0 to k-1 do

TempAudio.WriteSample(j+n, Channel, Round(Smp1+(Smp2-Smp1)/k*n));

Interval := Interval-Trunc(Interval)+Speed;

Inc(i);

Inc(j, k);

end;

end;

end;

DeleteAudio(AudioData, Start, Start+Count-1);

InsertAudio(TempAudio, AudioData, Start);

TempAudio.Destroy;

end;

function ChangeSpeedOfAudio(var AudioData: TAudioData; Start, Count: Cardinal; Speed: Real): Cardinal;

var

i, j, k, n: Cardinal;

Channel: Byte;

Smp1, Smp2: Integer;

Interval, FinalSpeed: Real;

TempAudio: TAudioData;

Buf: Int64;

begin

if (Speed = 1) or (Speed = 0) then Exit;

TempAudio := TAudioData.Create;

TempAudio.nChannels := AudioData.nChannels;

TempAudio.nSamplesPerSec := AudioData.nSamplesPerSec;

TempAudio.nBitsPerSample := AudioData.nBitsPerSample;

TempAudio.nBlockAlign := AudioData.nBlockAlign;

FinalSpeed := Speed;

if Speed > 1 then

begin

Speed := 1;

Interval := Speed;

AudioData.Data.Position := Start*AudioData.nBlockAlign;

while AudioData.Data.Position div AudioData.nBlockAlign < Start+Count do

begin

AudioData.Data.Read(Buf, AudioData.nBlockAlign);

TempAudio.Data.Write(Buf, AudioData.nBlockAlign);

AudioData.Data.Position := AudioData.Data.Position - AudioData.nBlockAlign + Trunc(Interval)*AudioData.nBlockAlign;

Interval := Interval-Trunc(Interval)+Speed;

Speed := Speed+Trunc(Interval)*(FinalSpeed-1)/Count;

end;

end

else

begin

FinalSpeed := 1/FinalSpeed;

for Channel := 0 to AudioData.nChannels-1 do

begin

i := 0;

j := 0;

Speed := 1;

Interval := Speed;

while i<>Count do

begin

AudioData.ReadSample(Start+i, Channel, Smp1);

if i+1<>Count then

AudioData.ReadSample(Start+i+1, Channel, Smp2)

else

Smp2 := Smp1;

k := Trunc(Interval);

for n := 0 to k-1 do

TempAudio.WriteSample(j+n, Channel, Round(Smp1+(Smp2-Smp1)/k*n));

Interval := Interval-Trunc(Interval)+Speed;

Inc(i);

Inc(j, k);

Speed := Speed+(FinalSpeed-1)/Count;

end;

end;

end;

DeleteAudio(AudioData, Start, Start+Count-1);

InsertAudio(TempAudio, AudioData, Start);

ChangeSpeedOfAudio := TempAudio.Data.Size div TempAudio.nBlockAlign;

TempAudio.Destroy;

end;

procedure SetnSamplesPerSec(var AudioData: TAudioData; Value: Cardinal);

var

AudioSize: Cardinal;

begin

if AudioData.nSamplesPerSec = Value then Exit;

with AudioData do

AudioSize := Data.Size div nBlockAlign;

if AudioSize <> 0 then SetSpeedOfAudio(AudioData, 0, AudioSize, AudioData.nSamplesPerSec/Value);

AudioData.nSamplesPerSec := Value;

end;

procedure SetnBitsPerSample(var AudioData: TAudioData; Value: Cardinal);

var

AudioSize, Max1, Max2, i: Cardinal;

Channel: Word;

Smp: Integer;

Mult: Real;

TempAudio: TAudioData;

begin

if AudioData.nBitsPerSample = Value then Exit;

with AudioData do

AudioSize := Data.Size div nBlockAlign;

TempAudio := TAudioData.Create;

TempAudio.nChannels := AudioData.nChannels;

TempAudio.nSamplesPerSec := AudioData.nSamplesPerSec;

TempAudio.nBitsPerSample := Value;

TempAudio.Calculate_nBlockAlign;

Max1 := 1; for i := 1 to AudioData.nBlockAlign div AudioData.nChannels do Max1 := Max1*256;

Max2 := 1; for i := 1 to TempAudio.nBlockAlign div TempAudio.nChannels do Max2 := Max2*256;

Mult := Max2/Max1;

if AudioSize<>0 then

begin

for Channel := 0 to AudioData.nChannels-1 do

for i := 0 to AudioSize-1 do

begin

AudioData.ReadSample(i, Channel, Smp);

Smp := Trunc(Smp*Mult);

TempAudio.WriteSample(i, Channel, Smp);

end;

AudioData.Data.Clear;

OverwriteAudio(TempAudio, AudioData, 0);

end;

TempAudio.Destroy;

AudioData.nBitsPerSample := Value;

AudioData.Calculate_nBlockAlign;

end;

procedure SetnChannels(var AudioData: TAudioData; Value: Cardinal);

var

AudioSize: Cardinal;

TempAudio: TAudioData;

i: Integer;

Channel: Cardinal;

Smp: Integer;

begin

if AudioData.nChannels = Value then Exit;

with AudioData do

AudioSize := Data.Size div nBlockAlign;

TempAudio := TAudioData.Create;

TempAudio.nChannels := Value;

TempAudio.nSamplesPerSec := AudioData.nSamplesPerSec;

TempAudio.nBitsPerSample := AudioData.nBitsPerSample;

TempAudio.Calculate_nBlockAlign;

for i := 0 to AudioSize-1 do

for Channel := 0 to Value-1 do

begin

if Channel < AudioData.nChannels then

AudioData.ReadSample(i, Channel, Smp)

else

AudioData.ReadSample(i, AudioData.nChannels-1, Smp);

TempAudio.WriteSample(i, Channel, Smp);

end;

AudioData.Data.Clear;

AudioData.nChannels := Value;

AudioData.Calculate_nBlockAlign;

OverWriteAudio(TempAudio, AudioData, 0);

TempAudio.Destroy;

end;

procedure SetVolumeOfAudio(var AudioData: TAudioData; Start, Count: Cardinal; Volume: Real);

var

MaxValue: Cardinal;

Value: Integer;

i: Cardinal;

Channel: Word;

begin

MaxValue := 1;

for i := 1 to AudioData.nBlockAlign div AudioData.nChannels do

MaxValue := MaxValue*256;

MaxValue := MaxValue div 2 - 1;

for Channel := 0 to AudioData.nChannels-1 do

for i := Start to Start+Count-1 do

begin

AudioData.ReadSample(i, Channel, Value);

//Value := Trunc(Value*Exp(Volume/20));

Value := Trunc(Value*Volume);

if Abs(Value)>MaxValue then

if Value<0 then Value := -MaxValue