Mega Code Archive

 
Categories / Delphi / VCL
 

Tonegenerator [component]

//drony@mynet.com //icq:266148308 {component} unit ToneGen; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs ,mmsystem,Math; //default values const AttDef=10; HoldDef=5; DecDef=20; SusDef=50; RelDef=30; DurDef=100; FreDef=440; VolDef=100; AMLevels=7; MaxFreq=20000; MinFreq=20; type TTGPercentage = 0..100; TTGWave = (tgSine,tgSquare,tgTriangle,tgSawtooth,tgNoise); TTGResolution = (tg16Bit,tg8Bit); TTGQuality = (tgHiQ,tgLoQ); TTGAMLevel = (tgAMLevel1,tgAMLevel2,tgAMLevel3,tgAMLevel4,tgAMLevel5,tgAMLevel6,tgAMLevel7,tgAMLevel8); TToneGen = class(TComponent) private { Private declarations } HasChanged: bool; HasADSRChanged: bool; HasToneChanged: bool; HasStopped: bool; Buffer: PChar; BufferSize: Integer; fFrequency: Smallint; fDuration: Smallint; fWaveform: TTGWave; fAttack: Smallint; fHold: Smallint; fDecay: Smallint; fSustain: Smallint; fRelease: Smallint; fAsync: bool; fLoop: bool; fResolution: TTGResolution; fQuality: TTGQuality; fLeftVolume: Smallint; fRightVolume: Smallint; DeviceID: Integer; fStereo: bool; fAMAmplitude: Smallint; fAMWaveform: TTGWave; fAMFrequency: Single; fAMUseMultiplier: bool; Octave: Integer; fAMLevel: TTGAMLevel; AMAmpArray: array[0..AMLevels] of Smallint; AMWaveArray: array[0..AMLevels] of TTGWave; AMFreqArray: array[0..AMLevels] of Single; AMOctaves: array[0..AMLevels] of Integer; procedure SetFrequency(Freq: Smallint); procedure SetDuration(Dur: Smallint); procedure SetWaveform(Wave: TTGWave); procedure SetAttack(Att: Smallint); procedure SetHold(Hld: Smallint); procedure SetDecay(Decy: Smallint); procedure SetSustain(Sus: Smallint); procedure SetRelease(Rel: Smallint); procedure SetResolution(Res: TTGResolution); procedure SetQuality(Qual: TTGQuality); function GetVolume: DWORD; procedure SetVolume; procedure SetLeftVolume(LVol: Smallint); procedure SetRightVolume(RVol: Smallint); function CreateWaveform(DoADSR: bool): bool; procedure ADSRWaveform(Buf: PChar;BufSize: Integer; DoStereo: bool); procedure PlayWave; function LimitValue(lower,upper,val: Smallint):Smallint; function GetPercentage(PC: Smallint): Smallint; procedure SetStereo(bstereo: bool); procedure SetAMLevel(level: TTGAMLevel); procedure SetAMAmplitude(Amp: Smallint); procedure SetAMWaveform(Wave: TTGWave); procedure SetAMFrequency(Freq: Single); procedure SetAMMultiplier(setit: bool); //DefineProperties procedures procedure ReadAMArrayData(Stream: TStream); procedure WriteAMArrayData(Stream: TStream); class function InstanceCount: Integer; class function GetOriginalVolume: DWORD; protected { Protected declarations } //write array data procedure DefineProperties(Filer:TFiler);override; public { Public declarations } constructor Create(AOwner: TComponent); override; destructor Destroy; override; published { Published declarations } property Frequency: Smallint read fFrequency write SetFrequency default FreDef; property Duration: Smallint read fDuration write SetDuration default DurDef; property Waveform: TTGWave read fWaveform write SetWaveform default tgSine; property Attack: Smallint read fAttack write SetAttack default AttDef; property Hold: Smallint read fHold write SetHold default HoldDef; property Decay: Smallint read fDecay write SetDecay default DecDef; property Sustain: Smallint read fSustain write SetSustain default SusDef; property Release: Smallint read fRelease write SetRelease default RelDef; property Async: bool read fAsync write fAsync default true; property Loop: bool read fLoop write fLoop default false; property Resolution: TTGResolution read fResolution write SetResolution default tg16Bit; property Quality: TTGQuality read fQuality write SetQuality default tgHiQ; property LeftVolume: Smallint read fLeftVolume write SetLeftVolume default VolDef; property RightVolume: Smallint read fRightVolume write SetRightVolume default VolDef; property Stereo: bool read fStereo write SetStereo default false; property AMLevel: TTGAMLevel read fAMLevel write SetAMLevel default tgAMLevel1; property AMAmplitude: Smallint read fAMAmplitude write SetAMAmplitude nodefault; property AMWaveform: TTGWave read fAMWaveform write SetAMWaveform nodefault; property AMFrequency: Single read fAMFrequency write SetAMFrequency nodefault; property AMUseMultiplier: bool read fAMUseMultiplier write SetAMMultiplier default true; procedure Play; procedure PlayADSR; procedure Stop; procedure PresetVolume; procedure Prepare; procedure PrepareADSR; procedure ResetAM; procedure SetAMParameter(Level: TTGAMLevel;Freq: Single; Amp: Smallint; Wav:TTGWave); function GetDataBuffer: PChar; function ExportFile(FileName: String): bool; function SetNote(NoteString:String): Integer; function SetAMNote(Level: TTGAMLevel;NoteString:String): Single; end; procedure Register; implementation type { format of WAV file header } TWavHeader = record { parameter description } rId : longint; { 'RIFF' 4 characters } rLen : longint; { length of DATA + FORMAT chunk } { FORMAT CHUNK } wId : longint; { 'WAVE' } fId : longint; { 'fmt ' } fLen : longint; { length of FORMAT DATA = 16 } { format data } wFormatTag : word; { $01 = PCM } nChannels : word; { 1 = mono, 2 = stereo } nSamplesPerSec : longint; { Sample frequency ie 11025} nAvgBytesPerSec : longint; { = nChannels * nSamplesPerSec * (nBitsPerSample/8) } nBlockAlign : word; { = nChannels * (nBitsPerSAmple / 8 } wBitsPerSample : word; { 8 or 16 } { DATA CHUNK } dId : longint; { 'data' } wSampleLength : longint; { length of SAMPLE DATA } { sample data : offset 44 } { for 8 bit mono = s[0],s[1]... :byte} { for 8 bit stereo = sleft[0],sright[0],sleft[1],sright[1]... :byte} { for 16 bit mono = s[0],s[1]... :word} { for 16 bit stereo = sleft[0],sright[0],sleft[1],sright[1]... :word} end; var TTGCount: Integer=0; OriginalVolume: DWORD=0; procedure Register; begin RegisterComponents('Plus', [TToneGen]); end; //limit value function TToneGen.LimitValue(lower,upper,val: Smallint):Smallint; var msg:String; begin if (val>=lower) and (val<=upper) then begin Result:=val; Exit; end; //error message? if csDesigning in ComponentState then begin msg:='Value must be between '+IntToStr(lower)+' and '+IntToStr(upper); MessageBox(0,PChar(msg),'Error',MB_OK or MB_ICONERROR); end; if val>upper then Result:=upper else Result:=lower; end; //limit values 0 to 100 ********************************************** //if designing give warning //force to limits function TToneGen.GetPercentage(PC: Smallint):Smallint; begin Result:=LimitValue(0,100,PC); end; //preset tone and volume settings ********************************************** procedure TToneGen.Prepare; begin //setup volume SetVolume; //create wave CreateWaveform(false); end; //set mono or stereo ********************************************** procedure TToneGen.SetStereo(bstereo: bool); begin HasChanged:=true; fStereo:=bstereo; end; //preset ADSR and volume settings ********************************************** procedure TToneGen.PrepareADSR; begin //setup volume SetVolume; //create wave CreateWaveform(true); end; //preset volume levels ********************************************** procedure TToneGen.PresetVolume; begin //setup volume SetVolume; end; //play sound ********************************************** procedure TToneGen.PlayWave; var Flags: DWORD; begin //stop any sounds first Stop; //setup volume SetVolume; Flags:=SND_SYNC; if fAsync then Flags:=SND_ASYNC; if fLoop then Flags:=SND_ASYNC or SND_LOOP; Flags:=Flags or SND_MEMORY; //play data in buffer if Buffer<>nil then PlaySound(Buffer, 0, Flags); end; //play simple tone ********************************************** procedure TToneGen.Play; begin if HasChanged or HasToneChanged then CreateWaveform(false); HasStopped:=false; PlayWave; //flag as having finished? HasStopped:=not(Async or Loop); end; //play enveloped tone ********************************************** procedure TToneGen.PlayADSR; begin if HasChanged or HasADSRChanged then CreateWaveform(true); HasStopped:=false; PlayWave; //flag as having finished? HasStopped:=not(Async or Loop); end; //stop sound ********************************************** procedure TToneGen.Stop; begin //stop any sounds PlaySound(nil, 0, 0); //flag as having finished HasStopped:=true; end; //get waveform volume ********************************************** function TToneGen.GetVolume: DWORD; var vol: DWORD; wocs: WAVEOUTCAPS; CanDoLR: bool; begin vol:=0; //can do left & right? waveOutGetDevCaps(DeviceID,@wocs,sizeof(WAVEOUTCAPS)); if(wocs.dwFormats and WAVECAPS_LRVOLUME)>0 then CanDoLR:=true else CanDoLR:=false; //get volume? waveOutGetVolume(DeviceID,@vol); //copy mono level to right channel? if not CanDoLR then vol:=vol+(vol shl $10); Result:=vol; end; //set waveform volume ********************************************** procedure TToneGen.SetVolume; var newvol: DWORD; begin //combine percentages newvol:=(($ffff * fLeftVolume) div 100)+((($ffff * fRightVolume) div 100) shl $10); //set volume waveOutSetVolume(DeviceID,newvol); end; //return original volume setting ********************************************** class function TToneGen.GetOriginalVolume: DWORD; begin Result:=OriginalVolume; end; //constructor ********************************************** constructor TToneGen.Create(AOwner: TComponent); var i: Integer; begin Inherited Create(AOwner); HasChanged:=true; HasADSRChanged:=true; HasToneChanged:=true; HasStopped:=true; Buffer:=nil; BufferSize:=0; fFrequency:=FreDef; fDuration:=DurDef; fWaveform:=tgSine; fAttack:=AttDef; fHold:=HoldDef; fDecay:=DecDef; fSustain:=SusDef; fRelease:=RelDef; fAsync:=true; fLoop:=false; fResolution:=tg16Bit; fQuality:=tgHiQ; fLeftVolume:=VolDef; fRightVolume:=VolDef; fStereo:=false; fAMUseMultiplier:=true; Octave:=4; //amplitude modulation settings fAMLevel:=tgAMLevel1; ResetAM; fAMFrequency:=AMFreqArray[Integer(fAMLevel)]; fAMWaveform:=AMWaveArray[Integer(fAMLevel)]; fAMAmplitude:=AMAmpArray[Integer(fAMLevel)]; for i:=0 to AMLevels do begin AMOctaves[i]:=Octave; end; DeviceID:=0; //store volume settings if (InstanceCount=0) and not(csDesigning in ComponentState)then begin //store original settings OriginalVolume:=GetVolume; //initialise volume SetVolume; end; //increment instance count Inc(TTGCount); end; //destructor ********************************************** destructor TToneGen.Destroy; var OV: DWORD; begin //stop playing Stop; //de-allocate memory If Buffer<>nil then begin FreeMem(Buffer); Buffer:=nil; BufferSize:=0; end; //decrement instance count Dec(TTGCount); //restore volume settings if (TTGCount=0) and not(csDesigning in ComponentState) then begin OV:=GetOriginalVolume; waveOutSetVolume(DeviceID,OV); end; inherited Destroy; end; //instance count ********************************************** class function TToneGen.InstanceCount: Integer; begin Result:=TTGCount; end; //set left volume ********************************************** procedure TToneGen.SetLeftVolume(LVol: Smallint); begin fLeftVolume:=GetPercentage(LVol); //initialise volume if (csLoading in ComponentState) or HasStopped then SetVolume; end; //set right volume ********************************************** procedure TToneGen.SetRightVolume(RVol: Smallint); begin fRightVolume:=GetPercentage(RVol); //initialise volume if (csLoading in ComponentState) or HasStopped then SetVolume; end; //set frequency ********************************************** procedure TToneGen.SetFrequency(Freq: Smallint); begin HasChanged:=true; fFrequency:=LimitValue(MinFreq,MaxFreq,Freq); end; //duration ********************************************** procedure TToneGen.SetDuration(Dur: Smallint); begin HasChanged:=true; fDuration:=LimitValue(10,$7FFF,Dur); end; //wave type ********************************************** procedure TToneGen.SetWaveform(Wave: TTGWave); begin HasChanged:=true; fWaveform:=Wave; end; //attack ********************************************** procedure TToneGen.SetAttack(Att: Smallint); begin HasADSRChanged:=true; fAttack:=GetPercentage(Att); end; //hold ********************************************** procedure TToneGen.SetHold(Hld: Smallint); begin HasADSRChanged:=true; fHold:=GetPercentage(Hld); end; //decay ********************************************** procedure TToneGen.SetDecay(Decy: Smallint); begin HasADSRChanged:=true; fDecay:=GetPercentage(Decy); end; //sustain ********************************************** procedure TToneGen.SetSustain(Sus: Smallint); begin HasADSRChanged:=true; fSustain:=GetPercentage(Sus); end; //release ********************************************** procedure TToneGen.SetRelease(Rel: Smallint); begin HasADSRChanged:=true; fRelease:=GetPercentage(Rel); end; //8 or 16 bit ********************************************** procedure TToneGen.SetResolution(Res: TTGResolution); begin HasChanged:=true; fResolution:=Res; end; //quality ********************************************** procedure TToneGen.SetQuality(Qual: TTGQuality); begin HasChanged:=true; fQuality:=Qual; end; //create wave header **************************************** procedure CreateWavHeader( stereo: bool;{ t=stereo f=mono } hires : bool; { t=16bits, f=8 } hirate : bool; { sample rate t=44100 f=22050} datasize: longint; {date block size} var wh: TWavHeader { Wavheader ref } ); var resolution,channels: word; rate: longint; begin //stereo/mono? if stereo=true then channels:=2 else channels:=1; //16bit/8bit? if hires=true then resolution:=16 else resolution:=8; //44100/22050 bps? if hirate=true then rate:=96000 else rate:=44100; wh.rId := $46464952; { 'RIFF' } wh.rLen := datasize+36; { length of sample + format } wh.wId := $45564157; { 'WAVE' } wh.fId := $20746d66; { 'fmt ' } wh.fLen := 16; { length of format chunk } wh.wFormatTag := 1; { PCM data } wh.nChannels := channels; { mono/stereo } wh.nSamplesPerSec := rate; { sample rate } wh.nAvgBytesPerSec := channels*rate*(resolution div 8); wh.nBlockAlign := channels*(resolution div 8); wh.wBitsPerSample := resolution;{ resolution 8/16 } wh.dId := $61746164; { 'data' } wh.wSampleLength := datasize; { sample size } end; //********************************************************************** //modify data to ADSR settings procedure TToneGen.ADSRWaveform(Buf: PChar;BufSize: Integer; DoStereo: bool); var Total,i: Cardinal; Start,Samples,Cnt: Cardinal; BufValue: Integer; SampleFactor,SusFactor: Real; Env,EnvDur: Cardinal; SusDuration: Cardinal; iBuffer: ^SmallInt; ResFactor: Integer; HoldV,AttackV,DecayV,SustainV,ReleaseV: Integer; HiRes: bool; ByteVal: Char; WordVal: Smallint; begin if fResolution=tg16Bit then begin HiRes:=true; end else begin HiRes:=false; end; AttackV:=fAttack; HoldV:=fHold; DecayV:=fDecay; SustainV:=fSustain; ReleaseV:=fRelease; //1/2 no of samples for 16bit if HiRes then ResFactor:=2 else ResFactor:=1; //1/2 no of samples for stereo if DoStereo then ResFactor:=ResFactor*2; Total:=AttackV+HoldV+DecayV+ReleaseV; //normalise percentages if Total>100 then begin AttackV:=AttackV * 100 div Total; HoldV:=HoldV * 100 div Total; DecayV:=DecayV * 100 div Total; ReleaseV:=100-(AttackV+HoldV+DecayV); SusDuration:=0; end; SusDuration:=100-(AttackV+HoldV+DecayV+ReleaseV); Samples:=SusDuration * BufSize div (100 * ResFactor); //sustain level SusFactor:=SustainV/100; if Samples<1 then begin //SustainV:=0; end; Start:=0; if HiRes then begin //create 16bit pointer iBuffer:=Pointer(Buf); end; for Env:=0 to 4 do begin //envelope entry case Env of 0://Attack begin EnvDur:=AttackV; Samples:=EnvDur * BufSize div (100 * ResFactor); if Samples>0 then SampleFactor:=1/Samples else EnvDur:=0; end; 1: //Hold begin EnvDur:=HoldV; Samples:=EnvDur * BufSize div (100 * ResFactor); if Samples>0 then SampleFactor:=1 else EnvDur:=0; end; 2://Decay begin EnvDur:=DecayV; Samples:=EnvDur * BufSize div (100 * ResFactor); if Samples>0 then SampleFactor:=(100-SustainV)/Samples/100 else EnvDur:=0; end; 3://Sustain begin EnvDur:=SusDuration; if ReleaseV=0 then begin Samples:=BufSize div ResFactor; if DoStereo then Samples:=max(0,Samples-(Start div 2)) else Samples:=max(0,Samples-Start); end else begin Samples:=EnvDur * BufSize div (100 * ResFactor); end; SampleFactor:=SusFactor; end; else//Release begin EnvDur:=ReleaseV; Samples:=BufSize div ResFactor; if DoStereo then Samples:=Samples-(Start div 2) else Samples:=Samples-Start; if Samples>0 then SampleFactor:=SusFactor/Samples else begin EnvDur:=0; Samples:=0; end; end; end; //process envelope entry if EnvDur >0 then begin if DoStereo then Samples:=Samples*2; Cnt:=0; i:=min(Start,BufSize); while i<=min(BufSize,Start+Samples) do begin if HiRes then //16bit begin BufValue:=((iBuffer)^); end else//8bit begin BufValue:=Integer((Buf+i)^); BufValue:=BufValue-$80; end; case Env of 0://Attack begin BufValue:=Trunc(Cnt * BufValue * SampleFactor); end; 1://Hold begin //no change to value end; 2://Decay begin BufValue:=BufValue-Trunc(Cnt * BufValue * SampleFactor); end; 3://Sustain begin BufValue:=Trunc(BufValue * SampleFactor); end; 4://Release begin if DoStereo then BufValue:=Trunc(((Samples div 2)-Cnt) * BufValue * SampleFactor) else BufValue:=Trunc((Samples-Cnt) * BufValue * SampleFactor); end; end; if HiRes then //16bit begin WordVal:=SmallInt(BufValue); (iBuffer)^:=WordVal; Inc(iBuffer); //stereo? if DoStereo then begin (iBuffer)^:=WordVal; Inc(iBuffer); Inc(i); end; end else//8bit begin ByteVal:=Char($80+BufValue); (Buf+i)^:=Char(ByteVal); //stereo? if DoStereo then begin Inc(i); (Buf+i)^:=ByteVal; end; end; Inc(i); Inc(Cnt); end; Start:=Start+Samples+1; end; end; HasADSRChanged:=false; HasChanged:=false; HasToneChanged:=true; end; //********************************************************************** //create waveform function TToneGen.CreateWaveform(DoADSR: bool): bool; var wh: TWavHeader; AllocSize,BufSize,HdrSize,i: Integer; DataBuf: PChar; MidValue,MaxVal,MinVal,CalcVal: Real; BytesPerSample,SampsPerInterval: Cardinal; DoStereo: bool; CycleCount,cnt,CycleMidPoint,SamplesPerCycle: Cardinal; FPSamplesPerCycle,FPVerticalStep,FPVerticalAdd :Real; HiRes,HiQ: bool; ByteVal: Integer; iBuffer: ^SmallInt; WordVal: Smallint; AmpPC: Integer; Levels,Total: Integer; wFrequency: Smallint; wWaveform: TTGWave; OldRandSeed: Longint; //wfh: Integer; begin //same random pattern each time OldRandSeed:=RandSeed; RandSeed:=1; //mono or stereo? DoStereo:=fStereo; //size of header record HdrSize:=sizeof(TWavHeader); //no of bytes per sample if fResolution=tg16Bit then begin BytesPerSample:=2; HiRes:=true; MidValue:=0; end else begin BytesPerSample:=1; HiRes:=false; MidValue:=128; end; //no of samples per S/100 if fQuality=tgHiQ then begin SampsPerInterval:=960; HiQ:=true; end else begin SampsPerInterval:=441; HiQ:=false; end; //buffer size BufSize:=(BytesPerSample * Duration * SampsPerInterval) div 10; //twice as big for stereo if DoStereo then BufSize:=BufSize*2; //create header CreateWavHeader(DoStereo,HiRes,HiQ,BufSize,wh); //allocate memory for data buffer if Buffer<>nil then begin FreeMem(Buffer); Buffer:=nil; BufferSize:=0; end; //stop any sounds PlaySound(nil, 0, 0); try AllocSize:=BufSize+HdrSize+32; Buffer:=AllocMem(AllocSize); except Result:=false; Exit; end; if (Buffer=nil) or (BufSize=0) then begin Result:=false; Exit; end; //initialise BufferSize:=AllocSize; FillMemory(Buffer,AllocSize,Trunc(MidValue)); //copy header data to start of buffer CopyMemory(Buffer,@wh,HdrSize); //amplitude percentages Total:=0; for i:=0 to AMLevels do begin Total:=Total+AMAmpArray[i]; end; //------------------------------- //start of creation loop for Levels:=-1 to AMLevels do begin if Levels=-1 then //base frequency begin AmpPC:=100-Total; wFrequency:=Frequency; wWaveform:=fWaveForm; end else //AM levels begin AmpPC:=AMAmpArray[Levels]; if Total>100 then AmpPC:=AmpPC*100 div Total; //frequency mutiplier or absolute? if AMUseMultiplier then begin wFrequency:=LimitValue(MinFreq,MaxFreq,Trunc(AMFreqArray[Levels]*fFrequency)); end else //absolute begin wFrequency:=Trunc(AMFreqArray[Levels]); end; //waveform wWaveform:=AMWaveArray[Levels]; end; //loop again if no amplitude if (AmpPC<=0) or (wFrequency<=0) then Continue; if fResolution=tg16Bit then begin MaxVal:=65534 * AmpPC /100; MinVal:=-32767 * AmpPC /100; end else begin MaxVal:=254 * AmpPC /100; MinVal:=-127 * AmpPC /100; end; //floating point samples per cycle FPSamplesPerCycle:=(SampsPerInterval*100)/wFrequency; //samples per cycle SamplesPerCycle:=Trunc(FPSamplesPerCycle); //CycleMidPoint of cycle //CycleMidPoint:=SamplesPerCycle div 2; CycleMidPoint:=Trunc(FPSamplesPerCycle+0.5) div 2; //offset to data area DataBuf:=Buffer+HdrSize; //counter to step through cycles CycleCount:=1; FPVerticalStep:=0; FPVerticalAdd:=0; //write wav data to buffer //sine step values if wWaveform=tgSine then begin FPVerticalStep:=(pi*2)/SamplesPerCycle; end; //sq step values if wWaveform=tgSquare then begin MaxVal:=MaxVal / 2;; end; //triangle vertical step size if wWaveform=tgTriangle then begin FPVerticalStep:=MinVal; FPVerticalAdd:=(MaxVal / CycleMidPoint); end; //sawtooth vertical step size if wWaveform=tgSawtooth then begin FPVerticalStep:=MinVal; FPVerticalAdd:=(MaxVal/SamplesPerCycle); end; cnt:=0; i:=0; while i<BufSize do begin //select wave type case wWaveform of //sine tgSine: begin CalcVal:=Trunc((sin(cnt * FPVerticalStep))/2*MaxVal); end; //square tgSquare: begin if cnt<CycleMidPoint then CalcVal:=MinVal else CalcVal:=MaxVal; end; //triangle tgTriangle: begin if cnt<CycleMidPoint then begin CalcVal:=Trunc(FPVerticalStep); FPVerticalStep:=FPVerticalStep+FPVerticalAdd; end else begin CalcVal:=Trunc(FPVerticalStep); FPVerticalStep:=FPVerticalStep-FPVerticalAdd; if FPVerticalStep<MinVal then FPVerticalStep:=MinVal; //if (CalcVal+MidValue)>MaxVal then CalcVal:=MaxVal+MidValue; end; end; //sawtooth tgSawtooth: begin CalcVal:=Trunc(FPVerticalStep); FPVerticalStep:=FPVerticalStep+FPVerticalAdd; end; //noise else CalcVal:=random(Trunc(MaxVal+1))+MinVal end; //offset CalcVal:=MidValue+CalcVal; //8bit or 16? if HiRes then begin iBuffer:=Pointer(DataBuf+i); WordVal:=iBuffer^; WordVal:=WordVal+Trunc(CalcVal); iBuffer^:=WordVal; Inc(i,2); //stereo? if DoStereo then begin iBuffer:=Pointer(DataBuf+i); (iBuffer)^:=WordVal; Inc(i,2); end end else //8bit begin ByteVal:=Integer((DataBuf+i)^)-Trunc(MidValue); ByteVal:=ByteVal+Trunc(CalcVal); (DataBuf+i)^:=Char(ByteVal); //stereo? if DoStereo then begin (DataBuf+i+1)^:=(DataBuf+i)^; Inc(i); end; Inc(i); end; Inc(cnt); if cnt=SamplesPerCycle then begin cnt:=0; if wWaveform<>tgSine then begin FPVerticalStep:=MinVal; end; Inc(CycleCount); //update samples per cycle SamplesPerCycle:=Trunc((FPSamplesPerCycle*CycleCount)-(Trunc(FPSamplesPerCycle*(CycleCount-1)))); //CycleMidPoint of cycle //CycleMidPoint:=SamplesPerCycle div 2; CycleMidPoint:=Trunc(FPSamplesPerCycle+0.5) div 2; end; end; end; HasADSRChanged:=true; HasChanged:=false; HasToneChanged:=false; //pass to ADSR routine if DoADSR then begin ADSRWaveform(DataBuf,BufSize,DoStereo); end; //restore random seed value RandSeed:=OldRandSeed; //temporary {wfh:=FileCreate('c:\test.wav'); if wfh<>-1 then begin FileWrite(wfh,Buffer^,BufSize+HdrSize); FileClose(wfh); end;} //****** Result:=true; end; //********************************************************************** //set AM Level selection procedure TToneGen.SetAMLevel(level: TTGAMLevel); begin fAMLevel:=level; AMAmplitude:=AMAmpArray[Integer(level)]; AMWaveform:=AMWaveArray[Integer(level)]; AMFrequency:=AMFreqArray[Integer(level)]; end; //********************************************************************** //AM frequency = multiplier or absolute? procedure TToneGen.SetAMMultiplier(setit: bool); begin fAMUseMultiplier:=setit; HasChanged:=true; end; //********************************************************************** //set selected AM Amplitude procedure TToneGen.SetAMAmplitude(Amp: Smallint); begin fAMAmplitude:=GetPercentage(Amp); AMAmpArray[Integer(fAMLevel)]:=fAMAmplitude; HasChanged:=true; end; //********************************************************************** //AM Waveform procedure TToneGen.SetAMWaveform(Wave: TTGWave); begin fAMWaveform:=Wave; AMWaveArray[Integer(fAMLevel)]:=fAMWaveform; HasChanged:=true; end; //********************************************************************** //AM Frequency procedure TToneGen.SetAMFrequency(Freq: Single); begin fAMFrequency:=Freq; AMFreqArray[Integer(fAMLevel)]:=fAMFrequency; HasChanged:=true; end; //********************************************************************** //DefineProperties procedures //register defineproerties proc's procedure TToneGen.DefineProperties(Filer: TFiler); begin inherited DefineProperties(Filer); Filer.DefineBinaryProperty('AMArrayData', ReadAMArrayData, WriteAMArrayData,true); end; //********************************************************************** //write AM array procedure TToneGen.WriteAMArrayData(Stream: TStream); var i: Integer; Temp: integer; STemp: Single; begin with Stream do begin Temp := AMLevels; WriteBuffer(Temp, SizeOf(Temp)); for i := 0 to AMLevels do begin //amplitude Temp := AMAmpArray[i]; WriteBuffer(Temp,sizeof(temp)); //waveform Temp := Integer(AMWaveArray[i]); WriteBuffer(Temp,sizeof(temp)); //frequency STemp := AMFreqArray[i]; WriteBuffer(STemp,sizeof(STemp)); end; end; end; //********************************************************************** //read AM array procedure TToneGen.ReadAMArrayData(Stream: TStream); var i, Temp, Levels: Integer; STemp: Single; begin with Stream do begin Levels := 0; ReadBuffer(Levels, SizeOf(Levels)); for i := 0 to Levels do begin //amplitude Temp := 0; ReadBuffer(Temp, SizeOf(Temp)); AMAmpArray[i]:=Temp; //waveform Temp := 0; ReadBuffer(Temp, SizeOf(Temp)); AMWaveArray[i]:=TTGWave(Temp); //frquency STemp := 0; ReadBuffer(STemp, SizeOf(STemp)); AMFreqArray[i]:=STemp; end; end; end; //********************************************************************** //reset AM parameters to defaults procedure TToneGen.ResetAM; var i: Integer; begin for i:=0 to AMLevels do begin //amplitude AMAmpArray[i]:=0; //wave AMWaveArray[i]:=tgSine; //frequency AMFreqArray[i]:=(i+1.0) / 2; end; HasChanged:=true; end; //********************************************************************** //set an AM parameter procedure TToneGen.SetAMParameter(Level: TTGAMLevel;Freq: Single; Amp: Smallint; Wav:TTGWave); begin //frequency AMFreqArray[Integer(Level)]:=Freq; //wave AMWaveArray[Integer(Level)]:=Wav; //amplitude AMAmpArray[Integer(Level)]:=Amp; HasChanged:=true; end; //********************************************************************** //return data buffer pointer function TToneGen.GetDataBuffer: PChar; begin Result:=Buffer; end; //********************************************************************** //export data function TToneGen.ExportFile(FileName: String): bool; var Success,FileHandle: Integer; begin Result:=false; if Buffer=nil then Exit; FileHandle:=FileCreate(FileName); if FileHandle<>-1 then begin Success:=FileWrite(Filehandle,Buffer^,BufferSize); FileClose(FileHandle); if Success<>-1 then Result:=true; end; end; //********************************************************************** //set frequency to note value function SetNoteToFreq(NoteString: String;var pOctave: Integer): Integer; var i,tOctave,Freq,Base,TempNote,NoteValue,MaxNoteVal: Integer; begin Result:=0; Base:=440; MaxNoteVal:=121; NoteValue:=-1; tOctave:=pOctave; NoteString:=AnsiUppercase(Trim(NoteString)); //direct note entry 'Nxx' if AnsiPos('N',NoteString)=1 then begin //delete 'N' Delete(NoteString,1,1); NoteValue:=StrToIntDef(NoteString,-1); if NoteValue>MaxNoteVal then NoteValue:=-1; NoteString:=''; end else begin if AnsiPos('O',NoteString)=1 then //Octave 'Ox' begin //delete 'O' Delete(NoteString,1,1); tOctave:=StrToIntDef(NoteString[1],-1); if tOctave=-1 then Exit; //delete 'x' Delete(NoteString,1,1); end // > or < else if (AnsiPos('<',NoteString)=1) or (AnsiPos('>',NoteString)=1) then begin while(AnsiPos('<',NoteString)=1) or (AnsiPos('>',NoteString)=1) do begin if AnsiPos('<',NoteString)=1 then begin Dec(tOctave); if tOctave<0 then tOctave:=0; end else begin Inc(tOctave); if tOctave>9 then tOctave:=9; end; Delete(NoteString,1,1); end; end; //extract note for i:=0 to 6 do begin //search for note (A - G) if AnsiPos(Char(Integer('A')+i),NoteString)=1 then begin NoteValue:=i; //delete note character Delete(NoteString,1,1); Break; end; end; //accidental # + - if NoteValue>-1 then begin //insert semitones TempNote:=NoteValue*2; //correct for BC & EF if NoteValue>4 then Dec(TempNote); if NoteValue>1 then Dec(TempNote); NoteValue:=TempNote; //# or + if (AnsiPos('+',NoteString)=1) or (AnsiPos('#',NoteString)=1) then begin Delete(NoteString,1,1); //B or E if (NoteValue=2) or (NoteValue=7) then NoteValue:=-1 else Inc(NoteValue); end //- else if AnsiPos('-',NoteString)=1 then begin Delete(NoteString,1,1); //C or F if (NoteValue=3) or (NoteValue=8) then NoteValue:=-1 else begin Dec(NoteValue); //A- = G# in previous octave if NoteValue<0 then begin NoteValue:=11;//G# Dec(tOctave); if tOctave<0 then NoteValue:=-1; end; end; end; end; if NoteValue>-1 then begin NoteValue:=12*tOctave+NoteValue; end; end; //should be empty now if Length(NoteString)>0 then NoteValue:=-1; if NoteValue>-1 then begin pOctave:=tOctave; NoteValue:=NoteValue-48; Freq:=Trunc(Base * Power(2,NoteValue/12)+0.5); if (Freq>=MinFreq) and (Freq<=MaxFreq) then begin Result:=Freq; end; end; end; //********************************************************************** //set frequency to note value function TToneGen.SetNote(NoteString: String): Integer; var Freq,pOctave: Integer; begin Result:=0; pOctave:=Octave; Freq:=SetNoteToFreq(NoteString,pOctave); if Freq>0 then begin Frequency:=Freq; Octave:=pOctave; HasChanged:=true; Result:=Freq; end; end; //********************************************************************** //set AM frequency to note value function TToneGen.SetAMNote(Level: TTGAMLevel;NoteString:String): Single; var Freq,pOctave: Integer; fFreq: Single; begin Result:=0; pOctave:=AMOctaves[Integer(Level)]; Freq:=SetNoteToFreq(NoteString,pOctave); fFreq:=Freq; if Freq>0 then begin //absolute or multiply? if fAMUseMultiplier then fFreq:=fFreq/fFrequency; AMFreqArray[Integer(Level)]:=fFreq; AMOctaves[Integer(Level)]:=pOctave; HasChanged:=true; Result:=fFreq; end; end; end. {=============================================================================} //samples unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,ExtCtrls, ComCtrls,Math, Buttons, ToneGen; type //data used for demos DemoData=record Wave: TTGWave; Dur: Integer; Freq: Integer; A,H,D,S,R: Integer; Reps: Integer; AMEntries: Integer; AMFreq: array[0..7] of Single; AMWave: array[0..7] of TTGWave; AMAmp: array[0..7] of Smallint; end; TForm1 = class(TForm) RadioGroup1: TRadioGroup; RadioGroup2: TRadioGroup; UpDown1: TUpDown; Edit1: TEdit; Label1: TLabel; RadioGroup3: TRadioGroup; Edit2: TEdit; UpDown2: TUpDown; Label2: TLabel; CheckBox1: TCheckBox; CheckBox2: TCheckBox; TrackBar1: TTrackBar; TrackBar2: TTrackBar; TrackBar3: TTrackBar; TrackBar4: TTrackBar; Label7: TLabel; Panel1: TPanel; Label3: TLabel; Panel2: TPanel; Label4: TLabel; Panel3: TPanel; Label5: TLabel; Panel4: TPanel; TrackBar5: TTrackBar; TrackBar6: TTrackBar; Label6: TLabel; Button6: TButton; Button7: TButton; Button8: TButton; Button9: TButton; Button10: TButton; Button11: TButton; Timer2: TTimer; Button12: TButton; Timer3: TTimer; Button13: TButton; Button14: TButton; GroupBox1: TGroupBox; GroupBox2: TGroupBox; Label9: TLabel; Label8: TLabel; Bevel1: TBevel; Bevel3: TBevel; Label10: TLabel; Bevel2: TBevel; Button1: TButton; Button2: TButton; CheckBox3: TCheckBox; ToneGen1: TToneGen; Label11: TLabel; Panel5: TPanel; TrackBar7: TTrackBar; Bevel4: TBevel; WaveTTG: TToneGen; TrackBar8: TTrackBar; Label12: TLabel; Label13: TLabel; Bevel5: TBevel; Label14: TLabel; Panel6: TPanel; TrackBar9: TTrackBar; Panel7: TPanel; TrackBar10: TTrackBar; RadioGroup4: TRadioGroup; Bevel6: TBevel; Label15: TLabel; Panel8: TPanel; TrackBar11: TTrackBar; Panel9: TPanel; TrackBar12: TTrackBar; RadioGroup5: TRadioGroup; Bevel7: TBevel; Label16: TLabel; Panel10: TPanel; TrackBar13: TTrackBar; Panel11: TPanel; TrackBar14: TTrackBar; RadioGroup6: TRadioGroup; Bevel8: TBevel; Label17: TLabel; Panel12: TPanel; TrackBar15: TTrackBar; Panel13: TPanel; TrackBar16: TTrackBar; RadioGroup7: TRadioGroup; Bevel9: TBevel; Label18: TLabel; Panel14: TPanel; TrackBar17: TTrackBar; Panel15: TPanel; TrackBar18: TTrackBar; RadioGroup8: TRadioGroup; Bevel10: TBevel; Label19: TLabel; Panel16: TPanel; TrackBar19: TTrackBar; Panel17: TPanel; TrackBar20: TTrackBar; RadioGroup9: TRadioGroup; Bevel11: TBevel; Label20: TLabel; Panel18: TPanel; TrackBar21: TTrackBar; Panel19: TPanel; TrackBar22: TTrackBar; RadioGroup10: TRadioGroup; Bevel12: TBevel; Label21: TLabel; Panel20: TPanel; TrackBar23: TTrackBar; Panel21: TPanel; TrackBar24: TTrackBar; RadioGroup11: TRadioGroup; Bevel13: TBevel; Label22: TLabel; Bevel14: TBevel; Label23: TLabel; Button4: TButton; Button5: TButton; Button15: TButton; Button16: TButton; Button17: TButton; Button18: TButton; Button19: TButton; Button20: TButton; Button21: TButton; Button22: TButton; Button23: TButton; Button24: TButton; TrackBar25: TTrackBar; Panel22: TPanel; Button25: TButton; Edit3: TEdit; RadioButton1: TRadioButton; RadioButton2: TRadioButton; Button26: TButton; Button27: TButton; GroupBox3: TGroupBox; Button3: TButton; Button28: TButton; procedure Button1Click(Sender: TObject); procedure TrackBar1Change(Sender: TObject); procedure FormActivate(Sender: TObject); procedure CheckBox1Click(Sender: TObject); procedure FormPaint(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure TrackBar5Change(Sender: TObject); procedure TrackBar6Change(Sender: TObject); procedure Button6Click(Sender: TObject); procedure Button7Click(Sender: TObject); procedure Button9Click(Sender: TObject); procedure Button8Click(Sender: TObject); procedure Button10Click(Sender: TObject); procedure Button11Click(Sender: TObject); procedure Timer2Timer(Sender: TObject); procedure Button12Click(Sender: TObject); procedure Timer3Timer(Sender: TObject); procedure Button13Click(Sender: TObject); procedure Button14Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure RadioGroup3Click(Sender: TObject); procedure TrackBar8Change(Sender: TObject); procedure RadioGroup4Click(Sender: TObject); procedure TrackBar9Change(Sender: TObject); procedure TrackBar10Change(Sender: TObject); procedure Button4Click(Sender: TObject); procedure TrackBar25Change(Sender: TObject); procedure Button25Click(Sender: TObject); procedure Button26Click(Sender: TObject); procedure Button27Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button28Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; DD: array [0 .. 9] of DemoData; Demo: Integer; PanRight: bool; //tune data notevals: array [0..13] of String=('A','A','E','E','F#','F#','E','D','D','C#','C#','B','B','A'); //note intervals interval: array[0..13] of Smallint=(1,1,1,1,1,1,2,1,1,1,1,1,1,1); notepos: Integer; WaveCount: Integer=5; DoRedraw: bool=true; //AM controls AMWav: array[0..7] of TRadioGroup; AMFreq: array[0..7] of TTrackBar; AMAmp: array[0..7] of TTrackBar; AMAmpV: array[0..7] of TPanel; AMFreqV: array[0..7] of TPanel; procedure SetupTone; implementation {$R *.DFM} //exit procedure TForm1.Button1Click(Sender: TObject); begin Close; end; //return wave type from index function WaveIndex(Index: Integer):TTGWave; begin case Index of 0: Result:=tgSine; 1: Result:=tgSquare; 2: Result:=tgTriangle; 3: Result:=tgSawtooth; else Result:=tgNoise; end; end; //draw envelope & wave graphic procedure RedrawADSR; var i,bleft,btop,apos,hpos,dpos,spos,rpos,wdth,hgt,total: Integer; xs,xe,ys,ye: Integer; fmc: TCanvas; Buf: PChar; wavdata: Char; begin if DoRedraw=false then exit; with Form1 do begin fmc:=Form1.Canvas; //ADSR wdth:=Bevel1.Width-1; hgt:=Bevel1.Height-4; bleft:=Bevel1.Left+1; btop:=Bevel1.Top+2; apos:=100-trackbar1.Position; hpos:=100-trackbar7.Position; dpos:=100-trackbar2.Position; spos:=trackbar3.Position; rpos:=100-trackbar4.Position; total:=apos+hpos+dpos+rpos; if total>100 then begin apos:=apos * 100 div total; hpos:=hpos * 100 div total; dpos:=dpos * 100 div total; rpos:=rpos * 100 div total; end; //attack fmc.Pen.Color:=clRed; xs:=bleft; xe:=bleft+(wdth * apos div 100); ys:=btop+hgt; ye:=btop; fmc.MoveTo(xs,ys); fmc.LineTo(xe,ye); //hold fmc.Pen.Color:=clPurple; xe:=xe+(wdth * hpos div 100); ye:=btop; fmc.LineTo(xe,ye); //decay fmc.Pen.Color:=clBlue; xe:=xe+(wdth * dpos div 100); ye:=btop+(hgt * spos div 100); fmc.LineTo(xe,ye); //sustain fmc.Pen.Color:=clGreen; if total<100 then begin xe:=(bleft+wdth)-(wdth * rpos div 100); fmc.LineTo(xe,ye); end; //release fmc.Pen.Color:=clNavy; xe:=bleft+wdth; ye:=btop+hgt; fmc.LineTo(xe,ye); //Waveform Buf:=WaveTTG.GetDataBuffer; if Buf<>nil then begin Buf:=Buf+44;//offset to data bleft:=Bevel4.Left+1; btop:=Bevel4.Top+2; fmc.Pen.Color:=clBlue; wavdata:=Buf^; fmc.MoveTo(bleft,(Integer(wavdata) div 2) + btop); Inc(Buf); for i:=1 to Bevel4.Width-2 do begin wavdata:=Buf^; fmc.LineTo(bleft+i,(Integer(wavdata) div 2) + btop); Inc(Buf); end; end; end; end; procedure TForm1.FormActivate(Sender: TObject); begin //reset AM parameters WaveTTG.ResetAM; ToneGen1.ResetAM; //draw wave TrackBar8Change(nil); //draw envelope TrackBar1Change(nil); //do am text TrackBar10Change(nil); SetupTone; Tonegen1.Prepare; end; //set async state from loop procedure TForm1.CheckBox1Click(Sender: TObject); begin CheckBox2.Enabled:=not CheckBox1.Checked; end; //set ADSR procedure TForm1.TrackBar1Change(Sender: TObject); var tb1,tb2,tb3,tb4,tb5,Total: Integer; begin tb1:=100-TrackBar1.Position; tb2:=100-TrackBar2.Position; tb3:=100-TrackBar3.Position; tb4:=100-TrackBar4.Position; tb5:=100-TrackBar7.Position; Total:=tb1+tb2+tb4+tb5; with ToneGen1 do begin Attack:=tb1; Hold:=tb5; Decay:=tb2; Sustain:=tb3; Release:=tb4; end; if Total>100 then begin tb1:=tb1 * 100 div Total; tb2:=tb2 * 100 div Total; tb4:=tb4 * 100 div Total; tb5:=tb5 * 100 div Total; end; Panel1.Caption:=IntToStr(tb1)+'%'; Panel2.Caption:=IntToStr(tb2)+'%'; Panel3.Caption:=IntToStr(tb3)+'%'; Panel4.Caption:=IntToStr(tb4)+'%'; Panel5.Caption:=IntToStr(tb5)+'%'; //update graphic if Doredraw then Form1.Bevel2.Invalidate; Update; end; procedure TForm1.FormPaint(Sender: TObject); begin RedrawADSR; end; procedure TForm1.FormCreate(Sender: TObject); begin //set volume TrackBar5.Position:=100-ToneGen1.LeftVolume; TrackBar6.Position:=100-ToneGen1.RightVolume; Randomize; //initialise demo records //morse with DD[0] do begin Freq:=440; Dur:=100; Wave:=tgSine; A:=0; H:=0; D:=0; S:=100; R:=0; AMEntries:=0; end; //alarm with DD[1] do begin Freq:=1500; Dur:=200; Wave:=tgTriangle; A:=0; H:=10; D:=20; S:=80; R:=0; AMEntries:=1; AMFreq[0]:=2.5; AMAmp[0]:=38; AMWave[0]:=tgSawtooth; end; //pan with DD[2] do begin Freq:=100; Dur:=100; Wave:=tgSquare; A:=10; H:=5; D:=15; S:=75; R:=0; AMEntries:=0; end; //tune with DD[3] do begin Freq:=500; Dur:=500; Wave:=tgSawtooth; A:=10; H:=21; D:=15; S:=75; R:=55; AMEntries:=2; AMAmp[0]:=45; AMFreq[0]:=3.0; AMWave[0]:=tgSquare; AMAmp[1]:=45; AMFreq[1]:=4.0; AMWave[1]:=tgSine; end; //bell with DD[5] do begin Freq:=3130; Dur:=450; Wave:=tgTriangle; A:=0; H:=10; D:=65; S:=30; R:=20; AMEntries:=2; AMAmp[0]:=40; AMFreq[0]:=0.1; AMWave[0]:=tgSine; AMAmp[1]:=5; AMFreq[1]:=3.0; AMWave[1]:=tgSquare; end; //C maj with DD[6] do begin Freq:=523; Dur:=900; Wave:=tgTriangle; A:=0; H:=10; D:=40; S:=30; R:=40; AMEntries:=2; AMAmp[0]:=33; AMFreq[0]:=1.3; AMWave[0]:=tgTriangle; AMAmp[1]:=33; AMFreq[1]:=1.5; AMWave[1]:=tgTriangle; end; //C min with DD[7] do begin Freq:=523; Dur:=900; Wave:=tgTriangle; A:=0; H:=10; D:=40; S:=30; R:=40; AMEntries:=2; AMAmp[0]:=33; AMFreq[0]:=1.2; AMWave[0]:=tgTriangle; AMAmp[1]:=33; AMFreq[1]:=1.5; AMWave[1]:=tgTriangle; end; //setup AM control arrays //wave AMWav[0]:=Form1.RadioGroup4; AMWav[1]:=Form1.RadioGroup5; AMWav[2]:=Form1.RadioGroup6; AMWav[3]:=Form1.RadioGroup7; AMWav[4]:=Form1.RadioGroup8; AMWav[5]:=Form1.RadioGroup9; AMWav[6]:=Form1.RadioGroup10; AMWav[7]:=Form1.RadioGroup11; //frequency AMFreq[0]:=Form1.TrackBar10; AMFreq[1]:=Form1.TrackBar12; AMFreq[2]:=Form1.TrackBar14; AMFreq[3]:=Form1.TrackBar16; AMFreq[4]:=Form1.TrackBar18; AMFreq[5]:=Form1.TrackBar20; AMFreq[6]:=Form1.TrackBar22; AMFreq[7]:=Form1.TrackBar24; //frequency display AMFreqV[0]:=Form1.Panel7; AMFreqV[1]:=Form1.Panel9; AMFreqV[2]:=Form1.Panel11; AMFreqV[3]:=Form1.Panel13; AMFreqV[4]:=Form1.Panel15; AMFreqV[5]:=Form1.Panel17; AMFreqV[6]:=Form1.Panel19; AMFreqV[7]:=Form1.Panel21; //amplitude AMAmp[0]:=Form1.TrackBar9; AMAmp[1]:=Form1.TrackBar11; AMAmp[2]:=Form1.TrackBar13; AMAmp[3]:=Form1.TrackBar15; AMAmp[4]:=Form1.TrackBar17; AMAmp[5]:=Form1.TrackBar19; AMAmp[6]:=Form1.TrackBar21; AMAmp[7]:=Form1.TrackBar23; //amplitude display AMAmpV[0]:=Form1.Panel6; AMAmpV[1]:=Form1.Panel8; AMAmpV[2]:=Form1.Panel10; AMAmpV[3]:=Form1.Panel12; AMAmpV[4]:=Form1.Panel14; AMAmpV[5]:=Form1.Panel16; AMAmpV[6]:=Form1.Panel18; AMAmpV[7]:=Form1.Panel20; end; procedure TForm1.FormDestroy(Sender: TObject); begin end; //left volume procedure TForm1.TrackBar5Change(Sender: TObject); begin ToneGen1.LeftVolume:=100-TrackBar5.Position; WaveTTG.LeftVolume:=100-TrackBar5.Position; end; //right volume procedure TForm1.TrackBar6Change(Sender: TObject); begin ToneGen1.RightVolume:=100-TrackBar6.Position; WaveTTG.RightVolume:=100-TrackBar6.Position; end; //set component parameters from controls procedure SetupTone; begin with Form1.Tonegen1 do begin Loop:=Form1.CheckBox1.Checked; Async:=Form1.CheckBox2.Checked; Frequency:=StrToIntDef(Form1.Edit2.Text,440); Duration:=StrToIntDef(Form1.Edit1.Text,440); Stereo:=Form1.CheckBox3.Checked; if Form1.RadioGroup2.ItemIndex=0 then Quality:=tgHiQ else Quality:=tgLoQ; if Form1.RadioGroup1.ItemIndex=0 then Resolution:=tg16Bit else Resolution:=tg8Bit; Waveform:=WaveIndex(Form1.RadioGroup3.ItemIndex); end; end; //play tone procedure TForm1.Button6Click(Sender: TObject); begin SetupTone; ToneGen1.Play; //Tonegen1.ExportFile('c:\test.wav'); end; //set volume procedure TForm1.Button7Click(Sender: TObject); begin ToneGen1.PresetVolume; end; //stop sound procedure TForm1.Button9Click(Sender: TObject); begin Timer2.Enabled:=false; Timer3.Enabled:=false; ToneGen1.Stop; end; //play ADSR procedure TForm1.Button8Click(Sender: TObject); begin SetupTone; ToneGen1.PlayADSR; //Tonegen1.ExportFile('c:\test.wav'); end; //setup demo parameters procedure SetDemo(ID:Integer); var ttg: TToneGen; i,al,amp: Integer; level:TTGAMLevel; freq: Single; wav: TTGWave; begin DoRedraw:=false; //set data Form1.Tonegen1.AMUseMultiplier:=true; Form1.RadioButton2.Checked:=true; ttg:=Form1.ToneGen1; for i:=0 to 1 do begin with ttg do begin Frequency:=DD[ID].Freq; Duration:=DD[ID].Dur; Waveform:=DD[ID].Wave; Attack:=DD[ID].A; Hold:=DD[ID].H; Decay:=DD[ID].D; Sustain:=DD[ID].S; Release:=DD[ID].R; //AM setup level:=tgAMLevel1; for al:=0 to 7 do begin if al>=DD[ID].AMEntries then begin amp:=0; freq:=0; wav:=tgSine; end else begin amp:=DD[ID].AMAmp[al]; freq:=DD[ID].AMFreq[al]; wav:=DD[ID].AMWave[al]; end; ttg.SetAMParameter(level,freq,amp,wav); //set AM controls if ttg=Form1.WaveTTG then begin AMWav[al].ItemIndex:=Integer(wav); AMAmp[al].Position:=50-amp; if al=7 then begin DoRedraw:=true; Form1.TrackBar9Change(nil); end; if freq>5.0 then freq:=5.0; if freq<=0.1 then AMFreq[al].Position:=50 else begin AMFreq[al].Position:=50-Trunc(freq*10+0.5); end; Inc(level); end; end; if ID<>4 then begin Loop:=false; Form1.Checkbox1.Checked:=Loop; Async:=true; Form1.Checkbox2.Checked:=Async; end else begin Loop:=Form1.Checkbox1.Checked; Async:=Form1.Checkbox2.Checked; end; end; ttg:=Form1.WaveTTG; end; Form1.WaveTTG.Loop:=false; Form1.WaveTTG.Async:=true; //setup controls with Form1 do begin Edit2.Text:=IntToStr(DD[ID].Freq); Edit1.Text:=IntToStr(DD[ID].Dur); Trackbar1.Position:=100-DD[ID].A; Trackbar2.Position:=100-DD[ID].D; Trackbar3.Position:=100-DD[ID].S; Trackbar4.Position:=100-DD[ID].R; Trackbar7.Position:=100-DD[ID].H; Radiogroup3.ItemIndex:=Integer(DD[ID].Wave); end; Form1.Timer2.Enabled:=false; Form1.Timer3.Enabled:=false; //chords? if (ID=6) or (ID=7) then begin Form1.ToneGen1.SetNote('C'); Form1.ToneGen1.SetAMNote(tgAMLevel1,'E'); if ID=6 then Form1.ToneGen1.SetAMNote(tgAMLevel2,'G')//major else Form1.ToneGen1.SetAMNote(tgAMLevel2,'F#');//minor Form1.ToneGen1.PlayADSR; Exit; end; //random if ID<>4 then begin Form1.Timer2.Enabled:=true; end; if ((ID=4) and Form1.Tonegen1.Loop) or (ID<>4) then Form1.Timer3.Enabled:=true; Form1.Timer3.Interval:=5000; //tune if ID=3 then Form1.Timer3.Interval:=10000; DoRedraw:=true; end; //random procedure TForm1.Button10Click(Sender: TObject); var i: Integer; begin Demo:=4; with DD[Demo] do begin Freq:=(10+random(1000))*10; Dur:=(10+random(90))*10; Wave:=TTGWave(random(5)); A:=random(101); H:=random(101); D:=random(101); S:=random(101); R:=random(101); AMEntries:=random(9); if AMEntries>0 then begin for i:=0 to AMEntries-1 do begin AMFreq[i]:=random(51)/10; AMAmp[i]:=random(50 div AMEntries); AMWave[i]:=TTGWave(random(6)); end; end; end; //loop? if random(2)>0 then Checkbox1.Checked:=true else Checkbox1.Checked:=false; SetDemo(Demo); Tonegen1.PlayADSR; end; //morse procedure TForm1.Button11Click(Sender: TObject); begin Demo:=0; Timer2.Interval:=100+Random(300); SetDemo(Demo); end; //demo timer procedure TForm1.Timer2Timer(Sender: TObject); begin //morse if Demo=0 then begin Timer2.Interval:=50+Random(300); end; //pan if Demo=2 then begin with Tonegen1 do begin if PanRight then begin if RightVolume<100 then RightVolume:=RightVolume+50 else if LeftVolume>0 then LeftVolume:=LeftVolume-50 else PanRight:=false; end else begin if LeftVolume<100 then LeftVolume:=LeftVolume+50 else if RightVolume>0 then RightVolume:=RightVolume-50 else PanRight:=true; end; PresetVolume; Trackbar5.Position:=100-LeftVolume; Trackbar6.Position:=100-RightVolume; end; end; //tune if Demo=3 then begin if Notepos>13 then Exit; //set note frequency Tonegen1.SetNote(notevals[Notepos]); Tonegen1.PlayADSR; Timer2.Interval:=interval[notepos]*400; Notepos:=Notepos+1; end; Tonegen1.PlayADSR; end; //alarm procedure TForm1.Button12Click(Sender: TObject); begin Demo:=1; Timer2.Interval:=400; SetDemo(Demo); end; //demo overall duration procedure TForm1.Timer3Timer(Sender: TObject); begin Timer3.Enabled:=false; Timer2.Enabled:=false; with Tonegen1 do begin Stop; //set volume after pan if Demo=2 then begin LeftVolume:=100; RightVolume:=100; WaveTTG.LeftVolume:=100; WaveTTG.RightVolume:=100; Trackbar5.Position:=100-LeftVolume; Trackbar6.Position:=100-RightVolume; end; end; end; //pan procedure TForm1.Button13Click(Sender: TObject); begin Tonegen1.LeftVolume:=100; Tonegen1.RightVolume:=0; Tonegen1.PresetVolume; Demo:=2; SetDemo(Demo); PanRight:=true; Timer2.Interval:=200; Timer2.Enabled:=true; end; //tune procedure TForm1.Button14Click(Sender: TObject); begin Demo:=3; Notepos:=0; SetDemo(Demo); end; procedure TForm1.Button2Click(Sender: TObject); begin Application.HelpFile := ExtractFilePath(Application.ExeName)+'TTonegen.hlp'; Application.HelpCommand(HELP_CONTENTS, 0); end; procedure TForm1.RadioGroup3Click(Sender: TObject); begin Form1.WaveTTG.Waveform:=WaveIndex(Form1.RadioGroup3.ItemIndex); WaveTTG.Prepare; if DoRedraw then Bevel4.Invalidate; Update; end; procedure TForm1.TrackBar8Change(Sender: TObject); begin WaveCount:=20-Trackbar8.Position; WaveTTG.Frequency:=(44100*WaveCount) div Bevel4.Width-2; WaveTTG.Prepare; //if DoRedraw then Bevel4.Invalidate; Bevel4.Invalidate; Bevel4.Update; end; //set all parameters from controls procedure SetAMParameters; var level: TTGAMLevel; i,amp,tf,Total: Integer; freq: Single; wav: TTGWave; mul: bool; begin if DoRedraw=false then Exit; level:=tgAMLevel1; //proportion factor from display Total:=0; for i:=0 to 7 do Total:=Total+50-AMAmp[i].Position; if Total<100 then Total:=100; //step through AM levels for i:=0 to 7 do begin Form1.WaveTTG.AMLevel:=level; //waveform wav:=WaveIndex(AMWav[i].ItemIndex); //amplitude amp:=50-AMAmp[i].Position; //update display values AMAmpV[i].Caption:=IntToStr(amp * 100 div Total)+'%'; //frequency mul:=Form1.RadioButton2.Checked; Form1.Tonegen1.AMUseMultiplier:=mul; tf:=50-AMFreq[i].Position; //absolute? if not mul then begin if tf=0 then freq:=20 else freq:=tf*100; AMFreqV[i].Caption:=IntToStr(Trunc(freq)); //modify frequency for display component (always useAMmultiplier) tf:=StrToIntDef(Form1.Edit2.Text,440); //freq:=tf/freq; freq:=freq/tf; end else //multiplier begin if tf=0 then freq:=0.1 else freq:=tf / 10; AMFreqV[i].Caption:='x'+FloatToStrF(freq,ffFixed,4,1); end; //setup wave display component this way Form1.WaveTTG.AMLevel:=level; Form1.WaveTTG.AMWaveform:=wav; Form1.WaveTTG.AMAmplitude:=amp; Form1.WaveTTG.AMFrequency:=freq; //setup play component the alternative way Form1.Tonegen1.SetAMParameter(level,freq,amp,wav); Inc(level); end; //draw wave Form1.TrackBar8Change(nil); end; procedure TForm1.RadioGroup4Click(Sender: TObject); begin SetAMParameters; end; procedure TForm1.TrackBar9Change(Sender: TObject); begin SetAMParameters; end; procedure TForm1.TrackBar10Change(Sender: TObject); begin SetAMParameters; end; //set note frequency procedure TForm1.Button4Click(Sender: TObject); var freq:Integer; btn: TButton; begin btn:=TButton(Sender); freq:=ToneGen1.SetNote('O'+IntToStr(TrackBar25.Position)+btn.Caption); if freq>0 then begin Edit2.Text:=IntToStr(freq); SetupTone; Tonegen1.PlayADSR; //Tonegen1.Play; end; end; procedure TForm1.TrackBar25Change(Sender: TObject); var en: bool; pos: Integer; begin pos:=TrackBar25.Position; Panel22.Caption:=IntToStr(pos); //do buttons if pos=9 then en:=false else en:=true; Button20.Enabled:=en; Button21.Enabled:=en; Button22.Enabled:=en; Button23.Enabled:=en; Button24.Enabled:=en; end; procedure TForm1.Button25Click(Sender: TObject); begin SetupTone; //Tonegen1.Prepare; Tonegen1.PrepareADSR; if Tonegen1.ExportFile(Edit3.Text)=false then begin Beep(); Application.MessageBox('Could Not Save File','Error',0); end; end; //reset AM parameters procedure TForm1.Button26Click(Sender: TObject); var i: Integer; begin DoRedraw:=false; Tonegen1.ResetAM; WaveTTG.ResetAM; for i:=0 to 7 do begin if i=7 then DoRedraw:=true; AMWav[i].ItemIndex:=0; AMFreq[i].Position:=50-((i+1)*5); AMAmp[i].Position:=50; end; end; //bell procedure TForm1.Button27Click(Sender: TObject); begin Demo:=5; Timer2.Interval:=900; SetDemo(Demo); end; //C maj procedure TForm1.Button3Click(Sender: TObject); begin Demo:=6; SetDemo(Demo); end; procedure TForm1.Button28Click(Sender: TObject); begin Demo:=7; SetDemo(Demo); end; end. //form .dfm object Form1: TForm1 Left = 180 Top = 146 BorderIcons = [biSystemMenu, biMinimize] BorderStyle = bsSingle Caption = 'ToneGen Demo' ClientHeight = 573 ClientWidth = 792 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] OldCreateOrder = False Position = poScreenCenter OnActivate = FormActivate OnCreate = FormCreate OnDestroy = FormDestroy OnPaint = FormPaint PixelsPerInch = 96 TextHeight = 13 object Bevel14: TBevel Left = 110 Top = 315 Width = 572 Height = 256 Shape = bsFrame end object Bevel5: TBevel Left = 112 Top = 157 Width = 570 Height = 152 Shape = bsFrame end object Bevel3: TBevel Left = 112 Top = 8 Width = 569 Height = 142 Shape = bsFrame end object Label1: TLabel Left = 21 Top = 273 Width = 65 Height = 13 Alignment = taCenter AutoSize = False Caption = 'Duration (mS)' end object Label2: TLabel Left = 15 Top = 312 Width = 80 Height = 14 Alignment = taCenter AutoSize = False Caption = 'Frequency (Hz)' end object Label7: TLabel Left = 129 Top = 17 Width = 31 Height = 13 Alignment = taCenter AutoSize = False Caption = 'Attack' Font.Charset = DEFAULT_CHARSET Font.Color = clRed Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False end object Label3: TLabel Left = 225 Top = 17 Width = 31 Height = 13 Alignment = taCenter AutoSize = False Caption = 'Decay' Font.Charset = DEFAULT_CHARSET Font.Color = clBlue Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False end object Label4: TLabel Left = 272 Top = 17 Width = 36 Height = 13 Alignment = taCenter AutoSize = False Caption = 'Sustain' Font.Charset = DEFAULT_CHARSET Font.Color = clGreen Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False end object Label5: TLabel Left = 320 Top = 17 Width = 38 Height = 13 Alignment = taCenter AutoSize = False Caption = 'Release' Font.Charset = DEFAULT_CHARSET Font.Color = clNavy Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False end object Label6: TLabel Left = 35 Top = 93 Width = 31 Height = 13 Alignment = taCenter AutoSize = False Caption = 'Left' Font.Charset = DEFAULT_CHARSET Font.Color = clMaroon Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False end object Bevel1: TBevel Left = 382 Top = 19 Width = 287 Height = 122 Style = bsRaised end object Label10: TLabel Left = 124 Top = 3 Width = 51 Height = 13 Caption = ' Envelope ' end object Bevel2: TBevel Left = 378 Top = 16 Width = 295 Height = 128 end object Label11: TLabel Left = 177 Top = 17 Width = 31 Height = 13 Alignment = taCenter AutoSize = False Caption = 'Hold' Font.Charset = DEFAULT_CHARSET Font.Color = clPurple Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False end object Bevel4: TBevel Left = 150 Top = 172 Width = 526 Height = 131 end object Label12: TLabel Left = 116 Top = 168 Width = 31 Height = 13 Alignment = taCenter AutoSize = False Caption = 'More' Font.Charset = DEFAULT_CHARSET Font.Color = clTeal Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False end object Label13: TLabel Left = 114 Top = 291 Width = 31 Height = 13 Alignment = taCenter AutoSize = False Caption = 'Less' Font.Charset = DEFAULT_CHARSET Font.Color = clTeal Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False end object Label14: TLabel Left = 124 Top = 152 Width = 92 Height = 13 Alignment = taCenter Caption = ' Waveform Display ' Font.Charset = DEFAULT_CHARSET Font.Color = clBlack Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False end object Bevel6: TBevel Left = 121 Top = 328 Width = 68 Height = 221 Shape = bsFrame end object Label15: TLabel Left = 125 Top = 322 Width = 41 Height = 13 Alignment = taCenter Caption = ' Level 1 ' Font.Charset = DEFAULT_CHARSET Font.Color = clBlack Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False end object Bevel7: TBevel Left = 190 Top = 329 Width = 68 Height = 221 Shape = bsFrame end object Label16: TLabel Left = 194 Top = 323 Width = 41 Height = 13 Alignment = taCenter Caption = ' Level 2 ' Font.Charset = DEFAULT_CHARSET Font.Color = clBlack Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False end object Bevel8: TBevel Left = 258 Top = 329 Width = 68 Height = 221 Shape = bsFrame end object Label17: TLabel Left = 262 Top = 323 Width = 41 Height = 13 Alignment = taCenter Caption = ' Level 3 ' Font.Charset = DEFAULT_CHARSET Font.Color = clBlack Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False end object Bevel9: TBevel Left = 327 Top = 329 Width = 68 Height = 221 Shape = bsFrame end object Label18: TLabel Left = 331 Top = 323 Width = 41 Height = 13 Alignment = taCenter Caption = ' Level 4 ' Font.Charset = DEFAULT_CHARSET Font.Color = clBlack Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False end object Bevel10: TBevel Left = 396 Top = 329 Width = 68 Height = 221 Shape = bsFrame end object Label19: TLabel Left = 400 Top = 323 Width = 41 Height = 13 Alignment = taCenter Caption = ' Level 5 ' Font.Charset = DEFAULT_CHARSET Font.Color = clBlack Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False end object Bevel11: TBevel Left = 465 Top = 329 Width = 68 Height = 221 Shape = bsFrame end object Label20: TLabel Left = 469 Top = 323 Width = 41 Height = 13 Alignment = taCenter Caption = ' Level 6 ' Font.Charset = DEFAULT_CHARSET Font.Color = clBlack Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False end object Bevel12: TBevel Left = 533 Top = 329 Width = 68 Height = 221 Shape = bsFrame end object Label21: TLabel Left = 537 Top = 323 Width = 41 Height = 13 Alignment = taCenter Caption = ' Level 7 ' Font.Charset = DEFAULT_CHARSET Font.Color = clBlack Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False end object Bevel13: TBevel Left = 601 Top = 329 Width = 68 Height = 221 Shape = bsFrame end object Label22: TLabel Left = 605 Top = 323 Width = 41 Height = 13 Alignment = taCenter Caption = ' Level 8 ' Font.Charset = DEFAULT_CHARSET Font.Color = clBlack Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False end object Label23: TLabel Left = 124 Top = 309 Width = 107 Height = 13 Alignment = taCenter Caption = ' Amplitude Modulation ' Font.Charset = DEFAULT_CHARSET Font.Color = clBlack Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False end object GroupBox1: TGroupBox Left = 685 Top = 220 Width = 105 Height = 219 Caption = ' Demo ' TabOrder = 28 object Button27: TButton Left = 12 Top = 158 Width = 81 Height = 25 Caption = 'Bell' TabOrder = 0 OnClick = Button27Click end object Button3: TButton Left = 12 Top = 186 Width = 40 Height = 25 Caption = 'C maj' TabOrder = 1 OnClick = Button3Click end object Button28: TButton Left = 53 Top = 186 Width = 40 Height = 25 Caption = 'C min' TabOrder = 2 OnClick = Button28Click end end object GroupBox3: TGroupBox Left = 1 Top = 419 Width = 106 Height = 43 Caption = ' Octave ' TabOrder = 95 end object GroupBox2: TGroupBox Left = 24 Top = 4 Width = 81 Height = 147 Caption = ' Volume ' TabOrder = 29 object Label9: TLabel Left = 7 Top = 15 Width = 31 Height = 13 Alignment = taCenter AutoSize = False Caption = 'Left' Font.Charset = DEFAULT_CHARSET Font.Color = clMaroon Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False end object Label8: TLabel Left = 41 Top = 15 Width = 31 Height = 13 Alignment = taCenter AutoSize = False Caption = 'Right' Font.Charset = DEFAULT_CHARSET Font.Color = clMaroon Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False end end object RadioGroup1: TRadioGroup Left = 688 Top = 3 Width = 97 Height = 68 Caption = ' Resolution ' ItemIndex = 0 Items.Strings = ( '16 bit' '8 bit') TabOrder = 0 end object RadioGroup2: TRadioGroup Left = 688 Top = 75 Width = 97 Height = 72 Caption = ' Sample Rate ' ItemIndex = 0 Items.Strings = ( '96000' '44100') TabOrder = 1 end object UpDown1: TUpDown Left = 78 Top = 288 Width = 16 Height = 21 Associate = Edit1 Min = 10 Max = 1000 Increment = 10 Position = 100 TabOrder = 2 Thousands = False end object Edit1: TEdit Left = 21 Top = 288 Width = 57 Height = 21 TabOrder = 3 Text = '100' end object RadioGroup3: TRadioGroup Left = 9 Top = 153 Width = 97 Height = 118 Caption = ' Base Waveform ' ItemIndex = 0 Items.Strings = ( 'Sine' 'Square' 'Triangle' 'Sawtooth' 'Noise') TabOrder = 4 OnClick = RadioGroup3Click end object Edit2: TEdit Left = 21 Top = 329 Width = 57 Height = 21 TabOrder = 5 Text = '440' OnChange = TrackBar10Change end object UpDown2: TUpDown Left = 78 Top = 329 Width = 16 Height = 21 Associate = Edit2 Min = 20 Max = 20000 Increment = 10 Position = 440 TabOrder = 6 Thousands = False end object CheckBox1: TCheckBox Left = 710 Top = 175 Width = 49 Height = 17 Caption = 'Loop' TabOrder = 7 OnClick = CheckBox1Click end object CheckBox2: TCheckBox Left = 710 Top = 151 Width = 51 Height = 17 Caption = 'Async' Checked = True State = cbChecked TabOrder = 8 end object TrackBar1: TTrackBar Left = 135 Top = 54 Width = 25 Height = 93 LineSize = 5 Max = 100 Orientation = trVertical PageSize = 10 Frequency = 10 Position = 90 TabOrder = 9 ThumbLength = 15 OnChange = TrackBar1Change end object TrackBar2: TTrackBar Left = 233 Top = 54 Width = 25 Height = 93 LineSize = 5 Max = 100 Orientation = trVertical PageSize = 10 Frequency = 10 Position = 80 TabOrder = 10 ThumbLength = 15 OnChange = TrackBar1Change end object TrackBar3: TTrackBar Left = 281 Top = 54 Width = 25 Height = 93 LineSize = 5 Max = 100 Orientation = trVertical PageSize = 10 Frequency = 10 Position = 50 TabOrder = 11 ThumbLength = 15 OnChange = TrackBar1Change end object TrackBar4: TTrackBar Left = 330 Top = 54 Width = 25 Height = 93 LineSize = 5 Max = 100 Orientation = trVertical PageSize = 10 Frequency = 10 Position = 90 TabOrder = 12 ThumbLength = 15 OnChange = TrackBar1Change end object Panel1: TPanel Left = 128 Top = 32 Width = 32 Height = 20 BevelInner = bvLowered BevelOuter = bvLowered Caption = '100%' Color = clWhite TabOrder = 13 end object Panel2: TPanel Left = 225 Top = 32 Width = 32 Height = 20 BevelInner = bvLowered BevelOuter = bvLowered Caption = '100%' Color = clWhite TabOrder = 14 end object Panel3: TPanel Left = 274 Top = 32 Width = 32 Height = 20 BevelInner = bvLowered BevelOuter = bvLowered Caption = '100%' Color = clWhite TabOrder = 15 end object Panel4: TPanel Left = 322 Top = 32 Width = 32 Height = 20 BevelInner = bvLowered BevelOuter = bvLowered Caption = '100%' Color = clWhite TabOrder = 16 end object TrackBar5: TTrackBar Left = 37 Top = 31 Width = 25 Height = 92 LineSize = 5 Max = 100 Orientation = trVertical PageSize = 10 Frequency = 10 Position = 60 TabOrder = 17 ThumbLength = 15 OnChange = TrackBar5Change end object TrackBar6: TTrackBar Left = 72 Top = 31 Width = 25 Height = 92 LineSize = 5 Max = 100 Orientation = trVertical PageSize = 10 Frequency = 10 Position = 80 TabOrder = 18 ThumbLength = 15 OnChange = TrackBar6Change end object Button6: TButton Left = 10 Top = 510 Width = 89 Height = 25 Caption = 'Play Tone' TabOrder = 19 OnClick = Button6Click end object Button7: TButton Left = 34 Top = 123 Width = 64 Height = 23 Caption = 'Preset' TabOrder = 20 OnClick = Button7Click end object Button8: TButton Left = 10 Top = 478 Width = 89 Height = 25 Caption = 'Play ADSR' TabOrder = 21 OnClick = Button8Click end object Button9: TButton Left = 10 Top = 542 Width = 89 Height = 25 Caption = 'Stop' TabOrder = 22 OnClick = Button9Click end object Button10: TButton Left = 697 Top = 238 Width = 81 Height = 25 Caption = 'Random' TabOrder = 23 OnClick = Button10Click end object Button11: TButton Left = 697 Top = 350 Width = 81 Height = 25 Caption = 'Morse' TabOrder = 24 OnClick = Button11Click end object Button12: TButton Left = 697 Top = 322 Width = 81 Height = 25 Caption = 'Alarm' TabOrder = 25 OnClick = Button12Click end object Button13: TButton Left = 697 Top = 294 Width = 81 Height = 25 Caption = 'Volume Pan' TabOrder = 26 OnClick = Button13Click end object Button14: TButton Left = 697 Top = 266 Width = 81 Height = 25 Caption = 'Tune' TabOrder = 27 OnClick = Button14Click end object Button1: TButton Left = 696 Top = 483 Width = 81 Height = 25 Cancel = True Caption = 'E&xit' TabOrder = 30 OnClick = Button1Click end object Button2: TButton Left = 695 Top = 450 Width = 81 Height = 25 Caption = '&Help' TabOrder = 31 OnClick = Button2Click end object CheckBox3: TCheckBox Left = 710 Top = 200 Width = 49 Height = 17 Caption = 'Stereo' Checked = True State = cbChecked TabOrder = 32 end object Panel5: TPanel Left = 177 Top = 32 Width = 32 Height = 20 BevelInner = bvLowered BevelOuter = bvLowered Caption = '100%' Color = clWhite TabOrder = 33 end object TrackBar7: TTrackBar Left = 184 Top = 54 Width = 25 Height = 93 LineSize = 5 Max = 100 Orientation = trVertical PageSize = 10 Frequency = 10 Position = 90 TabOrder = 34 ThumbLength = 15 OnChange = TrackBar1Change end object TrackBar8: TTrackBar Left = 122 Top = 180 Width = 25 Height = 113 LineSize = 5 Max = 19 Orientation = trVertical PageSize = 10 Frequency = 2 Position = 14 TabOrder = 35 ThumbLength = 15 OnChange = TrackBar8Change end object Panel6: TPanel Left = 124 Top = 339 Width = 29 Height = 20 Hint = 'Amplitude' BevelInner = bvLowered BevelOuter = bvLowered Caption = '0%' Color = clWhite Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 36 end object TrackBar9: TTrackBar Left = 129 Top = 359 Width = 25 Height = 89 Hint = 'Amplitude' LineSize = 5 Max = 50 Orientation = trVertical ParentShowHint = False PageSize = 10 Frequency = 5 Position = 50 ShowHint = True TabOrder = 37 ThumbLength = 15 OnChange = TrackBar9Change end object Panel7: TPanel Left = 156 Top = 339 Width = 29 Height = 20 Hint = 'Frequency' BevelInner = bvLowered BevelOuter = bvLowered Caption = 'x0.1' Color = clWhite ParentShowHint = False ShowHint = True TabOrder = 38 end object TrackBar10: TTrackBar Left = 160 Top = 359 Width = 25 Height = 89 Hint = 'Frequency' LineSize = 5 Max = 50 Orientation = trVertical ParentShowHint = False PageSize = 10 Frequency = 5 Position = 45 ShowHint = True TabOrder = 39 ThumbLength = 15 OnChange = TrackBar10Change end object RadioGroup4: TRadioGroup Left = 126 Top = 442 Width = 58 Height = 102 Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ItemIndex = 0 Items.Strings = ( 'Sin' 'Sq' 'Tri' 'Saw' 'Noise') ParentFont = False TabOrder = 40 OnClick = RadioGroup4Click end object Panel8: TPanel Left = 193 Top = 340 Width = 29 Height = 20 Hint = 'Amplitude' BevelInner = bvLowered BevelOuter = bvLowered Caption = '0%' Color = clWhite Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 41 end object TrackBar11: TTrackBar Left = 198 Top = 360 Width = 25 Height = 89 Hint = 'Amplitude' LineSize = 5 Max = 50 Orientation = trVertical ParentShowHint = False PageSize = 10 Frequency = 5 Position = 50 ShowHint = True TabOrder = 42 ThumbLength = 15 OnChange = TrackBar9Change end object Panel9: TPanel Left = 225 Top = 340 Width = 29 Height = 20 Hint = 'Frequency' BevelInner = bvLowered BevelOuter = bvLowered Caption = 'x0.1' Color = clWhite ParentShowHint = False ShowHint = True TabOrder = 43 end object TrackBar12: TTrackBar Left = 229 Top = 360 Width = 25 Height = 89 Hint = 'Frequency' LineSize = 5 Max = 50 Orientation = trVertical ParentShowHint = False PageSize = 10 Frequency = 5 Position = 40 ShowHint = True TabOrder = 44 ThumbLength = 15 OnChange = TrackBar10Change end object RadioGroup5: TRadioGroup Left = 195 Top = 443 Width = 58 Height = 102 Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ItemIndex = 0 Items.Strings = ( 'Sin' 'Sq' 'Tri' 'Saw' 'Noise') ParentFont = False TabOrder = 45 OnClick = RadioGroup4Click end object Panel10: TPanel Left = 261 Top = 340 Width = 29 Height = 20 Hint = 'Amplitude' BevelInner = bvLowered BevelOuter = bvLowered Caption = '0%' Color = clWhite Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 46 end object TrackBar13: TTrackBar Left = 266 Top = 360 Width = 25 Height = 89 Hint = 'Amplitude' LineSize = 5 Max = 50 Orientation = trVertical ParentShowHint = False PageSize = 10 Frequency = 5 Position = 50 ShowHint = True TabOrder = 47 ThumbLength = 15 OnChange = TrackBar9Change end object Panel11: TPanel Left = 293 Top = 340 Width = 29 Height = 20 Hint = 'Frequency' BevelInner = bvLowered BevelOuter = bvLowered Caption = 'x0.1' Color = clWhite ParentShowHint = False ShowHint = True TabOrder = 48 end object TrackBar14: TTrackBar Left = 297 Top = 360 Width = 25 Height = 89 Hint = 'Frequency' LineSize = 5 Max = 50 Orientation = trVertical ParentShowHint = False PageSize = 10 Frequency = 5 Position = 35 ShowHint = True TabOrder = 49 ThumbLength = 15 OnChange = TrackBar10Change end object RadioGroup6: TRadioGroup Left = 263 Top = 443 Width = 58 Height = 102 Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ItemIndex = 0 Items.Strings = ( 'Sin' 'Sq' 'Tri' 'Saw' 'Noise') ParentFont = False TabOrder = 50 OnClick = RadioGroup4Click end object Panel12: TPanel Left = 330 Top = 340 Width = 29 Height = 20 Hint = 'Amplitude' BevelInner = bvLowered BevelOuter = bvLowered Caption = '0%' Color = clWhite Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 51 end object TrackBar15: TTrackBar Left = 335 Top = 360 Width = 25 Height = 89 Hint = 'Amplitude' LineSize = 5 Max = 50 Orientation = trVertical ParentShowHint = False PageSize = 10 Frequency = 5 Position = 50 ShowHint = True TabOrder = 52 ThumbLength = 15 OnChange = TrackBar9Change end object Panel13: TPanel Left = 362 Top = 340 Width = 29 Height = 20 Hint = 'Frequency' BevelInner = bvLowered BevelOuter = bvLowered Caption = 'x0.1' Color = clWhite ParentShowHint = False ShowHint = True TabOrder = 53 end object TrackBar16: TTrackBar Left = 366 Top = 360 Width = 25 Height = 89 Hint = 'Frequency' LineSize = 5 Max = 50 Orientation = trVertical ParentShowHint = False PageSize = 10 Frequency = 5 Position = 30 ShowHint = True TabOrder = 54 ThumbLength = 15 OnChange = TrackBar10Change end object RadioGroup7: TRadioGroup Left = 332 Top = 443 Width = 58 Height = 102 Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ItemIndex = 0 Items.Strings = ( 'Sin' 'Sq' 'Tri' 'Saw' 'Noise') ParentFont = False TabOrder = 55 OnClick = RadioGroup4Click end object Panel14: TPanel Left = 399 Top = 340 Width = 29 Height = 20 Hint = 'Amplitude' BevelInner = bvLowered BevelOuter = bvLowered Caption = '0%' Color = clWhite Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 56 end object TrackBar17: TTrackBar Left = 404 Top = 360 Width = 25 Height = 89 Hint = 'Amplitude' LineSize = 5 Max = 50 Orientation = trVertical ParentShowHint = False PageSize = 10 Frequency = 5 Position = 50 ShowHint = True TabOrder = 57 ThumbLength = 15 OnChange = TrackBar9Change end object Panel15: TPanel Left = 431 Top = 340 Width = 29 Height = 20 Hint = 'Frequency' BevelInner = bvLowered BevelOuter = bvLowered Caption = 'x0.1' Color = clWhite ParentShowHint = False ShowHint = True TabOrder = 58 end object TrackBar18: TTrackBar Left = 435 Top = 360 Width = 25 Height = 89 Hint = 'Frequency' LineSize = 5 Max = 50 Orientation = trVertical ParentShowHint = False PageSize = 10 Frequency = 5 Position = 25 ShowHint = True TabOrder = 59 ThumbLength = 15 OnChange = TrackBar10Change end object RadioGroup8: TRadioGroup Left = 401 Top = 443 Width = 58 Height = 102 Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ItemIndex = 0 Items.Strings = ( 'Sin' 'Sq' 'Tri' 'Saw' 'Noise') ParentFont = False TabOrder = 60 OnClick = RadioGroup4Click end object Panel16: TPanel Left = 468 Top = 340 Width = 29 Height = 20 Hint = 'Amplitude' BevelInner = bvLowered BevelOuter = bvLowered Caption = '0%' Color = clWhite Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 61 end object TrackBar19: TTrackBar Left = 473 Top = 360 Width = 25 Height = 89 Hint = 'Amplitude' LineSize = 5 Max = 50 Orientation = trVertical ParentShowHint = False PageSize = 10 Frequency = 5 Position = 50 ShowHint = True TabOrder = 62 ThumbLength = 15 OnChange = TrackBar9Change end object Panel17: TPanel Left = 500 Top = 340 Width = 29 Height = 20 Hint = 'Frequency' BevelInner = bvLowered BevelOuter = bvLowered Caption = 'x0.1' Color = clWhite ParentShowHint = False ShowHint = True TabOrder = 63 end object TrackBar20: TTrackBar Left = 504 Top = 360 Width = 25 Height = 89 Hint = 'Frequency' LineSize = 5 Max = 50 Orientation = trVertical ParentShowHint = False PageSize = 10 Frequency = 5 Position = 20 ShowHint = True TabOrder = 64 ThumbLength = 15 OnChange = TrackBar10Change end object RadioGroup9: TRadioGroup Left = 470 Top = 443 Width = 58 Height = 102 Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ItemIndex = 0 Items.Strings = ( 'Sin' 'Sq' 'Tri' 'Saw' 'Noise') ParentFont = False TabOrder = 65 OnClick = RadioGroup4Click end object Panel18: TPanel Left = 536 Top = 340 Width = 29 Height = 20 Hint = 'Amplitude' BevelInner = bvLowered BevelOuter = bvLowered Caption = '0%' Color = clWhite Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 66 end object TrackBar21: TTrackBar Left = 541 Top = 360 Width = 25 Height = 89 Hint = 'Amplitude' LineSize = 5 Max = 50 Orientation = trVertical ParentShowHint = False PageSize = 10 Frequency = 5 Position = 50 ShowHint = True TabOrder = 67 ThumbLength = 15 OnChange = TrackBar9Change end object Panel19: TPanel Left = 568 Top = 340 Width = 29 Height = 20 Hint = 'Frequency' BevelInner = bvLowered BevelOuter = bvLowered Caption = 'x0.1' Color = clWhite ParentShowHint = False ShowHint = True TabOrder = 68 end object TrackBar22: TTrackBar Left = 572 Top = 360 Width = 25 Height = 89 Hint = 'Frequency' LineSize = 5 Max = 50 Orientation = trVertical ParentShowHint = False PageSize = 10 Frequency = 5 Position = 15 ShowHint = True TabOrder = 69 ThumbLength = 15 OnChange = TrackBar10Change end object RadioGroup10: TRadioGroup Left = 538 Top = 443 Width = 58 Height = 102 Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ItemIndex = 0 Items.Strings = ( 'Sin' 'Sq' 'Tri' 'Saw' 'Noise') ParentFont = False TabOrder = 70 OnClick = RadioGroup4Click end object Panel20: TPanel Left = 604 Top = 340 Width = 29 Height = 20 Hint = 'Amplitude' BevelInner = bvLowered BevelOuter = bvLowered Caption = '0%' Color = clWhite Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 71 end object TrackBar23: TTrackBar Left = 609 Top = 360 Width = 25 Height = 89 Hint = 'Amplitude' LineSize = 5 Max = 50 Orientation = trVertical ParentShowHint = False PageSize = 10 Frequency = 5 Position = 50 ShowHint = True TabOrder = 72 ThumbLength = 15 OnChange = TrackBar9Change end object Panel21: TPanel Left = 636 Top = 340 Width = 29 Height = 20 Hint = 'Frequency' BevelInner = bvLowered BevelOuter = bvLowered Caption = 'x0.1' Color = clWhite ParentShowHint = False ShowHint = True TabOrder = 73 end object TrackBar24: TTrackBar Left = 640 Top = 360 Width = 25 Height = 89 Hint = 'Frequency' LineSize = 5 Max = 50 Orientation = trVertical ParentShowHint = False PageSize = 10 Frequency = 5 Position = 10 ShowHint = True TabOrder = 74 ThumbLength = 15 OnChange = TrackBar10Change end object RadioGroup11: TRadioGroup Left = 606 Top = 443 Width = 58 Height = 102 Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ItemIndex = 0 Items.Strings = ( 'Sin' 'Sq' 'Tri' 'Saw' 'Noise') ParentFont = False TabOrder = 75 OnClick = RadioGroup4Click end object Button4: TButton Left = 5 Top = 364 Width = 25 Height = 19 Caption = 'A' TabOrder = 76 OnClick = Button4Click end object Button5: TButton Left = 30 Top = 364 Width = 25 Height = 19 Caption = 'A#' TabOrder = 77 OnClick = Button4Click end object Button15: TButton Left = 55 Top = 364 Width = 25 Height = 19 Caption = 'B' TabOrder = 78 OnClick = Button4Click end object Button16: TButton Left = 80 Top = 364 Width = 25 Height = 19 Caption = 'C' TabOrder = 79 OnClick = Button4Click end object Button17: TButton Left = 5 Top = 382 Width = 25 Height = 19 Caption = 'C#' TabOrder = 80 OnClick = Button4Click end object Button18: TButton Left = 30 Top = 382 Width = 25 Height = 19 Caption = 'D' TabOrder = 81 OnClick = Button4Click end object Button19: TButton Left = 55 Top = 382 Width = 25 Height = 19 Caption = 'D#' TabOrder = 82 OnClick = Button4Click end object Button20: TButton Left = 80 Top = 382 Width = 25 Height = 19 Caption = 'E' TabOrder = 83 OnClick = Button4Click end object Button21: TButton Left = 5 Top = 400 Width = 25 Height = 19 Caption = 'F' TabOrder = 84 OnClick = Button4Click end object Button22: TButton Left = 30 Top = 400 Width = 25 Height = 19 Caption = 'F#' TabOrder = 85 OnClick = Button4Click end object Button23: TButton Left = 55 Top = 400 Width = 25 Height = 19 Caption = 'G' TabOrder = 86 OnClick = Button4Click end object Button24: TButton Left = 80 Top = 400 Width = 25 Height = 19 Caption = 'G#' TabOrder = 87 OnClick = Button4Click end object TrackBar25: TTrackBar Left = 3 Top = 435 Width = 81 Height = 25 Hint = 'Octave' Max = 9 ParentShowHint = False Position = 4 ShowHint = True TabOrder = 88 ThumbLength = 10 OnChange = TrackBar25Change end object Panel22: TPanel Left = 83 Top = 436 Width = 18 Height = 19 Hint = 'Octave' BevelInner = bvLowered BevelOuter = bvLowered Caption = '4' Color = clWhite Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 89 end object Button25: TButton Left = 687 Top = 544 Width = 103 Height = 26 Caption = 'Export File' TabOrder = 90 OnClick = Button25Click end object Edit3: TEdit Left = 687 Top = 521 Width = 101 Height = 21 TabOrder = 91 Text = 'c:\test.wav' end object RadioButton1: TRadioButton Left = 607 Top = 553 Width = 65 Height = 14 Caption = 'Absolute' TabOrder = 92 OnClick = TrackBar10Change end object RadioButton2: TRadioButton Left = 535 Top = 553 Width = 65 Height = 14 Caption = 'Multiply' Checked = True TabOrder = 93 TabStop = True OnClick = TrackBar10Change end object Button26: TButton Left = 123 Top = 551 Width = 52 Height = 16 Caption = 'Reset' TabOrder = 94 OnClick = Button26Click end object Timer2: TTimer Enabled = False Interval = 150 OnTimer = Timer2Timer Left = 638 Top = 22 end object Timer3: TTimer Enabled = False Interval = 5000 OnTimer = Timer3Timer Left = 606 Top = 22 end object ToneGen1: TToneGen Frequency = 100 Hold = 10 AMAmplitude = 30 AMWaveform = tgSine AMFrequency = 0.300000011920929000 Left = 574 Top = 22 AMArrayData = { 070000001E000000000000009A99993E00000000000000000000C03F00000000 000000000000A04100000000000000000000A04100000000000000000000A041 00000000000000000000A04100000000000000000000A0410000000002000000 0000A041} end object WaveTTG: TToneGen Frequency = 800 Duration = 50 Resolution = tg8Bit Quality = tgLoQ AMAmplitude = 30 AMWaveform = tgSquare AMFrequency = 4.000000000000000000 Left = 544 Top = 22 AMArrayData = { 070000001E00000001000000000080400A000000010000000000003F00000000 040000000000C03F000000000000000000000040000000000000000000002040 0000000000000000000040400000000000000000000060400000000000000000 00008040} end end