{$R *.dfm}
procedure TMainForm.FormCreate(Sender: TObject);
var
WaveOutCaps: TWaveOutCaps;
WaveInCaps: TWaveInCaps;
i: Cardinal;
begin
SamplesPerPoint := 16;
BorderIcons := BorderIcons - [biMaximize];
AudioData := TAudioData.Create;
AudioClipBoard := TAudioData.Create;
with AudioData do
nChannels := 2;
nBitsPerSample := 16;
nSamplesPerSec := 44100;
Calculate_nBlockAlign;
end;
AudioPosition := 0;
if WaveOutGetNumDevs<>0 then
for i := 0 to WaveOutGetNumDevs-1 do
WaveOutGetDevCaps(i, @WaveOutCaps, SizeOf(TWaveOutCaps));
OutDeviceComboBox.Items.Add(PChar(@WaveOutCaps.szPname));
OutDeviceComboBox.ItemIndex := 0;
if WaveInGetNumDevs<>0 then
for i := 0 to WaveInGetNumDevs-1 do
WaveInGetDevCaps(i, @WaveInCaps, SizeOf(TWaveInCaps));
InDeviceComboBox.Items.Add(PChar(@WaveInCaps.szPname));
InDeviceComboBox.ItemIndex := 0;
AudioData.Calculate_nBlockAlign;
UndoInfo.AudioData := TAudioData.Create;
Status := 'starting';
procedure TMainForm.SetAudioPosition;
AudioSize, Long: Cardinal;
S, S2: String;
PaintBox1.Repaint;
with AudioData do AudioSize := Data.Size div nBlockAlign;
if AudioSize = 0 then Exit;
if AudioSize<TrackBar.Width then TrackBar.Max := AudioSize else TrackBar.Max := TrackBar.Width;
with PositionSpinEdit do
Value := AudioPosition;
MinValue := 0;
MaxValue := AudioSize;
if TrackBar.Position <> Round(AudioPosition*TrackBar.Max/AudioSize) then TrackBar.Position := Round(AudioPosition*TrackBar.Max/AudioSize);
S2 := '';
Long := Trunc(AudioPosition/AudioData.nSamplesPerSec);
Str(Trunc(Long/3600), S);
Long := Long - Trunc(Long/3600)*3600;
S2 := S2 + S +':';
Str(Trunc(Long/60), S);
Long := Long - Trunc(Long/60)*60;
if Length(S)=1 then S2 := S2 + '0';
Str(Long, S);
S2 := S2 + S +' / ';
Long := Trunc(AudioSize/AudioData.nSamplesPerSec);
S2 := S2 + S + ' ';
if TimePosition.Caption<>S2 then TimePosition.Caption := S2;
{PaintBox1.Repaint;}
PaintAudioGraph;
procedure TMainForm.SetMarker;
AudioSize: Cardinal;
if (Status = 'starting') then Exit;
with Selection do
if (AudioPosition=Start)and(StartExists) or (AudioPosition=Finish)and(FinishExists) then Exit;
if not StartExists then
Start := AudioPosition;
StartExists := True;
Marker1.Left := 8+Round(Start*(TrackBar.Max-20)/AudioSize);
Marker1.Visible := True;
Exit;
if (StartExists) and (not FinishExists) then
if AudioPosition>Start then
Finish := AudioPosition
else
Finish := Start;
FinishExists := True;
TrackBar.SelStart := Round(Start*TrackBar.Max/AudioSize);
TrackBar.SelEnd := Round(Finish*TrackBar.Max/AudioSize);
Marker2.Left := 8+Round(Finish*(TrackBar.Max-20)/AudioSize);
Marker2.Visible := True;
if (StartExists) and (FinishExists) then
if AudioPosition<Start then
Start := AudioPosition
if AudioPosition>Finish then
Finish := AudioPosition;
procedure TMainForm.DeleteMarkers;
Selection.StartExists := False;
Selection.FinishExists := False;
Marker1.Visible := False;
Marker2.Visible := False;
TrackBar.SelStart := 0;
TrackBar.SelEnd := 0;
procedure TMainForm.OpenButtonClick(Sender: TObject);
FileName, S, Ext: String;
i: Byte;
PCM: TPCMFile;
MP3: TMP3File;
EM1: TEM1File;
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
PCM := TPCMFile.Open(FileName);
PCM.ReadAudioData(AudioData);
PCM.Destroy;
if Ext = '.MP3' then
MP3 := TMP3File.Open(FileName);
MP3.ReadAudioData(AudioData);
MP3.Destroy;
if Ext = '.EM1' then
EM1 := TEM1File.Open(FileName);
EM1.ReadAudioData(AudioData);
EM1.Destroy;
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';
SetAudioPosition;
DeleteMarkers;
Status := 'waiting';
procedure TMainForm.PlayButtonClick(Sender: TObject);
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);
procedure TPlayThread.Execute;
const
BlockSize = 1024*24;
hEvent: THandle;
WaveFormatEx: TWaveFormatEx;
WaveHdr: array [0..1] of TWaveHdr;
Buf: array [0..1] of array [0..BlockSize-1] of Byte;
with WaveFormatEx do
wFormatTag := WAVE_FORMAT_PCM;
nChannels := AudioData.nChannels;
nSamplesPerSec := AudioData.nSamplesPerSec;
wBitsPerSample := AudioData.nBitsPerSample;
nBlockAlign := wBitsPerSample div 8 * nChannels;
nAvgBytesPerSec := nSamplesPerSec * nBlockAlign;
cbSize := 0;
hEvent := CreateEvent(nil, False, False, nil);
if WaveOutOpen(@WaveOut, MainForm.OutDeviceComboBox.ItemIndex , @WaveFormatEx, hEvent, 0, CALLBACK_EVENT) <> MMSYSERR_NOERROR then
CloseHandle(hEvent);
Terminate;
MainForm.PlayButton.Flat := True;
for i := 0 to 1 do
WaveHdr[i].lpData := @Buf[i];
WaveHdr[i].dwBufferLength := BlockSize;
AudioData.Data.Position := AudioPosition*AudioData.nBlockAlign;
if i<>1 then
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;
WaveOutPrepareHeader(WaveOut, @WaveHdr[i], SizeOf(TWaveHdr));
i := 0;
while (not Terminated) and (AudioData.Data.Position<AudioData.Data.Size) do
WaveOutWrite(WaveOut, @WaveHdr[i], SizeOf(TWaveHdr));
WaitForSingleObject(hEvent, INFINITE);
i := i xor 1;
AudioPosition := AudioPosition + (BlockSize div AudioData.nBlockAlign);
MainForm.SetAudioPosition;
WaveOutReset(WaveOut);
for i := 0 to 1 do WaveOutUnprepareHeader(WaveOut, @WaveHdr[i], SizeOf(WaveHdr));
WaveOutClose(WaveOut);
if not Terminated then Terminate;
MainForm.PlayButton.Flat := False;
procedure TMainForm.RecordButtonClick(Sender: TObject);
if (Status<>'waiting')and(Status<>'starting') then Exit;
if InDeviceComboBox.ItemIndex = -1 then Exit;
Status := 'recording';
RecordThread := TRecordThread.Create(False);
procedure TRecordThread.Execute;
BufNumber = 8;
WaveHdr: array [0..BufNumber-1] of TWaveHdr;
Buf: array [0..BufNumber-1] of array [0..BlockSize-1] of Byte;
if WaveInOpen(@WaveIn, MainForm.InDeviceComboBox.ItemIndex , @WaveFormatEx, hEvent, 0, CALLBACK_EVENT) <> MMSYSERR_NOERROR then
Ñòðàíèöû: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25