Мегаобучалка Главная | О нас | Обратная связь


Дмитрий Малышев. Звук: немного теории.



2019-12-29 196 Обсуждений (0)
Дмитрий Малышев. Звук: немного теории. 0.00 из 5.00 0 оценок




http://www.websound.ru/articles/theory/sound-theory.htm (22.05.2006).

Дмитрий Шмунк. Восприятие и сжатие звука.

http://www.websound.ru/articles/theory/sound-theory.htm (22.05.2006).

Александр Радзишевский. Аналоговый блюз.

http://www.websound.ru/articles/theory/sound_user.htm (22.05.2006).

Александр Радзишевский, Александр Чижов. Цифровой звук – обо всем по-порядку.

http://www.websound.ru/articles/theory/sound-theory.htm (22.05.2006).

Евгений Музыченко. Принципы цифрового звука.

http://www.websound.ru/articles/theory/digsnd.htm (22.05.2006).

Дмитрий Михайлов. Параметры цифрового звука.

http://www.websound.ru/articles/theory/sound-theory.htm (22.05.2006).

Дмитрий Михайлов. Обработка звука – фильтры.

http://www.websound.ru/articles/theory/filter.htm (22.05.2006).

24. Максим Лядов. FAQ по звуку - свежий взгляд на звуковые вопросы и ответы.

http://www.ixbt.com/multimedia/sound-faq.shtml (22.05.2006).

Александр Радзишевский. Пространственное звучание (3D-звук).

http://www.websound.ru/articles/technol/3dsound.htm (22.05.2006).

Александр Радзишевский. Способы преобразования звука, звуковые эффекты.

http://www.websound.ru/articles/processing/effects.htm (22.05.2006).

Сергей Котов. Эффект реверберации - теория и практика.

http://www.ixbt.com/multimedia/theory-of-reverb.shtml (22.05.2006).

 

Дмитрий Шмунк. Восприятие и сжатие звука.

http://www.websound.ru/articles/theory/sound-theory.htm (22.05.2006).

Дмитрий Шмунк. Восприятие и сжатие звука.

http://www.websound.ru/articles/theory/sound-theory.htm (22.05.2006).

Дмитрий Шмунк. Восприятие и сжатие звука.

http://www.websound.ru/articles/theory/sound-theory.htm (22.05.2006).

31.Мандел Т. Разработка пользовательского интерфейса. ДМК Пресс, 2001.

32.Э. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссидес. Приемы объектно-ориентированного проектирования. Паттерны проектирования. – С-Пб.: Питер, 2001.

33.ГОСТ 19.505-79 ЕСПД. Руководство оператора. Требования к содержанию и оформлению. – М.: Издательство стандартов, 1979.

34.ГОСТ 19.504-79 ЕСПД. Руководство программиста. Требования к содержанию и оформлению. – М.: Издательство стандартов, 1979.

35.ГОСТ 19.701-90 ЕСПД. Схемы алгоритмов и программ. Правила выполнения. – М.: Издательство стандартов, 1991.

36.ГОСТ 12.0.002-80 ССБТ. Термины и определения. – М.: Издательство стандартов, 1980.

37.Соболева В.П. Методические указания по оформлению курсовых работ, курсовых и дипломных проектов. – Ижевск: Издательство ИМИ, 2003.

38.Почерняев С.В., Килин И.В. Методические указания по дипломному проектированию. – Ижевск: Издательство ИжГТУ, 1994.

39.Технико-экономическое обоснование дипломных проектов при разработке приборов и методов контроля качества. – Ижевск: Издательство ИжГТУ, 2001.


ПРИЛОЖЕНИЕ 1

ТЕКСТ ПРОГРАММЫ

 

П. 1.1. ТЕКСТ МОДУЛЯ MAIN.PAS

 

unit Main;

interface

uses

 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

 Dialogs, StdCtrls, Buttons, ExtCtrls, ComCtrls, Spin,

 MMSystem, ShellApi, FileUtils, AudioFormat,

 PCM_Format, MP3_Format, EM1_Format, Menus, Help, AudioForm, MP3Form, EffectsForm;

type

 TMainForm = class(TForm)

 OutDeviceComboBox: TComboBox;

 InDeviceComboBox: TComboBox;

 TrackBar: TTrackBar;

 PlayButton: TSpeedButton;

 PauseButton: TSpeedButton;

 RecordButton: TSpeedButton;

 OpenButton: TSpeedButton;

 SaveButton: TSpeedButton;

 TimePosition: TStaticText;

 PositionSpinEdit: TSpinEdit;

 OpenDialog: TOpenDialog;

 Marker1: TBitBtn;

 Marker2: TBitBtn;

 PageControl1: TPageControl;

 TabSheet1: TTabSheet;

 TabSheet2: TTabSheet;

 SetMarkerButton: TButton;

 DeleteMarkersButton: TButton;

 CopyButton: TBitBtn;

 CutButton: TBitBtn;

 ClearButton: TBitBtn;

 PasteButton: TBitBtn;

 PasteFileButton: TBitBtn;

 DeleteButton: TBitBtn;

 TabSheet3: TTabSheet;

 SetSpeedText: TStaticText;

 SetVolumeText: TStaticText;

 EffectButton: TButton;

 EffectBox: TComboBox;

 PaintBox1: TPaintBox;

 WaveOutButton: TSpeedButton;

 WaveInButton: TSpeedButton;

 PasteSilenceButton: TButton;

 CopyToFileButton: TBitBtn;

 UndoButton: TBitBtn;

 HelpButton: TBitBtn;

 SaveDialog: TSaveDialog;

 TabSheet9: TTabSheet;

 BrainWaveButton: TButton;

 BWFreqEdit1: TSpinEdit;

 StaticText15: TStaticText;

 BWFreqEdit2: TSpinEdit;

 StaticText16: TStaticText;

 SSelButton: TBitBtn;

 FSelButton: TBitBtn;

 StaticText4: TStaticText;

 UndoCheckBox: TCheckBox;

 EMailButton: TSpeedButton;

 Label1: TLabel;

 Label2: TLabel;

 Label3: TLabel;

 Label4: TLabel;

 BitBtn1: TBitBtn;

 BitBtn3: TBitBtn;

 BitBtn4: TBitBtn;

 BitBtn2: TBitBtn;

 BitBtn5: TBitBtn;

 BitBtn6: TBitBtn;

 BitBtn7: TBitBtn;

 BitBtn8: TBitBtn;

 BitBtn9: TBitBtn;

 BitBtn10: TBitBtn;

 Button1: TBitBtn;

 Button2: TBitBtn;

 Button6: TBitBtn;

 BitBtn13: TBitBtn;

 BitBtn14: TBitBtn;

 BitBtn15: TBitBtn;

 BitBtn16: TBitBtn;

 MainMenu1: TMainMenu;

 N1: TMenuItem;

 N2: TMenuItem;

 N3: TMenuItem;

 N4: TMenuItem;

 N11: TMenuItem;

 N12: TMenuItem;

 N13: TMenuItem;

 N14: TMenuItem;

 N15: TMenuItem;

 N31: TMenuItem;

 N30: TMenuItem;

 N16: TMenuItem;

 N17: TMenuItem;

 N18: TMenuItem;

 N19: TMenuItem;

 N24: TMenuItem;

 N20: TMenuItem;

 N21: TMenuItem;

 N22: TMenuItem;

 N23: TMenuItem;

 N25: TMenuItem;

 N26: TMenuItem;

 N27: TMenuItem;

 N28: TMenuItem;

 N29: TMenuItem;

 N32: TMenuItem;

 N33: TMenuItem;

 N34: TMenuItem;

 N35: TMenuItem;

 N36: TMenuItem;

 N37: TMenuItem;

 N38: TMenuItem;

 N39: TMenuItem;

 N40: TMenuItem;

 N41: TMenuItem;

 N8: TMenuItem;

 N9: TMenuItem;

 N10: TMenuItem;

 N5: TMenuItem;

 N6: TMenuItem;

 N7: TMenuItem;

 N42: TMenuItem;

 SilenceTime: TSpinEdit;

 Memo1: TMemo;

 PasteModeComboBox: TComboBox;

 PasteModeText: TStaticText;

 Left10Button: TButton;

 StaticText17: TStaticText;

 Right10Button: TButton;

 SpeedEdit: TSpinEdit;

 VolumeEdit: TSpinEdit;

 ChangeVolumeBitBtn: TBitBtn;

 ChangeSpeedButton: TBitBtn;

 SetSpeedBitBtn: TBitBtn;

 SetVolumeBitBtn: TBitBtn;

 ReverseButton: TBitBtn;

 NormalizeBitBtn: TBitBtn;

 PageControl2: TPageControl;

 TabSheet4: TTabSheet;

 Label5: TLabel;

 Label6: TLabel;

 Label7: TLabel;

 nSamplesPerSecText: TStaticText;

 nSamplesPerSecButton: TButton;

 nSamplesBox: TComboBox;

 nBitsBox: TComboBox;

 nBitsPerSampleButton: TButton;

 nBitsPerSampleText: TStaticText;

 nChannelsText: TStaticText;

 nChannelsButton: TButton;

 nChannelsBox: TComboBox;

 TabSheet5: TTabSheet;

 ConstantBitrateComboBox: TComboBox;

 StaticText1: TStaticText;

 RadioButton1: TRadioButton;

 RadioButton2: TRadioButton;

 RadioButton3: TRadioButton;

 AverageBitrateComboBox: TComboBox;

 VariableBitRateComboBox: TComboBox;

 StaticText2: TStaticText;

 StaticText3: TStaticText;

 StereoModeComboBox: TComboBox;

 TabSheet6: TTabSheet;

 PageControl3: TPageControl;

 TabSheet7: TTabSheet;

 StaticText5: TStaticText;

 nResponsesEdit: TSpinEdit;

 ResponseTimeEdit: TSpinEdit;

 ResponseVolumeEdit: TSpinEdit;

 StaticText6: TStaticText;

 StaticText7: TStaticText;

 StaticText8: TStaticText;

 StaticText9: TStaticText;

 TabSheet8: TTabSheet;

 nEchosEdit: TSpinEdit;

 DelayEdit: TSpinEdit;

 EchoVolumeEdit: TSpinEdit;

 StaticText10: TStaticText;

 StaticText11: TStaticText;

 StaticText12: TStaticText;

 StaticText13: TStaticText;

 StaticText14: TStaticText;

 N43: TMenuItem;

 MP31: TMenuItem;

 N44: TMenuItem;

 ButtonZoomIn: TBitBtn;

 ButtonZoomOut: TBitBtn;

 AudioOptionsButton: TBitBtn;

 MP3OptionsButton: TBitBtn;

 EffOptionsButton: TBitBtn;

 procedure FormCreate(Sender: TObject);

 procedure OpenButtonClick(Sender: TObject);

 procedure FormClose(Sender: TObject; var Action: TCloseAction);

 procedure PlayButtonClick(Sender: TObject);

 procedure PauseButtonClick(Sender: TObject);

 procedure RecordButtonClick(Sender: TObject);

 procedure TrackBarChange(Sender: TObject);

 procedure PositionSpinEditChange(Sender: TObject);

 procedure SaveButtonClick(Sender: TObject);

 procedure SetMarkerButtonClick(Sender: TObject);

 procedure DeleteMarkersButtonClick(Sender: TObject);

 procedure CopyButtonClick(Sender: TObject);

 procedure CutButtonClick(Sender: TObject);

 procedure ClearButtonClick(Sender: TObject);

 procedure PasteButtonClick(Sender: TObject);

 procedure ReverseButtonClick(Sender: TObject);

 procedure SetSpeedButtonClick(Sender: TObject);

 procedure ChangePropertie(Sender: TObject);

 procedure AboutButtonClick(Sender: TObject);

 procedure HomePageLinkClick(Sender: TObject);

 procedure SetVolumeButtonClick(Sender: TObject);

 procedure DeleteButtonClick(Sender: TObject);

 procedure NormalizeButtonClick(Sender: TObject);

 procedure PasteSilenceButtonClick(Sender: TObject);

 procedure SetSpeedBitBtnClick(Sender: TObject);

 procedure ChangeSpeedButtonClick(Sender: TObject);

 procedure SetVolumeBitBtnClick(Sender: TObject);

 procedure ChangeVolumeBitBtnClick(Sender: TObject);

 procedure NormalizeBitBtnClick(Sender: TObject);

 procedure EffectButtonClick(Sender: TObject);

 procedure PaintBox1Paint(Sender: TObject);

 procedure WaveOutButtonClick(Sender: TObject);

 procedure WaveInButtonClick(Sender: TObject);

 procedure CopyToFileButtonClick(Sender: TObject);

 procedure UndoButtonClick(Sender: TObject);

 procedure EMailButtonClick(Sender: TObject);

 procedure BrainWaveButtonClick(Sender: TObject);

 procedure Left10ButtonClick(Sender: TObject);

 procedure SSelButtonClick(Sender: TObject);

 procedure HelpButtonClick(Sender: TObject);

 procedure UndoCheckBoxClick(Sender: TObject);

 procedure N4Click(Sender: TObject);

 procedure N43Click(Sender: TObject);

 procedure MP31Click(Sender: TObject);

 procedure N44Click(Sender: TObject);

 procedure ButtonZoomInClick(Sender: TObject);

 procedure ButtonZoomOutClick(Sender: TObject);

 procedure AudioOptionsButtonClick(Sender: TObject);

 procedure MP3OptionsButtonClick(Sender: TObject);

 procedure EffOptionsButtonClick(Sender: TObject);

 private

 { Private declarations }

 public

 procedure SetAudioPosition;

 procedure SetMarker;

 procedure DeleteMarkers;

 procedure PaintAudioGraph;

 procedure SaveUndoInfo;

 end;

type

 TPlayThread = class(TThread)

 public

 WaveOut: HWaveOut;

 procedure Execute; override;

 end;

 TRecordThread = class(TThread)

 public

 WaveIn: HWaveIn;

 procedure Execute; override;

 end;

var

 MainForm: TMainForm;

 SamplesPerPoint: Cardinal;

 Status: String;

 AudioPosition: Cardinal;

 AudioData: TAudioData;

 AudioClipBoard: TAudioData;

 PlayThread: TPlayThread;

 RecordThread: TRecordThread;

 Selection: record

 Start: Cardinal;

 Finish: Cardinal;

 StartExists: Boolean;

 FinishExists: Boolean;

 end;

 UndoInfo: record

 Selection: record

 Start: Cardinal;

 Finish: Cardinal;

 StartExists: Boolean;

 FinishExists: Boolean;

 end;

 AudioPosition: Cardinal;

 AudioData: TAudioData;

 end;

implementation

{$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

 begin

 nChannels := 2;

 nBitsPerSample := 16;

 nSamplesPerSec := 44100;

 Calculate_nBlockAlign;

 end;

 AudioPosition := 0;

 if WaveOutGetNumDevs<>0 then

 begin

 for i := 0 to WaveOutGetNumDevs-1 do

 begin

 WaveOutGetDevCaps(i, @WaveOutCaps, SizeOf(TWaveOutCaps));

 OutDeviceComboBox.Items.Add(PChar(@WaveOutCaps.szPname));

 end;

 OutDeviceComboBox.ItemIndex := 0;

 end;

 if WaveInGetNumDevs<>0 then

 begin

 for i := 0 to WaveInGetNumDevs-1 do

 begin

 WaveInGetDevCaps(i, @WaveInCaps, SizeOf(TWaveInCaps));

 InDeviceComboBox.Items.Add(PChar(@WaveInCaps.szPname));

 end;

 InDeviceComboBox.ItemIndex := 0;

 end;

 AudioData.Calculate_nBlockAlign;

 UndoInfo.AudioData := TAudioData.Create;

 Status := 'starting';

end;

 

procedure TMainForm.SetAudioPosition;

var

 AudioSize, Long: Cardinal;

 S, S2: String;

begin

 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

 begin

 Value := AudioPosition;

 MinValue := 0;

 MaxValue := AudioSize;

 end;

 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';

 S2 := S2 + S +':';

 Str(Long, S);

 if Length(S)=1 then S2 := S2 + '0';

 S2 := S2 + S +' / ';

 Long := Trunc(AudioSize/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';

 S2 := S2 + S +':';

 Str(Long, S);

 if Length(S)=1 then S2 := S2 + '0';

 S2 := S2 + S + ' ';

 if TimePosition.Caption<>S2 then TimePosition.Caption := S2;

 {PaintBox1.Repaint;}

 PaintAudioGraph;

end;

procedure TMainForm.SetMarker;

var

 AudioSize: Cardinal;

begin

 if (Status = 'starting') then Exit;

 with AudioData do AudioSize := Data.Size div nBlockAlign;

 with Selection do

 begin

 if (AudioPosition=Start)and(StartExists) or (AudioPosition=Finish)and(FinishExists) then Exit;

 if not StartExists then

 begin

 Start := AudioPosition;

 StartExists := True;

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

 Marker1.Visible := True;

 Exit;

 end;

 if (StartExists) and (not FinishExists) then

 begin

 if AudioPosition>Start then

 Finish := AudioPosition

 else

 begin

 Finish := Start;

 Start := AudioPosition;

 end;

 FinishExists := True;

 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;

 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

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

 Status := 'editing';

 SaveUndoInfo;

 TempAudio := TAudioData.Create;

 TempAudio.nChannels := AudioData.nChannels;

 TempAudio.nSamplesPerSec := AudioData.nSamplesPerSec;

 TempAudio.nBitsPerSample := AudioData.nBitsPerSample;

 TempAudio.Calculate_nBlockAlign;

 b := 0;

 for i := 1 to TempAudio.nSamplesPerSec*SilenceTime.Value*TempAudio.nBlockAlign do

 TempAudio.Data.Write(b, 1);

 InsertAudio(TempAudio, AudioData, AudioPosition);

 DeleteMarkers;

 SetAudioPosition;

 SetMarker;

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

 SetAudioPosition;

 SetMarker;

 TempAudio.Destroy;

 Status := 'waiting';

end;

procedure TMainForm.ReverseButtonClick(Sender: TObject);

var

 AudioSize: Cardinal;

begin

 if Status<>'waiting' then Exit;

 Status := 'deformation';

 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;

 ReverseAudio(AudioData, Start, Finish-Start+1);

 end;

 Status := 'waiting';

end;

procedure TMainForm.NormalizeButtonClick(Sender: TObject);

var

 AudioSize: Cardinal;

begin

 if Status<>'waiting' then Exit;

 Status := 'deformation';

 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;

 Normalize(AudioData, Start, Finish-Start+1);

 end;

 Status := 'waiting';

 PaintBox1.Repaint;

end;

procedure TMainForm.SetSpeedButtonClick(Sender: TObject);

var

 AudioSize: Cardinal;

begin

 if Status<>'waiting' then Exit;

 Status := 'deformation';

 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;

 SetSpeedOfAudio(AudioData, Start, Finish-Start+1, SpeedEdit.Value/100);

 DeleteMarkers;

 AudioPosition := Start;

 SetMarker;

 AudioPosition := Trunc(Start+(Finish-Start)*100/SpeedEdit.Value);

 SetMarker;

 AudioPosition := Start;

 SetAudioPosition;

 end;

 Status := 'waiting';

end;

procedure TMainForm.ChangePropertie(Sender: TObject);

var

 S: String;

 Value, Code: Cardinal;

begin

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

 Status := 'editing';

 if Sender = AudioOptionsForm.nSamplesPerSecButton then

 begin

 Val(AudioOptionsForm.nSamplesBox.Text, Value, Code);

 SetnSamplesPerSec(AudioData, Value);

 end;

 if Sender = AudioOptionsForm.nBitsPerSampleButton then

 begin

 Val(AudioOptionsForm.nBitsBox.Text, Value, Code);

 SetnBitsPerSample(AudioData, Value);

 end;

 if Sender = AudioOptionsForm.nChannelsButton then

 begin

 SetnChannels(AudioData, AudioOptionsForm.nChannelsBox.ItemIndex+1);

 end;

 AudioData.Calculate_nBlockAlign;

 DeleteMarkers;

 AudioPosition := 0;

 SetAudioPosition;

 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';

 Status := 'waiting';

end;

procedure TMainForm.SetVolumeButtonClick(Sender: TObject);

var

 AudioSize: Cardinal;

begin

 if Status<>'waiting' then Exit;

 Status := 'deformation';

 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;

 SetVolumeOfAudio(AudioData, Start, Finish-Start+1, VolumeEdit.Value/100);

 end;

 Status := 'waiting';

end;

procedure TMainForm.AboutButtonClick(Sender: TObject);

begin

 MessageBox(MainForm.Handle, 'AudioEditor v02.2006'#13#13'Выполнил Суханов М.А.'#13#13'ИжГТУ, 2006'#13#13'[email protected]', 'О программе', MB_OK);

end;

procedure TMainForm.HomePageLinkClick(Sender: TObject);

begin

 ShellExecute(Handle, 'open', PChar('http://Andrei512.narod.ru'), '', '', SW_Show);

end;

procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);

begin

 AudioData.Destroy;

 AudioClipBoard.Destroy;

 UndoInfo.AudioData.Destroy;

end;

procedure TMainForm.SetSpeedBitBtnClick(Sender: TObject);

var

 AudioSize: Cardinal;

begin

 if Status<>'waiting' then Exit;

 Status := 'deformation';

 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;

 SetSpeedOfAudio(AudioData, Start, Finish-Start+1, SpeedEdit.Value/100);

 DeleteMarkers;

 AudioPosition := Start;

 SetMarker;

 AudioPosition := Trunc(Start+(Finish-Start)*100/SpeedEdit.Value);

 SetMarker;

 AudioPosition := Start;

 SetAudioPosition;

 end;

 Status := 'waiting';

end;

procedure TMainForm.ChangeSpeedButtonClick(Sender: TObject);

var

 AudioSize, NewCount: Cardinal;

begin

 if Status<>'waiting' then Exit;

 Status := 'deformation';

 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;

 NewCount := ChangeSpeedOfAudio(AudioData, Start, Finish-Start+1, SpeedEdit.Value/100);

 DeleteMarkers;

 AudioPosition := Start;

 SetMarker;

 AudioPosition := Start+NewCount;

 SetMarker;

 AudioPosition := Start;

 SetAudioPosition;

 end;

 Status := 'waiting';

end;

procedure TMainForm.SetVolumeBitBtnClick(Sender: TObject);

var

 AudioSize: Cardinal;

begin

 if Status<>'waiting' then Exit;

 Status := 'deformation';

 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;

 SetVolumeOfAudio(AudioData, Start, Finish-Start+1, VolumeEdit.Value/100);

 end;

 Status := 'waiting';

 PaintBox1.Repaint;

end;

procedure TMainForm.ChangeVolumeBitBtnClick(Sender: TObject);

var

 AudioSize: Cardinal;

begin

 if Status<>'waiting' then Exit;

 Status := 'deformation';

 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;

 ChangeVolumeOfAudio(AudioData, Start, Finish-Start+1, VolumeEdit.Value/100);

 end;

 Status := 'waiting';

 PaintBox1.Repaint;

end;

procedure TMainForm.NormalizeBitBtnClick(Sender: TObject);

var

 AudioSize: Cardinal;

begin

 if Status<>'waiting' then Exit;

 Status := 'deformation';

 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;

 Normalize(AudioData, Start, Finish-Start+1);

 end;

 Status := 'waiting';

end;

procedure TMainForm.EffectButtonClick(Sender: TObject);

var

 AudioSize: Cardinal;

begin

 if Status<>'waiting' then Exit;

 Status := 'deformation';

 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;

 if Sender = BitBtn13 then Echo(AudioData, Start, Finish-Start+1, EffOptionsForm.nResponsesEdit.Value, EffOptionsForm.ResponseTimeEdit.Value, EffOptionsForm.ResponseVolumeEdit.Value/100);

 if Sender = BitBtn14 then Reverberation(AudioData, Start, Finish-Start+1, EffOptionsForm.nEchosEdit.Value, EffOptionsForm.DelayEdit.Value, EffOptionsForm.EchoVolumeEdit.Value/100);

 if Sender = BitBtn15 then ChangeVolumeOfAudio(AudioData, Start, Finish-Start+1, 0);

 if Sender = BitBtn16 then ReChangeVolumeOfAudio(AudioData, Start, Finish-Start+1, 1);

 {case EffectBox.ItemIndex of

 0: ChangeVolumeOfAudio(AudioData, Start, Finish-Start+1, 0);

 1: ReChangeVolumeOfAudio(AudioData, Start, Finish-Start+1, 1);

 2: Echo(AudioData, Start, Finish-Start+1, nResponsesEdit.Value, ResponseTimeEdit.Value, ResponseVolumeEdit.Value/100);

 3: Reverberation(AudioData, Start, Finish-Start+1, nEchosEdit.Value, DelayEdit.Value, EchoVolumeEdit.Value/100);

 end;}

 end;

 Status := 'waiting';

 PaintBox1.Repaint;

end;

procedure TMainForm.PaintAudioGraph;

var

 PaintPos, MaxPaintPos: Cardinal;

 AudioPos, {SamplesPerPoint,} LeftSamples, MaxAmplitude: Cardinal;

 numChannels, Channel, i: Word;

 Smp, Smp1: Integer;

begin

 with PaintBox1.Canvas do

 begin

 Pen.Color := clBlack;

 MoveTo(Round(PaintBox1.Width/2),0);

 LineTo(Round(PaintBox1.Width/2), Round(PaintBox1.Height));

 MoveTo(0, Round(PaintBox1.Height/2));

 LineTo(PaintBox1.Width, Round(PaintBox1.Height/2));

 Pen.Color := clGreen;

 end;

 MaxPaintPos := PaintBox1.Width;

 if AudioPosition-PaintBox1.Width*SamplesPerPoint >= 0 then

 begin

 AudioPos := AudioPosition-PaintBox1.Width*SamplesPerPoint;

 PaintPos := 0;

 end

 else

 begin

 AudioPos := 0;

 PaintPos := PaintBox1.Width - Trunc(AudioPosition/SamplesPerPoint);

 end;

 numChannels := AudioData.nChannels;

 MaxAmplitude := 1;

 for i := 1 to AudioData.nBitsPerSample do

 MaxAmplitude := MaxAmplitude*2;

 Smp := 0;

 for Channel := 0 to numChannels-1 do

 begin

 AudioData.ReadSample(AudioPos, Channel, Smp1);

 Smp := Smp + Smp1;

 end;

 Smp := Round(Smp/numChannels);

 PaintBox1.Canvas.MoveTo(PaintPos-Round(PaintBox1.Width/2), Round(PaintBox1.Height/2-Smp/MaxAmplitude*PaintBox1.Height));

 LeftSamples := SamplesPerPoint;

 while PaintPos<=(MaxPaintPos+Round(PaintBox1.Width/2)) do

 begin

 Smp := 0;

 for Channel := 0 to numChannels-1 do

 begin

 AudioData.ReadSample(AudioPos, Channel, Smp1);

 Smp := Smp + Smp1;

 end;

 if (Selection.StartExists)and(Selection.FinishExists)and

 (AudioPos>Selection.Start)and(AudioPos<Selection.Finish)

 then PaintBox1.Canvas.Pen.Color := clRed

 else PaintBox1.Canvas.Pen.Color := clGreen;

 Smp := Round(Smp/numChannels);

 PaintBox1.Canvas.LineTo(PaintPos-Round(PaintBox1.Width/2), Round(PaintBox1.Height/2-Smp/MaxAmplitude*PaintBox1.Height));

 Inc(AudioPos);

 Dec(LeftSamples);

 if LeftSamples = 0 then

 begin

 Inc(PaintPos);

 LeftSamples := SamplesPerPoint;

 end;

 end;

end;

procedure TMainForm.PaintBox1Paint(Sender: TObject);

begin

 PaintAudioGraph;

end;

procedure TMainForm.WaveOutButtonClick(Sender: TObject);

begin

 ShellExecute(Handle, 'open', PChar('sndvol32.exe'), '', '', SW_Show);

end;

procedure TMainForm.WaveInButtonClick(Sender: TObject);

begin

 ShellExecute(Handle, 'open', PChar('sndvol32.exe'), PChar('/r'), '', SW_Show);

end;

procedure TMainForm.CopyToFileButtonClick(Sender: TObject);

var

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

 i: Byte;

 TempAudio: TAudioData;

 Code: Integer;

 PCM: TPCMFile;

 MP3: TMP3File;

 EM1: TEM1File;

 AudioSize: Cardinal;

begin

 if Status<>'waiting' then Exit;

 if SaveDialog.Execute then

 FileName := SaveDialog.FileName else Exit;

 Ext := ExtractFileExt(FileName);

 with AudioData do

 AudioSize := Data.Size div nBlockAlign;

 TempAudio := TAudioData.Create;

 with Selection do

 begin

 if not StartExists or not FinishExists then

 begin

 DeleteMarkers;

 Start := 0;

 Finish := AudioSize-1;

 end;

 CopyAudio(AudioData, TempAudio, Start, Finish);

 end;

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

 if Ext = '.WAV' then

 begin

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

 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, TempAudio, BitRate, EncMode, StereoMode);

 MP3.Destroy;

 end;

 if Ext = '.EM1' then

 begin

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

 EM1.Destroy;

 end;

 TempAudio.Destroy;

end;

procedure TMainForm.SaveUndoInfo;

begin

 if not UndoCheckBox.Checked then Exit;

 UndoInfo.AudioPosition := AudioPosition;

 UndoInfo.Selection.Start := Selection.Start;

 UndoInfo.Selection.Finish := Selection.Finish;

 UndoInfo.Selection.StartExists := Selection.StartExists;

 UndoInfo.Selection.FinishExists := Selection.FinishExists;

 UndoInfo.AudioData.Data.Clear;

 CopyAudio(AudioData, UndoInfo.AudioData, 0, AudioData.Data.Size div AudioData.nBlockAlign - 1);

end;

procedure TMainForm.UndoButtonClick(Sender: TObject);

begin

 if Status<>'waiting' then Exit;

 if UndoInfo.AudioData.Data.Size = 0 then Exit;

 Status := 'undo';

 DeleteMarkers;

 AudioData.Data.Clear;

 CopyAudio(UndoInfo.AudioData, AudioData, 0, UndoInfo.AudioData.Data.Size div UndoInfo.AudioData.nBlockAlign - 1);

 if UndoInfo.Selection.StartExists then

 begin

 AudioPosition := UndoInfo.Selection.Start;

 SetMarker;

 end;

 if UndoInfo.Selection.FinishExists then

 begin

 AudioPosition := UndoInfo.Selection.Finish;

 SetMarker;

 end;

 AudioPosition := UndoInfo.AudioPosition;

 SetAudioPosition;

 UndoInfo.AudioData.Data.Clear;

 Status := 'waiting';

end;

procedure TMainForm.EMailButtonClick(Sender: TObject);

begin

 ShellExecute(Handle, 'open', PChar('mailto:[email protected]'), PChar(''), '', SW_Show);

end;

procedure TMainForm.BrainWaveButtonClick(Sender: TObject);

var

 AudioSize: Cardinal;

begin

 if Status<>'waiting' then Exit;

 Status := 'deformation';

 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;

 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



2019-12-29 196 Обсуждений (0)
Дмитрий Малышев. Звук: немного теории. 0.00 из 5.00 0 оценок









Обсуждение в статье: Дмитрий Малышев. Звук: немного теории.

Обсуждений еще не было, будьте первым... ↓↓↓

Отправить сообщение

Популярное:



©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (196)

Почему 1285321 студент выбрали МегаОбучалку...

Система поиска информации

Мобильная версия сайта

Удобная навигация

Нет шокирующей рекламы



(0.009 сек.)