Class TForm1 (unit DTSweep)

Inherits from

TForm

Constructors



Functions

procedure btnExitClick(Sender: TObject);

return allocated memory

procedure btnStartClick(Sender: TObject);

inform user of failure translate the most common error into English!

procedure btnStartKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);


procedure chkLeftClick(Sender: TObject);

on both channels

procedure chkLockFrequenciesClick(Sender: TObject);

handle a click on either output enable check boxes

procedure edtF1Change(Sender: TObject);


procedure edtF2Change(Sender: TObject);


procedure Exit1Click(Sender: TObject);


procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);

point to next left sample

procedure FormCreate(Sender: TObject);


procedure FormDestroy(Sender: TObject);

get a valid value for the amplitudes

procedure grpChannelsClick(Sender: TObject);


procedure grpFrequencyRangeClick(Sender: TObject);

same as the left trackbar

procedure grpSweepModeClick(Sender: TObject);

and for the right channel

procedure grpSweepSpeedClick(Sender: TObject);

The sweep parameters have changed, so restart any sweep in progress

procedure SaveAs1Click(Sender: TObject);

finished reading the MMIO wave file

procedure Timer1Timer(Sender: TObject);

1 second delay

procedure tkbLeftFrequencyChange(Sender: TObject);

Page Down key

procedure tkbLeftLevelChange(Sender: TObject);


procedure tkbRightFrequencyChange(Sender: TObject);

record the right freq

procedure tkbRightLevelChange(Sender: TObject);

update as required

procedure build_left_sine_table;

Assume 16-bit audio goes from -32767.

procedure build_right_sine_table;

fill left channel sine table

nothing to do


procedure build_sine_table (magnitude: extended; table: PSineTable);

populate a sine table for the present amplitude

and this for half-octave markers


function fill_buffer (h: HMMIO): integer;

procedure just to fill a buffer - independent of mode

is a sweep running? if so, stop it


procedure fill_buffer_with_sinewave ( sine_table: PSineTable; bfr: pBuffer; f: extended; var angle: integer; index, samples: integer);

copies from sine table into buffer, offset if right channel sine table

nothing to do invert the sinewave by negating the amplitude


function fill_pink_noise_bfr (bfr: PBuffer): integer;

point to next left sample

function fill_single_sweep_bfr (bfr: PBuffer; num_freqs: integer): integer;

wrap to 360 degrees

function fill_white_noise_bfr (bfr: PBuffer): integer;

compute next frequency according to the sweep mode

function get_octave (f: extended): integer;

fill right channel sine table

restore the output channels options group


procedure level_changed;


procedure mm_wom_Close (var Msg: TMessage);

and write the next buffer, re-using the one just played

procedure mm_wom_Done (var Msg: TMessage);

and make the right channel the same frequency

procedure mm_wom_Open (var Msg: TMessage);

call-backs from waveform out functions

actual buffer sizes


function read_pink_noise_file (const filename: string): boolean;


procedure restart_sweep;

record the new frequency range in the Edit boxes and trackbar labels

procedure start_sweep;

Is a sweep running? If so, stop it

procedure stop_sweep;


procedure write_next_buffer (header: PWaveHdr);

now write the first two buffers into the wave output this will result in two mm_wom_done messages

Properties

Events

Variables

btnExit : TButton;


btnStart : TButton;


chkLeft : TCheckBox;


chkLockFrequencies : TCheckBox;


chkOctaveMarker : TCheckBox;


chkRight : TCheckBox;


edtF1 : TEdit;


edtF2 : TEdit;


Exit1 : TMenuItem;


File1 : TMenuItem;


GroupBox1 : TGroupBox;


grpChannels : TRadioGroup;


grpFrequencyRange : TRadioGroup;


grpOctaveMarkers : TGroupBox;


grpSetFrequency : TGroupBox;


grpSweepMode : TRadioGroup;


grpSweepSpeed : TRadioGroup;


Label1 : TLabel;


Label2 : TLabel;


Label3 : TLabel;


lblFLeft : TLabel;


lblFMaxL : TLabel;


lblFMaxR : TLabel;


lblFMinL : TLabel;


lblFMinR : TLabel;


lblFnow : TLabel;


lblFRight : TLabel;


lblLastMarker : TLabel;


lblLeftLevel : TLabel;


lblRightLevel : TLabel;


LED1 : TLED;


MainMenu1 : TMainMenu;


N2 : TMenuItem;


Panel1 : TPanel;


Panel2 : TPanel;


SaveAs1 : TMenuItem;


SaveDialog1 : TSaveDialog;


Timer1 : TTimer;


tkbLeftFrequency : TTrackBar;


tkbLeftLevel : TTrackBar;


tkbRightFrequency : TTrackBar;


tkbRightLevel : TTrackBar;


all_written : boolean;

for tracking the slow sweep

buffers_played : integer;


buffers_written : integer;

limits of sweep range

buffer_bytes : integer;


chunk_freq : ^out_freqs;

true for same freq in left and right

chunk_ms : integer;

the number of chunks in the buffer

closed : boolean;


closing : boolean;


current_octave : integer;

for manual sweep mode

direction : (up, down, holding);


do_markers : boolean;


fl : extended;

so we know when to stop the sweep

fr : extended;


f_inv_ratio : extended;


f_max : integer;


f_min : integer;

max number of bytes in each output buffer

f_ratio : extended;

current left and right frequencies

f_step : extended;


hBuffer1 : HGlobal;


hBuffer2 : HGlobal;

output buffer handles

hWave_hdr1 : HGlobal;

pre-stored pink noise

hWave_hdr2 : HGlobal;

wave header handles

hWave_out : HWaveOut;

true if makers (balnks) are required

last_f : extended;


left_amplitude : extended;

duration of each chunk in milliseconds

left_angle : integer;

Private declarations

left_sine_table : PSineTable;

current sine wave angles

left_sine_table_valid : boolean;

pre-stored sine-wave values

locked_frequencies : boolean;

in-phase, out-of-phase or independent

log_lin : modes;


next_octave : integer;

to know whether to add a marker

out_level : out_levels;


pcm : TWaveFormatEx;

handle to wave out device

pink_noise_buffer : PMonoBuffer;

table-valid flags

present_left_amplitude : extended;


present_right_amplitude : extended;

to tell if the amplitude has changed

p_buffer1 : PBuffer;


p_buffer2 : PBuffer;

output buffer pointers

p_wave_hdr1 : PWaveHdr;


p_wave_hdr2 : PWaveHdr;

wave header pointers

range : ranges;


right_amplitude : extended;

1.

right_angle : integer;


right_sine_table : PSineTable;


right_sine_table_valid : boolean;


shutoff : boolean;


slow_sweep_chunks : integer;

duration of slow sweep (milliseconds

slow_sweep_time : integer;


speed : speeds;


sweep_running : boolean;

wave format descriptor


Constructors


Functions


procedure btnExitClick(Sender: TObject);

return allocated memory


procedure btnStartClick(Sender: TObject);

inform user of failure translate the most common error into English!


procedure btnStartKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);


procedure chkLeftClick(Sender: TObject);

on both channels


procedure chkLockFrequenciesClick(Sender: TObject);

handle a click on either output enable check boxes


procedure edtF1Change(Sender: TObject);


procedure edtF2Change(Sender: TObject);


procedure Exit1Click(Sender: TObject);


procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);

point to next left sample


procedure FormCreate(Sender: TObject);


procedure FormDestroy(Sender: TObject);

get a valid value for the amplitudes


procedure grpChannelsClick(Sender: TObject);


procedure grpFrequencyRangeClick(Sender: TObject);

same as the left trackbar


procedure grpSweepModeClick(Sender: TObject);

and for the right channel


procedure grpSweepSpeedClick(Sender: TObject);

The sweep parameters have changed, so restart any sweep in progress


procedure SaveAs1Click(Sender: TObject);

finished reading the MMIO wave file


procedure Timer1Timer(Sender: TObject);

1 second delay


procedure tkbLeftFrequencyChange(Sender: TObject);

Page Down key


procedure tkbLeftLevelChange(Sender: TObject);


procedure tkbRightFrequencyChange(Sender: TObject);

record the right freq


procedure tkbRightLevelChange(Sender: TObject);

update as required


procedure build_left_sine_table;

Assume 16-bit audio goes from -32767..32767, avoids clipping. There are only 2^15 samples here, this simplfies the subsequent angle calculation but might restrict the dynamic range produced with noise sidebands. However, in the quality of equipment likely to be encountered this won't matter. You've got the source code, so you can alter this if you like.


procedure build_right_sine_table;

fill left channel sine table

nothing to do


procedure build_sine_table (magnitude: extended; table: PSineTable);

populate a sine table for the present amplitude

and this for half-octave markers


function fill_buffer (h: HMMIO): integer;

procedure just to fill a buffer - independent of mode

is a sweep running? if so, stop it


procedure fill_buffer_with_sinewave ( sine_table: PSineTable; bfr: pBuffer; f: extended; var angle: integer; index, samples: integer);

copies from sine table into buffer, offset if right channel sine table

nothing to do invert the sinewave by negating the amplitude


function fill_pink_noise_bfr (bfr: PBuffer): integer;

point to next left sample


function fill_single_sweep_bfr (bfr: PBuffer; num_freqs: integer): integer;

wrap to 360 degrees


function fill_white_noise_bfr (bfr: PBuffer): integer;

compute next frequency according to the sweep mode


function get_octave (f: extended): integer;

fill right channel sine table

restore the output channels options group


procedure level_changed;


procedure mm_wom_Close (var Msg: TMessage);

and write the next buffer, re-using the one just played


procedure mm_wom_Done (var Msg: TMessage);

and make the right channel the same frequency


procedure mm_wom_Open (var Msg: TMessage);

call-backs from waveform out functions

actual buffer sizes


function read_pink_noise_file (const filename: string): boolean;


procedure restart_sweep;

record the new frequency range in the Edit boxes and trackbar labels


procedure start_sweep;

Is a sweep running? If so, stop it


procedure stop_sweep;


procedure write_next_buffer (header: PWaveHdr);

now write the first two buffers into the wave output this will result in two mm_wom_done messages


Properties


Events


Variables


btnExit : TButton;


btnStart : TButton;


chkLeft : TCheckBox;


chkLockFrequencies : TCheckBox;


chkOctaveMarker : TCheckBox;


chkRight : TCheckBox;


edtF1 : TEdit;


edtF2 : TEdit;


Exit1 : TMenuItem;


File1 : TMenuItem;


GroupBox1 : TGroupBox;


grpChannels : TRadioGroup;


grpFrequencyRange : TRadioGroup;


grpOctaveMarkers : TGroupBox;


grpSetFrequency : TGroupBox;


grpSweepMode : TRadioGroup;


grpSweepSpeed : TRadioGroup;


Label1 : TLabel;


Label2 : TLabel;


Label3 : TLabel;


lblFLeft : TLabel;


lblFMaxL : TLabel;


lblFMaxR : TLabel;


lblFMinL : TLabel;


lblFMinR : TLabel;


lblFnow : TLabel;


lblFRight : TLabel;


lblLastMarker : TLabel;


lblLeftLevel : TLabel;


lblRightLevel : TLabel;


LED1 : TLED;


MainMenu1 : TMainMenu;


N2 : TMenuItem;


Panel1 : TPanel;


Panel2 : TPanel;


SaveAs1 : TMenuItem;


SaveDialog1 : TSaveDialog;


Timer1 : TTimer;


tkbLeftFrequency : TTrackBar;


tkbLeftLevel : TTrackBar;


tkbRightFrequency : TTrackBar;


tkbRightLevel : TTrackBar;


all_written : boolean;

for tracking the slow sweep


buffers_played : integer;


buffers_written : integer;

limits of sweep range


buffer_bytes : integer;


chunk_freq : ^out_freqs;

true for same freq in left and right


chunk_ms : integer;

the number of chunks in the buffer


closed : boolean;


closing : boolean;


current_octave : integer;

for manual sweep mode


direction : (up, down, holding);


do_markers : boolean;


fl : extended;

so we know when to stop the sweep


fr : extended;


f_inv_ratio : extended;


f_max : integer;


f_min : integer;

max number of bytes in each output buffer


f_ratio : extended;

current left and right frequencies


f_step : extended;


hBuffer1 : HGlobal;


hBuffer2 : HGlobal;

output buffer handles


hWave_hdr1 : HGlobal;

pre-stored pink noise


hWave_hdr2 : HGlobal;

wave header handles


hWave_out : HWaveOut;

true if makers (balnks) are required


last_f : extended;


left_amplitude : extended;

duration of each chunk in milliseconds


left_angle : integer;

Private declarations


left_sine_table : PSineTable;

current sine wave angles


left_sine_table_valid : boolean;

pre-stored sine-wave values


locked_frequencies : boolean;

in-phase, out-of-phase or independent


log_lin : modes;


next_octave : integer;

to know whether to add a marker


out_level : out_levels;


pcm : TWaveFormatEx;

handle to wave out device


pink_noise_buffer : PMonoBuffer;

table-valid flags


present_left_amplitude : extended;


present_right_amplitude : extended;

to tell if the amplitude has changed


p_buffer1 : PBuffer;


p_buffer2 : PBuffer;

output buffer pointers


p_wave_hdr1 : PWaveHdr;


p_wave_hdr2 : PWaveHdr;

wave header pointers


range : ranges;


right_amplitude : extended;

1.0 is 0dB, 0.5 is -6dB etc


right_angle : integer;


right_sine_table : PSineTable;


right_sine_table_valid : boolean;


shutoff : boolean;


slow_sweep_chunks : integer;

duration of slow sweep (milliseconds


slow_sweep_time : integer;


speed : speeds;


sweep_running : boolean;

wave format descriptor