Author Topic: WAV Player with Graphical Output Displays  (Read 4744 times)

0 Members and 1 Guest are viewing this topic.

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
WAV Player with Graphical Output Displays
« on: November 03, 2019, 01:09:20 am »
Most of this is by Petr. Thank you Petr! I added 6 more graphical displays for the music to go by. I also added the ability to type in a name of the .wav file you want to play.
I made this new thread so people can easily find a WAV player with graphical output displays better when they search. Petr helped me learn how to grab the left and right outputs and form them into graphics from the .wav sound file.
After you type in a .wav file name (with the .wav ending), use the Space Bar to change between 7 different graphical output displays. Petr made the first one. After the 7th, it goes back to the first. If you wonder how you can save an .mp3 as a .wav file, I use a free program called Audacity. But just remember, .wav files are about 10 times larger than .mp3.

Code: QB64: [Select]
  1. 'Almost all of this was made by Petr from the QB64.org forum.
  2. 'Some of the displays added by SierraKen (Ken G.).
  3. _TITLE "WAV Music Player - Space Bar Changes Display When Playing. Esc to Quit."
  4. SCREEN _NEWIMAGE(800, 600, 256)
  5.     CLS
  6.     PRINT: PRINT: PRINT
  7.     INPUT "Type .WAV music filename here or only Enter to quit:", nm$
  8.     IF nm$ = "" THEN END
  9.     CLS
  10.     wav nm$ 'insert uncompressed wav audio filename here
  11. SUB wav (file$)
  12.     TYPE head
  13.         chunk AS STRING * 4 '       4 bytes  (RIFF)
  14.         size AS LONG '              4 bytes  (?E??)
  15.         fomat AS STRING * 4 '       4 bytes  (WAVE)
  16.         sub1 AS STRING * 4 '        4 bytes  (fmt )
  17.         subchunksize AS LONG '      4 bytes  (lo / hi), $00000010 for PCM audio
  18.         format AS STRING * 2 '      2 bytes  (0001 = standard PCM, 0101 = IBM mu-law, 0102 = IBM a-law, 0103 = IBM AVC ADPCM)
  19.         channels AS INTEGER '       2 bytes  (1 = mono, 2 = stereo)
  20.         rate AS LONG '              4 bytes  (sample rate, standard is 44100)
  21.         ByteRate AS LONG '          4 bytes  (= sample rate * number of channels * (bits per channel /8))
  22.         Block AS INTEGER '          2 bytes  (block align = number of channels * bits per sample /8)
  23.         Bits AS INTEGER '           2 bytes  (bits per sample. 8 = 8, 16 = 16)
  24.         subchunk2 AS STRING * 4 '   4 bytes  ("data")  contains begin audio samples
  25.     END TYPE '                     40 bytes  total
  26.     DIM H AS head
  27.     ch = FREEFILE
  28.  
  29.     IF _FILEEXISTS(file$) THEN OPEN file$ FOR BINARY AS #ch ELSE PRINT file$; " not found": SLEEP 2: SYSTEM
  30.     GET #ch, , H
  31.  
  32.     block = H.Block
  33.     RATE = H.rate
  34.     chan = H.channels
  35.     bits = H.Bits
  36.  
  37.  
  38.     DO WHILE NOT EOF(ch)
  39.  
  40.         vz = 44100 / 80
  41.         IF (SEEK(ch) - 40) MOD vz = 0 THEN
  42.             visual lefVis / vz, righVis / vz
  43.             lefVis = 0
  44.             righVis = 0
  45.         END IF
  46.         lefVis = lefVis + ABS(lef)
  47.         righVis = righVis + ABS(righ)
  48.  
  49.  
  50.  
  51.         IF bits = 16 AND chan = 2 THEN
  52.             REDIM lefi AS INTEGER, righi AS INTEGER
  53.             GET #ch, , lefi
  54.             GET #ch, , righi
  55.             lef = lefi / RATE
  56.             righ = righi / RATE
  57.         END IF
  58.  
  59.         IF bits = 16 AND chan = 1 THEN
  60.             REDIM leftMono AS INTEGER
  61.             GET #ch, , leftMono
  62.             lef = leftMono / RATE
  63.             righ = leftMono / RATE
  64.         END IF
  65.  
  66.         IF bits = 8 AND chan = 2 THEN
  67.             REDIM lleft8 AS _UNSIGNED _BYTE, rright8 AS _UNSIGNED _BYTE
  68.             GET #ch, , lleft8
  69.             GET #ch, , rright8
  70.             lef = lleft8 / 256
  71.             righ = rright8 / 256
  72.         END IF
  73.  
  74.         IF bits = 8 AND chan = 1 THEN
  75.             REDIM mono8 AS _UNSIGNED _BYTE
  76.             GET #ch, , mono8
  77.             lef = mono8 / 256
  78.             righ = lef
  79.         END IF
  80.  
  81.         IF RATE > 44100 THEN frekvence = RATE ELSE frekvence = 44100
  82.         FOR plll = 1 TO frekvence / RATE
  83.             _SNDRAW lef, righ
  84.         NEXT plll
  85.  
  86.         DO WHILE _SNDRAWLEN > 0: LOOP: REM By commenting this row you DAMAGE SOUND / VIDEO synchronizing. TRY IT.
  87.  
  88.  
  89.     LOOP
  90.     CLOSE ch
  91.  
  92. SUB visual (lef, righ)
  93.     SHARED x, oldx1, oldx2, disp, tt, xxx, yyy, xxx2, yyy2, oldxxx, oldyyy, oldxxx2, oldyyy2
  94.     STP = 5 ' TRY rewriting STP value to other
  95.     x1 = lef * 200
  96.     x2 = righ * 200
  97.     a$ = INKEY$
  98.     IF a$ = " " THEN CLS: disp = disp + 1: tt = 0
  99.     IF a$ = CHR$(27) THEN END
  100.     IF disp > 6 THEN disp = 0
  101.  
  102.     IF oldx1 AND disp = 6 THEN
  103.         LINE (0, 0)-(800, 450), _RGBA(0, 0, 0, 30), BF
  104.         CIRCLE (200, 200), 182, 25
  105.         CIRCLE (600, 200), 182, 25
  106.         p = x1 * 5
  107.         p2 = x2 * 5
  108.         sec = (p * .6) + seconds
  109.         sec2 = (p2 * .6) + seconds2
  110.         seconds = sec
  111.         seconds2 = sec2
  112.         IF seconds > 359 THEN seconds = 0
  113.         seconds = seconds + 1
  114.         s = (60 - seconds) * 6 + 180
  115.         oldxxx = xxx: oldyyy = yyy
  116.         xxx = INT(SIN(s / 180 * _PI) * 180) + 200
  117.         yyy = INT(COS(s / 180 * _PI) * 180) + 200
  118.         LINE (200, 200)-(xxx, yyy), 14
  119.  
  120.         IF seconds2 > 359 THEN seconds = 0
  121.         seconds2 = seconds2 + 1
  122.         s2 = (60 - seconds2) * 6 + 180
  123.         oldxxx2 = xxx2: oldyyy2 = yyy2
  124.         xxx2 = INT(SIN(s2 / 180 * _PI) * 180) + 600
  125.         yyy2 = INT(COS(s2 / 180 * _PI) * 180) + 200
  126.         LINE (600, 200)-(xxx2, yyy2), 3
  127.         _DISPLAY
  128.     END IF
  129.  
  130.  
  131.     IF oldx1 AND disp = 5 THEN
  132.         IF x > 200 THEN CLS: x = 0
  133.         xx = x + 100
  134.         xx2 = x + 500
  135.         LINE (xx, 0)-(xx + STP, 400), 0, BF
  136.         FOR sz = .25 TO 5 STEP .25
  137.             CIRCLE (xx, 300 - (x1 * 2)), sz, 1
  138.             CIRCLE (xx - STP, 300 - (oldx1 * 2)), sz, 1
  139.         NEXT sz
  140.         FOR sz2 = .25 TO 5 STEP .25
  141.             CIRCLE (xx2, 300 - (x2 * 2)), sz2, 10
  142.             CIRCLE (xx2 - STP, 300 - (oldx2 * 2)), sz2, 10
  143.         NEXT sz2
  144.     END IF
  145.  
  146.  
  147.     IF oldx1 AND disp = 4 THEN
  148.         IF x > 799.9 THEN CLS: x = 0
  149.         LINE (x, 0)-(x + STP, 400), 0, BF
  150.         FOR sz = .25 TO 5 STEP .25
  151.             CIRCLE (x, 300 - (x1 * 2)), sz, 1
  152.             CIRCLE (x - STP, 300 - (oldx1 * 2)), sz, 1
  153.         NEXT sz
  154.         FOR sz2 = .25 TO 5 STEP .25
  155.             CIRCLE (x, 300 - (x2 * 2)), sz2, 10
  156.             CIRCLE (x - STP, 300 - (oldx2 * 2)), sz2, 10
  157.         NEXT sz2
  158.     END IF
  159.  
  160.  
  161.     IF oldx1 AND disp = 3 THEN
  162.         IF x = 800 THEN CLS: x = 0
  163.         LINE (x, 0)-(x + STP, 400), 0, BF
  164.         LINE (x, 300 - (x1 * 4))-(x - STP, 300 - (oldx1 * 4)), 15
  165.  
  166.         LINE (x, 200 - (x2 * 4))-(x - STP, 200 - (oldx2 * 4)), 14
  167.     END IF
  168.  
  169.  
  170.     IF oldx1 AND disp = 2 THEN
  171.         tt = tt + 1
  172.         IF tt < 5 THEN GOTO skip:
  173.         tt = 0
  174.         c1 = RND * 255
  175.         c2 = RND * 255
  176.         c3 = RND * 255
  177.         xx = RND * 800
  178.         yy = RND * 600
  179.         LINE (xx, yy)-((xx + x1) * 2, (yy + x2) * 2), _RGB32(c1, c2, c3), BF
  180.         skip:
  181.     END IF
  182.     IF oldx1 AND disp = 1 THEN
  183.         tt = tt + 1
  184.         IF tt < 5 THEN GOTO skip2:
  185.         tt = 0
  186.         c1 = RND * 255
  187.         c2 = RND * 255
  188.         c3 = RND * 255
  189.         xx = RND * 800
  190.         yy = RND * 600
  191.         CIRCLE (xx, yy), x1 * 2, _RGB32(c1, c2, c3)
  192.         PAINT (xx, yy), _RGB32(c1, c2, c3)
  193.         skip2:
  194.     END IF
  195.     IF oldx1 AND disp = 0 THEN
  196.         IF x = 800 THEN CLS: x = 0
  197.         LINE (x, 0)-(x + STP, 400), 0, BF
  198.         LINE (x, 200 - x1)-(x - STP, 200 - oldx1), 15
  199.  
  200.         LINE (x, 100 - x2)-(x - STP, 100 - oldx2), 14
  201.     END IF
  202.  
  203.     oldx1 = x1
  204.     oldx2 = x2
  205.     x = x + STP: IF x > _WIDTH THEN x = 0
  206.  
  207.     LINE (100, 600)-(300, 400), 0, BF
  208.     LINE (100, 600)-(300, 600 - 500 * lef), 14, BF
  209.  
  210.     LINE (700, 600)-(500, 400), 0, BF
  211.     LINE (700, 600)-(500, 600 - 500 * righ), 3, BF
  212.  


Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: WAV Player with Graphical Output Displays
« Reply #1 on: November 03, 2019, 04:27:49 am »
Nice work, SierraKen. if I have time today, I will also write some visualizations.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: WAV Player with Graphical Output Displays
« Reply #2 on: November 03, 2019, 05:26:38 am »
SierraKen, this source code containst 1 visualization. Better solution. Program load 800 samples to array for both channels (because screen width is 800) and when is array full (contains 800 samples), so then draw all as two lines to screen, erase both arrays and again save next samples to arrays. For faster visualization speed is possible saving less samples and placing it in step to screen (second source code)

Source code: Show all samples (not fast)

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 600, 256)
  2.  
  3. REDIM SHARED LeftCurve(799) AS INTEGER
  4. REDIM SHARED RightCurve(799) AS INTEGER
  5.  
  6. wav "s.wav" 'insert uncompressed wav audio filename here
  7.  
  8. SUB wav (file$)
  9.     TYPE head
  10.         chunk AS STRING * 4 '       4 bytes  (RIFF)
  11.         size AS LONG '              4 bytes  (?E??)
  12.         fomat AS STRING * 4 '       4 bytes  (WAVE)
  13.         sub1 AS STRING * 4 '        4 bytes  (fmt )
  14.         subchunksize AS LONG '      4 bytes  (lo / hi), $00000010 for PCM audio
  15.         format AS STRING * 2 '      2 bytes  (0001 = standard PCM, 0101 = IBM mu-law, 0102 = IBM a-law, 0103 = IBM AVC ADPCM)
  16.         channels AS INTEGER '       2 bytes  (1 = mono, 2 = stereo)
  17.         rate AS LONG '              4 bytes  (sample rate, standard is 44100)
  18.         ByteRate AS LONG '          4 bytes  (= sample rate * number of channels * (bits per channel /8))
  19.         Block AS INTEGER '          2 bytes  (block align = number of channels * bits per sample /8)
  20.         Bits AS INTEGER '           2 bytes  (bits per sample. 8 = 8, 16 = 16)
  21.         subchunk2 AS STRING * 4 '   4 bytes  ("data")  contains begin audio samples
  22.     END TYPE '                     40 bytes  total
  23.     DIM H AS head
  24.  
  25.  
  26.  
  27.     ch = FREEFILE
  28.  
  29.     IF _FILEEXISTS(file$) THEN OPEN file$ FOR BINARY AS #ch ELSE PRINT file$; " not found": SLEEP 2: SYSTEM
  30.     GET #ch, , H
  31.  
  32.     block = H.Block
  33.     RATE = H.rate
  34.     chan = H.channels
  35.     bits = H.Bits
  36.  
  37.  
  38.     DO WHILE NOT EOF(ch)
  39.  
  40.         IF bits = 16 AND chan = 2 THEN
  41.             REDIM lefi AS INTEGER, righi AS INTEGER
  42.             GET #ch, , lefi
  43.             GET #ch, , righi
  44.             Lef = lefi / RATE
  45.             righ = righi / RATE
  46.         END IF
  47.  
  48.         IF bits = 16 AND chan = 1 THEN
  49.             REDIM leftMono AS INTEGER
  50.             GET #ch, , leftMono
  51.             Lef = leftMono / RATE
  52.             righ = leftMono / RATE
  53.         END IF
  54.  
  55.         IF bits = 8 AND chan = 2 THEN
  56.             REDIM lleft8 AS _UNSIGNED _BYTE, rright8 AS _UNSIGNED _BYTE
  57.             GET #ch, , lleft8
  58.             GET #ch, , rright8
  59.             Lef = lleft8 / 256
  60.             righ = rright8 / 256
  61.         END IF
  62.  
  63.         IF bits = 8 AND chan = 1 THEN
  64.             REDIM mono8 AS _UNSIGNED _BYTE
  65.             GET #ch, , mono8
  66.             Lef = mono8 / 256
  67.             righ = Lef
  68.         END IF
  69.  
  70.         IF RATE > 44100 THEN frekvence = RATE ELSE frekvence = 44100
  71.         FOR plll = 1 TO frekvence / RATE
  72.             _SNDRAW Lef, righ
  73.         NEXT plll
  74.  
  75.         DO WHILE _SNDRAWLEN > 0: LOOP: REM By commenting this row you DAMAGE SOUND / VIDEO synchronizing. TRY IT.
  76.  
  77.         '----------------------------------------
  78.         Sample = Sample + 1
  79.         IF Sample > 799 THEN
  80.             Visual
  81.             REDIM LeftCurve(799) AS INTEGER
  82.             REDIM RightCurve(799) AS INTEGER
  83.             Sample = 0
  84.         END IF
  85.         LeftCurve(Sample) = 300 + Lef * 300
  86.         RightCurve(Sample) = 300 + righ * 300
  87.         '---------------------------------------
  88.  
  89.     LOOP
  90.     CLOSE ch
  91.  
  92. SUB Visual
  93.     CLS
  94.     FOR x = 0 TO 798 STEP 1
  95.         LINE (x, LeftCurve(x))-(x + 1, LeftCurve(x + 1)), 14
  96.         LINE (x, RightCurve(x))-(x + 1, RightCurve(x + 1)), 15
  97.     NEXT
  98.  

Source code: Show less samples at once (faster)

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 600, 256)
  2.  
  3. REDIM SHARED LeftCurve(79) AS INTEGER
  4. REDIM SHARED RightCurve(79) AS INTEGER
  5.  
  6. wav "s.wav" 'insert uncompressed wav audio filename here
  7.  
  8. SUB wav (file$)
  9.     TYPE head
  10.         chunk AS STRING * 4 '       4 bytes  (RIFF)
  11.         size AS LONG '              4 bytes  (?E??)
  12.         fomat AS STRING * 4 '       4 bytes  (WAVE)
  13.         sub1 AS STRING * 4 '        4 bytes  (fmt )
  14.         subchunksize AS LONG '      4 bytes  (lo / hi), $00000010 for PCM audio
  15.         format AS STRING * 2 '      2 bytes  (0001 = standard PCM, 0101 = IBM mu-law, 0102 = IBM a-law, 0103 = IBM AVC ADPCM)
  16.         channels AS INTEGER '       2 bytes  (1 = mono, 2 = stereo)
  17.         rate AS LONG '              4 bytes  (sample rate, standard is 44100)
  18.         ByteRate AS LONG '          4 bytes  (= sample rate * number of channels * (bits per channel /8))
  19.         Block AS INTEGER '          2 bytes  (block align = number of channels * bits per sample /8)
  20.         Bits AS INTEGER '           2 bytes  (bits per sample. 8 = 8, 16 = 16)
  21.         subchunk2 AS STRING * 4 '   4 bytes  ("data")  contains begin audio samples
  22.     END TYPE '                     40 bytes  total
  23.     DIM H AS head
  24.  
  25.  
  26.  
  27.     ch = FREEFILE
  28.  
  29.     IF _FILEEXISTS(file$) THEN OPEN file$ FOR BINARY AS #ch ELSE PRINT file$; " not found": SLEEP 2: SYSTEM
  30.     GET #ch, , H
  31.  
  32.     block = H.Block
  33.     RATE = H.rate
  34.     chan = H.channels
  35.     bits = H.Bits
  36.  
  37.  
  38.     DO WHILE NOT EOF(ch)
  39.  
  40.         IF bits = 16 AND chan = 2 THEN
  41.             REDIM lefi AS INTEGER, righi AS INTEGER
  42.             GET #ch, , lefi
  43.             GET #ch, , righi
  44.             Lef = lefi / RATE
  45.             righ = righi / RATE
  46.         END IF
  47.  
  48.         IF bits = 16 AND chan = 1 THEN
  49.             REDIM leftMono AS INTEGER
  50.             GET #ch, , leftMono
  51.             Lef = leftMono / RATE
  52.             righ = leftMono / RATE
  53.         END IF
  54.  
  55.         IF bits = 8 AND chan = 2 THEN
  56.             REDIM lleft8 AS _UNSIGNED _BYTE, rright8 AS _UNSIGNED _BYTE
  57.             GET #ch, , lleft8
  58.             GET #ch, , rright8
  59.             Lef = lleft8 / 256
  60.             righ = rright8 / 256
  61.         END IF
  62.  
  63.         IF bits = 8 AND chan = 1 THEN
  64.             REDIM mono8 AS _UNSIGNED _BYTE
  65.             GET #ch, , mono8
  66.             Lef = mono8 / 256
  67.             righ = Lef
  68.         END IF
  69.  
  70.         IF RATE > 44100 THEN frekvence = RATE ELSE frekvence = 44100
  71.         FOR plll = 1 TO frekvence / RATE
  72.             _SNDRAW Lef, righ
  73.         NEXT plll
  74.  
  75.         DO WHILE _SNDRAWLEN > 0: LOOP: REM By commenting this row you DAMAGE SOUND / VIDEO synchronizing. TRY IT.
  76.  
  77.         '----------------------------------------
  78.         Sam = Sam + 1
  79.         IF Sam MOD 10 = 0 THEN 'Save every 10th sample to array for visualising (save CPU time and power)
  80.             sample = sample + 1
  81.             IF sample > 79 THEN
  82.                 Visual
  83.                 REDIM LeftCurve(799) AS INTEGER
  84.                 REDIM RightCurve(799) AS INTEGER
  85.                 sample = 0
  86.                 Sam = 0
  87.             END IF
  88.             LeftCurve(sample) = 300 + Lef * 300
  89.             RightCurve(sample) = 300 + righ * 300
  90.         END IF
  91.         '---------------------------------------
  92.  
  93.     LOOP
  94.     CLOSE ch
  95.  
  96. SUB Visual
  97.     CLS
  98.     FOR x = 0 TO 78
  99.         LINE (x * 10, LeftCurve(x))-(x * 10 + 10, LeftCurve(x + 1)), 14
  100.         LINE (x * 10, RightCurve(x))-(x * 10 + 10, RightCurve(x + 1)), 15
  101.     NEXT
  102.  


Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: WAV Player with Graphical Output Displays
« Reply #3 on: November 03, 2019, 06:51:29 pm »
That's really good and tightly made. But I don't have the experience with SUBs to implement my displays on your new ones. I do see that your loop in the visual sub keeps going pretty much the same time as your wav sub does. Maybe if I played around with it enough I could figure out how to add to it, but I think I'm just going to leave it as it is so people can have a choice on what to do with these examples. Thanks your help.

Offline Lucky_Strikez

  • Newbie
  • Posts: 7
    • View Profile
Re: WAV Player with Graphical Output Displays
« Reply #4 on: November 07, 2019, 04:25:45 pm »
That's awesome!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: WAV Player with Graphical Output Displays
« Reply #5 on: November 08, 2019, 12:07:42 pm »
Small upgrade, which show you how to add next visualisations:

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 600, 256)
  2.  
  3. REDIM SHARED LeftCurve(799) AS INTEGER
  4. REDIM SHARED RightCurve(799) AS INTEGER
  5. DIM SHARED Angle1, Angle2
  6.  
  7. wav "w.wav" 'insert uncompressed wav audio filename here
  8.  
  9. SUB wav (file$)
  10.     TYPE head
  11.         chunk AS STRING * 4 '       4 bytes  (RIFF)
  12.         size AS LONG '              4 bytes  (?E??)
  13.         fomat AS STRING * 4 '       4 bytes  (WAVE)
  14.         sub1 AS STRING * 4 '        4 bytes  (fmt )
  15.         subchunksize AS LONG '      4 bytes  (lo / hi), $00000010 for PCM audio
  16.         format AS STRING * 2 '      2 bytes  (0001 = standard PCM, 0101 = IBM mu-law, 0102 = IBM a-law, 0103 = IBM AVC ADPCM)
  17.         channels AS INTEGER '       2 bytes  (1 = mono, 2 = stereo)
  18.         rate AS LONG '              4 bytes  (sample rate, standard is 44100)
  19.         ByteRate AS LONG '          4 bytes  (= sample rate * number of channels * (bits per channel /8))
  20.         Block AS INTEGER '          2 bytes  (block align = number of channels * bits per sample /8)
  21.         Bits AS INTEGER '           2 bytes  (bits per sample. 8 = 8, 16 = 16)
  22.         subchunk2 AS STRING * 4 '   4 bytes  ("data")  contains begin audio samples
  23.     END TYPE '                     40 bytes  total
  24.     DIM H AS head
  25.  
  26.  
  27.  
  28.     ch = FREEFILE
  29.  
  30.     IF _FILEEXISTS(file$) THEN OPEN file$ FOR BINARY AS #ch ELSE PRINT file$; " not found": SLEEP 2: SYSTEM
  31.     GET #ch, , H
  32.  
  33.     block = H.Block
  34.     RATE = H.rate
  35.     chan = H.channels
  36.     bits = H.Bits
  37.  
  38.  
  39.     DO WHILE NOT EOF(ch)
  40.  
  41.         IF bits = 16 AND chan = 2 THEN
  42.             REDIM lefi AS INTEGER, righi AS INTEGER
  43.             GET #ch, , lefi
  44.             GET #ch, , righi
  45.             Lef = lefi / RATE
  46.             righ = righi / RATE
  47.         END IF
  48.  
  49.         IF bits = 16 AND chan = 1 THEN
  50.             REDIM leftMono AS INTEGER
  51.             GET #ch, , leftMono
  52.             Lef = leftMono / RATE
  53.             righ = leftMono / RATE
  54.         END IF
  55.  
  56.         IF bits = 8 AND chan = 2 THEN
  57.             REDIM lleft8 AS _UNSIGNED _BYTE, rright8 AS _UNSIGNED _BYTE
  58.             GET #ch, , lleft8
  59.             GET #ch, , rright8
  60.             Lef = lleft8 / 256
  61.             righ = rright8 / 256
  62.         END IF
  63.  
  64.         IF bits = 8 AND chan = 1 THEN
  65.             REDIM mono8 AS _UNSIGNED _BYTE
  66.             GET #ch, , mono8
  67.             Lef = mono8 / 256
  68.             righ = Lef
  69.         END IF
  70.  
  71.         IF RATE > 44100 THEN frekvence = RATE ELSE frekvence = 44100
  72.         FOR plll = 1 TO frekvence / RATE
  73.             _SNDRAW Lef, righ
  74.         NEXT plll
  75.  
  76.         DO WHILE _SNDRAWLEN > 0: LOOP: REM By commenting this row you DAMAGE SOUND / VIDEO synchronizing. TRY IT.
  77.  
  78.         '----------------------------------------
  79.         IF _KEYHIT = 32 THEN eff = eff + 1: IF eff > 2 THEN eff = 0
  80.  
  81.  
  82.  
  83.         Sample = Sample + 1
  84.         IF Sample > 799 THEN
  85.             Visual eff
  86.             REDIM LeftCurve(799) AS INTEGER
  87.             REDIM RightCurve(799) AS INTEGER
  88.             Sample = 0
  89.         END IF
  90.         LeftCurve(Sample) = 300 + Lef * 300
  91.         RightCurve(Sample) = 300 + righ * 300
  92.         '---------------------------------------
  93.  
  94.     LOOP
  95.     CLOSE ch
  96.  
  97. SUB Visual (EffectNr)
  98.  
  99.     CLS
  100.     SELECT CASE EffectNr
  101.         CASE 0
  102.             _AUTODISPLAY
  103.             FOR x = 0 TO 798 STEP 1
  104.                 LINE (x, LeftCurve(x))-(x + 1, LeftCurve(x + 1)), 14
  105.                 LINE (x, RightCurve(x))-(x + 1, RightCurve(x + 1)), 15
  106.             NEXT
  107.  
  108.         CASE 1 'do circle.
  109.             _AUTODISPLAY
  110.             Angle1 = Angle1 + .01
  111.             Angle2 = Angle2 - .01
  112.             STP = _PI(2) / 800
  113.             FOR C = 0 TO _PI(2) - STP STEP STP
  114.                 X1 = 400 + SIN(C + Angle1) * LeftCurve(i) / 2
  115.                 X2 = 400 + SIN(C + STP + Angle1) * LeftCurve(i + 1) / 2
  116.                 Y1 = 300 + COS(C + Angle1) * LeftCurve(i) / 2
  117.                 Y2 = 300 + COS(C + STP + Angle1) * LeftCurve(i + 1) / 2
  118.                 IF ox1 = 0 THEN ox1 = X1: oy1 = Y1
  119.                 LINE (X1, Y1)-(X2, Y2), 14
  120.  
  121.                 X3 = 400 + SIN(C + Angle2) * RightCurve(i) / 3
  122.                 X4 = 400 + SIN(C + STP + Angle2) * RightCurve(i + 1) / 3
  123.                 Y3 = 300 + COS(C + Angle2) * RightCurve(i) / 3
  124.                 Y4 = 300 + COS(C + STP + Angle2) * RightCurve(i + 1) / 3
  125.                 IF ox3 = 0 THEN ox3 = X3: oy3 = Y3
  126.                 LINE (X3, Y3)-(X4, Y4), 15
  127.  
  128.                 i = i + 1
  129.             NEXT
  130.             LINE (X2, Y2)-(ox1, oy1), 14: ox1 = 0
  131.             LINE (X4, Y4)-(ox3, oy3), 15: ox3 = 0
  132.  
  133.         CASE 2 'small modification CASE 1
  134.             STP = _PI(2) / 800
  135.             Angle1 = Angle1 + .01
  136.             Angle2 = Angle2 - .01
  137.             FOR C = 0 TO _PI(2) - STP STEP STP
  138.                 X1 = 150 + SIN(C + Angle1) * LeftCurve(i) / 3
  139.                 Y1 = 300 + COS(C + Angle1) * LeftCurve(i) / 3
  140.                 X2 = 650 + SIN(C + Angle2) * RightCurve(i) / 3
  141.                 Y2 = 300 + COS(C + Angle2) * RightCurve(i) / 3
  142.  
  143.                 LINE (X2, Y2)-(650, 300), 14
  144.                 LINE (X1, Y1)-(150, 300), 15
  145.                 i = i + 1
  146.             NEXT
  147.             _DISPLAY
  148.     END SELECT
  149.  

All values, which you need are in SHARED arrays LeftCurve and RightCurve. Both are from 0 to 799. Use spaceboard for switching visualisations.

For testing it, i recommend SPEEDCORE, or HARDCORE music style :-)
« Last Edit: November 08, 2019, 12:30:00 pm by Petr »

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: WAV Player with Graphical Output Displays
« Reply #6 on: November 08, 2019, 02:14:04 pm »
I added a couple of visuals to your new one Petr. :) Thanks!

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 600, 256)
  2.  
  3. REDIM SHARED LeftCurve(799) AS INTEGER
  4. REDIM SHARED RightCurve(799) AS INTEGER
  5. DIM SHARED Angle1, Angle2
  6.  
  7. wav "Delight.wav" 'insert uncompressed wav audio filename here
  8.  
  9. SUB wav (file$)
  10.     TYPE head
  11.         chunk AS STRING * 4 '       4 bytes  (RIFF)
  12.         size AS LONG '              4 bytes  (?E??)
  13.         fomat AS STRING * 4 '       4 bytes  (WAVE)
  14.         sub1 AS STRING * 4 '        4 bytes  (fmt )
  15.         subchunksize AS LONG '      4 bytes  (lo / hi), $00000010 for PCM audio
  16.         format AS STRING * 2 '      2 bytes  (0001 = standard PCM, 0101 = IBM mu-law, 0102 = IBM a-law, 0103 = IBM AVC ADPCM)
  17.         channels AS INTEGER '       2 bytes  (1 = mono, 2 = stereo)
  18.         rate AS LONG '              4 bytes  (sample rate, standard is 44100)
  19.         ByteRate AS LONG '          4 bytes  (= sample rate * number of channels * (bits per channel /8))
  20.         Block AS INTEGER '          2 bytes  (block align = number of channels * bits per sample /8)
  21.         Bits AS INTEGER '           2 bytes  (bits per sample. 8 = 8, 16 = 16)
  22.         subchunk2 AS STRING * 4 '   4 bytes  ("data")  contains begin audio samples
  23.     END TYPE '                     40 bytes  total
  24.     DIM H AS head
  25.  
  26.  
  27.  
  28.     ch = FREEFILE
  29.  
  30.     IF _FILEEXISTS(file$) THEN OPEN file$ FOR BINARY AS #ch ELSE PRINT file$; " not found": SLEEP 2: SYSTEM
  31.     GET #ch, , H
  32.  
  33.     block = H.Block
  34.     RATE = H.rate
  35.     chan = H.channels
  36.     bits = H.Bits
  37.  
  38.  
  39.     DO WHILE NOT EOF(ch)
  40.  
  41.         IF bits = 16 AND chan = 2 THEN
  42.             REDIM lefi AS INTEGER, righi AS INTEGER
  43.             GET #ch, , lefi
  44.             GET #ch, , righi
  45.             Lef = lefi / RATE
  46.             righ = righi / RATE
  47.         END IF
  48.  
  49.         IF bits = 16 AND chan = 1 THEN
  50.             REDIM leftMono AS INTEGER
  51.             GET #ch, , leftMono
  52.             Lef = leftMono / RATE
  53.             righ = leftMono / RATE
  54.         END IF
  55.  
  56.         IF bits = 8 AND chan = 2 THEN
  57.             REDIM lleft8 AS _UNSIGNED _BYTE, rright8 AS _UNSIGNED _BYTE
  58.             GET #ch, , lleft8
  59.             GET #ch, , rright8
  60.             Lef = lleft8 / 256
  61.             righ = rright8 / 256
  62.         END IF
  63.  
  64.         IF bits = 8 AND chan = 1 THEN
  65.             REDIM mono8 AS _UNSIGNED _BYTE
  66.             GET #ch, , mono8
  67.             Lef = mono8 / 256
  68.             righ = Lef
  69.         END IF
  70.  
  71.         IF RATE > 44100 THEN frekvence = RATE ELSE frekvence = 44100
  72.         FOR plll = 1 TO frekvence / RATE
  73.             _SNDRAW Lef, righ
  74.         NEXT plll
  75.  
  76.         DO WHILE _SNDRAWLEN > 0: LOOP: REM By commenting this row you DAMAGE SOUND / VIDEO synchronizing. TRY IT.
  77.  
  78.         '----------------------------------------
  79.         IF _KEYHIT = 32 THEN eff = eff + 1: IF eff > 6 THEN eff = 0
  80.  
  81.  
  82.  
  83.         Sample = Sample + 1
  84.         IF Sample > 799 THEN
  85.             Visual eff
  86.             REDIM LeftCurve(799) AS INTEGER
  87.             REDIM RightCurve(799) AS INTEGER
  88.             Sample = 0
  89.         END IF
  90.         LeftCurve(Sample) = 300 + Lef * 300
  91.         RightCurve(Sample) = 300 + righ * 300
  92.         '---------------------------------------
  93.  
  94.     LOOP
  95.     CLOSE ch
  96.  
  97. SUB Visual (EffectNr)
  98.  
  99.     CLS
  100.     SELECT CASE EffectNr
  101.         CASE 0
  102.             _AUTODISPLAY
  103.             FOR x = 0 TO 798 STEP 1
  104.                 LINE (x, LeftCurve(x))-(x + 1, LeftCurve(x + 1)), 14
  105.                 LINE (x, RightCurve(x))-(x + 1, RightCurve(x + 1)), 15
  106.             NEXT
  107.  
  108.         CASE 1 'do circle.
  109.             _AUTODISPLAY
  110.             Angle1 = Angle1 + .01
  111.             Angle2 = Angle2 - .01
  112.             STP = _PI(2) / 800
  113.             FOR C = 0 TO _PI(2) - STP STEP STP
  114.                 X1 = 400 + SIN(C + Angle1) * LeftCurve(i) / 2
  115.                 X2 = 400 + SIN(C + STP + Angle1) * LeftCurve(i + 1) / 2
  116.                 Y1 = 300 + COS(C + Angle1) * LeftCurve(i) / 2
  117.                 Y2 = 300 + COS(C + STP + Angle1) * LeftCurve(i + 1) / 2
  118.                 IF ox1 = 0 THEN ox1 = X1: oy1 = Y1
  119.                 LINE (X1, Y1)-(X2, Y2), 14
  120.  
  121.                 X3 = 400 + SIN(C + Angle2) * RightCurve(i) / 3
  122.                 X4 = 400 + SIN(C + STP + Angle2) * RightCurve(i + 1) / 3
  123.                 Y3 = 300 + COS(C + Angle2) * RightCurve(i) / 3
  124.                 Y4 = 300 + COS(C + STP + Angle2) * RightCurve(i + 1) / 3
  125.                 IF ox3 = 0 THEN ox3 = X3: oy3 = Y3
  126.                 LINE (X3, Y3)-(X4, Y4), 15
  127.  
  128.                 i = i + 1
  129.             NEXT
  130.             LINE (X2, Y2)-(ox1, oy1), 14: ox1 = 0
  131.             LINE (X4, Y4)-(ox3, oy3), 15: ox3 = 0
  132.  
  133.         CASE 2 'small modification CASE 1
  134.             STP = _PI(2) / 800
  135.             Angle1 = Angle1 + .01
  136.             Angle2 = Angle2 - .01
  137.             FOR C = 0 TO _PI(2) - STP STEP STP
  138.                 X1 = 150 + SIN(C + Angle1) * LeftCurve(i) / 3
  139.                 Y1 = 300 + COS(C + Angle1) * LeftCurve(i) / 3
  140.                 X2 = 650 + SIN(C + Angle2) * RightCurve(i) / 3
  141.                 Y2 = 300 + COS(C + Angle2) * RightCurve(i) / 3
  142.  
  143.                 LINE (X2, Y2)-(650, 300), 14
  144.                 LINE (X1, Y1)-(150, 300), 15
  145.                 i = i + 1
  146.             NEXT
  147.  
  148.         CASE 3
  149.             LINE (0, 0)-(800, 450), _RGBA(0, 0, 0, 30), BF
  150.             CIRCLE (200, 200), 182, 25
  151.             CIRCLE (600, 200), 182, 25
  152.             X1 = LeftCurve(i)
  153.             p = X1 * 5
  154.             sec = (p * .6) + seconds
  155.             seconds = sec
  156.             IF seconds > 359 THEN seconds2 = 0
  157.             seconds = seconds + 1
  158.             s = (60 - seconds) * 6 + 90
  159.             xxx = INT(SIN(s / 90 * _PI) * 180) + 200
  160.             yyy = INT(COS(s / 90 * _PI) * 180) + 200
  161.             LINE (200, 200)-(xxx, yyy), 14
  162.             X2 = RightCurve(i)
  163.             p2 = X2 * 5
  164.             sec2 = (p2 * .6) + seconds2
  165.             seconds2 = sec2
  166.             IF seconds2 > 359 THEN seconds = 0
  167.             seconds2 = seconds2 + 1
  168.             s2 = (60 - seconds2) * 6 + 90
  169.             xxx2 = INT(SIN(s2 / 90 * _PI) * 180) + 600
  170.             yyy2 = INT(COS(s2 / 90 * _PI) * 180) + 200
  171.             LINE (600, 200)-(xxx2, yyy2), 3
  172.  
  173.  
  174.         CASE 4
  175.  
  176.             FOR x = 0 TO 798 STEP 1
  177.                 LINE (x, LeftCurve(x))-(x + 1, LeftCurve(x + 1) * 1.25), 14
  178.                 LINE (x, RightCurve(x))-(x + 1, RightCurve(x + 1) * 1.25), 15
  179.             NEXT
  180.  
  181.         CASE 5
  182.             FOR x = 0 TO 798 STEP 1
  183.                 LINE (LeftCurve(x), x)-(LeftCurve(x + 1) * 1.25, x + 1), 14
  184.                 LINE (RightCurve(x), x)-(RightCurve(x + 1) * 1.25, x + 1), 15
  185.             NEXT
  186.         CASE 6
  187.             xx = LeftCurve(x)
  188.             yy = LeftCurve(x)
  189.             xx2 = RightCurve(x) + 200
  190.             yy2 = RightCurve(x)
  191.             CIRCLE (xx, yy), LeftCurve(x) / 10, 14
  192.             PAINT (xx, yy), 14
  193.             CIRCLE (xx2, yy2), RightCurve(x) / 10, 15
  194.             PAINT (xx2, yy2), 15
  195.             _DISPLAY
  196.     END SELECT
  197.