Blend up to four waveforms with independent frequency, amplitude, and balance control.
Choose between sine wave, or square wave with duty cycle adjustment.
Choose between mono or stereo output.
When 'hop' mode is selected F1 and F4 set upper and lower boundaries of random frequencies.
F2 and F3 values have no effect in this mode.

Code: Select all
;====================================
; Title : Awesome Audio Generator |
; Author : BasicallyPure |
; Date : 8/29/2015 |
; Version : 1.0 |
; OS : Windows |
; License : Free and risky |
; Compiler: PureBasic 5.31 |
;====================================
EnableExplicit
#Version = "1.0"
#WinMain = 0
#PIx2 = 2*#PI
#Mono = 1
#Stereo = 2
#Menu_1 = 0
#BuffSize = 8192 ; determines BlockSize per channel
#Input_Finished = #PB_EventType_FirstCustomValue
;{ gadgets
Enumeration
#Spin_F1 : #Spin_F2 : #Spin_F3 : #Spin_F4
#Track_Vol_F1 : #Track_Vol_F2 : #Track_Vol_F3 : #Track_Vol_F4
#Track_Bal_F1 : #Track_Bal_F2 : #Track_Bal_F3 : #Track_Bal_F4
#Track_Duty_F1 : #Track_Duty_F2 : #Track_Duty_F3 : #Track_Duty_F4
#Check_Sq_F1 : #Check_Sq_F2 : #Check_Sq_F3 : #Check_Sq_F4
#Check_Hop : #Button_Run : #Option_Mono : #Option_Stereo
#Text_Duty_F1 : #Text_Duty_F2 : #Text_Duty_F3 : #Text_Duty_F4
#Text_Vol_F1 : #Text_Vol_F2 : #Text_Vol_F3 : #Text_Vol_F4
#Text_Bal_F1 : #Text_Bal_F2 : #Text_Bal_F3 : #Text_Bal_F4
#Canvas_Scope_L: #Canvas_Scope_R: #Text_Scope : #Track_Scope
EndEnumeration : ;}
;menu items
#MenuItem_EnterKey = 0
#MenuItem_OnTop = 1
#MenuItem_ScopeAuto = 2
#Last_Menu_Item = 3
;{ Global variables
Global WinColor = GetSysColor_(#COLOR_BTNFACE) ;use for default system color
;Global WinColor = $BAB5A1 ; use for modified color scheme
Global SampleClock = 44100 ; Sampling frequency in 'samples per second'
Global BytesPerSample = 2 ; Number of bytes needed for each sample, don't change this
Global Channels = #Stereo ; Number of channels, 1 for mono, 2 for stereo.
Global nBuf = 8 ; Number of buffers
Global DevOut = 1 ; default audio output device
Global Freq_F1 = 220 ; initial frequencies
Global Freq_F2 = 330
Global Freq_F3 = 440
Global Freq_F4 = 550
Global Vol_F1.f = 0.20 ; initial volumes
Global Vol_F2.f = 0.20
Global Vol_F3.f = 0.20
Global Vol_F4.f = 0.20
Global Bal_F1.f = 0.50 ; initial balance settings
Global Bal_F2.f = 0.50
Global Bal_F3.f = 0.50
Global Bal_F4.f = 0.50
Global hWaveOut ;Pointer to a buffer that receives a handle identifying the open waveform-audio output device
Global NumOutDevs
Global BlockSize ; determined by #BuffSize and Channels
Global OutDev_1 ; the first available audio output device
Global Hop = #False
Global Pause = #True
Global Trig = #True
Global Square_F1 = #False
Global Square_F2 = #False
Global Square_F3 = #False
Global Square_F4 = #False
Global Duty_F1.f = #PI * 0.02 * 50 ;50% duty
Global Duty_F2.f = #PI * 0.02 * 50 ;50% duty
Global Duty_F3.f = #PI * 0.02 * 50 ;50% duty
Global Duty_F4.f = #PI * 0.02 * 50 ;50% duty
Global Hscale.i = 15 ;scope horizontal scale, 1...|...20
Global stickyState = 0
Global autoTrig = 1
Global.d Vol_L1,Vol_L2,Vol_L3,Vol_L4,Vol_R1,Vol_R2,Vol_R3,Vol_R4
Global imgID_L, imgID_R ;scope bkgnd images
Global *ScopeBuff
Global PlayFormat.WAVEFORMATEX
Global MyOutDevs.WAVEOUTCAPS
Global Dim outHdr.WAVEHDR(nBuf)
;}
Procedure SCOPE()
Static sf.d = 50.0/32767.0 ;scale factor
Protected a,x,y, Lx, Ly, aMax, stp
If *ScopeBuff = 0 : ProcedureReturn : EndIf
Trig = #False
aMax = *ScopeBuff + (200 * Hscale * Channels * BytesPerSample)
stp = BytesPerSample * Channels * Hscale
StartDrawing(CanvasOutput(#Canvas_Scope_L))
DrawImage(imgID_L,0,0)
a = *ScopeBuff
Ly = 50 + PeekW(a) * sf
While a < aMax
y = 50 + PeekW(a) * sf
LineXY(Lx,Ly,x,y,$00FFFF)
a + stp
Lx = x : Ly = y
x + 1
Wend
StopDrawing()
StartDrawing(CanvasOutput(#Canvas_Scope_R))
DrawImage(imgID_R,0,0)
a = *ScopeBuff
If Channels = #Stereo : a + BytesPerSample : EndIf
x = 0 : Lx = 0
Ly = 50 + PeekW(a) * sf
While a < aMax
y = 50 + PeekW(a) * sf
LineXY(Lx,Ly,x,y,$00FFFF)
a + stp
Lx = x : Ly = y
x + 1
Wend
StopDrawing()
EndProcedure
Procedure MAKE_WAVES(*SBuf)
Static.d A1,A2,A3,A4,S1,S2,S3,S4,LL,UL,K1,K2,K3,K4
Static.l value_L, value_R, sample
*ScopeBuff = *SBuf
If Hop
LL = GetGadgetState(#Spin_F1)
UL = GetGadgetState(#Spin_F4)
If LL > UL : Swap LL,UL : EndIf
Freq_F1 = Random(UL,LL)
Freq_F2 = Random(UL,LL)
Freq_F3 = Random(UL,LL)
Freq_F4 = Random(UL,LL)
Trig = #True
EndIf
; calculate angel increments
K1 = #PIx2 * Freq_F1 / SampleClock
K2 = #PIx2 * Freq_F2 / SampleClock
K3 = #PIx2 * Freq_F3 / SampleClock
K4 = #PIx2 * Freq_F4 / SampleClock
sample = 1
Repeat ; Generate waveform data
If Square_F1 : S1 = Sign(Duty_F1-A1) : Else : S1 = Sin(A1) : EndIf
If Square_F2 : S2 = Sign(Duty_F2-A2) : Else : S2 = Sin(A2) : EndIf
If Square_F3 : S3 = Sign(Duty_F3-A3) : Else : S3 = Sin(A3) : EndIf
If Square_F4 : S4 = Sign(Duty_F4-A4) : Else : S4 = Sin(A4) : EndIf
value_L = S1 * Vol_L1 + S2 * Vol_L2 + S3 * Vol_L3 + S4 * Vol_L4
PokeW(*SBuf,value_L) ; Put data point in buffer
*SBuf + BytesPerSample ; move buffer pointer to next sample
If Channels = #Stereo
value_R = S1 * Vol_R1 + S2 * Vol_R2 + S3 * Vol_R3 + S4 * Vol_R4
PokeW(*SBuf,value_R)
*SBuf + BytesPerSample
EndIf
; calculate angle for next time
A1 + K1 : If A1 > #PIx2 : A1 - #PIx2 : EndIf
A2 + K2 : If A2 > #PIx2 : A2 - #PIx2 : EndIf
A3 + K3 : If A3 > #PIx2 : A3 - #PIx2 : EndIf
A4 + K4 : If A4 > #PIx2 : A4 - #PIx2 : EndIf
sample + PlayFormat\nBlockAlign
Until sample > BlockSize
If autoTrig : SCOPE() : ElseIf Trig : SCOPE() : EndIf
EndProcedure
Procedure WIN_CALLBACK(hwnd, uMsg, wParam, lParam)
; Window callback to service sound output message
; also generate LostFocus events for spin gadgets
Static *hWaveO.WAVEHDR
Protected gadget
Select uMsg
Case #MM_WOM_DONE ; Sound output, a play buffer has been returned.
*hWaveO.WAVEHDR = lParam ; lParam has the address of WAVEHDR
MAKE_WAVES(*hWaveO\lpData) ; send pointer where to write NEW data
*hWaveO\dwBytesRecorded = BlockSize ; Number of bytes written into buffer
waveOutWrite_(hWaveOut,lParam, SizeOf(WAVEHDR)) ; Send to sound device => jack socket => cable =>
Case #WM_COMMAND
Select wParam >> 16 ; get HiWord
Case #EN_KILLFOCUS
gadget = wParam & $FFFF ; get LoWord
If GadgetType(gadget) = #PB_GadgetType_Spin
PostEvent(#PB_Event_Gadget, #WinMain, gadget, #PB_EventType_LostFocus)
EndIf
;Case #EN_SETFOCUS
;PostEvent(#PB_Event_Gadget, #WinMain, gadget, #PB_EventType_Focus)
EndSelect
EndSelect
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
Procedure BUILD_GUI(x = 0, y = 0, width = 710, height = 320)
Protected hWinMain, n, result
Protected flags = #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered
hWinMain = OpenWindow(#WinMain, x, y, width, height, "Awesome Audio Generator "+#Version, flags)
If hWinMain
result = hWinMain
SetWindowColor(#WinMain,WinColor)
StickyWindow(#WinMain,stickyState)
CreateMenu(#Menu_1, hWinMain)
MenuTitle("Sound Output Devices")
OutDev_1 = #Last_Menu_Item
NumOutDevs = waveOutGetNumDevs_()
If NumOutDevs <> 0 : NumOutDevs - 1
For n = OutDev_1 To OutDev_1 + NumOutDevs
If waveOutGetDevCaps_(n-OutDev_1,@MyOutDevs,SizeOf(WAVEOUTCAPS)) = 0
MenuItem(n ,PeekS(@MyOutDevs\szPname))
EndIf
Next
SetMenuItemState(#Menu_1,OutDev_1,#True)
SetWindowCallback(@WIN_CALLBACK()) ; Handle Sound Output callback
Else
MessageRequester("Error!","No audio output device found.")
result = 0
EndIf
MenuTitle("Options")
MenuItem(#MenuItem_ScopeAuto,"Scope Continuous")
SetMenuItemState(#Menu_1,#MenuItem_ScopeAuto,autoTrig)
MenuItem(#MenuItem_OnTop,"Always on top")
AddKeyboardShortcut(#WinMain,#PB_Shortcut_Return,#MenuItem_EnterKey)
; ================= the scopes ======================
CanvasGadget(#Canvas_Scope_L,290,5,200,101)
CanvasGadget(#Canvas_Scope_R,500,5,200,101)
imgID_L = CreateImage(0,200,101,24,$1A6A0F)
imgID_R = CreateImage(1,200,101,24,$1A6A0F)
For n = 0 To 1 ; draw graticules
StartDrawing(ImageOutput(n))
For x = 0 To 200 Step 25 : LineXY(x,0,x,101,0) : Next x
For y = 0 To 100 Step 25 : LineXY(0,y,200,y,0) : Next y
If n =0
DrawText(5,5,"Left",$00FF00,$1A6A0F)
Else
DrawText(5,5,"Right",$00FF00,$1A6A0F)
EndIf
StopDrawing()
Next n
StartDrawing(CanvasOutput(#Canvas_Scope_L)) : DrawImage(imgID_L,0,0) : StopDrawing()
StartDrawing(CanvasOutput(#Canvas_Scope_R)) : DrawImage(imgID_R,0,0) : StopDrawing()
; =====================================================
ButtonGadget(#Button_Run, 10, 05, 65, 95, "R U N", #PB_Button_Toggle)
SetGadgetState(#Button_Run,Pause)
SpinGadget(#Spin_F1, 45, 140, 65, 20, 10, 10000, #PB_Spin_Numeric)
SpinGadget(#Spin_F2, 45, 180, 65, 20, 10, 10000, #PB_Spin_Numeric)
SpinGadget(#Spin_F3, 45, 220, 65, 20, 10, 10000, #PB_Spin_Numeric)
SpinGadget(#Spin_F4, 45, 260, 65, 20, 10, 10000, #PB_Spin_Numeric)
FrameGadget(#PB_Any, 80, 0, 200, 50, "Mode")
FrameGadget(#PB_Any, 130, 110, 150, 180, "Amplitude")
FrameGadget(#PB_Any, 10, 110, 110, 180, "Frequency")
FrameGadget(#PB_Any, 290, 110, 200, 180, "Balance")
FrameGadget(#PB_Any, 500, 110, 200, 180, "SquareWave option")
TrackBarGadget(#Track_Vol_F1, 140, 140, 100, 20, 0, 100)
TrackBarGadget(#Track_Vol_F2, 140, 180, 100, 20, 0, 100)
TrackBarGadget(#Track_Vol_F3, 140, 220, 100, 20, 0, 100)
TrackBarGadget(#Track_Vol_F4, 140, 260, 100, 20, 0, 100)
TrackBarGadget(#Track_Bal_F1, 325, 140, 100, 20, 0, 100)
TrackBarGadget(#Track_Bal_F2, 325, 180, 100, 20, 0, 100)
TrackBarGadget(#Track_Bal_F3, 325, 220, 100, 20, 0, 100)
TrackBarGadget(#Track_Bal_F4, 325, 260, 100, 20, 0, 100)
CheckBoxGadget(#Check_Sq_F1, 510, 140, 20, 20, " ")
TrackBarGadget(#Track_Duty_F1, 565, 140, 100, 20, 1, 99)
CheckBoxGadget(#Check_Sq_F2, 510, 180, 20, 20, " ")
TrackBarGadget(#Track_Duty_F2, 565, 180, 100, 20, 1, 99)
CheckBoxGadget(#Check_Sq_F3, 510, 220, 20, 20, " ")
TrackBarGadget(#Track_Duty_F3, 565, 220, 100, 20, 1, 99)
CheckBoxGadget(#Check_Sq_F4, 510, 260, 20, 20, " ")
TrackBarGadget(#Track_Duty_F4, 565, 260, 100, 20, 1, 99)
TrackBarGadget(#Track_Scope, 140, 80, 100, 20, 1, 20)
CheckBoxGadget(#Check_Hop , 230, 020, 40, 20, "Hop")
OptionGadget(#Option_Mono , 090, 20, 60, 20, "Mono")
OptionGadget(#Option_Stereo, 160, 20, 60, 20, "Stereo")
SetGadgetColor(TextGadget(#PB_Any, 20, 143, 20, 20, "F1", #PB_Text_Right),
#PB_Gadget_BackColor,WinColor)
SetGadgetColor(TextGadget(#PB_Any, 20, 183, 20, 20, "F2", #PB_Text_Right),
#PB_Gadget_BackColor,WinColor)
SetGadgetColor(TextGadget(#PB_Any, 20, 223, 20, 20, "F3", #PB_Text_Right),
#PB_Gadget_BackColor,WinColor)
SetGadgetColor(TextGadget(#PB_Any, 20, 263, 20, 20, "F4", #PB_Text_Right),
#PB_Gadget_BackColor,WinColor)
SetGadgetColor(TextGadget(#PB_Any, 300, 143, 20, 20, "L", #PB_Text_Right),
#PB_Gadget_BackColor,WinColor)
SetGadgetColor(TextGadget(#PB_Any, 300, 183, 20, 20, "L", #PB_Text_Right),
#PB_Gadget_BackColor,WinColor)
SetGadgetColor(TextGadget(#PB_Any, 300, 223, 20, 20, "L", #PB_Text_Right),
#PB_Gadget_BackColor,WinColor)
SetGadgetColor(TextGadget(#PB_Any, 300, 263, 20, 20, "L", #PB_Text_Right),
#PB_Gadget_BackColor,WinColor)
SetGadgetColor(TextGadget(#PB_Any, 430, 143, 20, 20, "R"),
#PB_Gadget_BackColor,WinColor)
SetGadgetColor(TextGadget(#PB_Any, 430, 183, 20, 20, "R"),
#PB_Gadget_BackColor,WinColor)
SetGadgetColor(TextGadget(#PB_Any, 430, 223, 20, 20, "R"),
#PB_Gadget_BackColor,WinColor)
SetGadgetColor(TextGadget(#PB_Any, 430, 263, 20, 20, "R"),
#PB_Gadget_BackColor,WinColor)
SetGadgetColor(TextGadget(#PB_Any, 535, 143, 25, 20, "Duty", #PB_Text_Right),
#PB_Gadget_BackColor,WinColor)
SetGadgetColor(TextGadget(#PB_Any, 535, 183, 25, 20, "Duty", #PB_Text_Right),
#PB_Gadget_BackColor,WinColor)
SetGadgetColor(TextGadget(#PB_Any, 535, 223, 25, 20, "Duty", #PB_Text_Right),
#PB_Gadget_BackColor,WinColor)
SetGadgetColor(TextGadget(#PB_Any, 535, 263, 25, 20, "Duty", #PB_Text_Right),
#PB_Gadget_BackColor,WinColor)
SetGadgetColor(TextGadget(#PB_Any, 140, 60, 140, 15, "Scope Horizontal Scale"),
#PB_Gadget_BackColor,WinColor)
TextGadget(#Text_Duty_F1, 675, 143, 20, 20, Str(Duty_F1*50/#PI))
SetGadgetColor(#Text_Duty_F1,#PB_Gadget_BackColor,WinColor)
TextGadget(#Text_Duty_F2, 675, 183, 20, 20, Str(Duty_F2*50/#PI))
SetGadgetColor(#Text_Duty_F2,#PB_Gadget_BackColor,WinColor)
TextGadget(#Text_Duty_F3, 675, 223, 20, 20, Str(Duty_F3*50/#PI))
SetGadgetColor(#Text_Duty_F3,#PB_Gadget_BackColor,WinColor)
TextGadget(#Text_Duty_F4, 675, 263, 20, 20, Str(Duty_F4*50/#PI))
SetGadgetColor(#Text_Duty_F4,#PB_Gadget_BackColor,WinColor)
TextGadget(#Text_Vol_F1, 250, 143, 20, 20, Str(Vol_F1*100))
SetGadgetColor(#Text_Vol_F1,#PB_Gadget_BackColor,WinColor)
TextGadget(#Text_Vol_F2, 250, 183, 20, 20, Str(Vol_F2*100))
SetGadgetColor(#Text_Vol_F2,#PB_Gadget_BackColor,WinColor)
TextGadget(#Text_Vol_F3, 250, 223, 20, 20, Str(Vol_F3*100))
SetGadgetColor(#Text_Vol_F3,#PB_Gadget_BackColor,WinColor)
TextGadget(#Text_Vol_F4, 250, 263, 20, 20, Str(Vol_F4*100))
SetGadgetColor(#Text_Vol_F4,#PB_Gadget_BackColor,WinColor)
TextGadget(#Text_Bal_F1, 450, 143, 20, 20, Str(Bal_F1*100),#PB_Text_Center)
SetGadgetColor(#Text_Bal_F1,#PB_Gadget_BackColor,WinColor)
TextGadget(#Text_Bal_F2, 450, 183, 20, 20, Str(Bal_F2*100),#PB_Text_Center)
SetGadgetColor(#Text_Bal_F2,#PB_Gadget_BackColor,WinColor)
TextGadget(#Text_Bal_F3, 450, 223, 20, 20, Str(Bal_F3*100),#PB_Text_Center)
SetGadgetColor(#Text_Bal_F3,#PB_Gadget_BackColor,WinColor)
TextGadget(#Text_Bal_F4, 450, 263, 20, 20, Str(Bal_F4*100),#PB_Text_Center)
SetGadgetColor(#Text_Bal_F4,#PB_Gadget_BackColor,WinColor)
TextGadget(#Text_Scope, 250, 83, 20, 20, Str(Hscale))
SetGadgetColor(#Text_Scope,#PB_Gadget_BackColor,WinColor)
EndIf
ProcedureReturn result
EndProcedure
Procedure SCALE_VOLUME()
Protected.d adj, m
; wave 1
m = 32767 / Abs(Bool(Bal_F1<0.5) - Bal_F1)
adj = m / (4 - (1-Vol_F2) - (1-Vol_F3) - (1-Vol_F4))
Vol_L1 = Vol_F1 * adj * (1.0 - Bal_F1)
Vol_R1 = Vol_F1 * adj * Bal_F1
;wave 2
m = 32767 / Abs(Bool(Bal_F2<0.5) - Bal_F2)
adj = m / (4 - (1-Vol_F1) - (1-Vol_F3) - (1-Vol_F4))
Vol_L2 = Vol_F2 * adj * (1.0 - Bal_F2)
Vol_R2 = Vol_F2 * adj * Bal_F2
; wave 3
m = 32767 / Abs(Bool(Bal_F3<0.5) - Bal_F3)
adj = m / (4 - (1-Vol_F1) - (1-Vol_F2) - (1-Vol_F4))
Vol_L3 = Vol_F3 * adj * (1.0 - Bal_F3)
Vol_R3 = Vol_F3 * adj * Bal_F3
; wave 4
m = 32767 / Abs(Bool(Bal_F4<0.5) - Bal_F4)
adj = m / (4 - (1-Vol_F1) - (1-Vol_F2) - (1-Vol_F3))
Vol_L4 = Vol_F4 * adj * (1.0 - Bal_F4)
Vol_R4 = Vol_F4 * adj * Bal_F4
Trig = #True
If pause And *ScopeBuff : MAKE_WAVES(*ScopeBuff) : EndIf
EndProcedure
Procedure INIT_GADGETS()
SetGadgetState(#Option_Stereo,1)
SetGadgetState(#Spin_F1,Freq_F1) : SetGadgetText(#Spin_F1,Str(Freq_F1))
SetGadgetState(#Spin_F2,Freq_F2) : SetGadgetText(#Spin_F2,Str(Freq_F2))
SetGadgetState(#Spin_F3,Freq_F3) : SetGadgetText(#Spin_F3,Str(Freq_F3))
SetGadgetState(#Spin_F4,Freq_F4) : SetGadgetText(#Spin_F4,Str(Freq_F4))
SetGadgetState(#Track_Vol_F1,Vol_F1*100)
SetGadgetState(#Track_Vol_F2,Vol_F2*100)
SetGadgetState(#Track_Vol_F3,Vol_F3*100)
SetGadgetState(#Track_Vol_F4,Vol_F4*100)
SetGadgetState(#Track_Bal_F1,Bal_F1*100)
SetGadgetState(#Track_Bal_F2,Bal_F2*100)
SetGadgetState(#Track_Bal_F3,Bal_F3*100)
SetGadgetState(#Track_Bal_F4,Bal_F4*100)
SetGadgetState(#Track_Duty_F1,50) : DisableGadget(#Track_Duty_F1,1)
SetGadgetState(#Track_Duty_F2,50) : DisableGadget(#Track_Duty_F2,1)
SetGadgetState(#Track_Duty_F3,50) : DisableGadget(#Track_Duty_F3,1)
SetGadgetState(#Track_Duty_F4,50) : DisableGadget(#Track_Duty_F4,1)
SetGadgetState(#Track_Scope,Hscale) : Hscale = 21-Hscale
SetActiveGadget(#Button_Run)
SCALE_VOLUME()
EndProcedure
Procedure START_SOUND_OUTPUT()
Protected T,i, *P
Static *OutBufMem
With PlayFormat
\wFormatTag = #WAVE_FORMAT_PCM
\nChannels = Channels
\wBitsPerSample = BytesPerSample * 8
\nSamplesPerSec = SampleClock
\nBlockAlign = Channels * BytesPerSample
\nAvgBytesPerSec = \nSamplesPerSec * \nBlockAlign
EndWith
BlockSize = #BuffSize * Channels
If *OutBufMem : FreeMemory(*OutBufMem) : EndIf ; Free a prior assignement
*OutBufMem = AllocateMemory(BlockSize * nBuf) ; Reserve memory for all the buffers
T = waveOutOpen_(@hWaveOut, #WAVE_MAPPER+DevOut, @PlayFormat, WindowID(#WinMain), #True, #CALLBACK_WINDOW | #WAVE_FORMAT_DIRECT)
If T = #MMSYSERR_NOERROR
*P = *OutBufMem ; Pointer to start of memory
For i = 0 To nBuf-1 ; For each buffer
outHdr(i)\lpData = *P ; start of buffer
outHdr(i)\dwBufferLength = BlockSize ; size of buffer
outHdr(i)\dwFlags = 0
outHdr(i)\dwLoops = 0
T | waveOutPrepareHeader_(hWaveOut, outHdr(i), SizeOf(WAVEHDR))
*P + BlockSize
Next
For i = 0 To nBuf-1
PostMessage_(WindowID(#WinMain),#MM_WOM_DONE,0,outHdr(i))
Next
EndIf
If T = #MMSYSERR_NOERROR
If Pause : waveOutPause_(hWaveOut) : EndIf
ProcedureReturn 1
Else : ProcedureReturn 0
EndIf
EndProcedure
Procedure STOP_SOUND_OUTPUT()
Protected i
waveOutReset_(hWaveOut)
For i = 0 To nBuf - 1
waveOutUnprepareHeader_(hWaveOut, outHdr(i), SizeOf(WAVEHDR))
Next
waveOutClose_(hWaveOut)
EndProcedure
Procedure PROCESS_RUN_PAUSE()
; handle 'Run' button event
Pause = GetGadgetState(#Button_Run)
If Pause
waveOutPause_(hWaveOut)
SetGadgetText(#Button_Run,"R U N")
Else
waveOutRestart_(hWaveOut)
SetGadgetText(#Button_Run,"PAUSE")
EndIf
EndProcedure
Procedure PROCESS_SPIN(nGad,*Freq)
Select EventType()
Case #PB_EventType_Up, #PB_EventType_Down
PokeI(*Freq, GetGadgetState(nGad))
Case #Input_Finished, #PB_EventType_LostFocus
SetGadgetState(nGad,Val(GetGadgetText(nGad)))
PokeI(*Freq, GetGadgetState(nGad))
EndSelect
EndProcedure
Procedure PROCESS_FREQUENCY_CHANGE()
; handle frequency spin gadget events
Select EventGadget()
Case #Spin_F1 : PROCESS_SPIN(#Spin_F1, @Freq_F1)
Case #Spin_F2 : PROCESS_SPIN(#Spin_F2, @Freq_F2)
Case #Spin_F3 : PROCESS_SPIN(#Spin_F3, @Freq_F3)
Case #Spin_F4 : PROCESS_SPIN(#Spin_F4, @Freq_F4)
EndSelect
Trig = #True
EndProcedure
Procedure PROCESS_VOLUME_CHANGE()
Protected gadget = EventGadget(), vol = GetGadgetState(gadget)
Select gadget
Case #Track_Vol_F1 : SetGadgetText(#Text_Vol_F1,Str(vol)) : Vol_F1 = vol/100
Case #Track_Vol_F2 : SetGadgetText(#Text_Vol_F2,Str(vol)) : Vol_F2 = vol/100
Case #Track_Vol_F3 : SetGadgetText(#Text_Vol_F3,Str(vol)) : Vol_F3 = vol/100
Case #Track_Vol_F4 : SetGadgetText(#Text_Vol_F4,Str(vol)) : Vol_F4 = vol/100
EndSelect
SCALE_VOLUME()
EndProcedure
Procedure PROCESS_BALANCE_CHANGE()
Protected gadget = EventGadget()
Protected bal = GetGadgetState(gadget)
Select gadget
Case #Track_Bal_F1 : SetGadgetText(#Text_Bal_F1,Str(bal)) : Bal_F1 = bal/100
Case #Track_Bal_F2 : SetGadgetText(#Text_Bal_F2,Str(bal)) : Bal_F2 = bal/100
Case #Track_Bal_F3 : SetGadgetText(#Text_Bal_F3,Str(bal)) : Bal_F3 = bal/100
Case #Track_Bal_F4 : SetGadgetText(#Text_Bal_F4,Str(bal)) : Bal_F4 = bal/100
EndSelect
SCALE_VOLUME()
EndProcedure
Procedure PROCESS_DUTY_CHANGE()
Select EventGadget()
Case #Track_Duty_F1 : Duty_F1 = #PI * 0.02 * GetGadgetState(#Track_Duty_F1)
SetGadgetText(#Text_Duty_F1,Str(GetGadgetState(#Track_Duty_F1)))
Case #Track_Duty_F2 : Duty_F2 = #PI * 0.02 * GetGadgetState(#Track_Duty_F2)
SetGadgetText(#Text_Duty_F2,Str(GetGadgetState(#Track_Duty_F2)))
Case #Track_Duty_F3 : Duty_F3 = #PI * 0.02 * GetGadgetState(#Track_Duty_F3)
SetGadgetText(#Text_Duty_F3,Str(GetGadgetState(#Track_Duty_F3)))
Case #Track_Duty_F4 : Duty_F4 = #PI * 0.02 * GetGadgetState(#Track_Duty_F4)
SetGadgetText(#Text_Duty_F4,Str(GetGadgetState(#Track_Duty_F4)))
EndSelect
SCALE_VOLUME()
EndProcedure
Procedure PROCESS_SQUARE_OPTION()
Select EventGadget()
Case #Check_Sq_F1 : Square_F1 = GetGadgetState(#Check_Sq_F1)
DisableGadget(#Track_Duty_F1, Square_F1 ! 1)
Case #Check_Sq_F2 : Square_F2 = GetGadgetState(#Check_Sq_F2)
DisableGadget(#Track_Duty_F2, Square_F2 ! 1)
Case #Check_Sq_F3 : Square_F3 = GetGadgetState(#Check_Sq_F3)
DisableGadget(#Track_Duty_F3, Square_F3 ! 1)
Case #Check_Sq_F4 : Square_F4 = GetGadgetState(#Check_Sq_F4)
DisableGadget(#Track_Duty_F4, Square_F4 ! 1)
EndSelect
SCALE_VOLUME()
EndProcedure
Procedure PROCESS_HOP_OPTION()
hop = GetGadgetState(#Check_Hop)
If Not hop
Freq_F1 = GetGadgetState(#Spin_F1)
Freq_F2 = GetGadgetState(#Spin_F2)
Freq_F3 = GetGadgetState(#Spin_F3)
Freq_F4 = GetGadgetState(#Spin_F4)
Trig = #True
EndIf
EndProcedure
Procedure SWITCH_MODE(mode)
Static Dim LB(3)
Protected gadget
If Channels = mode : ProcedureReturn : EndIf
Select mode
Case #Mono
STOP_SOUND_OUTPUT() : Channels = #Mono : START_SOUND_OUTPUT()
For gadget = #Track_Bal_F1 To #Track_Bal_F4
DisableGadget(gadget,1)
LB(gadget - #Track_Bal_F1) = GetGadgetState(gadget)
SetGadgetState(gadget,0)
PostEvent(#PB_Event_Gadget,#WinMain,gadget)
Next gadget
Case #Stereo
STOP_SOUND_OUTPUT() : Channels = #Stereo : START_SOUND_OUTPUT()
For gadget = #Track_Bal_F1 To #Track_Bal_F4
DisableGadget(gadget,0)
SetGadgetState(gadget,LB(gadget - #Track_Bal_F1))
PostEvent(#PB_Event_Gadget,#WinMain,gadget)
Next gadget
EndSelect
SCALE_VOLUME()
EndProcedure
Procedure CHANGE_SCOPE_SCALE()
Hscale = 21 - GetGadgetState(#Track_Scope)
SetGadgetText(#Text_Scope,Str(21-Hscale))
SCOPE()
EndProcedure
Procedure SET_SCOPE_MODE()
autoTrig = GetMenuItemState(#Menu_1,#MenuItem_ScopeAuto) ! 1
SetMenuItemState(#Menu_1,#MenuItem_ScopeAuto,autoTrig)
EndProcedure
Procedure ACTIVATE_STICKY_WINDOW()
stickyState = GetMenuItemState(#Menu_1,#MenuItem_OnTop) ! 1
SetMenuItemState(#Menu_1,#MenuItem_OnTop,stickyState)
StickyWindow(#WinMain,stickyState)
EndProcedure
Procedure PROCESS_OUTPUT_SELECTION()
Static LastMenuSelection = #Last_Menu_Item
Protected menuSelection = EventMenu()
If GetMenuItemState(#Menu_1,menuSelection) = #False
SetMenuItemState(#Menu_1,LastMenuSelection,#False)
SetMenuItemState(#Menu_1,menuSelection,#True)
LastMenuSelection = menuSelection
DevOut = menuSelection - OutDev_1 + 1
STOP_SOUND_OUTPUT()
START_SOUND_OUTPUT()
EndIf
EndProcedure
Procedure PROCESS_ENTER_KEY()
Protected ActiveGadget = GetActiveGadget()
Select ActiveGadget
Case #Spin_F1 To #Spin_F4
PostEvent(#PB_Event_Gadget,#WinMain,ActiveGadget,#Input_Finished)
EndSelect
EndProcedure
Procedure EVENT_LOOP()
Protected event
Repeat
event = WaitWindowEvent()
Select event
Case #PB_Event_Gadget
Select EventGadget()
Case #Button_Run : PROCESS_RUN_PAUSE()
Case #Check_Hop : PROCESS_HOP_OPTION()
Case #Spin_F1 To #Spin_F4 : PROCESS_FREQUENCY_CHANGE()
Case #Track_Vol_F1 To #Track_Vol_F4 : PROCESS_VOLUME_CHANGE()
Case #Track_Bal_F1 To #Track_Bal_F4 : PROCESS_BALANCE_CHANGE()
Case #Track_Duty_F1 To #Track_Duty_F4 : PROCESS_DUTY_CHANGE()
Case #Check_Sq_F1 To #Check_Sq_F4 : PROCESS_SQUARE_OPTION()
Case #Option_Mono : SWITCH_MODE(#Mono)
Case #Option_Stereo : SWITCH_MODE(#Stereo)
Case #Track_Scope : CHANGE_SCOPE_SCALE()
EndSelect
Case #PB_Event_Menu
Select EventMenu()
Case OutDev_1 To OutDev_1 + NumOutDevs : PROCESS_OUTPUT_SELECTION()
Case #MenuItem_ScopeAuto : SET_SCOPE_MODE()
Case #MenuItem_OnTop : ACTIVATE_STICKY_WINDOW()
Case #MenuItem_EnterKey : PROCESS_ENTER_KEY()
EndSelect
EndSelect
Until event = #PB_Event_CloseWindow
EndProcedure
If BUILD_GUI()
INIT_GADGETS()
If START_SOUND_OUTPUT()
EVENT_LOOP()
Else
MessageRequester("Error!","Unable to activate sound output.")
EndIf
STOP_SOUND_OUTPUT()
EndIf