Author Topic: HOW do i sample (not play) audio?  (Read 8388 times)

0 Members and 1 Guest are viewing this topic.

Offline Parkland

  • Newbie
  • Posts: 51
    • View Profile
Re: HOW do i sample (not play) audio?
« Reply #30 on: April 28, 2020, 07:26:28 pm »
It works in windows, I'll try the linux sfml library. Didn't even consider that being an issue. I'm not the sharpest board in the metal shop.

Is there a way to live sample mic ? Or do you have to record samples then analyze data from the recorded sample?

Offline Parkland

  • Newbie
  • Posts: 51
    • View Profile
Re: HOW do i sample (not play) audio?
« Reply #31 on: April 28, 2020, 11:50:56 pm »
I tried to use this program to load the buffer and keep displaying it live, seems like the waveform does'nt match up though so I'm probably doing it wrong

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: HOW do i sample (not play) audio?
« Reply #32 on: April 29, 2020, 11:20:10 am »
Hi. Try this:

Code: QB64: [Select]
  1. DECLARE LIBRARY "SFML_Audio_Wrapper", "sfml\libsfml-audio"
  2.     SUB Mic_Start (BYVAL SampleRate&)
  3.     SUB Mic_End
  4.     SUB Mic_Play
  5.     SUB Mic_Pause
  6.     SUB Mic_Stop
  7.     SUB Mic_Save (Filename$)
  8.     FUNCTION Mic_Get_SampleCount&
  9.     FUNCTION Mic_Get_Sample% (BYVAL SampleNum&)
  10.     FUNCTION Sound_Load (FileName$)
  11.     FUNCTION Sound_Num_Samples
  12.     FUNCTION Sound_Get_Sample% (BYVAL SampleNum&)
  13.     SUB SNDRAW_Save (RawSnd%, BYVAL NumSamples&, BYVAL SampleRate&, BYVAL Channels&, FileName$)
  14.     FUNCTION Sound_Num_Channels&
  15.  
  16. SCREEN _NEWIMAGE(800, 600, 256)
  17.  
  18. '// Record 5 seconds of audio @ 36000 samples per second
  19. Mic_Start 44100
  20.  
  21. '// End the recording
  22. Mic_End
  23.  
  24. '// Play the mic sound directly
  25. Mic_Play
  26. 'after this delay is record size: 44100 (microphone sample rate) * 5 seconds
  27.  
  28.  
  29.  
  30.  
  31.  
  32. '// Load the samples into an array
  33. '// This is if you want to analyse the sound in anyway or distort it or something
  34. NumSamples& = Mic_Get_SampleCount& - 1
  35. DIM Sample(NumSamples&) AS INTEGER
  36. FOR I& = 0 TO NumSamples&
  37.     Sample(I&) = Mic_Get_Sample(I&)
  38.  
  39.  
  40. '// Play the samples stored in the array using sndraw - i dont now what you need to / or * the value by to get accurate
  41. '// playback from sndraw
  42.  
  43. TYPE SND
  44.     left AS SINGLE
  45.     right AS SINGLE
  46. size = NumSamples&
  47. DIM S(size) AS SND
  48.  
  49.  
  50.  
  51. FOR I& = 0 TO NumSamples& - 1 STEP 2
  52.     _SNDRAW Sample(I&) / 65535, Sample(I& + 1) / 65535
  53.     S(j).left = Sample(I&) / 65535
  54.     S(j).right = Sample(I& + 1) / 65535
  55.     j = j + 1
  56.  
  57.     X = X + 1: IF X > _WIDTH THEN CLS: X = 1
  58.     OYl = Yl
  59.     Yl = 200 + S(j&).left * 200
  60.     OYr = Yr
  61.     Yr = 400 + S(j&).right * 200
  62.     LINE (X - 1, OYl)-(X, Yl)
  63.     LINE (X - 1, OYr)-(X, Yr)
  64.  
  65.     DO WHILE _SNDRAWLEN > 0: LOOP
  66.     j& = j& + 1
  67.  
  68. SAVESOUND16S S(), "next_test.wav"
  69.  
  70.  
  71.  
  72. REM Mic_Save ("microphone.wav")
  73.  
  74. SUB SAVESOUND16S (arr() AS SND, file AS STRING)
  75. TYPE head16
  76.     chunk AS STRING * 4 '       4 bytes  (RIFF)
  77.     size AS LONG '              4 bytes  (file size)
  78.     fomat AS STRING * 4 '       4 bytes  (WAVE)
  79.     sub1 AS STRING * 4 '        4 bytes  (fmt )
  80.     subchunksize AS LONG '      4 bytes  (lo / hi), $00000010 for PCM audio
  81.     format AS INTEGER '         2 bytes  (0001 = standard PCM, 0101 = IBM mu-law, 0102 = IBM a-law, 0103 = IBM AVC ADPCM)
  82.     channels AS INTEGER '       2 bytes  (1 = mono, 2 = stereo)
  83.     rate AS LONG '              4 bytes  (sample rate, standard is 44100)
  84.     ByteRate AS LONG '          4 bytes  (= sample rate * number of channels * (bits per channel /8))
  85.     Block AS INTEGER '          2 bytes  (block align = number of channels * bits per sample /8)
  86.     Bits AS INTEGER '           2 bytes  (bits per sample. 8 = 8, 16 = 16)
  87.     subchunk2 AS STRING * 4 '   4 bytes  ("data")  contains begin audio samples
  88.     lenght AS LONG '            4 bytes  Data block size
  89. END TYPE '                     44 bytes  total
  90. DIM H16 AS head16
  91.  
  92. H16.chunk = "RIFF"
  93. H16.size = 44 + UBOUND(arr) * 4 'two channels, it create 16 bit, stereo wav file, one sample use 2 bytes to one channel
  94.  
  95. H16.fomat = "WAVE"
  96. H16.sub1 = "fmt "
  97. H16.subchunksize = 16
  98. H16.format = 1
  99. H16.channels = 2
  100. H16.rate = 44100
  101. H16.ByteRate = 44100 * 2 * 16 / 8
  102. H16.Block = 4
  103. H16.Bits = 16
  104. H16.subchunk2 = "data"
  105. H16.lenght = UBOUND(arr) * 4
  106. IF _FILEEXISTS(file$) THEN KILL file$
  107.  
  108. OPEN file$ FOR BINARY AS #ch
  109. PUT #ch, , H16
  110. DIM LeftChannel AS INTEGER, RightChannel AS INTEGER
  111.  
  112. FOR audiodata = 0 TO UBOUND(arr)
  113.     LeftChannel = arr(audiodata).left * 32768
  114.     RightChannel = arr(audiodata).right * 32768
  115.  
  116.     PUT #ch, , LeftChannel
  117.     PUT #ch, , RightChannel
  118.  

There are several ways to proceed: Do you want a program that allows you to move left - right to view the painted curve, or, a simpler program - to make a BMP output file that will have a resolution (for example) of 50000 * 600 and will contain the resulting curves?

Offline MB

  • Newbie
  • Posts: 7
    • View Profile
Re: HOW do i sample (not play) audio?
« Reply #33 on: April 29, 2020, 02:20:51 pm »
Parkland,

When I do this code (running under 32-bit windows):

   Mic_Start 22000
   _DELAY 2
   Mic_End

I collect 33673 samples, my first 10515 samples are all zeros. samples 10516 through 44188 have data.

Every time I sample my hardware lags for around 10k samples when using the 22000 sample rate.

Do a simpler test of just running this codet:

   Mic_Start 22000
   _DELAY 5
   Mic_End
   Mic_Save ("test.raw") ' change .raw to a format you use on your platform.

just as a sanity check to see how much lag/(if any) you have before data begins to accumulate.

- MB


Offline Unseen Machine

  • Forum Regular
  • Posts: 158
  • Make the game not the engine!
    • View Profile
Re: HOW do i sample (not play) audio?
« Reply #34 on: April 29, 2020, 02:54:42 pm »
Quote
Is there a way to live sample mic ? Or do you have to record samples then analyze data from the recorded sample?

There is (well almost) but this library doesnt support it. I know that in SFML 2.5 you can get samples back whilst a mic is still recording and i think i remember every 100mili seconds or something. I'll have a look into it and see if i can put something together in the next day or so.

As for the rest of the questions...i got no idea i wrote the wrapper the best part of a decade ago and have never used it since, i look forward to seeing what you guys make with it...

Unseen

Offline MB

  • Newbie
  • Posts: 7
    • View Profile
Re: HOW do i sample (not play) audio?
« Reply #35 on: April 29, 2020, 03:01:36 pm »
Parkland,

This is the code I used to see the leading dead space, file "rec2sav.bas" attached.

Code just tells you amount of samples where about the empty buffer ends and the noise floor begins. Then the total samples.


Unseen, I love that you made this wrapper... as I only need to record samples and analyze data, this is a neat tool in my books!

- MB

Offline Parkland

  • Newbie
  • Posts: 51
    • View Profile
Re: HOW do i sample (not play) audio?
« Reply #36 on: April 29, 2020, 08:41:20 pm »
I don't know how well this approach works, but it may do what I need. (see attached file)  [ You are not allowed to view this attachment ]  

Offline Parkland

  • Newbie
  • Posts: 51
    • View Profile
Re: HOW do i sample (not play) audio?
« Reply #37 on: April 29, 2020, 08:50:49 pm »
By chance does anyone have any idea / experience with what method is used to figure out frequencies?
Possibly similar to FFT?

I tried measuring every time the wave crosses 0, but that only works for the loudest frequency.
I tried measuring every peak and valley, but that only works for the smallest frequency.

Wondering what process would normally be employed if you want to know strengths of certain frequencies in the sound.

Offline MB

  • Newbie
  • Posts: 7
    • View Profile
Re: HOW do i sample (not play) audio?
« Reply #38 on: April 30, 2020, 08:07:29 am »
By chance does anyone have any idea / experience with what method is used to figure out frequencies?
Possibly similar to FFT?

I tried measuring every time the wave crosses 0, but that only works for the loudest frequency.
I tried measuring every peak and valley, but that only works for the smallest frequency.

Wondering what process would normally be employed if you want to know strengths of certain frequencies in the sound.

Crossing zero only works well with a single cycle style of waveform. 

I have been porting over some of my own code that I made in C for one of my "Teensy 4.0" microprocessor into QB64; however, it is far from being ready to share as is it implements the Laplace Transform.

QB64 user "_vince" made a real nice clean sample of a fast algorithm for computing the DFT for N=2^k in QB64. He also list a optimization for real only input FFT in the same thread, take a look at his post in this link:

https://www.qb64.org/forum/index.php?topic=1938.msg111661;topicseen#msg111661

-MB
« Last Edit: April 30, 2020, 08:26:39 am by MB »

Offline _vince

  • Seasoned Forum Regular
  • Posts: 422
    • View Profile
Re: HOW do i sample (not play) audio?
« Reply #39 on: April 30, 2020, 10:22:01 pm »
I've revised that FFT post to address some of this interest, particularly the last example

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. declare sub fft(xx_r(), xx_i(), x_r(), x_i(), n)
  11. declare sub dft(xx_r(), xx_i(), x_r(), x_i(), n)
  12.  
  13.  
  14. dim x_r(sw-1), x_i(sw-1)
  15. dim xx_r(sw-1), xx_i(sw-1)
  16.  
  17. for i=0 to sw-1
  18.         x_r(i) = 100*sin(2*pi*(sw*2000/44000)*i/sw) + (100*rnd - 50)
  19.  
  20.  
  21. 'screenres sw, sh, 32
  22. screen _newimage(sw, sh, 32)
  23.  
  24. 'plot signal
  25. pset (0, sh/4 - x_r(0))
  26. for i=0 to sw-1
  27.         line -(i, sh/4 - x_r(i)), _rgb(255,0,0)
  28. line (0, sh/4)-step(sw,0), _rgb(255,0,0),,&h5555
  29.  
  30. _printstring (0, 0), "2000 kHz signal with RND noise sampled at 44 kHz in 1024 samples"
  31.  
  32.  
  33. rfft xx_r(), xx_i(), x_r(), sw
  34.  
  35. 'plot its fft
  36. 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)
  37. for i=0 to sw/2
  38.         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)
  39. line (0, 50+3*sh/4)-step(sw,0), _rgb(255,255,0),,&h5555
  40.  
  41.  
  42. 'find peak
  43. max = 0
  44. m = 0
  45. for i=0 to sw/2
  46.         d = 0.01*sqr(xx_r(i)*xx_r(i) + xx_i(i)*xx_i(i))
  47.         if d > max then
  48.                 max = d
  49.                 m = i
  50.         end if
  51.  
  52. _printstring (0, sh/2), "m_peak ="+str$(m)
  53. _printstring (0, sh/2 + 16), "f_peak = m_peak * 44 kHz / 1024 samples = "+str$(m*44000/1024)+" Hz"
  54.  
  55. 'apply frequency correction, only works for some signals
  56. dim u_r as double, u_i as double
  57. dim v_r as double, v_i as double
  58.  
  59. u_r = xx_r(m - 1) - xx_r(m + 1)
  60. u_i = xx_i(m - 1) - xx_i(m + 1)
  61. v_r = 2*xx_r(m) - xx_r(m - 1) - xx_r(m + 1)
  62. v_i = 2*xx_i(m) - xx_i(m - 1) - xx_i(m + 1)
  63. c = (u_r*v_r + u_i*v_i)/(v_r*v_r + v_i*v_i)
  64.  
  65. _printstring (0, sh/2 + 2*16), "f_corrected = "+str$((m+c)*44000/1024)+" Hz"
  66.  
  67.  
  68.  
  69. sub rfft(xx_r(), xx_i(), x_r(), n)
  70.         dim w_r as double, w_i as double, wm_r as double, wm_i as double
  71.         dim u_r as double, u_i as double, v_r as double, v_i as double
  72.  
  73.         log2n = log(n/2)/log(2)
  74.  
  75.         for i=0 to n/2 - 1
  76.                 rev = 0
  77.                 for j=0 to log2n - 1
  78.                         if i and (2^j) then rev = rev + (2^(log2n - 1 - j))
  79.                 next
  80.  
  81.                 xx_r(i) = x_r(2*rev)
  82.                 xx_i(i) = x_r(2*rev + 1)
  83.         next
  84.  
  85.         for i=1 to log2n
  86.                 m = 2^i
  87.                 wm_r = cos(-2*pi/m)
  88.                 wm_i = sin(-2*pi/m)
  89.  
  90.                 for j=0 to n/2 - 1 step m
  91.                         w_r = 1
  92.                         w_i = 0
  93.  
  94.                         for k=0 to m/2 - 1
  95.                                 p = j + k
  96.                                 q = p + (m \ 2)
  97.  
  98.                                 u_r = w_r*xx_r(q) - w_i*xx_i(q)
  99.                                 u_i = w_r*xx_i(q) + w_i*xx_r(q)
  100.                                 v_r = xx_r(p)
  101.                                 v_i = xx_i(p)
  102.  
  103.                                 xx_r(p) = v_r + u_r
  104.                                 xx_i(p) = v_i + u_i
  105.                                 xx_r(q) = v_r - u_r
  106.                                 xx_i(q) = v_i - u_i
  107.  
  108.                                 u_r = w_r
  109.                                 u_i = w_i
  110.                                 w_r = u_r*wm_r - u_i*wm_i
  111.                                 w_i = u_r*wm_i + u_i*wm_r
  112.                         next
  113.                 next
  114.         next
  115.  
  116.         xx_r(n/2) = xx_r(0)
  117.         xx_i(n/2) = xx_i(0)
  118.  
  119.         for i=1 to n/2 - 1
  120.                 xx_r(n/2 + i) = xx_r(n/2 - i)
  121.                 xx_i(n/2 + i) = xx_i(n/2 - i)
  122.         next
  123.  
  124.         dim xpr as double, xpi as double
  125.         dim xmr as double, xmi as double
  126.  
  127.         for i=0 to n/2 - 1
  128.                 xpr = (xx_r(i) + xx_r(n/2 + i)) / 2
  129.                 xpi = (xx_i(i) + xx_i(n/2 + i)) / 2
  130.  
  131.                 xmr = (xx_r(i) - xx_r(n/2 + i)) / 2
  132.                 xmi = (xx_i(i) - xx_i(n/2 + i)) / 2
  133.  
  134.                 xx_r(i) = xpr + xpi*cos(2*pi*i/n) - xmr*sin(2*pi*i/n)
  135.                 xx_i(i) = xmi - xpi*sin(2*pi*i/n) - xmr*cos(2*pi*i/n)
  136.         next
  137.  
  138.         'symmetry, complex conj
  139.         for i=0 to n/2 - 1
  140.                 xx_r(n/2 + i) = xx_r(n/2 - 1 - i)
  141.                 xx_i(n/2 + i) =-xx_i(n/2 - 1 - i)
  142.         next
  143.  
« Last Edit: April 30, 2020, 10:32:53 pm by _vince »

Offline Parkland

  • Newbie
  • Posts: 51
    • View Profile
Re: HOW do i sample (not play) audio?
« Reply #40 on: May 04, 2020, 03:30:33 pm »
Wow! very awesome.
Thanks everyone.

Also attached is the most recent version of what I glued together for live sampling