Hi. You can know this program from my Youtube channel. Of course, I improved it a bit, I added a frequency analyzer and offered this source code. Again, I came across several limits that I want to mention. First...
For everyone who uses ON TIMER in programming, I would like to write my experience here. The command works great, but it is such a C ++ god for QB64, because it is essentially driven by time, as the name implies. I needed to define the way the program ran so that one part of it was processed every one twentieth per second. After editing, the program started making unprecedented errors. I had to write out the contents of the fields to screen, because the caused errors was not logic. By doing so, I found out that ON TIMER simply call the subroutine even in the middle of a loop that is not complete, and then causes such errors. After I added a value validity test in the subroutine before it was processed, the program finally began to behave as expected.
That's one piece of information for everyone. One more information -
sad for developers:. _SNDRAWLEN only works correctly if left or left and right channels are used. If I use just right channel or twice right chnnel, then _SNDRAW work not. Try it on row 152, 153 in attached example. Please use WAV file, 16 bit, stereo or attached link.
Next limit is inability to redefine the field type as needed (this is probably impossible in Basic and thus QB64 for compatibility).
It is a great pity. If it worked as expected, I'd like to. This is shown in lines 120-127.
What a pity, it is SNDRAW and its stereo which does not play as stereo. Please let developers get directions, I have minimal knowledge, but I assume that somewhere in C ++ code there will be some thing that does this. Where can I find the source code for SNDRAW? At worst, it will still be the same ...
_TITLE "Celebrate your programming language with music!"
INPUT "Insert WAV audio file (16 bit, stereo) name:"; file$
CONST CACHE
= 441 ' minimal detected frequency for analyzer is 100 Hz, so this is enought value (with 44100 biterate) subchunksize
AS LONG ' 4 bytes (lo / hi), $00000010 for PCM audio format
AS STRING * 2 ' 2 bytes (0001 = standard PCM, 0101 = IBM mu-law, 0102 = IBM a-law, 0103 = IBM AVC ADPCM) channels
AS INTEGER ' 2 bytes (1 = mono, 2 = stereo) rate
AS LONG ' 4 bytes (sample rate, standard is 44100) ByteRate
AS LONG ' 4 bytes (= sample rate * number of channels * (bits per channel /8)) Block
AS INTEGER ' 2 bytes (block align = number of channels * bits per sample /8) Bits
AS INTEGER ' 2 bytes (bits per sample. 8 = 8, 16 = 16) subchunk2
AS STRING * 4 ' 4 bytes ("data") contains begin audio samples
'REDIM scache(CACHE) AS .... FLOAT can not be used, because is for decimaly numbers only, but program need integer values OR decimaly values!
'next for analyzer use
REDIM sour
(62) AS Sour
' for visualisation
block = H.Block
RATE = H.rate
chan = H.channels
bits = H.Bits
IF bits
<> 16 OR chan
<> 2 THEN BEEP:
PRINT "QB64 limit: Your WAV format is "; bits;
" bits and "; chan;
" channels. For replaying it comment row 106 and set valid type on row 77.":
SLEEP 3:
SYSTEM 'STUPID BASIC LIMITS...
ToScreen = 1 / 1256 '3140
'---- This work NOT under QB64v1.3------------------------- Please comment row 77 for verify!
'----------------------------------------------------------
FrekvLeft = 0
FrekvRight = 0
f = f + 1
lef = scache(P).Left
IF chan
= 1 THEN righ
= lef
ELSE righ
= scache
(P
).Right
lef = lef / 256
righ = righ / 256
lef = lef / RATE
righ = righ / RATE
CASE 32 'values are the same (tested)
IF RATE
> 44100 THEN frekvence
= RATE
ELSE frekvence
= 44100 FOR plll
= 1 TO frekvence
/ RATE
CurrentMovementL = WaveMovement(lef, lf)
CurrentMovementR = WaveMovement(righ, rf)
IF OldMovementL
= 0 THEN OldMovementL
= CurrentMovementL
IF OldMovementR
= 0 THEN OldMovementR
= CurrentMovementR
IF OldMovementL
<> CurrentMovementL
THEN OldMovementL
= CurrentMovementL: FrekvLeft
= FrekvLeft
+ 1 IF OldMovementR
<> CurrentMovementR
THEN OldMovementR
= CurrentMovementR: FrekvRight
= FrekvRight
+ 1
lf = lef
rf = righ
DrawTo:
IF lef
>= -1 AND lef
<= 1 THEN 'comment this two IF conditions for show, what ON TIMER then do.
k = 0
COLOR &HFFFFFF00 ', &HFFAA56D7 LINE (EqL
+ 700, 600)-(EqL
+ 708, 700), _RGB32(255), B
'right lenght = U(ff).L1
lenght2 = U(ff).L2
IF lenght
> 95 THEN lenght
= 95 IF lenght2
> 95 THEN lenght2
= 95
U(ff).L1 = 0
U(ff).L2 = 0
IF lenght
> U
(ff
).max1
THEN U
(ff
).max1
= lenght
IF lenght
> U
(ff
).X
THEN U
(ff
).X
= lenght
IF lenght2
> U
(ff
).max2
THEN U
(ff
).max2
= lenght2
IF lenght2
> U
(ff
).Y
THEN U
(ff
).Y
= lenght2
IF U
(ff
).X
<= 0 THEN U
(ff
).X
= 0: U
(ff
).t
= 0: U
(ff
).max1
= 0 IF U
(ff
).max1
- U
(ff
).X
> 6 THEN U
(ff
).max1
= 0 IF U
(ff
).Y
<= 0 THEN U
(ff
).Y
= 0: U
(ff
).t2
= 0: U
(ff
).max2
= 0 IF U
(ff
).max2
- U
(ff
).Y
> 6 THEN U
(ff
).max2
= 0
IF U
(ff
).X
> 0 AND U
(ff
).max1
THEN LINE (100 + ff
* 10, 700 - U
(ff
).max1
- 5)-(100 + (ff
* 10) + 8, 700 - U
(ff
).max1
), &HFFFF0000, BF
IF U
(ff
).Y
> 0 AND U
(ff
).max2
THEN LINE (800 + ff
* 10, 700 - U
(ff
).max2
- 5)-(800 + (ff
* 10) + 8, 700 - U
(ff
).max2
), &HFFFF0000, BF
LINE (100 + ff
* 10, 700)-(100 + (ff
* 10) + 8, 700 - U
(ff
).X
), , BF
LINE (800 + ff
* 10, 700)-(800 + (ff
* 10) + 8, 700 - U
(ff
).Y
), , BF
I = 0
lfV = (lef * 150)
riV = (righ * 150)
X
= MiddleX
+ SIN(k
) * Radius
+ lfV
Y
= MiddleY
+ COS(k
) * Radius
+ riV
sour(I).X = X
sour(I).Y = Y
I = I + 1
oX = sour(D - 1).X
oY = sour(D - 1).Y
nX = sour(D).X
nY = sour(D).Y
oX = sour(0).X
oY = sour(0).Y
nX = sour(62).X
nY = sour(62).Y
oX = sour(D - 1).X
oY = sour(D - 1).Y
nX = sour(D).X
nY = sour(D).Y
iiX
= mIx
+ SIN(D
/ 10) * mIx
iiY
= mIh
+ COS(D
/ 10) * mIh
oiX
= mIx
+ SIN((D
- 1) / 10) * mIx
oiY
= mIh
+ COS((D
- 1) / 10) * mIh
_MAPTRIANGLE (iiX
, iiY
)-(oiX
, oiY
)-(mIx
, mIh
), image&
TO(oX
, oY
)-(nX
, nY
)-(mmIx
, mmiY
), Virtual&
oX = sour(0).X
oY = sour(0).Y
nX = sour(62).X
nY = sour(62).Y
oiX
= mIx
+ SIN(6.2) * mIx
oiY
= mIh
+ COS(6.2) * mIh
_MAPTRIANGLE (iiX
, iiY
)-(oiX
, oiY
)-(mIx
, mIh
), image&
TO(oX
, oY
)-(nX
, nY
)-(mmIx
, mmiY
), Virtual&
text$ = "Example how visualise music in QB64. Writed Petr Preclik."
analyzer:
FrekvL = FrekvLeft * 100: lf = 0
FrekvR = FrekvRight * 100: rf = 0
U(sh).L1 = U(sh).L1 + .09
U(sh2).L2 = U(sh2).L2 + .09
FUNCTION WaveMovement
(New_Value
, Old_Value
) ' Tested with WAV from 100 Hz to 20 KHz and return correct outputs (see row 156 to 164, previous signal values on row 163, 164 are needed) IF New_Value
> Old_Value
THEN WaveMovement
= 1 IF New_Value
< Old_Value
THEN WaveMovement
= -1
If you need, download WAV file from
https://drive.google.com/file/d/10HBu8_QD_fBRc_JO3P3K_iPZVSE-7O-_/view?usp=sharing