Смекни!
smekni.com

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

TrackBar.SelEnd := Round(Finish*TrackBar.Max/AudioSize);

Marker1.Left := 8+Round(Start*(TrackBar.Max-20)/AudioSize);

Marker1.Visible := True;

Marker2.Left := 8+Round(Finish*(TrackBar.Max-20)/AudioSize);

Marker2.Visible := True;

PaintBox1.Repaint;

Exit;

end;

if (StartExists) and (FinishExists) then

begin

if AudioPosition<Start then

Start := AudioPosition

else

if AudioPosition>Finish then

Finish := AudioPosition;

TrackBar.SelStart := Round(Start*TrackBar.Max/AudioSize);

TrackBar.SelEnd := Round(Finish*TrackBar.Max/AudioSize);

Marker1.Left := 8+Round(Start*(TrackBar.Max-20)/AudioSize);

Marker1.Visible := True;

Marker2.Left := 8+Round(Finish*(TrackBar.Max-20)/AudioSize);

Marker2.Visible := True;

PaintBox1.Repaint;

Exit;

end;

end;

end;

procedure TMainForm.DeleteMarkers;

begin

Selection.StartExists := False;

Selection.FinishExists := False;

Marker1.Visible := False;

Marker2.Visible := False;

TrackBar.SelStart := 0;

TrackBar.SelEnd := 0;

PaintBox1.Repaint;

end;

procedure TMainForm.OpenButtonClick(Sender: TObject);

var

FileName, S, Ext: String;

i: Byte;

PCM: TPCMFile;

MP3: TMP3File;

EM1: TEM1File;

begin

if (Status<>'starting')and(Status<>'waiting') then Exit;

if OpenDialog.Execute then FileName := OpenDialog.FileName else Exit;

Status := 'opening';

AudioData.Data.Clear;

if GetFileAttributes(PChar(FileName)) and FILE_ATTRIBUTE_READONLY = FILE_ATTRIBUTE_READONLY then

SetFileAttributes(PChar(FileName), GetFileAttributes(PChar(FileName)) xor FILE_ATTRIBUTE_READONLY);

Ext := ExtractFileExt(FileName);

for i := 1 to Length(Ext) do Ext[i] := UpCase(Ext[i]);

if Ext = '.WAV' then

begin

PCM := TPCMFile.Open(FileName);

PCM.ReadAudioData(AudioData);

PCM.Destroy;

end;

if Ext = '.MP3' then

begin

MP3 := TMP3File.Open(FileName);

MP3.ReadAudioData(AudioData);

MP3.Destroy;

end;

if Ext = '.EM1' then

begin

EM1 := TEM1File.Open(FileName);

EM1.ReadAudioData(AudioData);

EM1.Destroy;

end;

Str(AudioData.nChannels, S);

AudioOptionsForm.nChannelsText.Caption := S + ' channels';

Str(AudioData.nBitsPerSample, S);

AudioOptionsForm.nBitsPerSampleText.Caption := S + ' bits';

Str(AudioData.nSamplesPerSec, S);

AudioOptionsForm.nSamplesPerSecText.Caption := S + ' Hz';

AudioPosition := 0;

AudioData.Calculate_nBlockAlign;

SetAudioPosition;

DeleteMarkers;

Status := 'waiting';

end;

procedure TMainForm.PlayButtonClick(Sender: TObject);

begin

if Status<>'waiting' then Exit;

if OutDeviceComboBox.ItemIndex = -1 then Exit;

if AudioPosition*AudioData.nBlockAlign >= AudioData.Data.Size then Exit;

Status := 'playing';

PlayThread := TPlayThread.Create(False);

end;

procedure TPlayThread.Execute;

const

BlockSize = 1024*24;

var

hEvent: THandle;

WaveFormatEx: TWaveFormatEx;

WaveHdr: array [0..1] of TWaveHdr;

Buf: array [0..1] of array [0..BlockSize-1] of Byte;

i: Cardinal;

begin

with WaveFormatEx do

begin

wFormatTag := WAVE_FORMAT_PCM;

nChannels := AudioData.nChannels;

nSamplesPerSec := AudioData.nSamplesPerSec;

wBitsPerSample := AudioData.nBitsPerSample;

nBlockAlign := wBitsPerSample div 8 * nChannels;

nAvgBytesPerSec := nSamplesPerSec * nBlockAlign;

cbSize := 0;

end;

hEvent := CreateEvent(nil, False, False, nil);

if WaveOutOpen(@WaveOut, MainForm.OutDeviceComboBox.ItemIndex , @WaveFormatEx, hEvent, 0, CALLBACK_EVENT) <> MMSYSERR_NOERROR then

begin

Status := 'waiting';

CloseHandle(hEvent);

Terminate;

Exit;

end;

MainForm.PlayButton.Flat := True;

for i := 0 to 1 do

begin

WaveHdr[i].lpData := @Buf[i];

WaveHdr[i].dwBufferLength := BlockSize;

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

if i<>1 then

begin

AudioData.Data.Read(Buf[i], BlockSize);

AudioPosition := AudioPosition + BlockSize div AudioData.nBlockAlign;

if AudioPosition*AudioData.nBlockAlign >= AudioData.Data.Size then AudioPosition := AudioData.Data.Size div AudioData.nBlockAlign;

end;

WaveOutPrepareHeader(WaveOut, @WaveHdr[i], SizeOf(TWaveHdr));

end;

i := 0;

while (not Terminated) and (AudioData.Data.Position<AudioData.Data.Size) do

begin

WaveOutWrite(WaveOut, @WaveHdr[i], SizeOf(TWaveHdr));

WaitForSingleObject(hEvent, INFINITE);

i := i xor 1;

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

AudioData.Data.Read(Buf[i], BlockSize);

AudioPosition := AudioPosition + (BlockSize div AudioData.nBlockAlign);

if AudioPosition*AudioData.nBlockAlign >= AudioData.Data.Size then AudioPosition := AudioData.Data.Size div AudioData.nBlockAlign;

MainForm.SetAudioPosition;

end;

WaveOutReset(WaveOut);

for i := 0 to 1 do WaveOutUnprepareHeader(WaveOut, @WaveHdr[i], SizeOf(WaveHdr));

WaveOutClose(WaveOut);

CloseHandle(hEvent);

if not Terminated then Terminate;

MainForm.PlayButton.Flat := False;

Status := 'waiting';

end;

procedure TMainForm.RecordButtonClick(Sender: TObject);

begin

if (Status<>'waiting')and(Status<>'starting') then Exit;

if InDeviceComboBox.ItemIndex = -1 then Exit;

Status := 'recording';

RecordThread := TRecordThread.Create(False);

end;

procedure TRecordThread.Execute;

const

BlockSize = 1024*24;

BufNumber = 8;

var

hEvent: THandle;

WaveFormatEx: TWaveFormatEx;

WaveHdr: array [0..BufNumber-1] of TWaveHdr;

Buf: array [0..BufNumber-1] of array [0..BlockSize-1] of Byte;

i: Cardinal;

begin

with WaveFormatEx do

begin

wFormatTag := WAVE_FORMAT_PCM;

nChannels := AudioData.nChannels;

nSamplesPerSec := AudioData.nSamplesPerSec;

wBitsPerSample := AudioData.nBitsPerSample;

nBlockAlign := wBitsPerSample div 8 * nChannels;

nAvgBytesPerSec := nSamplesPerSec * nBlockAlign;

cbSize := 0;

end;

hEvent := CreateEvent(nil, False, False, nil);

if WaveInOpen(@WaveIn, MainForm.InDeviceComboBox.ItemIndex , @WaveFormatEx, hEvent, 0, CALLBACK_EVENT) <> MMSYSERR_NOERROR then

begin

Status := 'waiting';

CloseHandle(hEvent);

Terminate;

Exit;

end;

MainForm.RecordButton.Flat := True;

for i := 0 to BufNumber-1 do

begin

WaveHdr[i].lpData := @Buf[i];

WaveHdr[i].dwBufferLength := BlockSize;

WaveInPrepareHeader(WaveIn, @WaveHdr[i], SizeOf(TWaveHdr));

end;

WaveInStart(WaveIn);

WaitForSingleObject(hEvent, INFINITE);

for i := 0 to BufNumber-1 do

WaveInAddBuffer(WaveIn, @WaveHdr[i], SizeOf(TWaveHdr));

i := BufNumber-1;

while not Terminated do

begin

if i = BufNumber-1 then i := 0 else Inc(i);

if (WaveHdr[i].dwFlags and WHDR_DONE) <> WHDR_DONE then

WaitForSingleObject(hEvent, INFINITE);

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

AudioData.Data.Write(Buf[i], WaveHdr[i].dwBytesRecorded);

AudioPosition := AudioPosition + (WaveHdr[i].dwBytesRecorded div AudioData.nBlockAlign);

WaveInAddBuffer(WaveIn, @WaveHdr[i], SizeOf(TWaveHdr));

MainForm.SetAudioPosition;

end;

WaveInReset(WaveIn);

for i := 0 to BufNumber-1 do

WaveInUnprepareHeader(WaveIn, @WaveHdr[i], SizeOf(WaveHdr));

WaveInClose(WaveIn);

CloseHandle(hEvent);

if not Terminated then Terminate;

with MainForm.PositionSpinEdit do

begin

Value := AudioPosition;

MinValue := 0;

MaxValue := AudioData.Data.Size div AudioData.nBlockAlign;;

end;

MainForm.RecordButton.Flat := False;

Status := 'waiting';

end;

procedure TMainForm.PauseButtonClick(Sender: TObject);

begin

if Status = 'playing' then PlayThread.Terminate;

if Status = 'recording' then RecordThread.Terminate;

end;

procedure TMainForm.TrackBarChange(Sender: TObject);

var

AudioSize: Cardinal;

begin

if Status<>'waiting' then Exit;

with AudioData do

AudioSize := Data.Size div nBlockAlign;

if TrackBar.Position <> Round(AudioPosition*TrackBar.Max/AudioSize) then

begin

AudioPosition := Round(TrackBar.Position/TrackBar.Max*AudioSize);

SetAudioPosition;

end;

end;

procedure TMainForm.PositionSpinEditChange(Sender: TObject);

begin

if Status<>'waiting' then Exit;

AudioPosition := PositionSpinEdit.Value;

SetAudioPosition;

end;

procedure TMainForm.SaveButtonClick(Sender: TObject);

var

FileName, Ext, EncMode, StereoMode, BitRate: String;

i: Byte;

Code: Integer;

PCM: TPCMFile;

MP3: TMP3File;

EM1: TEM1File;

begin

if Status<>'waiting' then Exit;

if SaveDialog.Execute then

FileName := SaveDialog.FileName else Exit;

Ext := ExtractFileExt(FileName);

for i := 1 to Length(Ext) do Ext[i] := UpCase(Ext[i]);

if Ext = '.WAV' then

begin

PCM := TPCMFile.Create(FileName, AudioData);

PCM.Destroy;

end;

if Ext = '.MP3' then

begin

if RadioButton1.Checked then

begin

BitRate := MP3OptionsForm.ConstantBitRateComboBox.Text;

EncMode := '-b';

end;

if RadioButton2.Checked then

begin

BitRate := MP3OptionsForm.AverageBitRateComboBox.Text;

EncMode := '--abr';

end;

if RadioButton3.Checked then

begin

Str(MP3OptionsForm.VariableBitrateComboBox.ItemIndex, BitRate);

EncMode := '-V';

end;

case MP3OptionsForm.StereoModeComboBox.ItemIndex of

0: StereoMode := 's';

1: StereoMode := 'j';

2: StereoMode := 'f';

3: StereoMode := 'd';

4: StereoMode := 'm';

end;

MP3 := TMP3File.Create(FileName, AudioData, BitRate, EncMode, StereoMode);

MP3.Destroy;

end;

if Ext = '.EM1' then

begin

EM1 := TEM1File.Create(FileName, AudioData);

EM1.Destroy;

end;

end;

procedure TMainForm.SetMarkerButtonClick(Sender: TObject);

begin

SetMarker;

end;

procedure TMainForm.DeleteMarkersButtonClick(Sender: TObject);

begin

DeleteMarkers;

end;

procedure TMainForm.CopyButtonClick(Sender: TObject);

var

AudioSize: Cardinal;

S: String;

begin

if Status<>'waiting' then Exit;

Status := 'editing';

with AudioData do

AudioSize := Data.Size div nBlockAlign;

with Selection do

begin

if not StartExists or not FinishExists then

begin

DeleteMarkers;

Start := 0;

Finish := AudioSize-1;

end;

CopyAudio(AudioData, AudioClipBoard, Start, Finish);

end;

Str(AudioClipBoard.Data.Size div AudioClipBoard.nBlockAlign div AudioClipBoard.nSamplesPerSec, S);

Memo1.Text := 'В буффере ' + S + ' сек.';

Status := 'waiting';

end;

procedure TMainForm.DeleteButtonClick(Sender: TObject);

var

AudioSize: Cardinal;

begin

if Status<>'waiting' then Exit;

Status := 'editing';

SaveUndoInfo;

with AudioData do

AudioSize := Data.Size div nBlockAlign;

with Selection do

begin

if not StartExists or not FinishExists then

begin

DeleteMarkers;

Start := 0;

Finish := AudioSize-1;

end;

DeleteAudio(AudioData, Start, Finish);

DeleteMarkers;

AudioPosition := Start;

SetAudioPosition;

end;

Status := 'waiting';

end;

procedure TMainForm.CutButtonClick(Sender: TObject);

var

AudioSize: Cardinal;

S: String;

begin

if Status<>'waiting' then Exit;

Status := 'editing';

SaveUndoInfo;

with AudioData do

AudioSize := Data.Size div nBlockAlign;

with Selection do

begin

if not StartExists or not FinishExists then

begin

DeleteMarkers;

Start := 0;

Finish := AudioSize-1;

end;

CopyAudio(AudioData, AudioClipBoard, Start, Finish);

DeleteAudio(AudioData, Start, Finish);

DeleteMarkers;

AudioPosition := Start;

SetAudioPosition;

end;

Str(AudioClipBoard.Data.Size div AudioClipBoard.nBlockAlign div AudioClipBoard.nSamplesPerSec, S);

Memo1.Text := 'В буффере ' + S + ' сек.';

Status := 'waiting';

end;

procedure TMainForm.ClearButtonClick(Sender: TObject);

var

AudioSize, i: Cardinal;

Buf: Byte;

begin

if Status<>'waiting' then Exit;

Status := 'editing';

SaveUndoInfo;

with AudioData do

AudioSize := Data.Size div nBlockAlign;

with Selection do

begin

if not StartExists or not FinishExists then

begin

DeleteMarkers;

Start := 0;

Finish := AudioSize-1;

end;

Buf := 0;

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

for i := Start*AudioData.nBlockAlign to Finish*AudioData.nBlockAlign-1 do

AudioData.Data.Write(Buf, 1);

end;

Status := 'waiting';

PaintAudioGraph;

end;

procedure TMainForm.PasteButtonClick(Sender: TObject);

var

MP3: TMP3File;

PCM: TPCMFile;

EM1: TEM1File;

i: Byte;

FileName, S, Ext: String;

TempAudio: TAudioData;

begin

if (Status<>'waiting')and(Status<>'starting') then Exit;

if Sender = PasteFileButton then

begin

if OpenDialog.Execute then FileName := OpenDialog.FileName else Exit;

Status := 'opening';

Ext := ExtractFileExt(FileName);

if GetFileAttributes(PChar(FileName)) and FILE_ATTRIBUTE_READONLY = FILE_ATTRIBUTE_READONLY then

SetFileAttributes(PChar(FileName), GetFileAttributes(PChar(FileName)) xor FILE_ATTRIBUTE_READONLY);

TempAudio := TAudioData.Create;

for i := 1 to Length(Ext) do Ext[i] := UpCase(Ext[i]);

if Ext = '.WAV' then

begin

PCM := TPCMFile.Open(FileName);

PCM.ReadAudioData(TempAudio);

PCM.Destroy;

end;

if Ext = '.MP3' then

begin

MP3 := TMP3File.Open(FileName);

MP3.ReadAudioData(TempAudio);

MP3.Destroy;

end;

if Ext = '.EM1' then

begin

EM1 := TEM1File.Open(FileName);

EM1.ReadAudioData(TempAudio);

EM1.Destroy;

end;

SetnSamplesPerSec(TempAudio, AudioData.nSamplesPerSec);

SetnBitsPerSample(TempAudio, AudioData.nBitsPerSample);

SetnChannels(TempAudio, AudioData.nChannels);

end

else

begin

SetnSamplesPerSec(AudioClipBoard, AudioData.nSamplesPerSec);

SetnBitsPerSample(AudioClipBoard, AudioData.nBitsPerSample);

SetnChannels(AudioClipBoard, AudioData.nChannels);

end;

Status := 'editing';

SaveUndoInfo;

if Sender <> PasteFileButton then

Case PasteModeComboBox.ItemIndex of

0: InsertAudio(AudioClipBoard, AudioData, AudioPosition);

1: OverWriteAudio(AudioClipBoard, AudioData, AudioPosition);

2: MixAudio(AudioClipBoard, AudioData, AudioPosition);

end

else

Case PasteModeComboBox.ItemIndex of

0: InsertAudio(TempAudio, AudioData, AudioPosition);

1: OverWriteAudio(TempAudio, AudioData, AudioPosition);

2: MixAudio(TempAudio, AudioData, AudioPosition);

end;

DeleteMarkers;

SetAudioPosition;

SetMarker;

if Sender <> PasteFileButton then

AudioPosition := AudioPosition + AudioClipBoard.Data.Size div AudioData.nBlockAlign - 1

else

begin

AudioPosition := AudioPosition + TempAudio.Data.Size div AudioData.nBlockAlign - 1;

TempAudio.Destroy;

end;

SetAudioPosition;

SetMarker;

Status := 'waiting';

end;

procedure TMainForm.PasteSilenceButtonClick(Sender: TObject);

var

i: Cardinal;

b: Byte;

TempAudio: TAudioData;

begin