Please notice the shown program is just a simple tip to display the aim of this video, this is:
to expose the fact that using a computer with at least a dual PCM output; like a PINE64, ODROID, Banana PI, Orange PI, CubieBoard, Raspberry PI, Teensy, PC i386, Amiga, etc. there is possible the more absolute control about electrical amplitudes and frequencies, not just digital pulses, but also analogically.
All it without electronic designs, like H-bridges, oscillators, impulses generators (bad called "inverters"), frequency variators, etc., but purely:
voltage amplifiers and optimal software.
https://www.youtube.com/watch?v=a6rFB0d0_gI
Tip program used:
Code: Select all
Structure Vector3D
x.f:y.f:z.f:m.f
EndStructure
Structure KSAUDIO_CHANNEL_CONFIG
;https://msdn.microsoft.com/library/windows/hardware/ff537083
ActiveSpeakerPositions.l
EndStructure
Enumeration
#MainWin=0
#OutDevice_1=0
#nhiloscolor=$27CF24
#SpinLostFocus=512
#Input_Finished=#PB_EventType_FirstCustomValue
#maxnhilos=6
;
#ACM_MPEG_LAYER1 =$0001
#ACM_MPEG_LAYER2 =$0002
#ACM_MPEG_LAYER3 =$0004
#ACM_MPEG_STEREO =$0001
#ACM_MPEG_JOINTSTEREO =$0002
#ACM_MPEG_DUALCHANNEL =$0004
#ACM_MPEG_SINGLECHANNEL =$0008
#ACM_MPEG_PRIVATEBIT =$0001
#ACM_MPEG_COPYRIGHT =$0002
#ACM_MPEG_ORIGINALHOME =$0004
#ACM_MPEG_PROTECTIONBIT =$0008
#ACM_MPEG_ID_MPEG1 =$0010
#SPEAKER_FRONT_LEFT =$1
#SPEAKER_FRONT_RIGHT =$2
#SPEAKER_FRONT_CENTER =$4
#SPEAKER_LOW_FREQUENCY =$8
#SPEAKER_BACK_LEFT =$10
#SPEAKER_BACK_RIGHT =$20
#SPEAKER_FRONT_LEFT_OF_CENTER =$40
#SPEAKER_FRONT_RIGHT_OF_CENTER =$80
#SPEAKER_BACK_CENTER =$100
#SPEAKER_SIDE_LEFT =$200
#SPEAKER_SIDE_RIGHT =$400
#SPEAKER_TOP_CENTER =$800
#SPEAKER_TOP_FRONT_LEFT =$1000
#SPEAKER_TOP_FRONT_CENTER =$2000
#SPEAKER_TOP_FRONT_RIGHT =$4000
#SPEAKER_TOP_BACK_LEFT =$8000
#SPEAKER_TOP_BACK_CENTER =$10000
#SPEAKER_TOP_BACK_RIGHT =$20000
#WAVE_FORMAT_UNKNOWN =$0000
#WAVE_FORMAT_PCM =$0001
#WAVE_FORMAT_ADPCM =$0002
#WAVE_FORMAT_IEEE_FLOAT =$0003
#WAVE_FORMAT_VSELP =$0004
#WAVE_FORMAT_IBM_CVSD =$0005
#WAVE_FORMAT_ALAW =$0006
#WAVE_FORMAT_MULAW =$0007
#WAVE_FORMAT_OKI_ADPCM =$0010
#WAVE_FORMAT_DVI_ADPCM =$0011
#WAVE_FORMAT_MEDIASPACE_ADPCM =$0012
#WAVE_FORMAT_SIERRA_ADPCM =$0013
#WAVE_FORMAT_G723_ADPCM =$0014
#WAVE_FORMAT_DIGIFIX =$0016
#WAVE_FORMAT_DIALOGIC_OKI_ADPCM =$0017
#WAVE_FORMAT_MEDIAVISION_ADPCM =$0018
#WAVE_FORMAT_CU_CODEC =$0019
#WAVE_FORMAT_YAMAHA_ADPCM =$0020
#WAVE_FORMAT_SONARC =$0021
#WAVE_FORMAT_DSPGROUP_TRUESPEECH =$0022
#WAVE_FORMAT_ECHOSC1 =$0023
#WAVE_FORMAT_AUDIOFILE_AF36 =$0024
#WAVE_FORMAT_APTX =$0025
#WAVE_FORMAT_AUDIOFILE_AF10 =$0026
#WAVE_FORMAT_PROSODY_1612 =$0027
#WAVE_FORMAT_LRC =$0028
#WAVE_FORMAT_DOLBY_AC2 =$0030
#WAVE_FORMAT_GSM610 =$0031
#WAVE_FORMAT_MSNAUDIO =$0032
#WAVE_FORMAT_ANTEX_ADPCME =$0033
#WAVE_FORMAT_CONTROL_RES_VQLPC =$0034
#WAVE_FORMAT_DIGIREAL =$0035
#WAVE_FORMAT_DIGIADPCM =$0036
#WAVE_FORMAT_CONTROL_RES_CR10 =$0037
#WAVE_FORMAT_NMS_VBXADPCM =$0038
#WAVE_FORMAT_ROLAND_RDAC =$0039
#WAVE_FORMAT_ECHOSC3 =$003A
#WAVE_FORMAT_ROCKWELL_ADPCM =$003B
#WAVE_FORMAT_ROCKWELL_DIGITALK =$003C
#WAVE_FORMAT_XEBEC =$003D
#WAVE_FORMAT_G721_ADPCM =$0040
#WAVE_FORMAT_G728_CELP =$0041
#WAVE_FORMAT_MSG723 =$0042
#WAVE_FORMAT_MPEG =$0050
#WAVE_FORMAT_RT24 =$0052
#WAVE_FORMAT_PAC =$0053
#WAVE_FORMAT_MPEGLAYER3 =$0055
#WAVE_FORMAT_LUCENT_G723 =$0059
#WAVE_FORMAT_CIRRUS =$0060
#WAVE_FORMAT_ESPCM =$0061
#WAVE_FORMAT_VOXWARE =$0062
#WAVE_FORMAT_CANOPUS_ATRAC =$0063
#WAVE_FORMAT_G726_ADPCM =$0064
#WAVE_FORMAT_G722_ADPCM =$0065
#WAVE_FORMAT_DSAT =$0066
#WAVE_FORMAT_DSAT_DISPLAY =$0067
#WAVE_FORMAT_VOXWARE_BYTE_ALIGNED =$0069
#WAVE_FORMAT_VOXWARE_AC8 =$0070
#WAVE_FORMAT_VOXWARE_AC10 =$0071
#WAVE_FORMAT_VOXWARE_AC16 =$0072
#WAVE_FORMAT_VOXWARE_AC20 =$0073
#WAVE_FORMAT_VOXWARE_RT24 =$0074
#WAVE_FORMAT_VOXWARE_RT29 =$0075
#WAVE_FORMAT_VOXWARE_RT29HW =$0076
#WAVE_FORMAT_VOXWARE_VR12 =$0077
#WAVE_FORMAT_VOXWARE_VR18 =$0078
#WAVE_FORMAT_VOXWARE_TQ40 =$0079
#WAVE_FORMAT_SOFTSOUND =$0080
#WAVE_FORMAT_VOXWARE_TQ60 =$0081
#WAVE_FORMAT_MSRT24 =$0082
#WAVE_FORMAT_G729A =$0083
#WAVE_FORMAT_MVI_MV12 =$0084
#WAVE_FORMAT_DF_G726 =$0085
#WAVE_FORMAT_DF_GSM610 =$0086
#WAVE_FORMAT_ISIAUDIO =$0088
#WAVE_FORMAT_ONLIVE =$0089
#WAVE_FORMAT_SBC24 =$0091
#WAVE_FORMAT_DOLBY_AC3_SPDIF =$0092
#WAVE_FORMAT_ZYXEL_ADPCM =$0097
#WAVE_FORMAT_PHILIPS_LPCBB =$0098
#WAVE_FORMAT_PACKED =$0099
#WAVE_FORMAT_RHETOREX_ADPCM =$0100
#WAVE_FORMAT_IRAT =$0101
#WAVE_FORMAT_VIVO_G723 =$0111
#WAVE_FORMAT_VIVO_SIREN =$0112
#WAVE_FORMAT_DIGITAL_G723 =$0113
#WAVE_FORMAT_CREATIVE_ADPCM =$0200
#WAVE_FORMAT_CREATIVE_FASTSPEECH8 =$0202
#WAVE_FORMAT_CREATIVE_FASTSPEECH10 =$0203
#WAVE_FORMAT_QUARTERDECK =$0220
#WAVE_FORMAT_FM_TOWNS_SND =$0300
#WAVE_FORMAT_BTV_DIGITAL =$0400
#WAVE_FORMAT_VME_VMPCM =$0680
#WAVE_FORMAT_OLIGSM =$1000
#WAVE_FORMAT_OLIADPCM =$1001
#WAVE_FORMAT_OLICELP =$1002
#WAVE_FORMAT_OLISBC =$1003
#WAVE_FORMAT_OLIOPR =$1004
#WAVE_FORMAT_LH_CODEC =$1100
#WAVE_FORMAT_NORRIS =$1400
#WAVE_FORMAT_ISIAUDIO_ =$1401
#WAVE_FORMAT_SOUNDSPACE_MUSICOMPRESS =$1500
#WAVE_FORMAT_DVM =$2000
; /* http://msdn.microsoft.com/en-us/library/aa372553%28VS.85%29.aspx */
#WAVE_FORMAT_RAW_AAC1 =$00FF
#WAVE_FORMAT_MPEG_HEAAC =$1610
#WAVE_FORMAT_MPEG_ADTS_AAC =$1600
#WAVE_FORMAT_DRM =$0009
#WAVE_FORMAT_DTS =$0008
#WAVE_FORMAT_WMAVOICE9 =$000A
#WAVE_FORMAT_WMASPDIF =$0164
#WAVE_FORMAT_WMAUDIO_LOSSLESS =$0163
#WAVE_FORMAT_WMAUDIO2 =$0161
#WAVE_FORMAT_WMAUDIO3 =$0162
; /* http://msdn.microsoft.com/en-us/library/dd317599%28VS.85%29.aspx */
#WAVE_FORMAT_MPEG_LOAS =$1602
#WAVE_FORMAT_RAW_SPORT =$0240
#WAVE_FORMAT_ESST_AC3 =$0241
#WAVE_FORMAT_DTS2 =$2001
; Audio quality constants
#KSAUDIO_QUALITY_WORST =$0
#KSAUDIO_QUALITY_PC =$1
#KSAUDIO_QUALITY_BASIC =$2
#KSAUDIO_QUALITY_ADVANCED =$3
; Audio CPU resource constants
#KSAUDIO_CPU_RESOURCES_NOT_HOST_CPU=$00000000
#KSAUDIO_CPU_RESOURCES_HOST_CPU =$7FFFFFFF
; Speaker Positions:
#SPEAKER_FRONT_LEFT =$1
#SPEAKER_FRONT_RIGHT =$2
#SPEAKER_FRONT_CENTER =$4
#SPEAKER_LOW_FREQUENCY =$8
#SPEAKER_BACK_LEFT =$10
#SPEAKER_BACK_RIGHT =$20
#SPEAKER_FRONT_LEFT_OF_CENTER =$40
#SPEAKER_FRONT_RIGHT_OF_CENTER =$80
#SPEAKER_BACK_CENTER =$100
#SPEAKER_SIDE_LEFT =$200
#SPEAKER_SIDE_RIGHT =$400
#SPEAKER_TOP_CENTER =$800
#SPEAKER_TOP_FRONT_LEFT =$1000
#SPEAKER_TOP_FRONT_CENTER =$2000
#SPEAKER_TOP_FRONT_RIGHT =$4000
#SPEAKER_TOP_BACK_LEFT =$8000
#SPEAKER_TOP_BACK_CENTER =$10000
#SPEAKER_TOP_BACK_RIGHT =$20000
; Bit mask locations reserved For future use
#SPEAKER_RESERVED =$7FFC0000
; Used To specify that any possible permutation of speaker configurations
#SPEAKER_ALL =$80000000
#KSAUDIO_SPEAKER_MONO=#SPEAKER_FRONT_CENTER
#KSAUDIO_SPEAKER_STEREO=#SPEAKER_FRONT_LEFT | #SPEAKER_FRONT_RIGHT
#KSAUDIO_SPEAKER_QUAD=#SPEAKER_FRONT_LEFT | #SPEAKER_FRONT_RIGHT | #SPEAKER_BACK_LEFT | #SPEAKER_BACK_RIGHT
#KSAUDIO_SPEAKER_SURROUND=#SPEAKER_FRONT_LEFT | #SPEAKER_FRONT_RIGHT | #SPEAKER_FRONT_CENTER | #SPEAKER_BACK_CENTER
#KSAUDIO_SPEAKER_5POINT1=#SPEAKER_FRONT_LEFT | #SPEAKER_FRONT_RIGHT | #SPEAKER_FRONT_CENTER | #SPEAKER_LOW_FREQUENCY | #SPEAKER_BACK_LEFT | #SPEAKER_BACK_RIGHT
#KSAUDIO_SPEAKER_7POINT1=#SPEAKER_FRONT_LEFT | #SPEAKER_FRONT_RIGHT | #SPEAKER_FRONT_CENTER | #SPEAKER_LOW_FREQUENCY | #SPEAKER_BACK_LEFT | #SPEAKER_BACK_RIGHT | #SPEAKER_FRONT_LEFT_OF_CENTER | #SPEAKER_FRONT_RIGHT_OF_CENTER
#KSAUDIO_SPEAKER_5POINT1_SURROUND=#SPEAKER_FRONT_LEFT | #SPEAKER_FRONT_RIGHT | #SPEAKER_FRONT_CENTER | #SPEAKER_LOW_FREQUENCY | #SPEAKER_SIDE_LEFT | #SPEAKER_SIDE_RIGHT
#KSAUDIO_SPEAKER_7POINT1_SURROUND=#SPEAKER_FRONT_LEFT | #SPEAKER_FRONT_RIGHT | #SPEAKER_FRONT_CENTER | #SPEAKER_LOW_FREQUENCY | #SPEAKER_BACK_LEFT | #SPEAKER_BACK_RIGHT | #SPEAKER_SIDE_LEFT | #SPEAKER_SIDE_RIGHT
#KSAUDIO_SPEAKER_DIRECTOUT=0
; The following are obsolete 5.1 And 7.1 settings (they lack side speakers). Note this means that the Default 5.1 And 7.1 settings (KSAUDIO_SPEAKER_5POINT1 And KSAUDIO_SPEAKER_7POINT1 are similarly obsolete but are unchanged For compatibility reasons).
#KSAUDIO_SPEAKER_5POINT1_BACK=#KSAUDIO_SPEAKER_5POINT1
#KSAUDIO_SPEAKER_7POINT1_WIDE=#KSAUDIO_SPEAKER_7POINT1
; DVD Speaker Positions
#KSAUDIO_SPEAKER_GROUND_FRONT_LEFT=#SPEAKER_FRONT_LEFT
#KSAUDIO_SPEAKER_GROUND_FRONT_CENTER=#SPEAKER_FRONT_CENTER
#KSAUDIO_SPEAKER_GROUND_FRONT_RIGHT=#SPEAKER_FRONT_RIGHT
#KSAUDIO_SPEAKER_GROUND_REAR_LEFT=#SPEAKER_BACK_LEFT
#KSAUDIO_SPEAKER_GROUND_REAR_RIGHT=#SPEAKER_BACK_RIGHT
#KSAUDIO_SPEAKER_TOP_MIDDLE=#SPEAKER_TOP_CENTER
#KSAUDIO_SPEAKER_SUPER_WOOFER=#SPEAKER_LOW_FREQUENCY
; menus
#Devices=0
#InputDevice
#OutputDevice
#formatodeondaentrada
#formatodeondasalida
; gadgets
#Canvas=100
#Canvasmemoria
#TrackbarA
#TrackbarB
#TrackbarC
#TrackbarE
#TextA
#TextB
#TextC
#TextE
#BotonResetView
#BotonPausa
#nhilos
#TrackLeft
#TrackRight
#formadeonda
#formadeondahilo1
#formadeondahilo2
#formadeondahilo3
#formadeondahilo4
#formadeondahilo5
#formadeondahilo6
#seleccionhilo1
#seleccionhilo2
#seleccionhilo3
#seleccionhilo4
#seleccionhilo5
#seleccionhilo6
#fase
#fasehilo1
#fasehilo2
#fasehilo3
#fasehilo4
#fasehilo5
#fasehilo6
#CheckboxrelacionFA
#SpinrelacionFA
EndEnumeration
Global .GUID KSDATAFORMAT_SUBTYPE_ANALOG,KSDATAFORMAT_SUBTYPE_PCM,KSDATAFORMAT_SUBTYPE_IEEE_FLOAT,KSDATAFORMAT_SUBTYPE_DRM,KSDATAFORMAT_SUBTYPE_ALAW,KSDATAFORMAT_SUBTYPE_MULAW,KSDATAFORMAT_SUBTYPE_ADPCM,KSDATAFORMAT_SUBTYPE_MPEG,KSDATAFORMAT_SPECIFIER_VC_ID,KSDATAFORMAT_SPECIFIER_WAVEFORMATEX,KSDATAFORMAT_SPECIFIER_DSOUND
Procedure.b HexByteStringToDecByteSequence(HexString.s,*seq.ascii)
;This function converts a given Hex string (.s) to a byte sequence stored in a given base address of sequential memory:
Protected c.a,Nibbles.l=Len(HexString.s),t.l
If Nibbles.l&1:HexString.s="0"+HexString.s:Nibbles.l+1:EndIf
For t.l=1 To Nibbles.l
c.a=Asc(LCase(Mid(HexString.s,t.l,1)))
If c<'0' Or c>'f' Or (c>'9' And c<'a')
ProcedureReturn 0
EndIf
If c>'9':c=(c&$5F)-$07:EndIf
c-'0'
If t.l&1
*seq\a=c<<4
Else
*seq\a|c
*seq+1
EndIf
Next
ProcedureReturn 1
EndProcedure
Macro DEFINE_GUIDSTRUCT(caracteres,nombre)
HexByteStringToDecByteSequence(StringField(caracteres#,1,"-"),@nombre#\Data1)
!mov eax,dword[v_#nombre#]
!bswap eax
!mov dword[v_#nombre#],eax
HexByteStringToDecByteSequence(StringField(caracteres#,2,"-"),@nombre#\Data2)
!rol word[v_#nombre#+4],8
HexByteStringToDecByteSequence(StringField(caracteres#,3,"-"),@nombre#\Data3)
!rol word[v_#nombre#+6],8
HexByteStringToDecByteSequence(StringField(caracteres#,4,"-"),@nombre#\Data4[0])
HexByteStringToDecByteSequence(StringField(caracteres#,5,"-"),@nombre#\Data4[2])
EndMacro
DEFINE_GUIDSTRUCT("6dba3190-67bd-11cf-a0f7-0020afd156e4", KSDATAFORMAT_SUBTYPE_ANALOG)
DEFINE_GUIDSTRUCT("00000001-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_PCM)
DEFINE_GUIDSTRUCT("00000003-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
DEFINE_GUIDSTRUCT("00000009-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_DRM)
DEFINE_GUIDSTRUCT("00000006-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_ALAW)
DEFINE_GUIDSTRUCT("00000007-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_MULAW)
DEFINE_GUIDSTRUCT("00000002-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_ADPCM)
DEFINE_GUIDSTRUCT("00000050-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_MPEG)
DEFINE_GUIDSTRUCT("AD98D184-AAC3-11D0-A41C-00A0C9223196", KSDATAFORMAT_SPECIFIER_VC_ID)
DEFINE_GUIDSTRUCT("05589f81-c356-11ce-bf01-00aa0055595a", KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
DEFINE_GUIDSTRUCT("518590a2-a184-11d0-8522-00c04fd9baf3", KSDATAFORMAT_SPECIFIER_DSOUND)
Structure gadgetmenu
nombre$
disponible.b
salida.b
EndStructure
Global NumDevicesIn.i,NumDevicesOut.i,NewList menuoptions.gadgetmenu()
#PIx2=2*#PI
; Global variables
Global a.f=80,b.f=200,c.f=60,e.f=3,i.i,j.i
Global DevOut.l=1,DevIn.l=1; default audio output device; default audio input device
Global nhilos.l=3,nhilosIn.l=3
Global BlockSize.l=4096,nBuf.l=16,*memoria=ReAllocateMemory(*memoria,nBuf*BlockSize),BlockSizeIn.l=4096,nBufIn.l=16,*memoriaIn=ReAllocateMemory(*memoriaIn,nBufIn*BlockSizeIn)
Global Dim formadeondahilo.u(#maxnhilos)
Global Dim fasehilo.f(#maxnhilos):fasehilo(1)=0:fasehilo(2)=120:fasehilo(3)=240:fasehilo(4)=0:fasehilo(5)=120:fasehilo(6)=240
Global Dim frecuenciahilo.f(#maxnhilos):frecuenciahilo(1)=1000:frecuenciahilo(2)=440:frecuenciahilo(3)=1000:frecuenciahilo(4)=440:frecuenciahilo(5)=1000:frecuenciahilo(6)=440
Global Dim alturahilo.f(#maxnhilos)
Global Dim amplitudhilo.f(#maxnhilos):amplitudhilo(1)=0.25*$7FFF:amplitudhilo(2)=0.25*$7FFF:amplitudhilo(3)=0.25*$7FFF:amplitudhilo(4)=0.25*$7FFF:amplitudhilo(5)=0.25*$7FFF:amplitudhilo(6)=0.25*$7FFF
Global Dim relacionAmplitudFrecuencia.f(#maxnhilos)
Global Dim xmem.f(#maxnhilos):For i=1 To #maxnhilos:xmem(i)=Radian(fasehilo(i)):Next
Global Dim paso.f(#maxnhilos)
Global hWaveOut.i,hWaveIn.i
Global FormatoOut.WAVEFORMATEXTENSIBLE,FormatoIn.WAVEFORMATEXTENSIBLE,CapsOut.WAVEOUTCAPS,CapsIn.WAVEINCAPS,Dim outHdr.WAVEHDR(nBuf),Dim inHdr.WAVEHDR(nBuf)
FormatoOut\format\wFormatTag=#WAVE_FORMAT_PCM ;#WAVE_FORMAT_EXTENSIBLE
FormatoOut\format\nChannels=2;nhilos-1
FormatoOut\format\nSamplesPerSec=44100
FormatoOut\format\wBitsPerSample=16
FormatoOut\format\nBlockAlign=FormatoOut\format\nChannels*FormatoOut\format\wBitsPerSample>>3
FormatoOut\format\nAvgBytesPerSec=FormatoOut\format\nSamplesPerSec*FormatoOut\format\nBlockAlign
FormatoOut\wValidBitsPerSample=FormatoOut\format\wBitsPerSample
FormatoOut\dwChannelMask=$63F ; 7.1 (ojo poner en la configuración de altavoces de windows el 7.1) ; https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/channel-mask
;Por ejemplos; si solo front-left y front-center son especificados, entonces front-left y front-center deben ser los canales 0 y 1 repectivamente en el intercalado en la memoria.
;Si el miembro 'format\nChannels' vale 4 y 'dwChannelMask' es $33, los canales se entienden como front-left, front-right, back-left y back-right.
;los datos en el intercalado en la memoria deben estar en ese orden.
FormatoOut\SubFormat=KSDATAFORMAT_SUBTYPE_PCM
FormatoIn\format\wFormatTag=#WAVE_FORMAT_PCM ;#WAVE_FORMAT_EXTENSIBLE
FormatoIn\format\nChannels=2;nhilos-1
FormatoIn\format\nSamplesPerSec=44100
FormatoIn\format\wBitsPerSample=16
FormatoIn\format\nBlockAlign=FormatoIn\format\nChannels*FormatoIn\format\wBitsPerSample>>3
FormatoIn\format\nAvgBytesPerSec=FormatoIn\format\nSamplesPerSec*FormatoOut\format\nBlockAlign
FormatoIn\wValidBitsPerSample=FormatoIn\format\wBitsPerSample
FormatoIn\dwChannelMask=$63F
FormatoIn\SubFormat=KSDATAFORMAT_SUBTYPE_PCM
Global canvasx.u=0,canvasy.u=0,canvasw.u=600,canvash.u=400
Global sliderax.u=canvasx+canvasw,slideray.u=canvasy,slideraw.u=25,sliderah.u=canvash
Global sliderbx.u=canvasx,sliderby.u=canvasy+canvash,sliderbw.u=canvasw,sliderbh.u=25
Global slidercx.u=canvasx,slidercy.u=sliderby+25,slidercw.u=canvasw,sliderch.u=25
Global sliderex.u=canvasx,sliderey.u=slidercy+25,sliderew.u=canvasw,slidereh.u=25
Global Dim colorhilo.l(#maxnhilos):colorhilo(1)=$CAD0EE:colorhilo(2)=$AAEE90:colorhilo(3)=$27D3E4:colorhilo(4)=$D327E4:colorhilo(5)=$E4D327:colorhilo(6)=$27A4F3
Global editando.b,hilo.a=1,referencia.u=canvash,canvasmousex.u,canvasmousey.u,canvassumdeltamousex.f=1.0,canvassumdeltamousey.f
Macro RND(v1,v2,ndecimales=3); maximo 'ndecimales' = 9
;genera un número aleatorio entre los valores v1 y v2
;NOTE: usar con variables de punto flotante para que esta macro funcione correctamente
(Random(1E#ndecimales#)*(v2#-v1#)/1E#ndecimales#+v1#)
EndMacro
Macro seno(f=0,desvx=0,desvy=0)
(a+desvy#)*Sin(Radian(f#)+(e*desvx#)*x.u/c)-b
EndMacro
Macro rectangular(f=0,desvx=0,desvy=0)
(a+desvy#)*Sign(Sin(Radian(f#)+x.u/(e*desvx#))-1+2*c/canvasw)-b
EndMacro
Macro canvashilos()
If editando
If EventType()=#PB_EventType_MouseMove
prevcanvasmousey.u=canvasmousey.u
canvasmousey.u=GetGadgetAttribute(#Canvas,#PB_Canvas_MouseY)
canvasdeltamousey.f=prevcanvasmousey-canvasmousey
prevcanvasmousex.u=canvasmousex.u
canvasmousex.u=GetGadgetAttribute(#Canvas,#PB_Canvas_MouseX)
canvasdeltamousex.f=prevcanvasmousex-canvasmousex
EndIf
canvassumdeltamousex.f+canvasdeltamousex.f/frecuenciahilo(1)/100:If canvassumdeltamousex<0:canvassumdeltamousex=0:EndIf
canvassumdeltamousey.f+canvasdeltamousey.f
EndIf
;dibuja:
StartDrawing(CanvasOutput(#Canvas))
Box(canvasx,canvasy,canvasw,canvash,0)
; dibujo todos los hilos menos el enfocado
For i=1 To nhilos
If i<>hilo
For x.u=canvasx To canvasw-1
y.f=a*(Sin(Radian(fasehilo(hilo))+(e*canvassumdeltamousex)*x.u/c)-Sin(Radian(fasehilo(i))+(e*canvassumdeltamousex)*x.u/c)); <- diferencia entre 'hilo' y 'i' en el instante 'x'
y.f+referencia-seno(fasehilo(hilo),canvassumdeltamousex,canvassumdeltamousey)
Circle(x,y.f,1,Colorhilo(i))
Next
alturahilo(i)
EndIf
Next
; dibujo el hilo enfocado el último para que quede visible sobre los demás
For x.u=canvasx To canvasw-1
; xp.u=x.u:yp.u=y.f
y.f=referencia-seno(fasehilo(hilo),canvassumdeltamousex,canvassumdeltamousey)
Circle(x,y.f,1,Colorhilo(hilo))
; LineXY(xp,yp,x,y.f,$AAEE90)
Next
StopDrawing()
;Canvas memoria hilos:
; CREAR_ONDA(*memoria,BlockSize/FormatoOut\format\nBlockAlign)
;dibuja:
StartDrawing(CanvasOutput(#Canvasmemoria))
Box(canvasx,canvasy,canvasw,canvash,0)
x.u=0:ymem.l=0:ref_2.u=referencia/2:mult.f=referencia/Pow(2,FormatoOut\format\wBitsPerSample)
Repeat
Plot(x*canvasw/BlockSize,ref_2,Colorhilo(1)); <- linea central = masa = hilo0
; Select FormatoOut\format\wBitsPerSample
; Case 8,16
y.f=ref_2-PeekW(*memoria+x)*mult
Plot(x*canvasw/BlockSize,y.f,Colorhilo(2))
x+FormatoOut\format\wBitsPerSample>>3
y.f=ref_2-PeekW(*memoria+x)*mult
Plot(x*canvasw/BlockSize,y.f,Colorhilo(3))
; Case 32
; y.f=ref_2-PeekL(*memoria+x)*mult
; Plot(x*canvasw/BlockSize,y.f,Colorhilo(2))
; x+FormatoOut\format\wBitsPerSample>>3
; y.f=ref_2-PeekL(*memoria+x)*mult
; Plot(x*canvasw/BlockSize,y.f,Colorhilo(3))
; Case 24
; ymem.l=PeekL(*memoria+x); extender el signo de 24bit a 32bit
; !mov al,byte[p.v_ymem+2]
; !cbw
; !shl eax,16
; !mov ax,word[p.v_ymem]
; !mov dword[p.v_ymem],eax
; y.f=ref_2-ymem*mult
; Plot(x*canvasw/BlockSize,y.f,Colorhilo(2))
; x+FormatoOut\format\wBitsPerSample>>3
; ymem.l=PeekL(*memoria+x); extender el signo de 24bit a 32bit
; !mov al,byte[p.v_ymem+2]
; !cbw
; !shl eax,16
; !mov ax,word[p.v_ymem]
; !mov dword[p.v_ymem],eax
; y.f=ref_2-ymem*mult
; Plot(x*canvasw/BlockSize,y.f,Colorhilo(3))
; EndSelect
x+FormatoOut\format\wBitsPerSample>>3
Until x>=BlockSize-1
StopDrawing()
EndMacro
Procedure CREAR_ONDA(*SBuf,nsamples.i)
; Esta rutina genera las formas de onda
; los samples se almecenan en la memoria alternativamente entre el canal L y el R: (para resolución de 8 bit o 16 bit es así: L.w, R.w, L.w, R.w, L.w, R.w....)
; Así es que el buffer donde se almacenan debe tener una longitud múltiplo de 'FormatoOut\format\nBlockAlign' = 'FormatoOut\format\nChannels * FormatoOut\format\wBitsPerSample>>3'
Protected V.f
paso(2)=#PIx2*frecuenciahilo(2)/FormatoOut\format\nSamplesPerSec:paso(3)=#PIx2*frecuenciahilo(3)/FormatoOut\format\nSamplesPerSec
For i=1 To nsamples
V=amplitudhilo(2)*Sin(xmem(2))+alturahilo(2)-Pow(2,FormatoOut\format\wBitsPerSample)/2
xmem(2)+paso(2):If xmem(2)>=#PIx2:xmem(2)-#PIx2:EndIf
PokeW(*SBuf,V):*SBuf+FormatoOut\format\wBitsPerSample>>3
If nhilos=2:V=0; <- si es mono
Else:V=amplitudhilo(3)*Sin(xmem(3))+alturahilo(3)-Pow(2,FormatoOut\format\wBitsPerSample)/2
EndIf
xmem(3)+paso(3):If xmem(3)>=#PIx2:xmem(3)-#PIx2:EndIf
PokeW(*SBuf,V):*SBuf+FormatoOut\format\wBitsPerSample>>3
Next
EndProcedure
Procedure.i WinCallback(hwnd, uMsg, wParam, lParam)
; Window callback to service sound output message
Static *hWaveO.WAVEHDR
If uMsg=#MM_WOM_DONE ; Sound output, a play buffer has been returned.
*hWaveO.WAVEHDR=lParam ; lParam has the address of WAVEHDR
CREAR_ONDA(*hWaveO\lpData,BlockSize/FormatoOut\format\nBlockAlign) ; 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=>
EndIf
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
Procedure.i StartSoundOutput()
Protected T.i,*P.byte
; FormatoOut\format\wFormatTag=#WAVE_FORMAT_PCM
; FormatoOut\format\nChannels=2;nhilos-1
; FormatoOut\format\nSamplesPerSec=44100
; FormatoOut\format\wBitsPerSample=16
; FormatoOut\format\nBlockAlign=FormatoOut\format\nChannels*FormatoOut\format\wBitsPerSample>>3
; FormatoOut\format\nAvgBytesPerSec=FormatoOut\format\nSamplesPerSec*FormatoOut\format\nBlockAlign
; FormatoOut\wValidBitsPerSample=FormatoOut\format\wBitsPerSample
; FormatoOut\dwChannelMask=$63F ; 7.1 (ojo poner en la configuración de altavoces de windows el 7.1) ; https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/channel-mask
; ;Por ejemplos; si solo front-left y front-center son especificados, entonces front-left y front-center deben ser los canales 0 y 1 repectivamente en el intercalado en la memoria.
; ;Si el miembro 'format\nChannels' vale 4 y 'dwChannelMask' es $33, los canales se entienden como front-left, front-right, back-left, and back-right.
; ;los datos en el intercalado en la memoria deben estar en ese orden.
; FormatoOut\SubFormat=KSDATAFORMAT_SUBTYPE_PCM
*memoria=ReAllocateMemory(*memoria,BlockSize*nBuf,#PB_Memory_NoClear) ; Reserve memory for all the buffers
T=waveOutOpen_(@hWaveOut,#WAVE_MAPPER+DevOut,@FormatoOut\format,WindowID(#MainWin),#True,#CALLBACK_WINDOW|#WAVE_FORMAT_DIRECT)
If T=#MMSYSERR_NOERROR
*P=*memoria ; 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(#MainWin),#MM_WOM_DONE,0,outHdr(i))
Next
EndIf
ProcedureReturn T
EndProcedure
Procedure StopSoundOutput()
waveOutReset_(hWaveOut)
For i=0 To nBuf-1
waveOutUnprepareHeader_(hWaveOut,outHdr(i),SizeOf(WAVEHDR))
Next
waveOutClose_(hWaveOut)
EndProcedure
Procedure.i caracteristicas(win.i)
Protected DeviceID.i
CreateMenu(#Devices,WindowID(win))
; locate all sound input devices:
NumDevicesIn.i=waveInGetNumDevs_()
If NumDevicesIn
MenuTitle("Input Devices")
For DeviceID=0 To NumDevicesIn-1
If waveInGetDevCaps_(DeviceID,@CapsIn, SizeOf(WAVEINCAPS))=#MMSYSERR_NOERROR
OpenSubMenu(PeekS(@CapsIn\szPname,#MAXPNAMELEN))
If CapsIn\dwFormats&#WAVE_FORMAT_1M08:AddElement(menuoptions()):menuoptions()\nombre$="11025 Hz, MONO, 8 bit":menuoptions()\disponible=1:menuoptions()\salida=0:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsIn\dwFormats&#WAVE_FORMAT_1S08:AddElement(menuoptions()):menuoptions()\nombre$="11025 Hz, STEREO, 8 bit":menuoptions()\disponible=1:menuoptions()\salida=0:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsIn\dwFormats&#WAVE_FORMAT_1M16:AddElement(menuoptions()):menuoptions()\nombre$="11025 Hz, MONO, 16 bit":menuoptions()\disponible=1:menuoptions()\salida=0:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsIn\dwFormats&#WAVE_FORMAT_1S16:AddElement(menuoptions()):menuoptions()\nombre$="11025 Hz, STEREO, 16 bit":menuoptions()\disponible=1:menuoptions()\salida=0:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsIn\dwFormats&#WAVE_FORMAT_2M08:AddElement(menuoptions()):menuoptions()\nombre$="22050 Hz, MONO, 8 bit":menuoptions()\disponible=1:menuoptions()\salida=0:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsIn\dwFormats&#WAVE_FORMAT_2S08:AddElement(menuoptions()):menuoptions()\nombre$="22050 Hz, STEREO, 8 bit":menuoptions()\disponible=1:menuoptions()\salida=0:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsIn\dwFormats&#WAVE_FORMAT_2M16:AddElement(menuoptions()):menuoptions()\nombre$="22050 Hz, MONO, 16 bit":menuoptions()\disponible=1:menuoptions()\salida=0:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsIn\dwFormats&#WAVE_FORMAT_2S16:AddElement(menuoptions()):menuoptions()\nombre$="22050 Hz, STEREO, 16 bit":menuoptions()\disponible=1:menuoptions()\salida=0:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsIn\dwFormats&#WAVE_FORMAT_4M08:AddElement(menuoptions()):menuoptions()\nombre$="44100 Hz, MONO, 8 bit":menuoptions()\disponible=1:menuoptions()\salida=0:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsIn\dwFormats&#WAVE_FORMAT_4S08:AddElement(menuoptions()):menuoptions()\nombre$="44100 Hz, STEREO, 8 bit":menuoptions()\disponible=1:menuoptions()\salida=0:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsIn\dwFormats&#WAVE_FORMAT_4M16:AddElement(menuoptions()):menuoptions()\nombre$="44100 Hz, MONO, 16 bit":menuoptions()\disponible=1:menuoptions()\salida=0:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsIn\dwFormats&#WAVE_FORMAT_4S16:AddElement(menuoptions()):menuoptions()\nombre$="44100 Hz, STEREO, 16 bit":menuoptions()\disponible=1:menuoptions()\salida=0:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsIn\dwFormats&#WAVE_FORMAT_48M08:AddElement(menuoptions()):menuoptions()\nombre$="48000 Hz, MONO, 8 bit":menuoptions()\disponible=1:menuoptions()\salida=0:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsIn\dwFormats&#WAVE_FORMAT_48S08:AddElement(menuoptions()):menuoptions()\nombre$="48000 Hz, STEREO, 8 bit":menuoptions()\disponible=1:menuoptions()\salida=0:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsIn\dwFormats&#WAVE_FORMAT_48M16:AddElement(menuoptions()):menuoptions()\nombre$="48000 Hz, MONO, 16 bit":menuoptions()\disponible=1:menuoptions()\salida=0:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsIn\dwFormats&#WAVE_FORMAT_48S16:AddElement(menuoptions()):menuoptions()\nombre$="48000 Hz, STEREO, 16 bit":menuoptions()\disponible=1:menuoptions()\salida=0:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsIn\dwFormats&#WAVE_FORMAT_96M08:AddElement(menuoptions()):menuoptions()\nombre$="96000 Hz, MONO, 8 bit":menuoptions()\disponible=1:menuoptions()\salida=0:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsIn\dwFormats&#WAVE_FORMAT_96S08:AddElement(menuoptions()):menuoptions()\nombre$="96000 Hz, STEREO, 8 bit":menuoptions()\disponible=1:menuoptions()\salida=0:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsIn\dwFormats&#WAVE_FORMAT_96M16:AddElement(menuoptions()):menuoptions()\nombre$="96000 Hz, MONO, 16 bit":menuoptions()\disponible=1:menuoptions()\salida=0:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsIn\dwFormats&#WAVE_FORMAT_96S16:AddElement(menuoptions()):menuoptions()\nombre$="96000 Hz, STEREO, 16 bit":menuoptions()\disponible=1:menuoptions()\salida=0:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
CloseSubMenu()
EndIf
Next
If ListSize(menuoptions())<2
MessageRequester("Error","No suitable wave capture devices found!"):ProcedureReturn 0
EndIf
Else
MessageRequester("Error","No input audio device found!"):ProcedureReturn 0
EndIf
; locate all sound output devices:
NumDevicesOut=waveOutGetNumDevs_(); <- numero de tarjetas de audio conectadas
If NumDevicesOut
MenuTitle("Output Devices")
For DeviceID=0 To NumDevicesOut-1
If waveOutGetDevCaps_(DeviceID,@CapsOut,SizeOf(WAVEOUTCAPS))=#MMSYSERR_NOERROR
OpenSubMenu(PeekS(@CapsOut\szPname,#MAXPNAMELEN))
If CapsOut\dwFormats&#WAVE_FORMAT_1M08:AddElement(menuoptions()):menuoptions()\nombre$="11025 Hz, MONO, 8 bit":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwFormats&#WAVE_FORMAT_1S08:AddElement(menuoptions()):menuoptions()\nombre$="11025 Hz, STEREO, 8 bit":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwFormats&#WAVE_FORMAT_1M16:AddElement(menuoptions()):menuoptions()\nombre$="11025 Hz, MONO, 16 bit":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwFormats&#WAVE_FORMAT_1S16:AddElement(menuoptions()):menuoptions()\nombre$="11025 Hz, STEREO, 16 bit":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwFormats&#WAVE_FORMAT_2M08:AddElement(menuoptions()):menuoptions()\nombre$="22050 Hz, MONO, 8 bit":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwFormats&#WAVE_FORMAT_2S08:AddElement(menuoptions()):menuoptions()\nombre$="22050 Hz, STEREO, 8 bit":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwFormats&#WAVE_FORMAT_2M16:AddElement(menuoptions()):menuoptions()\nombre$="22050 Hz, MONO, 16 bit":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwFormats&#WAVE_FORMAT_2S16:AddElement(menuoptions()):menuoptions()\nombre$="22050 Hz, STEREO, 16 bit":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwFormats&#WAVE_FORMAT_4M08:AddElement(menuoptions()):menuoptions()\nombre$="44100 Hz, MONO, 8 bit":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwFormats&#WAVE_FORMAT_4S08:AddElement(menuoptions()):menuoptions()\nombre$="44100 Hz, STEREO, 8 bit":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwFormats&#WAVE_FORMAT_4M16:AddElement(menuoptions()):menuoptions()\nombre$="44100 Hz, MONO, 16 bit":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwFormats&#WAVE_FORMAT_4S16:AddElement(menuoptions()):menuoptions()\nombre$="44100 Hz, STEREO, 16 bit":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwFormats&#WAVE_FORMAT_48M08:AddElement(menuoptions()):menuoptions()\nombre$="48000 Hz, MONO, 8 bit":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwFormats&#WAVE_FORMAT_48S08:AddElement(menuoptions()):menuoptions()\nombre$="48000 Hz, STEREO, 8 bit":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwFormats&#WAVE_FORMAT_48M16:AddElement(menuoptions()):menuoptions()\nombre$="48000 Hz, MONO, 16 bit":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwFormats&#WAVE_FORMAT_48S16:AddElement(menuoptions()):menuoptions()\nombre$="48000 Hz, STEREO, 16 bit":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwFormats&#WAVE_FORMAT_96M08:AddElement(menuoptions()):menuoptions()\nombre$="96000 Hz, MONO, 8 bit":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwFormats&#WAVE_FORMAT_96S08:AddElement(menuoptions()):menuoptions()\nombre$="96000 Hz, STEREO, 8 bit":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwFormats&#WAVE_FORMAT_96M16:AddElement(menuoptions()):menuoptions()\nombre$="96000 Hz, MONO, 16 bit":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwFormats&#WAVE_FORMAT_96S16:AddElement(menuoptions()):menuoptions()\nombre$="96000 Hz, STEREO, 16 bit":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
MenuBar()
If CapsOut\dwSupport&#WAVECAPS_LRVOLUME:AddElement(menuoptions()):menuoptions()\nombre$="Supports separate left And right volume control":menuoptions()\disponible=0:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwSupport&#WAVECAPS_PITCH:AddElement(menuoptions()):menuoptions()\nombre$="Supports pitch control":menuoptions()\disponible=0:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwSupport&#WAVECAPS_PLAYBACKRATE:AddElement(menuoptions()):menuoptions()\nombre$="Supports playback rate control":menuoptions()\disponible=0:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwSupport&#WAVECAPS_SYNC:AddElement(menuoptions()):menuoptions()\nombre$="The driver is synchronous And will block While playing a buffer":menuoptions()\disponible=1:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwSupport&#WAVECAPS_VOLUME:AddElement(menuoptions()):menuoptions()\nombre$="Supports volume control":menuoptions()\disponible=0:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
If CapsOut\dwSupport&#WAVECAPS_SAMPLEACCURATE:AddElement(menuoptions()):menuoptions()\nombre$="Returns sample-accurate position information":menuoptions()\disponible=0:menuoptions()\salida=1:MenuItem(ListIndex(menuoptions())+1,menuoptions()\nombre$):EndIf
CloseSubMenu()
EndIf
Next
If ListSize(menuoptions())<4
MessageRequester("Error","No suitable wave output devices found!"):ProcedureReturn 0
EndIf
Else
MessageRequester("Error!","No output audio device found!"):ProcedureReturn 0
EndIf
ProcedureReturn ListSize(menuoptions())
EndProcedure
Macro gadgethilos()
If nhilos<6:DisableGadget(#seleccionhilo6,1):DisableGadget(#formadeondahilo6,1):DisableGadget(#fasehilo6,1)
If nhilos<5:DisableGadget(#seleccionhilo5,1):DisableGadget(#formadeondahilo5,1):DisableGadget(#fasehilo5,1)
If nhilos<4:DisableGadget(#seleccionhilo4,1):DisableGadget(#formadeondahilo4,1):DisableGadget(#fasehilo4,1)
If nhilos<3:DisableGadget(#seleccionhilo3,1):DisableGadget(#formadeondahilo3,1):DisableGadget(#fasehilo3,1)
If nhilos<2:DisableGadget(#seleccionhilo2,1):DisableGadget(#formadeondahilo2,1):DisableGadget(#fasehilo2,1)
Else:DisableGadget(#seleccionhilo2,0):DisableGadget(#formadeondahilo2,0):DisableGadget(#fasehilo2,0)
EndIf
Else:DisableGadget(#seleccionhilo3,0):DisableGadget(#formadeondahilo3,0):DisableGadget(#fasehilo3,0)
EndIf
Else:DisableGadget(#seleccionhilo4,0):DisableGadget(#formadeondahilo4,0):DisableGadget(#fasehilo4,0)
EndIf
Else:DisableGadget(#seleccionhilo5,0):DisableGadget(#formadeondahilo5,0):DisableGadget(#fasehilo5,0)
EndIf
Else:DisableGadget(#seleccionhilo6,0):DisableGadget(#formadeondahilo6,0):DisableGadget(#fasehilo6,0)
EndIf
EndMacro
Procedure.i Init_GUI()
If OpenWindow(#MainWin,0,0,canvasw+220,canvash+100+410,"Amplitudes y Frecuencias",#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_SizeGadget)=0:ProcedureReturn 0:EndIf
CanvasGadget(#Canvas,canvasx,canvasy,canvasw,canvash)
CanvasGadget(#Canvasmemoria,canvasx,canvasy+490,canvasw,canvash)
TrackBarGadget(#TrackbarA,sliderax,slideray,slideraw,sliderah,0,1E4,#PB_TrackBar_Vertical); <- a
TrackBarGadget(#TrackbarB,sliderbx,sliderby,sliderbw,sliderbh,0,1E4); <- b
TrackBarGadget(#TrackbarC,slidercx,slidercy,slidercw,sliderch,0,1E4); <- c
TrackBarGadget(#TrackbarE,sliderex,sliderey,sliderew,slidereh,0,1E4); <- e
SetGadgetState(#TrackbarA,a*1E4/canvash)
SetGadgetState(#TrackbarB,b*1E4/canvash)
SetGadgetState(#TrackbarC,c*1E4/canvasw)
SetGadgetState(#TrackbarE,e*1E4/canvasw)
For i=1 To nhilos
amplitudhilo(i)=a*Pow(2,FormatoOut\format\wBitsPerSample)/canvash
alturahilo(i)=b*Pow(2,FormatoOut\format\wBitsPerSample)/canvash
frecuenciahilo(i)=100/c*e
Next
TextGadget(#TextA,sliderax+slideraw,slideray,slideraw*1.8,slideraw,Str(amplitudhilo(1)))
TextGadget(#TextB,sliderbx+sliderbw,sliderby,sliderbh*1.8,sliderbh,Str(alturahilo(1)-Pow(2,FormatoOut\format\wBitsPerSample-1)))
TextGadget(#TextC,slidercx+slidercw,slidercy,sliderch*10,sliderch,StrF(frecuenciahilo(1),3)+" Hz = "+StrF(frecuenciahilo(1)*60,3)+" RPM")
TextGadget(#TextE,sliderex+sliderew,sliderey,slidereh*1.8,slidereh,StrF(e.f,3))
ButtonGadget(#BotonResetView,canvasw+70,0,50,25,"ResetView")
ButtonGadget(#BotonPausa,canvasw+120,0,50,25,"Pause",#PB_Button_Toggle)
OptionGadget(#seleccionhilo1,canvasw+25,60,50,20,"hilo1")
OptionGadget(#seleccionhilo2,canvasw+25,80,50,20,"hilo2")
OptionGadget(#seleccionhilo3,canvasw+25,100,50,20,"hilo3")
OptionGadget(#seleccionhilo4,canvasw+25,120,50,20,"hilo4")
OptionGadget(#seleccionhilo5,canvasw+25,140,50,20,"hilo5")
OptionGadget(#seleccionhilo6,canvasw+25,160,50,20,"hilo6")
SetGadgetState(#seleccionhilo1,1)
TextGadget(#formadeonda,canvasw+90,30,40,25,"forma de onda",#PB_Text_Center)
ComboBoxGadget(#formadeondahilo1,canvasw+75,57,70,25):AddGadgetItem(#formadeondahilo1,-1,"seno"):AddGadgetItem(#formadeondahilo1,-1,"rectangular"):AddGadgetItem(#formadeondahilo1,-1,"triangular1"):SetGadgetState(#formadeondahilo1,formadeondahilo(1))
ComboBoxGadget(#formadeondahilo2,canvasw+75,77,70,25):AddGadgetItem(#formadeondahilo2,-1,"seno"):AddGadgetItem(#formadeondahilo2,-1,"rectangular"):AddGadgetItem(#formadeondahilo2,-1,"triangular1"):SetGadgetState(#formadeondahilo2,formadeondahilo(2))
ComboBoxGadget(#formadeondahilo3,canvasw+75,97,70,25):AddGadgetItem(#formadeondahilo3,-1,"seno"):AddGadgetItem(#formadeondahilo3,-1,"rectangular"):AddGadgetItem(#formadeondahilo3,-1,"triangular1"):SetGadgetState(#formadeondahilo3,formadeondahilo(3))
ComboBoxGadget(#formadeondahilo4,canvasw+75,117,70,25):AddGadgetItem(#formadeondahilo4,-1,"seno"):AddGadgetItem(#formadeondahilo4,-1,"rectangular"):AddGadgetItem(#formadeondahilo4,-1,"triangular1"):SetGadgetState(#formadeondahilo4,formadeondahilo(4))
ComboBoxGadget(#formadeondahilo5,canvasw+75,137,70,25):AddGadgetItem(#formadeondahilo5,-1,"seno"):AddGadgetItem(#formadeondahilo5,-1,"rectangular"):AddGadgetItem(#formadeondahilo5,-1,"triangular1"):SetGadgetState(#formadeondahilo5,formadeondahilo(5))
ComboBoxGadget(#formadeondahilo6,canvasw+75,157,70,25):AddGadgetItem(#formadeondahilo6,-1,"seno"):AddGadgetItem(#formadeondahilo6,-1,"rectangular"):AddGadgetItem(#formadeondahilo6,-1,"triangular1"):SetGadgetState(#formadeondahilo6,formadeondahilo(6))
SpinGadget(#nhilos,canvasw+80,360,70,25,1,6,#PB_Spin_Numeric|#PB_Spin_ReadOnly):SetGadgetState(#nhilos,nhilos):SetGadgetColor(#nhilos,#PB_Gadget_BackColor,#nhiloscolor)
TextGadget(#fase,canvasw+160,40,30,25,"fase",#PB_Text_Center)
SpinGadget(#fasehilo1,canvasw+150,57,50,20,0,0,#PB_Spin_Numeric):SetGadgetState(#fasehilo1,fasehilo(1))
SpinGadget(#fasehilo2,canvasw+150,77,50,20,0,360,#PB_Spin_Numeric):SetGadgetState(#fasehilo2,fasehilo(2))
SpinGadget(#fasehilo3,canvasw+150,97,50,20,0,360,#PB_Spin_Numeric):SetGadgetState(#fasehilo3,fasehilo(3))
SpinGadget(#fasehilo4,canvasw+150,117,50,20,0,360,#PB_Spin_Numeric):SetGadgetState(#fasehilo4,fasehilo(4))
SpinGadget(#fasehilo5,canvasw+150,137,50,20,0,360,#PB_Spin_Numeric):SetGadgetState(#fasehilo5,fasehilo(5))
SpinGadget(#fasehilo6,canvasw+150,157,50,20,0,360,#PB_Spin_Numeric):SetGadgetState(#fasehilo6,fasehilo(6))
CheckBoxGadget(#CheckboxrelacionFA,canvasw+40,300,180,20,"Ligado Frecuencia/Amplitud"):SetGadgetState(#CheckboxrelacionFA,0)
SpinGadget(#SpinrelacionFA,canvasw+40,320,50,20,0,360,#PB_Spin_Numeric):SetGadgetAttribute(#SpinrelacionFA,#PB_Spin_Minimum,-1000):SetGadgetAttribute(#SpinrelacionFA,#PB_Spin_Maximum,1000):SetGadgetState(#SpinrelacionFA,0):DisableGadget(#SpinrelacionFA,GetGadgetState(#CheckboxrelacionFA)!1)
gadgethilos()
ProcedureReturn caracteristicas(#MainWin)
EndProcedure
Procedure EventLoop()
Protected Event.i,eventgadget.i,eventmenu.i
Repeat
Event.i=WaitWindowEvent()
Select Event
Case #PB_Event_Gadget
eventgadget.i=EventGadget()
Select eventgadget
Case #TrackbarA;:EventType()
For i=1 To #maxnhilos:amplitudhilo(i)=GetGadgetState(#TrackbarA)*Pow(2,FormatoOut\format\wBitsPerSample)/1E4:Next
a.f=amplitudhilo(1)*canvash/Pow(2,FormatoOut\format\wBitsPerSample)
SetGadgetText(#TextA,Str(amplitudhilo(1)))
Case #TrackbarB;:EventType()
For i=1 To #maxnhilos:alturahilo(i)=GetGadgetState(#TrackbarB)*Pow(2,FormatoOut\format\wBitsPerSample)/1E4:Next
b.f=alturahilo(1)*canvash/Pow(2,FormatoOut\format\wBitsPerSample)
SetGadgetText(#TextB,Str(alturahilo(1)-Pow(2,FormatoOut\format\wBitsPerSample-1)))
Case #TrackbarC;:EventType()
c.f=GetGadgetState(#TrackbarC)*canvasw/1E4
If c<2:c=2:EndIf
SetGadgetState(#TrackbarC,c*1E4/canvasw)
For i=1 To #maxnhilos:frecuenciahilo(i)=100/c*e:Next
SetGadgetText(#TextC,StrF(frecuenciahilo(1),3)+" Hz = "+StrF(frecuenciahilo(1)*60,3)+" RPM")
Case #TrackbarE;:EventType()
e.f=GetGadgetState(#TrackbarE)*canvasw/1E4
SetGadgetText(#TextE,StrF(e.f,3))
For i=1 To #maxnhilos:frecuenciahilo(i)=100/c*e:Next
SetGadgetText(#TextC,StrF(frecuenciahilo(1),3)+" Hz = "+StrF(frecuenciahilo(1)*60,3)+" RPM")
Case #formadeondahilo1 To #formadeondahilo6:formadeondahilo(eventgadget-#formadeondahilo1+1)=GetGadgetState(eventgadget)
Case #nhilos:hilo=1:SetGadgetState(#seleccionhilo1,1)
; nhilos=GetGadgetState(#nhilos)
gadgethilos()
Case #fasehilo1 To #fasehilo6
For i=1 To #maxnhilos:xmem(i)-Radian(fasehilo(i)):Next
fasehilo(eventgadget-#fasehilo1+1)=GetGadgetState(eventgadget)
gadgethilos()
For i=1 To #maxnhilos:xmem(i)+Radian(fasehilo(i)):Next
Case #Canvas
If EventType()=#PB_EventType_LeftButtonDown:editando=1
canvasmousex.u=GetGadgetAttribute(#Canvas,#PB_Canvas_MouseX)
canvasmousey.u=GetGadgetAttribute(#Canvas,#PB_Canvas_MouseY)
Beep_(800,10)
EndIf
If EventType()=#PB_EventType_LeftButtonUp:editando=0
Beep_(200,10)
EndIf
Case #seleccionhilo1 To #seleccionhilo6:hilo=eventgadget-#seleccionhilo1+1
Case #BotonResetView:canvassumdeltamousex=1.0:canvassumdeltamousey=0
Case #CheckboxrelacionFA:DisableGadget(#SpinrelacionFA,GetGadgetState(#CheckboxrelacionFA)!1)
For i=1 To #maxnhilos:frecuenciahilo(i)=100/c*e:Next
SetGadgetText(#TextC,StrF(frecuenciahilo(1),3)+" Hz = "+StrF(frecuenciahilo(1)*60,3)+" RPM")
Case #SpinrelacionFA
For i=1 To #maxnhilos
relacionAmplitudFrecuencia(i)=GetGadgetState(#SpinrelacionFA)/10000
Next
EndSelect
For i=1 To #maxnhilos
amplitudhilo(i)=a*Pow(2,FormatoOut\format\wBitsPerSample)/canvash
frecuenciahilo(i)=100/c*e
alturahilo(i)=b*Pow(2,FormatoOut\format\wBitsPerSample)/canvash
Next
If GetGadgetState(#CheckboxrelacionFA)
For i=1 To #maxnhilos
frecuenciahilo(i)+amplitudhilo(i)*relacionAmplitudFrecuencia(i)
Next
SetGadgetText(#TextC,StrF(frecuenciahilo(1),3)+" Hz = "+StrF(frecuenciahilo(1)*60,3)+" RPM")
EndIf
Case #PB_Event_Menu
eventmenu.i=EventMenu()
SelectElement(menuoptions(),eventmenu.i-1)
If menuoptions()\disponible
StopSoundOutput()
If menuoptions()\salida
If FindString(menuoptions()\nombre$,"8 bit",1,#PB_String_NoCase):FormatoOut\format\wBitsPerSample=16
ElseIf FindString(menuoptions()\nombre$,"16 bit",1,#PB_String_NoCase):FormatoOut\format\wBitsPerSample=16
ElseIf FindString(menuoptions()\nombre$,"24 bit",1,#PB_String_NoCase):FormatoOut\format\wBitsPerSample=32
ElseIf FindString(menuoptions()\nombre$,"32 bit",1,#PB_String_NoCase):FormatoOut\format\wBitsPerSample=32
EndIf
If FindString(menuoptions()\nombre$,"mono",1,#PB_String_NoCase):nhilos.l=2
ElseIf FindString(menuoptions()\nombre$,"stereo",1,#PB_String_NoCase):nhilos.l=3
EndIf
SetGadgetText(#nhilos,Str(nhilos))
gadgethilos()
;frecuenciahilo(1)=Val(StringField(menuoptions()\nombre$,1," Hz"))
ForEach menuoptions()
If menuoptions()\salida
SetMenuItemState(#Devices,ListIndex(menuoptions())+1,0)
EndIf
Next
SetWindowCallback(@WinCallback()) ; Handle Sound Output callback
StartSoundOutput()
Else
If FindString(menuoptions()\nombre$,"8 bit",1,#PB_String_NoCase):FormatoIn\format\wBitsPerSample=16
ElseIf FindString(menuoptions()\nombre$,"16 bit",1,#PB_String_NoCase):FormatoIn\format\wBitsPerSample=16
ElseIf FindString(menuoptions()\nombre$,"24 bit",1,#PB_String_NoCase):FormatoIn\format\wBitsPerSample=32
ElseIf FindString(menuoptions()\nombre$,"32 bit",1,#PB_String_NoCase):FormatoIn\format\wBitsPerSample=32
EndIf
If FindString(menuoptions()\nombre$,"mono",1,#PB_String_NoCase):nhilosIn.l=2
ElseIf FindString(menuoptions()\nombre$,"stereo",1,#PB_String_NoCase):nhilosIn.l=3
EndIf
;frecuenciahiloin(1)=Val(StringField(menuoptions()\nombre$,1," Hz"))
ForEach menuoptions()
If menuoptions()\salida=0
SetMenuItemState(#Devices,ListIndex(menuoptions())+1,0)
EndIf
Next
EndIf
SetMenuItemState(#Devices,eventmenu,1)
; Debug Str(FormatoOut\format\nSamplesPerSec)+" , "+Str(nhilos)+" , "+Str(FormatoOut\format\wBitsPerSample)+" bit"
; Debug Str(FormatoIn\format\nSamplesPerSec)+" , "+Str(nhilosIn)+" , "+Str(FormatoIn\format\wBitsPerSample)+" bit"
EndIf
Case #WM_KEYUP
ActiveGadget=GetActiveGadget()
Select ActiveGadget
EndSelect
EndSelect
canvashilos()
Until Event=#PB_Event_CloseWindow
EndProcedure
If Init_GUI()
EventLoop()
StopSoundOutput()
EndIf