Class TForm1 (unit DTSweep) |
Inherits from
TForm
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 modeis 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
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
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
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