begin
DeleteMarkers;
Start := 0;
Finish := AudioSize-1;
end;
AddBrainWave(AudioData, Start, Finish-Start+1, BWFreqEdit1.Value, BWFreqEdit2.Value);
end;
Status := 'waiting';
end;
procedure TMainForm.Left10ButtonClick(Sender: TObject);
var
AudioSize, Smp10ms: Cardinal;
begin
if Status<>'waiting' then Exit;
with AudioData do
AudioSize := Data.Size div nBlockAlign;
Smp10ms := Round(AudioData.nSamplesPerSec/100);
if Sender = Left10Button then
if AudioPosition < Smp10ms then AudioPosition := 0 else AudioPosition := AudioPosition - Smp10ms
else
if AudioPosition + Smp10ms >= AudioSize then AudioPosition := AudioSize - 1 else AudioPosition := AudioPosition + Smp10ms;
SetAudioPosition;
end;
procedure TMainForm.SSelButtonClick(Sender: TObject);
var
AudioSize: Cardinal;
begin
if Status<>'waiting' then Exit;
with AudioData do
AudioSize := Data.Size div nBlockAlign;
if Sender = {SSelButton}BitBtn3 then
if Selection.StartExists then AudioPosition := Selection.Start else AudioPosition := 0
else
if Selection.FinishExists then AudioPosition := Selection.Finish else AudioPosition := AudioSize - 1;
SetAudioPosition;
end;
procedure TMainForm.HelpButtonClick(Sender: TObject);
begin
HelpForm.Visible := True;
HelpForm.Show;
end;
procedure TMainForm.UndoCheckBoxClick(Sender: TObject);
begin
if UndoCheckBox.Checked then
UndoButton.Enabled := True
else
begin
UndoButton.Enabled := False;
UndoInfo.AudioData.Data.Clear;
end;
end;
procedure TMainForm.N4Click(Sender: TObject);
begin
MainForm.Close;
end;
procedure TMainForm.N43Click(Sender: TObject);
begin
AudioOptionsForm.Visible := True;
AudioOptionsForm.Show;
end;
procedure TMainForm.MP31Click(Sender: TObject);
begin
MP3OptionsForm.Visible := True;
MP3OptionsForm.Show;
end;
procedure TMainForm.N44Click(Sender: TObject);
begin
EffOptionsForm.Visible := True;
EffOptionsForm.Show;
end;
procedure TMainForm.ButtonZoomInClick(Sender: TObject);
begin
SamplesPerPoint := SamplesPerPoint div 2;
if (SamplesPerPoint<1) then SamplesPerPoint:=1;
PaintBox1.Repaint;
end;
procedure TMainForm.ButtonZoomOutClick(Sender: TObject);
begin
SamplesPerPoint := SamplesPerPoint * 2;
PaintBox1.Repaint;
end;
procedure TMainForm.AudioOptionsButtonClick(Sender: TObject);
begin
AudioOptionsForm.Visible := True;
AudioOptionsForm.Show;
end;
procedure TMainForm.MP3OptionsButtonClick(Sender: TObject);
begin
MP3OptionsForm.Visible := True;
MP3OptionsForm.Show;
end;
procedure TMainForm.EffOptionsButtonClick(Sender: TObject);
begin
EffOptionsForm.Visible := True;
EffOptionsForm.Show;
end;
end.
П. 1.2. ТЕКСТ МОДУЛЯ PCM_FORMAT.PAS
unit PCM_Format;
interface
uses
SysUtils, AudioFormat;
type
TPCMFile = class(TAudioFile)
public
RIFFLabel: String;
RIFFSize: LongWord;
fccType: String;
fmt_Label: String;
fmtSize: LongWord;
formatTag: Word;
nChannels: Word;
nSamplesPerSec: LongWord;
nAvgBytesPerSec: LongWord;
nBlockAlign: Word;
nBitsPerSample: Word;
DataID: String;
AdvDataBegin: LongWord; //*
DataSize: LongWord;
DataLabel: String;
SndDataBegin: LongWord; //*
nDataBytes: LongWord;
constructor Open(FileName: string);
function ReadSample(Number, Channel: LongInt): Integer;
procedure WriteSample(Number, Channel: LongInt; Value: Integer);
procedure ReadAudioData(var AudioData: TAudioData);
constructor Create(FileName: string; var AudioData: TAudioData);
private
{ Private declarations }
end;
implementation
constructor TPCMFile.Open(FileName: String);
begin
inherited Open(FileName);
ReadString(RIFFLabel, 4);
Read(RIFFSize, 4);
ReadString(fccType, 4);
ReadString(fmt_Label, 4);
Read(fmtSize, 4);
Read(formatTag, 2);
Read(nChannels, 2);
Read(nSamplesPerSec, 4);
Read(nAvgBytesPerSec, 4);
Read(nBlockAlign, 2);
Read(nBitsPerSample, 2);
Position := $14 + fmtSize;
ReadString(DataLabel, 4);
if DataLabel <> 'data' then
begin
DataId := DataLabel;
Read(DataSize, 4);
AdvDataBegin := Position;
Position := Position + DataSize;
ReadString(DataLabel, 4);
end
else
begin
DataID := '';
DataSize := 0;
end;
Read(nDataBytes, 4);
SndDataBegin := Position;
end;
function TPCMFile.ReadSample(Number, Channel: LongInt): Integer;
var
i: Byte;
Value, Mult: LongWord;
begin
Position := SndDataBegin + Number*nBlockAlign + Channel*Trunc(nBlockAlign/nChannels);
Value := 0;
Read(Value, Trunc(nBlockAlign/nChannels));
Mult := 1;
for i := 0 to Trunc(nBlockAlign/nChannels)-1 do Mult := Mult*256;
if nBitsPerSample>8 then
if Value >= Mult/2 then ReadSample := Value - Mult else ReadSample := Value
else
ReadSample := Value-128;
end;
procedure TPCMFile.WriteSample(Number, Channel: LongInt; Value: Integer);
begin
Position := SndDataBegin + Number*nBlockAlign + Channel*Trunc(nBlockAlign/nChannels);
if nBitsPerSample<=8 then Value := Value+128;
Write(Value, Trunc(nBlockAlign/nChannels));
end;
procedure TPCMFile.ReadAudioData(var AudioData: TAudioData);
const
MaxBufSize = 65536;
var
i: Cardinal;
BufSize: Cardinal;
Buf: array [0..MaxBufSize] of Byte;
begin
AudioData.Data.Clear;
Position := SndDataBegin;
while Position<Size do
begin
if Size-Position>=MaxBufSize then BufSize := MaxBufSize else BufSize := Size-Position;
Read(Buf, BufSize);
AudioData.Data.Write(Buf, BufSize);
end;
AudioData.nChannels := nChannels;
AudioData.nSamplesPerSec := nSamplesPerSec;
AudioData.nBitsPerSample := nBitsPerSample;
AudioData.Calculate_nBlockAlign;
end;
constructor TPCMFile.Create(FileName: string; var AudioData: TAudioData);
const
MaxBufSize = 65536;
var
i: Cardinal;
BufSize: Cardinal;
Buf: array [0..MaxBufSize] of Byte;
begin
inherited Create(FileName);
RIFFLabel := 'RIFF';
RIFFSize := AudioData.Data.Size+4*3+2*2+4*2+2*2+4*2;
fccType := 'WAVE';
fmt_Label := 'fmt ';
fmtSize := 16;
formatTag := 1; //???
nChannels := AudioData.nChannels;
nSamplesPerSec := AudioData.nSamplesPerSec;
nBlockAlign := AudioData.nBitsPerSample div 8;
if AudioData.nBitsPerSample mod 8 <> 0 then Inc(nBlockAlign);
nBlockAlign := nBlockAlign*nChannels;
nAvgBytesPerSec := nSamplesPerSec*nBlockAlign;
nBitsPerSample := AudioData.nBitsPerSample;
DataLabel := 'data';
nDataBytes := AudioData.Data.Size;
WriteString(RIFFLabel, 4);
Write(RIFFSize, 4);
WriteString(fccType, 4);
WriteString(fmt_Label, 4);
Write(fmtSize, 4);
Write(formatTag, 2);
Write(nChannels, 2);
Write(nSamplesPerSec, 4);
Write(nAvgBytesPerSec, 4);
Write(nBlockAlign, 2);
Write(nBitsPerSample, 2);
WriteString(DataLabel, 4);
Write(nDataBytes, 4);
DataID := '';
DataSize := 0;
SndDataBegin := Position;
AudioData.Data.Position := 0;
while AudioData.Data.Position < AudioData.Data.Size do
begin
with AudioData.Data do
begin
if Size-Position>=MaxBufSize then BufSize := MaxBufSize else BufSize := Size-Position;
Read(Buf, BufSize);
end;
Write(Buf, BufSize);
end;
end;
end.
П. 1.3. ТЕКСТ МОДУЛЯ MP3_FORMAT.PAS
unit MP3_Format;
interface
uses
SysUtils, ShellApi, Windows, Classes, AudioFormat, PCM_Format;
type
TMP3File = class(TAudioFile)
public
constructor Open(FileName: string);
constructor Create(FileName: string; var AudioData: TAudioData; BitRate, EncMode, StereoMode: String);
procedure ReadAudioData(var AudioData: TAudioData);
private
Name: String;
end;
implementation
{$R Lame.res}
var
Res: TResourceStream;
TempDir: String;
LameFile: String;
LameParameters: String;
constructor TMP3File.Open(FileName: string);
begin
inherited Open(FileName);
Name := FileName;
end;
constructor TMP3File.Create(FileName: string; var AudioData: TAudioData; BitRate, EncMode, StereoMode: String);
var
TempWaveFile: String;
PCM: TPCMFile;
StartupInfo: TStartupInfo;
ProcessInformation: TProcessInformation;
begin
TempWaveFile := TempDir+'TempWave.wav';
PCM := TPCMFile.Create(TempWaveFile, AudioData);
PCM.Destroy;
LameParameters := LameFile+' -m '+StereoMode+' '+EncMode+' '+BitRate+' "'+TempWaveFile+'" "'+FileName+'"';
FillChar(StartupInfo, SizeOf(StartupInfo), 0 );
StartupInfo.cb := SizeOf(StartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := SW_HIDE;
CreateProcess(nil, PChar(LameParameters), nil, nil, False, CREATE_DEFAULT_ERROR_MODE+HIGH_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInformation);
WaitForSingleObject(ProcessInformation.hProcess, infinite);
DeleteFile(PChar(TempWaveFile));
inherited Open(FileName);
Name := FileName;
end;
procedure TMP3File.ReadAudioData(var AudioData: TAudioData);
var
TempWaveFile: String;
PCM: TPCMFile;
Result: Word;
StartupInfo: TStartupInfo;
ProcessInformation: TProcessInformation;
begin
TempWaveFile := TempDir+'TempWave.wav';
LameParameters := LameFile+' --decode '+'"'+Name+'" "'+TempWaveFile+'"';
FillChar(StartupInfo, SizeOf(StartupInfo), 0 );
StartupInfo.cb := SizeOf(StartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := SW_HIDE;
CreateProcess(nil, PChar(LameParameters), nil, nil, False, CREATE_DEFAULT_ERROR_MODE+HIGH_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInformation);
WaitForSingleObject(ProcessInformation.hProcess, infinite);
PCM := TPCMFile.Open(TempWaveFile);
PCM.ReadAudioData(AudioData);
PCM.Destroy;
DeleteFile(PChar(TempWaveFile));
end;
initialization
TempDir := GetEnvironmentVariable('TEMP')+'\';
Res := TResourceStream.Create(Hinstance, 'Lame', 'ExeFile');
LameFile := TempDir+'Lame.exe';
Res.SaveToFile(LameFile);
Res.Destroy;
end.
П. 1.4. ТЕКСТ МОДУЛЯ EM1_FORMAT.PAS
unit EM1_Format;
interface
uses
SysUtils, AudioFormat;
type
TEM1File = class(TAudioFile)
public
EM1Label: String;
nChannels: Word;
nSamplesPerSec: LongWord;
nBytesPerSample: Word;
nSamples: LongWord;
procedure ReadAudioData(var AudioData: TAudioData);
constructor Create(FileName: string; var AudioData: TAudioData);
constructor Open(FileName: string);
end;
implementation
constructor TEM1File.Create(FileName: string; var AudioData: TAudioData);
var
Channel: Word;
NumberOfBit, NumberOfSample, NumberOfSample0, i: Cardinal;
Sample: Integer;
Bit: Byte;
begin
inherited Create(FileName);
EM1Label := 'EM1 ';
nChannels := AudioData.nChannels;
nSamplesPerSec := AudioData.nSamplesPerSec;
nBytesPerSample := AudioData.nBitsPerSample div 8;
nSamples := AudioData.Data.Size div AudioData.nBlockAlign;
WriteString(EM1Label, 4);
Write(nChannels, 2);
Write(nSamplesPerSec, 4);
Write(nBytesPerSample, 2);
Write(nSamples, 4);
for Channel := 0 to nChannels-1 do
begin
NumberOfBit := Position*8;
NumberOfSample0 := 0;
NumberOfSample := 1;
Bit := 0;
while NumberOfSample < nSamples do
begin
while not AudioData.Extremum(NumberOfSample, Channel) do
Inc(NumberOfSample);
Inc(NumberOfSample);
for i := 1 to NumberOfSample-NumberOfSample0 do
begin
WriteBit(NumberOfBit, Bit);
Inc(NumberOfBit);
end;
Bit := 1 - Bit;
NumberOfSample0 := NumberOfSample;
end;
NumberOfSample0 := 0;
NumberOfSample := 1;
while NumberOfSample < nSamples do
begin
while not AudioData.Extremum(NumberOfSample, Channel) do
Inc(NumberOfSample);
AudioData.ReadSample(NumberOfSample, Channel, Sample);
Inc(NumberOfSample);
Write(Sample, nBytesPerSample);
NumberOfSample0 := NumberOfSample;
end;
end;
end;
constructor TEM1File.Open(FileName: String);
begin
inherited Open(FileName);
ReadString(EM1Label, 4);
Read(nChannels, 2);
Read(nSamplesPerSec, 4);
Read(nBytesPerSample, 2);
Read(nSamples, 4);
end;
procedure TEM1File.ReadAudioData(var AudioData: TAudioData);
var
Channel: Word;
NumberOfBit, NumberOfSample, NumberOfSample0, i: Cardinal;
Sample, Sample0, Sample1: Integer;
Bit: Byte;
Value, Mult: LongWord;
begin
AudioData.Data.Clear;
AudioData.nChannels := nChannels;
AudioData.nSamplesPerSec := nSamplesPerSec;
AudioData.nBitsPerSample := nBytesPerSample*8;
AudioData.Calculate_nBlockAlign;
Position := 16;
Mult := 1;
for i := 0 to nBytesPerSample-1 do Mult := Mult*256;
for Channel := 0 to nChannels-1 do
begin
NumberOfBit := Position*8;
for i := 0 to nSamples-1 do
begin
ReadBit(NumberOfBit, Bit);
if Bit = 0 then Sample := -32768 else Sample := 32767;
AudioData.WriteSample(i, Channel, Sample);
Inc(NumberOfBit);
end;
NumberOfSample0 := 0;
NumberOfSample := 0;
Sample0 := 0;
while NumberOfSample < nSamples do
begin
AudioData.ReadSample(NumberOfSample, Channel, Sample1);
Sample := Sample1;
while (Sample = Sample1)and(NumberOfSample < nSamples) do
begin
Inc(NumberOfSample);
if NumberOfSample < nSamples then
AudioData.ReadSample(NumberOfSample, Channel, Sample);
end;
Value := 0;
Read(Value, nBytesPerSample);
if Value >= Mult/2 then Sample := Value - Mult else Sample := Value;
for i := 0 to NumberOfSample-NumberOfSample0-1 do
begin
Sample1 := Sample0 + Round((Sample-Sample0)/2 - (Sample-Sample0)/2*Cos(i*Pi/(NumberOfSample-NumberOfSample0)));
AudioData.WriteSample(NumberOfSample0+i, Channel, Sample1);
end;
NumberOfSample0 := NumberOfSample;
Sample0 := Sample;
end;
end;
end;
end.
П. 1.5. ТЕКСТ МОДУЛЯ AUDIOFORMAT.PAS
unit AudioFormat;
interface
uses
SysUtils, FileUtils;
type
TAudioFile = class(TFile)
end;
type
TAudioData = class(TObject)
public
nChannels: Word;
nSamplesPerSec: LongWord;
nBitsPerSample: Word;
nBlockAlign: Word;
Data: TFile;
constructor Create;
destructor Destroy;
procedure Calculate_nBlockAlign;
procedure ReadSample(Number, Channel: LongInt; var Value: Integer);
procedure WriteSample(Number, Channel: LongInt; Value: Integer);
function Extremum(Number, Channel: LongInt): Boolean;
private
Name: String;
end;
procedure CopyAudio(var AudioSource, AudioGeter: TAudioData; Start, Finish: Cardinal);
procedure DeleteAudio(var AudioData: TAudioData; Start, Finish: Cardinal);
procedure InsertAudio(var AudioSource, AudioGeter: TAudioData; Start: Cardinal);
procedure OverwriteAudio(var AudioSource, AudioGeter: TAudioData; Start: Cardinal);
procedure MixAudio(var AudioSource, AudioGeter: TAudioData; Start: Cardinal);
procedure ReverseAudio(var AudioData: TAudioData; Start, Count: Cardinal);