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

0 Members and 1 Guest are viewing this topic.

This topic contains a post which is marked as Best Answer. Press here if you would like to see it.

FellippeHeitor

  • Guest
Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« on: December 31, 2020, 10:42:44 am »
Hello @Petr and everyone else. Look at this:

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(600, 200, 32)
  2. DIM bonus AS LONG, x AS LONG, x0 AS LONG, i AS _OFFSET, a%, c~&
  3. bonus = _SNDOPEN("sine.ogg")
  4. PRINT bonus
  5.  
  6. IF bonus THEN _SNDPLAY bonus
  7.  
  8. s = _MEMSOUND(bonus, 1)
  9.  
  10. i = s.OFFSET
  11.     _MEMGET s, i, a%
  12.     IF x MOD 2 = 0 THEN
  13.         x0 = x0 + 1
  14.         c~& = _RGB32(map(a%, -32768, 32767, 0, 255), 0, 255)
  15.         LINE (x0, _HEIGHT / 2)-STEP(0, map(a%, -32768, 32767, -_HEIGHT / 2, _HEIGHT / 2)), c~&, BF
  16.         IF x0 >= _WIDTH THEN x0 = 0: _DISPLAY: CLS
  17.     END IF
  18.     x = x + 1
  19.  
  20.     i = i + 3
  21.     LOCATE 1, 1: PRINT i, s.OFFSET + s.SIZE
  22.     IF i + 2 >= s.OFFSET + s.SIZE THEN EXIT DO
  23.  
  24. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  25.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  26.  

_MEMSOUND is supposed to give you access to raw sound data after a file is decoded by using _SNDOPEN - in the same fashion as _MEMIMAGE gives you raw access to an image's data after you use _LOADIMAGE.

The code above won't work with v1.4 and not even with the latest dev build, as it's still in a separate branch for development. But it will yield the following results:



Is that what you had in mind, @Petr?
« Last Edit: December 31, 2020, 11:04:28 am by FellippeHeitor »

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 #1 on: December 31, 2020, 01:05:24 pm »
Hi Fellippe,

That's absolutely great. Perfect. That's exactly what I've wanted for so long. If this feature really will be in the next version of QB64, I will be absolutely happy. It will greatly expand the possibilities for everyone. We will no longer be limited to graphics, in which we have really huge possibilities, but will be able to combine it.

 
MEMSOUND is a fullfiled wish for me!

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 #2 on: December 31, 2020, 01:18:25 pm »
I think quickly and find that the following is needed:
- Function that returns the number of channels in the audio track:

 - if the data format is RAW, then all audio data will probably be in INTEGER format (if the output RAW format is 16 bits) and the number of channels will determine whether every other INTEGER should be read for the left channel (ie bytes 1.2 for the left track, bytes 3.4 for the right track, bytes 5.6 for the left track .... and so on, or in the case of mono all bytes will belong to the left audio channel), or if this will be handled differently and the left audio channel will be read separately into its own MEM block and right audio channel also in own separated memory block?

That's actually all, because with information about the number of channels in the audio track and RAW audio data, we can add everything else, if the stored RAW format in memory will always be the same type (16 bit). There are also WAV files that contain audio data in the format _UNSIGNED _BYTE (8 bit) or 32 bit, these contain audio data in the SINGLE format. Of course, it can be converted between each other, so one uniform format is enough in memory.

One thing is also needed. Audio sampling frequency. Will it always be the same, or will a new function be needed to return the current state of the sampling frequency? (in RAW MEM block)?
« Last Edit: December 31, 2020, 01:33:27 pm by Petr »

FellippeHeitor

  • Guest
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #3 on: December 31, 2020, 01:29:49 pm »
Notice in the sample code above that I'm getting the memory block with _MEMSOUND(handle, channel) - if it's mono, I'm getting channel 1, if it's stereo, I can get channel 2. It'll return a memblock of size 0 if you try to read the right channel (channel 2) and it's a mono sound.

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 #4 on: December 31, 2020, 01:36:30 pm »
I see! It never occurred to me what the number one meant there! In that case, it is already solved! And even it can be loaded separately. This is absolutely perfect! Looks really very, very nice!

FellippeHeitor

  • Guest
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #5 on: December 31, 2020, 01:38:06 pm »
One thing is also needed. Audio sampling frequency. Will it always be the same, or will a new function be needed to return the current state of the sampling frequency? (in RAW MEM block)?

The data available after _SNDOPEN is used is the result of the decoding and resampling that OpenAL does automatically, which means the output will (i believe) always be in accordance with _SNDRATE (usually returns 44100) and 16 bits per sample.
« Last Edit: December 31, 2020, 01:39:23 pm by FellippeHeitor »

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 #6 on: December 31, 2020, 01:46:52 pm »
Quote
The data available after _SNDOPEN is used is the result of the decoding and resampling that OpenAL does automatically, which means the output will (i believe) always be in accordance with _SNDRATE (usually returns 44100) and 16 bits per sample.

So in that case, I think it's on the right track! I look forward to it. This feature function is a big amazing news!

FellippeHeitor

  • Guest
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #7 on: December 31, 2020, 04:17:24 pm »
I can't wait for you to test it, @Petr. I don't know how comfortable you are with cloning the repository (or maybe you already have it cloned) - either way, let me know and I can provide instructions for you to get started with it, even though it still requires more thought before it goes live, even for the dev build.



Code: QB64: [Select]
  1. CONST true = -1, false = 0
  2.  
  3. DIM theSound AS LONG, x0 AS LONG, i AS _OFFSET, j AS _OFFSET
  4. DIM a%, c~&, k&, trackerHeight AS INTEGER
  5. DIM y0 AS LONG, y1 AS LONG
  6. DIM mouseDown AS _BYTE, f$, mouseDownOn AS INTEGER
  7. DIM sleft AS _MEM, sright AS _MEM
  8. DIM stereo AS _BYTE
  9. DIM stereoScreen AS LONG, monoScreen AS LONG
  10.  
  11. stereoScreen = _NEWIMAGE(882, 400, 32)
  12. monoScreen = _NEWIMAGE(882, 200, 32)
  13. SCREEN monoScreen
  14.  
  15. _TITLE "QB64 Sound Player"
  16.  
  17.     f$ = COMMAND$
  18.     start:
  19.     INPUT "File to load: ", f$
  20.  
  21. PRINT "Loading '"; f$; "'..."
  22. theSound = _SNDOPEN(f$)
  23. IF theSound = 0 THEN PRINT "Load failed.": END
  24.  
  25. loaded:
  26. sleft = _MEMSOUND(theSound, 1)
  27. sright = _MEMSOUND(theSound, 2)
  28.  
  29. IF sright.SIZE > 0 THEN
  30.     SCREEN stereoScreen
  31.     stereo = true
  32.     y0 = _HEIGHT / 4
  33.     y1 = _HEIGHT - _HEIGHT / 4
  34.     SCREEN monoScreen
  35.     stereo = false
  36.     y0 = _HEIGHT / 2
  37.  
  38. trackerHeight = 50
  39. _SNDPLAY theSound
  40. _SNDPAUSE theSound
  41.  
  42.         IF mouseDown = false THEN
  43.             mouseDown = true
  44.             IF _MOUSEY < _HEIGHT - trackerHeight THEN
  45.                 mouseDownOn = 1 'plot area
  46.             ELSE
  47.                 mouseDownOn = 2 'track area
  48.             END IF
  49.         ELSE
  50.             IF mouseDownOn = 2 AND _SNDPLAYING(theSound) = 0 THEN
  51.                 _SNDSETPOS theSound, map(_MOUSEX, 0, _WIDTH, 0, _SNDLEN(theSound))
  52.             END IF
  53.         END IF
  54.     ELSE
  55.         IF mouseDown THEN
  56.             'toggle play
  57.             IF mouseDownOn = 1 THEN
  58.                 toggleSoundState theSound
  59.             ELSEIF mouseDownOn = 2 THEN
  60.                 _SNDSETPOS theSound, map(_MOUSEX, 0, _WIDTH, 0, _SNDLEN(theSound))
  61.             END IF
  62.             mouseDown = false
  63.             mouseDownOn = 0
  64.         END IF
  65.     END IF
  66.  
  67.     k& = _KEYHIT
  68.     IF k& = 32 THEN toggleSoundState theSound
  69.  
  70.             _SNDSTOP theSound
  71.             _SNDCLOSE theSound
  72.             theSound = 0
  73.             f$ = _DROPPEDFILE$(1)
  74.             _PRINTSTRING (_WIDTH / 2 - _PRINTWIDTH("Loading...") / 2, _HEIGHT / 2 - _FONTHEIGHT), "Loading..."
  75.             _DISPLAY
  76.             theSound = _SNDOPEN(f$)
  77.             IF theSound THEN
  78.                 _FINISHDROP
  79.                 GOTO loaded
  80.             ELSE
  81.                 PRINT "Load failed."
  82.                 END
  83.             END IF
  84.         END IF
  85.         _FINISHDROP
  86.     END IF
  87.  
  88.     DIM alpha AS INTEGER
  89.     alpha = 50 'IF _SNDPLAYING(theSound) THEN alpha = 40 ELSE alpha = 20
  90.     LINE (0, 0)-(_WIDTH - 1, _HEIGHT - 1), _RGB32(0, alpha), BF
  91.     GOSUB render
  92.     IF _SNDPLAYING(theSound) = 0 THEN _PRINTSTRING (_WIDTH / 2 - 16, _HEIGHT / 2 - _FONTHEIGHT), CHR$(221) + CHR$(222)
  93.  
  94.     _DISPLAY
  95.     _LIMIT 60
  96.  
  97. render:
  98. o = INT((_SNDGETPOS(theSound)) * _SNDRATE)
  99. WHILE o MOD 2 <> 0: o = o + 1: WEND
  100. i = sleft.OFFSET + o
  101. IF stereo THEN j = sright.OFFSET + o
  102. FOR x0 = 0 TO _WIDTH
  103.     _MEMGET sleft, i, a%
  104.     IF a% < 0 THEN
  105.         c~& = _RGB32(67, 150, 33, map(a%, 0, -32767, 80, 255))
  106.     ELSE
  107.         c~& = _RGB32(67, 150, 33, map(a%, 0, 32767, 80, 255))
  108.     END IF
  109.     LINE (x0, y0)-STEP(0, map(a%, -32768, 32767, -_HEIGHT / 4, _HEIGHT / 4)), c~&, BF
  110.  
  111.     IF stereo THEN
  112.         _MEMGET sright, j, a%
  113.         IF a% < 0 THEN
  114.             c~& = _RGB32(67, 150, 33, map(a%, 0, -32767, 80, 255))
  115.         ELSE
  116.             c~& = _RGB32(67, 150, 33, map(a%, 0, 32767, 80, 255))
  117.         END IF
  118.         LINE (x0, y1)-STEP(0, map(a%, -32768, 32767, -_HEIGHT / 4, _HEIGHT / 4)), c~&, BF
  119.     END IF
  120.  
  121.     i = i + 2
  122.     IF stereo THEN j = j + 2
  123.     IF i + 2 >= sleft.OFFSET + sleft.SIZE THEN EXIT FOR
  124.  
  125. 'tracker:
  126. LINE (0, _HEIGHT - trackerHeight / 3)-STEP(map(_SNDGETPOS(theSound), 0, _SNDLEN(theSound), 0, _WIDTH), -trackerHeight / 3), _RGB32(255, 180), BF
  127. IF _MOUSEY > _HEIGHT - trackerHeight THEN
  128.     LINE (0, _HEIGHT - trackerHeight)-STEP(_WIDTH, trackerHeight), _RGB32(255, 30), BF
  129.  
  130.  
  131. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  132.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  133.  
  134. SUB toggleSoundState (theSound AS LONG)
  135.     IF _SNDPLAYING(theSound) THEN
  136.         _SNDPAUSE theSound
  137.     ELSE
  138.         DIM i AS INTEGER
  139.         FOR i = -20 TO 20
  140.             LINE (_WIDTH / 2 + 20, _HEIGHT / 2 - 5)-STEP(-40, i)
  141.         NEXT
  142.         _SNDLOOP theSound
  143.     END IF
  144.  
« Last Edit: January 05, 2021, 10:13:18 pm by FellippeHeitor »

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 #8 on: December 31, 2020, 05:24:41 pm »
I didn't know it was possible to download it from GitHub. I downloaded a version with the last update eight hours ago, now it's unpacking. The computer says it will unpack for an hour because the ZIP contains 31067 files. That means it will end sometime around midnight of my time. Then I run setup-win.bat and after finishing I will try it :)

FellippeHeitor

  • Guest
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #9 on: December 31, 2020, 05:26:05 pm »
Hm, that might not be enough, unfortunately. Can you confirm you downloaded the memsound branch?

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #10 on: December 31, 2020, 05:29:03 pm »
Hm, that might not be enough, unfortunately. Can you confirm you downloaded the memsound branch?

If it’s the development branch, you should be able to test out the quick insert feature I just ended up pushing.  I’m thinking it should be working as intended now, without any issues, but it’d be nice to hear how it performs for others as well. ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

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 #11 on: December 31, 2020, 05:31:32 pm »
Oops... An error has occurred ... I'm already downloading the correct version! Where did I look?

FellippeHeitor

  • Guest
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #12 on: December 31, 2020, 05:34:25 pm »
Oops... An error has occurred ... I'm already downloading the correct version! Where did I look?

Assuming you're using Windows:
  • After the memsound branch gets downloaded, run setup_win.bat. That'll generate qb64.exe - but this still doesn't contain _MEMSOUND
  • Launch QB64 and load source/qb64.bas. Make sure "Output exe to source folder" is unchecked in the Run menu.
  • Hit F11 and wait for compilation.
  • Once compiled, you will have a qb64(2).exe file in your new QB64 folder. That's the version that will allow you to test _MEMSOUND

Let me know how it goes.

PS: The 7Zip version will likely unpack faster, but I don't know if you have 7Zip.

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 #13 on: December 31, 2020, 05:37:39 pm »
I use internal decompressors in Total Commander to unpack, 7zip can also. I'm already unpacking it to disk.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #14 on: December 31, 2020, 05:41:32 pm »
Quick question:  Are you looking to implement a _NEWSOUND type command so we can _MEMPUT information to it directly?

For example:

I =  _NEWIMAGE(640,480,32)
M = _MEMIMAGE(I)
_MEMPUT M, M.OFFSET, image_data()

The above can take a memblock that we saved to disk, and upload it up into a new image handle, so we can then _PUTIMAGE it, or work with it the same as any other image.

Will we be able to do something like:

S = _NEWSOUND(123, 441000, 1) 123 seconds at 44100 sndrate, with 1 channel
DIM M AS _MEM
M = _MEMSOUND(S, 1)
CALL Load_Routine ‘Load sound data from disk
_MEMPUT M, M.OFFSET, Sound_Data()
SNDPLAY S
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!