Author Topic: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)  (Read 16482 times)

0 Members and 1 Guest are viewing this topic.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #60 on: January 14, 2021, 03:31:35 pm »
I will return to the beginning of this thread with a few questions to @STxAxTIC

I implanted your frequency acquisition program. Finally. It seems to work perfectly. The only thing I need to clarify: The resulting frequency in your second example is given by the number of samples analyzed. It is so? Therefore, a small number of samples is sufficient to obtain low frequencies. In your example, these are pixels, my solution is _SNDGETPOS - 300 TO _SNDGETPOS + 300. This way I get 600 audio samples, that's enough to get low frequencies. But if I wanted a frequency of 20 KHz, I would need to analyze the whole second (44100 samples for precise detection). Am I getting it right, or am I completely out of it again?

Wait. What I'm writing is nonsense. After all, a high frequency can be interspersed several times, even in a small number of samples. So it will be possible to construct the frequency detection as an average in six hundred samples. This is an imperceptible moment to the ear (0.014 seconds) but is enough to detect the frequency. Then it can be argued that the average frequency in a 0.014 second sample has some value. This will be the right solution, right?
« Last Edit: January 14, 2021, 03:56:49 pm by Petr »

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #61 on: January 15, 2021, 03:58:47 pm »
Hi. Here is a little work with _MEMSOUND, the movement of the stars in the background is the output of the implanted program from @STxAxTIC


FellippeHeitor

  • Guest
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #62 on: January 15, 2021, 03:59:57 pm »
Whooooooa that's so cool!

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #63 on: January 15, 2021, 04:11:27 pm »
@Petr  - this is just great!

I ran into a few - what I will call "windowing" problems with the frequency measurement code, so I will shortly dust off my latest copy and show where I left off. There is still something to fix - but we're *almost* there on a solution for reliably getting frequencies... I'll return to this as soon as I can.
You're not done when it works, you're done when it's right.

Offline _vince

  • Seasoned Forum Regular
  • Posts: 422
    • View Profile
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #64 on: January 15, 2021, 08:02:57 pm »
This all sounds very interesting!   Could something like this be used to analyze a played pitch and see if it's in tune?  Like frequency 440 Hz is the note A.    I tune pianos on the side, wonder if it would be possible to make a piano tuning app in QB64?

- Dav

if you know the sampling frequency, ie
Code: QB64: [Select]
  1. 'defdbl a-z
  2.  
  3. CONST sw = 1024
  4. CONST sh = 600
  5.  
  6. 'pi = 2*asin(1)
  7. pi = 4*ATN(1)
  8.  
  9. DECLARE SUB rfft(xx_r(), xx_i(), x_r(), n)
  10.  
  11. DIM x_r(sw-1), x_i(sw-1)
  12. DIM xx_r(sw-1), xx_i(sw-1)
  13.  
  14. FOR i=0 TO sw-1
  15.         x_r(i) = 100*SIN(2*pi*(sw*2000/44000)*i/sw) + (100*RND - 50)
  16.  
  17.  
  18. 'screenres sw, sh, 32
  19. SCREEN _NEWIMAGE(sw, sh, 32)
  20.  
  21. 'plot signal
  22. PSET (0, sh/4 - x_r(0))
  23. FOR i=0 TO sw-1
  24.         LINE -(i, sh/4 - x_r(i)), _RGB(255,0,0)
  25. LINE (0, sh/4)-STEP(sw,0), _RGB(255,0,0),,&h5555
  26.  
  27. _PRINTSTRING (0, 0), "2000 Hz signal with RND noise sampled at 44 kHz in 1024 samples"
  28.  
  29.  
  30. rfft xx_r(), xx_i(), x_r(), sw
  31.  
  32. 'plot its fft
  33. PSET (0, 50+3*sh/4 - 0.005*SQR(xx_r(0)*xx_r(0) + xx_i(0)*xx_i(0)) ), _RGB(255,255,0)
  34. FOR i=0 TO sw/2
  35.         LINE -(i*2, 50+3*sh/4 - 0.005*SQR(xx_r(i)*xx_r(i) + xx_i(i)*xx_i(i)) ), _RGB(255,255,0)
  36. LINE (0, 50+3*sh/4)-STEP(sw,0), _RGB(255,255,0),,&h5555
  37.  
  38.  
  39. 'find peak
  40. max = 0
  41. m = 0
  42. FOR i=0 TO sw/2
  43.         d = 0.01*SQR(xx_r(i)*xx_r(i) + xx_i(i)*xx_i(i))
  44.         IF d > max THEN
  45.                 max = d
  46.                 m = i
  47.         END IF
  48.  
  49. _PRINTSTRING (0, sh/2), "m_peak ="+STR$(m)
  50. _PRINTSTRING (0, sh/2 + 16), "f_peak = m_peak * 44 kHz / 1024 samples = "+STR$(m*44000/1024)+" Hz"
  51.  
  52. 'apply frequency correction, only works for some signals
  53. DIM u_r AS DOUBLE, u_i AS DOUBLE
  54. DIM v_r AS DOUBLE, v_i AS DOUBLE
  55.  
  56. u_r = xx_r(m - 1) - xx_r(m + 1)
  57. u_i = xx_i(m - 1) - xx_i(m + 1)
  58. v_r = 2*xx_r(m) - xx_r(m - 1) - xx_r(m + 1)
  59. v_i = 2*xx_i(m) - xx_i(m - 1) - xx_i(m + 1)
  60. c = (u_r*v_r + u_i*v_i)/(v_r*v_r + v_i*v_i)
  61.  
  62. _PRINTSTRING (0, sh/2 + 2*16), "f_corrected = "+STR$((m+c)*44000/1024)+" Hz"
  63.  
  64.  
  65.  
  66. SUB rfft(xx_r(), xx_i(), x_r(), n)
  67.         DIM w_r AS DOUBLE, w_i AS DOUBLE, wm_r AS DOUBLE, wm_i AS DOUBLE
  68.         DIM u_r AS DOUBLE, u_i AS DOUBLE, v_r AS DOUBLE, v_i AS DOUBLE
  69.  
  70.         log2n = LOG(n/2)/LOG(2)
  71.  
  72.         FOR i=0 TO n/2 - 1
  73.                 rev = 0
  74.                 FOR j=0 TO log2n - 1
  75.                         IF i AND (2^j) THEN rev = rev + (2^(log2n - 1 - j))
  76.                 NEXT
  77.  
  78.                 xx_r(i) = x_r(2*rev)
  79.                 xx_i(i) = x_r(2*rev + 1)
  80.         NEXT
  81.  
  82.         FOR i=1 TO log2n
  83.                 m = 2^i
  84.                 wm_r = COS(-2*pi/m)
  85.                 wm_i = SIN(-2*pi/m)
  86.  
  87.                 FOR j=0 TO n/2 - 1 STEP m
  88.                         w_r = 1
  89.                         w_i = 0
  90.  
  91.                         FOR k=0 TO m/2 - 1
  92.                                 p = j + k
  93.                                 q = p + (m \ 2)
  94.  
  95.                                 u_r = w_r*xx_r(q) - w_i*xx_i(q)
  96.                                 u_i = w_r*xx_i(q) + w_i*xx_r(q)
  97.                                 v_r = xx_r(p)
  98.                                 v_i = xx_i(p)
  99.  
  100.                                 xx_r(p) = v_r + u_r
  101.                                 xx_i(p) = v_i + u_i
  102.                                 xx_r(q) = v_r - u_r
  103.                                 xx_i(q) = v_i - u_i
  104.  
  105.                                 u_r = w_r
  106.                                 u_i = w_i
  107.                                 w_r = u_r*wm_r - u_i*wm_i
  108.                                 w_i = u_r*wm_i + u_i*wm_r
  109.                         NEXT
  110.                 NEXT
  111.         NEXT
  112.  
  113.         xx_r(n/2) = xx_r(0)
  114.         xx_i(n/2) = xx_i(0)
  115.  
  116.         FOR i=1 TO n/2 - 1
  117.                 xx_r(n/2 + i) = xx_r(n/2 - i)
  118.                 xx_i(n/2 + i) = xx_i(n/2 - i)
  119.         NEXT
  120.  
  121.         DIM xpr AS DOUBLE, xpi AS DOUBLE
  122.         DIM xmr AS DOUBLE, xmi AS DOUBLE
  123.  
  124.         FOR i=0 TO n/2 - 1
  125.                 xpr = (xx_r(i) + xx_r(n/2 + i)) / 2
  126.                 xpi = (xx_i(i) + xx_i(n/2 + i)) / 2
  127.  
  128.                 xmr = (xx_r(i) - xx_r(n/2 + i)) / 2
  129.                 xmi = (xx_i(i) - xx_i(n/2 + i)) / 2
  130.  
  131.                 xx_r(i) = xpr + xpi*COS(2*pi*i/n) - xmr*SIN(2*pi*i/n)
  132.                 xx_i(i) = xmi - xpi*SIN(2*pi*i/n) - xmr*COS(2*pi*i/n)
  133.         NEXT
  134.  
  135.         'symmetry, complex conj
  136.         FOR i=0 TO n/2 - 1
  137.                 xx_r(n/2 + i) = xx_r(n/2 - 1 - i)
  138.                 xx_i(n/2 + i) =-xx_i(n/2 - 1 - i)
  139.         NEXT
  140.  

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #65 on: January 16, 2021, 03:29:11 am »
Thank you @_vince ! I try apply it to real audio signal and then give here my outputs.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #66 on: January 16, 2021, 04:26:28 am »
@_vince Please look to my modification your code, if it is modfified correctly? Use some MP3 file.

I am not sure on row 101 in this source code, if can it be with _CONTINUE, if m = 0.

Thank you.


Code: QB64: [Select]
  1. 'defdbl a-z
  2.  
  3. CONST sw = 1024
  4. CONST sh = 600
  5.  
  6.  
  7. '''
  8. DIM Left AS _MEM
  9. '''
  10.  
  11. 'pi = 2*asin(1)
  12. pi = 4 * ATN(1)
  13.  
  14. DECLARE SUB rfft(xx_r(), xx_i(), x_r(), n)
  15.  
  16. DIM x_r(sw - 1), x_i(sw - 1)
  17. DIM xx_r(sw - 1), xx_i(sw - 1)
  18.  
  19. '''
  20. AudioFile$ = "Track10.mp3"
  21. S = _SNDOPEN(AudioFile$)
  22. Left = _MEMSOUND(S, 1)
  23. '''
  24. SCREEN _NEWIMAGE(sw, sh, 32)
  25.  
  26.  
  27. '''
  28.     i = 0: j = 0
  29.     Position& = _SNDGETPOS(S) * _SNDRATE
  30.     IF Position& > 1024 AND Position& < Left.SIZE - 1024 THEN 'current (actual playing) sound frame is in middle - in position Position&
  31.         j& = Position& - 1022
  32.         DO UNTIL i = 1024
  33.  
  34.             x_r(i) = 100 * (_MEMGET(Left, Left.OFFSET + j&, INTEGER) / 32767)
  35.             i = i + 1
  36.             j& = j& + 2
  37.         LOOP
  38.         test& = j& - Position&
  39.  
  40.     END IF
  41.  
  42.     'FOR i = 0 TO sw - 1
  43.     'x_r(i) = 100 * SIN(2 * pi * (sw * 20000 / 44000) * i / sw) + (100 * RND - 50)
  44.     'NEXT
  45.  
  46.     i = 0
  47.     j = 0
  48.     '''
  49.  
  50.  
  51.  
  52.     'screenres sw, sh, 32
  53.     'SCREEN _NEWIMAGE(sw, sh, 32)
  54.  
  55.     'plot signal
  56.     CLS
  57.     PSET (0, sh / 4 - x_r(0))
  58.     FOR i = 0 TO sw - 1
  59.         LINE -(i, sh / 4 - x_r(i)), _RGB(255, 0, 0)
  60.     NEXT
  61.     LINE (0, sh / 4)-STEP(sw, 0), _RGB(255, 0, 0), , &H5555
  62.  
  63.     ' _PRINTSTRING (0, 0), "2000 Hz signal with RND noise sampled at 44 kHz in 1024 samples"
  64.  
  65.  
  66.     rfft xx_r(), xx_i(), x_r(), sw
  67.  
  68.     'plot its fft
  69.     PSET (0, 50 + 3 * sh / 4 - 0.005 * SQR(xx_r(0) * xx_r(0) + xx_i(0) * xx_i(0))), _RGB(255, 255, 0)
  70.     FOR i = 0 TO sw / 2
  71.         LINE -(i * 2, 50 + 3 * sh / 4 - 0.005 * SQR(xx_r(i) * xx_r(i) + xx_i(i) * xx_i(i))), _RGB(255, 255, 0)
  72.     NEXT
  73.     LINE (0, 50 + 3 * sh / 4)-STEP(sw, 0), _RGB(255, 255, 0), , &H5555
  74.  
  75.  
  76.     'find peak
  77.     DIM max AS DOUBLE, d AS DOUBLE
  78.     max = 0
  79.     m = 0
  80.     FOR i = 0 TO sw / 2
  81.         d = 0.01 * SQR(xx_r(i) * xx_r(i) + xx_i(i) * xx_i(i))
  82.         IF d > max THEN
  83.             max = d
  84.             m = i
  85.         END IF
  86.     NEXT
  87.  
  88.     _PRINTSTRING (0, sh / 2), "m_peak =" + STR$(m)
  89.     _PRINTSTRING (0, sh / 2 + 16), "f_peak = m_peak * 44 kHz / 1024 samples = " + STR$(m * 44000 / 1024) + " Hz"
  90.  
  91.     'apply frequency correction, only works for some signals
  92.     DIM c AS DOUBLE
  93.     DIM u_r AS DOUBLE, u_i AS DOUBLE
  94.     DIM v_r AS DOUBLE, v_i AS DOUBLE
  95.  
  96.     IF m = 0 THEN _CONTINUE 'm = 1
  97.     u_r = xx_r(m - 1) - xx_r(m + 1)
  98.     u_i = xx_i(m - 1) - xx_i(m + 1)
  99.     v_r = 2 * xx_r(m) - xx_r(m - 1) - xx_r(m + 1)
  100.     v_i = 2 * xx_i(m) - xx_i(m - 1) - xx_i(m + 1)
  101.     c = (u_r * v_r + u_i * v_i) / (v_r * v_r + v_i * v_i)
  102.  
  103.     _PRINTSTRING (0, sh / 2 + 2 * 16), "f_corrected = " + STR$((m + c) * 44000 / 1024) + " Hz"
  104.  
  105.     ' SLEEP
  106.     PRINT test&
  107.     _DISPLAY
  108.     _LIMIT 20
  109.  
  110.  
  111.  
  112. SUB rfft (xx_r(), xx_i(), x_r(), n)
  113.     DIM w_r AS DOUBLE, w_i AS DOUBLE, wm_r AS DOUBLE, wm_i AS DOUBLE
  114.     DIM u_r AS DOUBLE, u_i AS DOUBLE, v_r AS DOUBLE, v_i AS DOUBLE
  115.  
  116.     log2n = LOG(n / 2) / LOG(2)
  117.  
  118.     FOR i = 0 TO n / 2 - 1
  119.         rev = 0
  120.         FOR j = 0 TO log2n - 1
  121.             IF i AND (2 ^ j) THEN rev = rev + (2 ^ (log2n - 1 - j))
  122.         NEXT
  123.  
  124.         xx_r(i) = x_r(2 * rev)
  125.         xx_i(i) = x_r(2 * rev + 1)
  126.     NEXT
  127.  
  128.     FOR i = 1 TO log2n
  129.         m = 2 ^ i
  130.         wm_r = COS(-2 * pi / m)
  131.         wm_i = SIN(-2 * pi / m)
  132.  
  133.         FOR j = 0 TO n / 2 - 1 STEP m
  134.             w_r = 1
  135.             w_i = 0
  136.  
  137.             FOR k = 0 TO m / 2 - 1
  138.                 p = j + k
  139.                 q = p + (m \ 2)
  140.  
  141.                 u_r = w_r * xx_r(q) - w_i * xx_i(q)
  142.                 u_i = w_r * xx_i(q) + w_i * xx_r(q)
  143.                 v_r = xx_r(p)
  144.                 v_i = xx_i(p)
  145.  
  146.                 xx_r(p) = v_r + u_r
  147.                 xx_i(p) = v_i + u_i
  148.                 xx_r(q) = v_r - u_r
  149.                 xx_i(q) = v_i - u_i
  150.  
  151.                 u_r = w_r
  152.                 u_i = w_i
  153.                 w_r = u_r * wm_r - u_i * wm_i
  154.                 w_i = u_r * wm_i + u_i * wm_r
  155.             NEXT
  156.         NEXT
  157.     NEXT
  158.  
  159.     xx_r(n / 2) = xx_r(0)
  160.     xx_i(n / 2) = xx_i(0)
  161.  
  162.     FOR i = 1 TO n / 2 - 1
  163.         xx_r(n / 2 + i) = xx_r(n / 2 - i)
  164.         xx_i(n / 2 + i) = xx_i(n / 2 - i)
  165.     NEXT
  166.  
  167.     DIM xpr AS DOUBLE, xpi AS DOUBLE
  168.     DIM xmr AS DOUBLE, xmi AS DOUBLE
  169.  
  170.     FOR i = 0 TO n / 2 - 1
  171.         xpr = (xx_r(i) + xx_r(n / 2 + i)) / 2
  172.         xpi = (xx_i(i) + xx_i(n / 2 + i)) / 2
  173.  
  174.         xmr = (xx_r(i) - xx_r(n / 2 + i)) / 2
  175.         xmi = (xx_i(i) - xx_i(n / 2 + i)) / 2
  176.  
  177.         xx_r(i) = xpr + xpi * COS(2 * pi * i / n) - xmr * SIN(2 * pi * i / n)
  178.         xx_i(i) = xmi - xpi * SIN(2 * pi * i / n) - xmr * COS(2 * pi * i / n)
  179.     NEXT
  180.  
  181.     'symmetry, complex conj
  182.     FOR i = 0 TO n / 2 - 1
  183.         xx_r(n / 2 + i) = xx_r(n / 2 - 1 - i)
  184.         xx_i(n / 2 + i) = -xx_i(n / 2 - 1 - i)
  185.     NEXT
  186.  
  187.  
  188.  

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #67 on: January 16, 2021, 01:26:41 pm »
@_vince  gave us a treasure. By no means do I understand what the hell SUB rfft is doing, but he's doing it damn well and incredibly fast. I sat down and played with it. Now it seems to work the way I wanted. I just had to take the results of the  _Vince program and categorize them. Now I'm going to try to turn this treasure into a SUB so that I just insert the _MEM field and get back a number indicating the frequency.

You can try it. The program includes a graphics analyzer. (on left depth, then next frequencies by the highest on right side). It seems that sometimes when there is a long deep frequency, it does not register a high frequency (cymbals) but it is highly likely that it is my fault.

@_vince, thank you. This took me a long time.

Code: QB64: [Select]
  1. 'defdbl a-z
  2.  
  3. CONST sw = 1024
  4. CONST sh = 600
  5.  
  6.  
  7. '''
  8. DIM Left AS _MEM
  9. DIM Right AS _MEM
  10. DIM Analyzer(8) AS SINGLE
  11. '''
  12.  
  13.  
  14. DIM u_r AS DOUBLE, u_i AS DOUBLE
  15. DIM v_r AS DOUBLE, v_i AS DOUBLE
  16.  
  17.  
  18. 'pi = 2*asin(1)
  19. pi = 4 * ATN(1)
  20.  
  21. DECLARE SUB rfft(xx_r(), xx_i(), x_r(), n)
  22.  
  23. DIM x_r(sw - 1), x_i(sw - 1)
  24. DIM xx_r(sw - 1), xx_i(sw - 1)
  25.  
  26. '''
  27. AudioFile$ = "01.mp3"
  28. S = _SNDOPEN(AudioFile$)
  29. Left = _MEMSOUND(S, 1)
  30. Right = _MEMSOUND(S, 2)
  31.  
  32. '''
  33. SCREEN _NEWIMAGE(sw, sh, 32)
  34.  
  35. TestT = TIMER
  36. '''
  37.     i = 0: j = 0 '                                             reset previous values
  38.     Position& = _SNDGETPOS(S) * _SNDRATE * 2 '                 *2, because sound data are in INTEGER format and INTEGER is always 2 byte long
  39.     IF Position& > 1024 AND Position& < Left.SIZE - 1024 THEN 'current (actual playing) sound frame is in middle - in position Position&
  40.         j& = Position& - 1022
  41.         DO UNTIL i >= 1024
  42.             x_r(i) = 100 * _MEMGET(Left, Left.OFFSET + j&, INTEGER) / 32767
  43.             i = i + 1
  44.             j& = j& + 2
  45.         LOOP
  46.         test& = j& - Position&
  47.     END IF
  48.  
  49.     'FOR i = 0 TO sw - 1
  50.     'x_r(i) = 100 * SIN(2 * pi * (sw * 20000 / 44000) * i / sw) + (100 * RND - 50)      '_Vince's signal generator in original source code
  51.     'NEXT
  52.  
  53.     i = 0
  54.     j& = 0
  55.     '''
  56.  
  57.  
  58.  
  59.     'screenres sw, sh, 32
  60.     'SCREEN _NEWIMAGE(sw, sh, 32)
  61.  
  62.     'plot signal
  63.     CLS
  64.     PSET (0, sh / 4 - x_r(0))
  65.     FOR i = 0 TO sw - 1
  66.         LINE -(i, sh / 4 - x_r(i)), _RGB(255, 0, 0)
  67.     NEXT
  68.     LINE (0, sh / 4)-STEP(sw, 0), _RGB(255, 0, 0), , &H5555
  69.  
  70.     ' _PRINTSTRING (0, 0), "2000 Hz signal with RND noise sampled at 44 kHz in 1024 samples"
  71.  
  72.  
  73.     rfft xx_r(), xx_i(), x_r(), sw
  74.  
  75.     'plot its fft
  76.     PSET (0, 50 + 3 * sh / 4 - 0.005 * SQR(xx_r(0) * xx_r(0) + xx_i(0) * xx_i(0))), _RGB(255, 255, 0)
  77.     FOR i = 0 TO sw / 2
  78.         LINE -(i * 2, 50 + 3 * sh / 4 - 0.005 * SQR(xx_r(i) * xx_r(i) + xx_i(i) * xx_i(i))), _RGB(255, 255, 0)
  79.     NEXT
  80.     LINE (0, 50 + 3 * sh / 4)-STEP(sw, 0), _RGB(255, 255, 0), , &H5555
  81.  
  82.  
  83.     'find peak
  84.     DIM max AS DOUBLE, d AS DOUBLE
  85.     max = 0
  86.     m = 0
  87.     FOR i = 0 TO sw / 2
  88.         d = 0.01 * SQR(xx_r(i) * xx_r(i) + xx_i(i) * xx_i(i))
  89.         IF d > max THEN
  90.             max = d
  91.             m = i
  92.         END IF
  93.     NEXT
  94.  
  95.     _PRINTSTRING (0, sh / 2), "m_peak =" + STR$(m)
  96.     _PRINTSTRING (0, sh / 2 + 16), "f_peak = m_peak * 44 kHz / 1024 samples = " + STR$(m * 44000 / 1024) + " Hz"
  97.  
  98.     'apply frequency correction, only works for some signals
  99.     '   DIM c AS DOUBLE
  100.     '  DIM u_r AS DOUBLE, u_i AS DOUBLE
  101.     ' DIM v_r AS DOUBLE, v_i AS DOUBLE
  102.  
  103.     IF m = 0 THEN _CONTINUE
  104.     u_r = xx_r(m - 1) - xx_r(m + 1)
  105.     u_i = xx_i(m - 1) - xx_i(m + 1)
  106.     v_r = 2 * xx_r(m) - xx_r(m - 1) - xx_r(m + 1)
  107.     v_i = 2 * xx_i(m) - xx_i(m - 1) - xx_i(m + 1)
  108.     c = (u_r * v_r + u_i * v_i) / (v_r * v_r + v_i * v_i)
  109.  
  110.     F = (m + c) * _SNDRATE / 1024 '                                                             1024 = number of samples
  111.     _PRINTSTRING (0, sh / 2 + 2 * 16), "f_corrected = " + STR$(F) '(m + c) * 44000 / 1024) + " Hz"
  112.  
  113.  
  114.     'If signal is contained in some range, add 30 pixels for Y coordinate (analyzer go up, its wroted as bottom - this value)
  115.     SELECT CASE F
  116.         CASE 20 TO 125: Analyzer(1) = Analyzer(1) + 30 'areas set by picture on google...
  117.         CASE 126 TO 300: Analyzer(2) = Analyzer(2) + 30
  118.         CASE 300 TO 500: Analyzer(3) = Analyzer(3) + 30
  119.         CASE 500 TO 1000: Analyzer(4) = Analyzer(4) + 30
  120.         CASE 1001 TO 2000: Analyzer(5) = Analyzer(5) + 30
  121.         CASE 2001 TO 4000: Analyzer(6) = Analyzer(6) + 30
  122.         CASE 4001 TO 8000: Analyzer(7) = Analyzer(7) + 30
  123.         CASE IS > 8001: Analyzer(8) = Analyzer(8) + 30
  124.     END SELECT
  125.  
  126.  
  127.  
  128.     'analyzer overflow control
  129.     FOR analyze = 1 TO 8 '                                    analyze 8 spectrums
  130.         IF Analyzer(analyze) > 150 THEN Analyzer(analyze) = 100
  131.     NEXT
  132.  
  133.     'draw analyzer
  134.     AnC = 0
  135.     FOR AnalyzatorX = 600 TO 670 STEP 10
  136.         AnC = AnC + 1
  137.         FreqHeight = Analyzer(AnC) '                          Y coordinate for drawing frequency analyzer, maximal size is 150 pixels
  138.         LINE (AnalyzatorX - 4, 400)-(AnalyzatorX + 4, 400 - FreqHeight), &HFFAD0000, BF
  139.         IF Analyzer(AnC) > 0 THEN Analyzer(AnC) = Analyzer(AnC) - 1 ' always, if analyzer contains some higher position than bottom, give one pixel out
  140.     NEXT
  141.  
  142.     PRINT Position&, _SNDGETPOS(S) * _SNDRATE
  143.     PRINT TIMER - TestT: TestT = TIMER
  144.     _DISPLAY
  145.     _LIMIT 200
  146.  
  147.  
  148.  
  149. SUB rfft (xx_r(), xx_i(), x_r(), n)
  150.     DIM w_r AS DOUBLE, w_i AS DOUBLE, wm_r AS DOUBLE, wm_i AS DOUBLE
  151.     DIM u_r AS DOUBLE, u_i AS DOUBLE, v_r AS DOUBLE, v_i AS DOUBLE
  152.  
  153.     log2n = LOG(n / 2) / LOG(2)
  154.  
  155.     FOR i = 0 TO n / 2 - 1
  156.         rev = 0
  157.         FOR j = 0 TO log2n - 1
  158.             IF i AND (2 ^ j) THEN rev = rev + (2 ^ (log2n - 1 - j))
  159.         NEXT
  160.  
  161.         xx_r(i) = x_r(2 * rev)
  162.         xx_i(i) = x_r(2 * rev + 1)
  163.     NEXT
  164.  
  165.     FOR i = 1 TO log2n
  166.         m = 2 ^ i
  167.         wm_r = COS(-2 * pi / m)
  168.         wm_i = SIN(-2 * pi / m)
  169.  
  170.         FOR j = 0 TO n / 2 - 1 STEP m
  171.             w_r = 1
  172.             w_i = 0
  173.  
  174.             FOR k = 0 TO m / 2 - 1
  175.                 p = j + k
  176.                 q = p + (m \ 2)
  177.  
  178.                 u_r = w_r * xx_r(q) - w_i * xx_i(q)
  179.                 u_i = w_r * xx_i(q) + w_i * xx_r(q)
  180.                 v_r = xx_r(p)
  181.                 v_i = xx_i(p)
  182.  
  183.                 xx_r(p) = v_r + u_r
  184.                 xx_i(p) = v_i + u_i
  185.                 xx_r(q) = v_r - u_r
  186.                 xx_i(q) = v_i - u_i
  187.  
  188.                 u_r = w_r
  189.                 u_i = w_i
  190.                 w_r = u_r * wm_r - u_i * wm_i
  191.                 w_i = u_r * wm_i + u_i * wm_r
  192.             NEXT
  193.         NEXT
  194.     NEXT
  195.  
  196.     xx_r(n / 2) = xx_r(0)
  197.     xx_i(n / 2) = xx_i(0)
  198.  
  199.     FOR i = 1 TO n / 2 - 1
  200.         xx_r(n / 2 + i) = xx_r(n / 2 - i)
  201.         xx_i(n / 2 + i) = xx_i(n / 2 - i)
  202.     NEXT
  203.  
  204.     DIM xpr AS DOUBLE, xpi AS DOUBLE
  205.     DIM xmr AS DOUBLE, xmi AS DOUBLE
  206.  
  207.     FOR i = 0 TO n / 2 - 1
  208.         xpr = (xx_r(i) + xx_r(n / 2 + i)) / 2
  209.         xpi = (xx_i(i) + xx_i(n / 2 + i)) / 2
  210.  
  211.         xmr = (xx_r(i) - xx_r(n / 2 + i)) / 2
  212.         xmi = (xx_i(i) - xx_i(n / 2 + i)) / 2
  213.  
  214.         xx_r(i) = xpr + xpi * COS(2 * pi * i / n) - xmr * SIN(2 * pi * i / n)
  215.         xx_i(i) = xmi - xpi * SIN(2 * pi * i / n) - xmr * COS(2 * pi * i / n)
  216.     NEXT
  217.  
  218.     'symmetry, complex conj
  219.     FOR i = 0 TO n / 2 - 1
  220.         xx_r(n / 2 + i) = xx_r(n / 2 - 1 - i)
  221.         xx_i(n / 2 + i) = -xx_i(n / 2 - 1 - i)
  222.     NEXT
  223.  

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #68 on: January 28, 2021, 08:34:32 am »
Quick thought:

Shouldn’t _MEMSOUND have a mem.TYPE associate with it?

http://www.qb64.org/wiki/MEM

mem.TYPE is an OFFSET, so it’s always a minimum of 32-bits in size.  _MEMSOUND could easily just take the 17th bit as an identifier.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

FellippeHeitor

  • Guest
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #69 on: January 28, 2021, 09:19:19 am »
It should. Thoughts?

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #70 on: January 29, 2021, 02:28:58 pm »
Nice one! @Petr 

I nominate you to do the Wiki demo example for this :)
« Last Edit: January 29, 2021, 02:30:01 pm by bplus »

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #71 on: January 29, 2021, 03:37:23 pm »
@bplus

I really appreciate this offer, do you mean the source code for the video above? Or a newer one that uses the _Vince solution to gain frequency? I'll probably get there on Sunday or Monday. Tomorrow my daughter celebrates her birthday, so there will be no time tomorrow. So I'll send you the source code, because I don't have access to the wiki myself, you'll be able to paste it there.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #72 on: January 29, 2021, 03:46:13 pm »
@bplus

I really appreciate this offer, do you mean the source code for the video above? Or a newer one that uses the _Vince solution to gain frequency? I'll probably get there on Sunday or Monday. Tomorrow my daughter celebrates her birthday, so there will be no time tomorrow. So I'll send you the source code, because I don't have access to the wiki myself, you'll be able to paste it there.

Oh I don't have access to Wiki either and I am sort of a generalist myself, but you seem expert in the arena of sound and all it's nuances. I think Wiki needs short and as little complicated as can get but still get the point of how to use the thing being demo'd, so _vince variation might go over the top in needs. You guys are already over my head so _vince thing might be just the thing, I don't know ;)

I could put demo in Infomatics Board if you say it's specially good.
« Last Edit: January 29, 2021, 03:52:05 pm by bplus »

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #73 on: January 29, 2021, 04:13:23 pm »
I understand. Just write the simplest program possible. Something light for visualization with descriptions in English. Good! I'll prepare it here.
But I don't feel like a sound expert myself. I'm just interested.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #74 on: January 29, 2021, 05:07:01 pm »
I understand. Just write the simplest program possible. Something light for visualization with descriptions in English. Good! I'll prepare it here.
But I don't feel like a sound expert myself. I'm just interested.


Petr for Infomatics (the thing I have some permission for) simple is not so important than cool! If the thing with _vince stuff is way cooler than a simple demo then let's go for that. It would be cool to get something with _vince contributing too!

For Wiki, it is only MHO that simple is better by simple I mean short and sweet and by sweet I mean gets the point across elegantly, one very fine example of this is Wiki's Rotozoom. But I am not involved with Wiki project, so far everyone has been doing great by me for that! And thanks again to those who do contribute to that project.

Quote
I'm just interested.
Yes that can go a long way towards getting your head into the game and coming up with something clever.
« Last Edit: January 29, 2021, 05:08:50 pm by bplus »