Author Topic: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)  (Read 28180 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 #45 on: January 04, 2021, 10:55:32 am »
My first version, named as qb64-memsound downloaded from github is 64bit. Which file you need? Created output WAV file or file on input (MP3)?

FellippeHeitor

  • Guest
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #46 on: January 04, 2021, 10:57:50 am »
I tried in my machine and it worked with some files, not with others - which leads me to believe it has to do with the file generated and how OpenAL is decoding it - in which case debugging it beyond my abilities, since it's a third-party library. Let me know if you find something else that could be the cause.

FellippeHeitor

  • Guest
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #47 on: January 04, 2021, 10:59:16 am »
Could you try playing the generated files with v1.4? I believe this has nothing to do with the new _MEMSOUND after all, since your issue is with regular _SNDPLAY.

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 #48 on: January 04, 2021, 11:02:23 am »
I'll try, but it will work. This cannot be a bug in OpenAl when the 64-bit version plays it. Even the 32-bit version reads correctly the length of the audio. But it won't start. 64 bit starts it. 32 bit sees the length of the music but does not start playing.

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 #49 on: January 04, 2021, 11:08:46 am »
This was wrong, I was too fast. Searching problems...
« Last Edit: January 04, 2021, 11:13:54 am by Petr »

FellippeHeitor

  • Guest
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #50 on: January 04, 2021, 11:10:27 am »
Something related to the audio library then, since none of that code has been touched recently.

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 #51 on: January 04, 2021, 11:38:01 am »
So..... IDIOT AM I. Again.  Bad writed head in WAV file was the problem.


in SAVESOUND16S replace this row:   H16.lenght = OFFSETasI64(arr.SIZE) - 2
We still using integers.... NOW 32 bit version works as expected!

BIG SORRY FOR THIS.   -2  miss

Please try it also. I have five IDEs open here and I'm quickly losing track.

FellippeHeitor

  • Guest
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #52 on: January 04, 2021, 11:38:52 am »
Hahaha, glad to hear all is solved.

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 #53 on: January 04, 2021, 11:44:12 am »
The big unknown is: Why the this bug is none problem for 64 bit version, but it is problem for 32 bit version? Just add -2 and is done...

I am also very glad, that it works and this nice function can be added!

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 #54 on: January 04, 2021, 11:51:47 am »
Fellippe, but still:

This code was work under 32 bit:

Code: QB64: [Select]
  1. 'Program create new WAV soundtrack + add echo
  2. 'if _fileexists("1d.mp3")
  3. '_SNDPLAYFILE ("1d.mp3")
  4. 'SLEEP
  5.  
  6. '_SNDPLAYFILE ("tracks-mix4.wav")
  7.  
  8. 'SLEEP
  9.  
  10. EchoLenght = 0.12 '0.06 seconds is echo duration
  11. OverSampling = 10 'number of echoes sample passes
  12.  
  13. Echo& = _SNDRATE * EchoLenght
  14.  
  15. DO UNTIL Echo& MOD 2 = 0
  16.     Echo& = Echo& + 1
  17. DIM Left AS _MEM, Right AS _MEM, NewSound AS _MEM, Audio AS INTEGER, Audio2 AS INTEGER, Audio3 AS INTEGER, Audio4 AS INTEGER
  18. REDIM PlayableFiles(0) AS STRING
  19.  
  20.  
  21. 'INPUT "Insert audio file name:"; a1$
  22.  
  23.     FUNCTION load_dir& (s AS STRING)
  24.     FUNCTION has_next_entry& ()
  25.     SUB close_dir ()
  26.     SUB get_next_entry (s AS STRING, flags AS LONG, file_size AS LONG)
  27.  
  28. REDIM Dir(0) AS STRING, File(0) AS STRING
  29. GetFileList _CWD$, Dir(), File()
  30.  
  31.  
  32. FOR s = LBOUND(file) TO UBOUND(file)
  33.     SELECT CASE UCASE$(RIGHT$(File(s), 3))
  34.         CASE "MP3", "OGG", "WAV"
  35.             PlayableFiles(i) = File(s)
  36.             i = i + 1
  37.             REDIM _PRESERVE PlayableFiles(i) AS STRING
  38.     END SELECT
  39.  
  40. PRINT "Files to play: "; i - 1
  41.  
  42.  
  43. FOR playit = 0 TO i - 1
  44.     a1$ = PlayableFiles(playit)
  45.     PRINT "Opening file "; playit + 1; "/"; i - 1; " - "; PlayableFiles(playit)
  46.     IF a THEN _SNDCLOSE a: a = 0
  47.     a = _SNDOPEN(a1$)
  48.     IF a THEN PRINT "Audio file opened" ELSE PRINT "Audio file 1 opening error.": END
  49.     LENa = _CEIL(_SNDLEN(a)) + EchoLenght
  50.     PRINT "Audio file lenght:"; LENa
  51.     NewTrackTime = LENa
  52.  
  53.  
  54.  
  55.  
  56.     Left = _MEMSOUND(a, 1)
  57.     Right = _MEMSOUND(a, 2)
  58.  
  59.     NewSoundSize& = _SNDRATE * NewTrackTime * 2 * 2 'use stereo  + use INTEGER
  60.     NewSound = _MEMNEW(NewSoundSize&)
  61.  
  62.     PRINT "SndRate:"; _SNDRATE
  63.     PRINT "Track memory len:"; Left.SIZE
  64.     PRINT "Creating audio..."
  65.  
  66.     VolDown = 1 / OverSampling
  67.     Create& = 0
  68.     NewAudio& = 0
  69.     DO UNTIL Create& >= Left.SIZE - 2
  70.         _MEMGET Left, Left.OFFSET + Create&, Audio
  71.         _MEMGET Right, Right.OFFSET + Create&, Audio2
  72.  
  73.         IF Create& > Echo& THEN
  74.  
  75.             E& = Create&
  76.             Vol = 1
  77.             DO UNTIL E& <= Create& - OverSampling
  78.                 Vol = Vol - VolDown
  79.                 _MEMGET Left, Left.OFFSET + Create& - Echo&, Audio3
  80.                 _MEMGET Left, Left.OFFSET + Create& - 2, Audio4
  81.                 Audio = (Audio + Audio3 * (Vol + .01) + Audio4 * Vol) \ 3
  82.                 E& = E& - 2
  83.             LOOP
  84.  
  85.             E& = Create&
  86.             Vol = 1
  87.             DO UNTIL E& <= Create& - OverSampling
  88.                 Vol = Vol - VolDown
  89.                 _MEMGET Right, Right.OFFSET + Create& - Echo&, Audio3
  90.                 _MEMGET Right, Right.OFFSET + Create& - 2, Audio4
  91.                 Audio2 = (Audio2 + Audio3 * (Vol + .01) + Audio4 * Vol) \ 3
  92.                 E& = E& - 2
  93.             LOOP
  94.         END IF
  95.  
  96.         _MEMPUT NewSound, NewSound.OFFSET + NewAudio&, Audio 'left channel
  97.         _MEMPUT NewSound, NewSound.OFFSET + NewAudio& + 2, Audio2 'right channel
  98.         NewAudio& = NewAudio& + 4
  99.         Create& = Create& + 2
  100.     LOOP
  101.  
  102.     PRINT "New sound created. Saving as Tracks-mix4.wav..."
  103.     SAVESOUND16S NewSound, "Tracks-mix4.wav"
  104.     PRINT "Sound saved, erasing RAM..."
  105.     _MEMFREE Left
  106.     _MEMFREE Right
  107.     _MEMFREE NewSound
  108.  
  109.     PRINT "Playing mixed sound"
  110.     _SNDCLOSE a
  111.     a = 0
  112.     snd2 = _SNDOPEN("tracks-mix4.wav")
  113.     PRINT _SNDLEN(snd2), snd2
  114.     SLEEP
  115.     _SNDPLAY snd2
  116.     DO UNTIL _SNDPLAYING(snd2) = 0
  117.         LOCATE 12
  118.         PRINT _SNDGETPOS(snd2), _SNDLEN(snd2)
  119.     LOOP
  120.     CLS
  121.     _SNDCLOSE snd2
  122.     '    KILL "tracks-mix4.wav"
  123.  
  124.  
  125.  
  126. FUNCTION OFFSETasI64&& (OffsetVal AS _OFFSET) 'convert OFFSET value to _INTEGER64 value -> 8 byte lenght to 8 byte lenght
  127.     DIM o AS _INTEGER64, mo AS _MEM
  128.     mo = _MEM(o)
  129.     _MEMPUT mo, mo.OFFSET, OffsetVal
  130.     _MEMFREE mo
  131.     OFFSETasI64&& = o
  132.  
  133.  
  134. SUB SAVESOUND16S (arr AS _MEM, file AS STRING)
  135.  
  136.     TYPE head16
  137.         chunk AS STRING * 4 '       4 bytes  (RIFF)
  138.         size AS LONG '              4 bytes  (file size)
  139.         fomat AS STRING * 4 '       4 bytes  (WAVE)
  140.         sub1 AS STRING * 4 '        4 bytes  (fmt )
  141.         subchunksize AS LONG '      4 bytes  (lo / hi), $00000010 for PCM audio
  142.         format AS INTEGER '         2 bytes  (0001 = standard PCM, 0101 = IBM mu-law, 0102 = IBM a-law, 0103 = IBM AVC ADPCM)
  143.         channels AS INTEGER '       2 bytes  (1 = mono, 2 = stereo)
  144.         rate AS LONG '              4 bytes  (sample rate, standard is 44100)
  145.         ByteRate AS LONG '          4 bytes  (= sample rate * number of channels * (bits per channel /8))
  146.         Block AS INTEGER '          2 bytes  (block align = number of channels * bits per sample /8)
  147.         Bits AS INTEGER '           2 bytes  (bits per sample. 8 = 8, 16 = 16)
  148.         subchunk2 AS STRING * 4 '   4 bytes  ("data")  contains begin audio samples
  149.         lenght AS LONG '            4 bytes  Data block size
  150.     END TYPE '                     44 bytes  total
  151.     DIM H16 AS head16
  152.     ch = FREEFILE
  153.  
  154.     H16.chunk = "RIFF"
  155.     H16.size = 44 + OFFSETasI64(arr.SIZE) / _SNDRATE / 4 'two channels, it create 16 bit, stereo wav file, one sample use 2 bytes to one channel
  156.  
  157.     H16.fomat = "WAVE"
  158.     H16.sub1 = "fmt "
  159.     H16.subchunksize = 16
  160.     H16.format = 1
  161.     H16.channels = 2
  162.     H16.rate = 44100
  163.     H16.ByteRate = 44100 * 2 * 16 / 8
  164.     H16.Block = 4
  165.     H16.Bits = 16
  166.     H16.subchunk2 = "data"
  167.     H16.lenght = OFFSETasI64(arr.SIZE) - 2 '  <---------------------- THIS IS THE PROBLEM. Without -2 works in 64 bit, with -2 works under 32 bit.
  168.     IF _FILEEXISTS(file$) THEN KILL file$
  169.  
  170.     Audio$ = SPACE$(OFFSETasI64(arr.SIZE))
  171.     _MEMGET arr, arr.OFFSET, Audio$
  172.  
  173.     OPEN file$ FOR BINARY AS #ch
  174.     PUT #ch, , H16
  175.     PUT #ch, , Audio$
  176.     Audio$ = ""
  177.  
  178.     CLOSE ch
  179.  
  180. SUB GetFileList (SearchDirectory AS STRING, DirList() AS STRING, FileList() AS STRING)
  181.     CONST IS_DIR = 1
  182.     CONST IS_FILE = 2
  183.     DIM flags AS LONG, file_size AS LONG
  184.  
  185.     REDIM _PRESERVE DirList(100), FileList(100)
  186.     DirCount = 0: FileCount = 0
  187.  
  188.     IF load_dir(SearchDirectory) THEN
  189.         DO
  190.             length = has_next_entry
  191.             IF length > -1 THEN
  192.                 nam$ = SPACE$(length)
  193.                 get_next_entry nam$, flags, file_size
  194.                 IF (flags AND IS_DIR) OR _DIREXISTS(SearchDirectory + nam$) THEN
  195.                     DirCount = DirCount + 1
  196.                     IF DirCount > UBOUND(DirList) THEN REDIM _PRESERVE DirList(UBOUND(DirList) + 100)
  197.                     DirList(DirCount) = nam$
  198.                 ELSEIF (flags AND IS_FILE) OR _FILEEXISTS(SearchDirectory + nam$) THEN
  199.                     FileCount = FileCount + 1
  200.                     IF FileCount > UBOUND(filelist) THEN REDIM _PRESERVE FileList(UBOUND(filelist) + 100)
  201.                     FileList(FileCount) = nam$
  202.                 END IF
  203.             END IF
  204.         LOOP UNTIL length = -1
  205.         close_dir
  206.     ELSE
  207.     END IF
  208.     REDIM _PRESERVE DirList(DirCount)
  209.     REDIM _PRESERVE FileList(FileCount)
  210.  


now do the same bug in 64 bit version as in previous case previous code in 32 bit! So something in 32 bit ide is shifted by 2 bytes down in 32 bit ide or is something shifted by 2 byte up in 64 bit version?

FellippeHeitor

  • Guest
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #55 on: January 04, 2021, 11:53:20 am »
Offset sizes are different depending on the platform. It could be that.
« Last Edit: January 04, 2021, 12:32:00 pm by FellippeHeitor »

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)
« Reply #56 on: January 04, 2021, 01:15:52 pm »
Code: QB64: [Select]
  1. m = _MEM(x)
  2. PRINT m.OFFSET
  3. PRINT ConvertOffset(m.OFFSET)
  4.  
  5.  
  6. FUNCTION ConvertOffset&& (value AS _OFFSET)
  7. DIM m AS _MEM 'Define a memblock
  8. m = _MEM(value) 'Point it to use value
  9. $IF 64BIT THEN
  10.     'On 64 bit OSes, an OFFSET is 8 bytes in size.  We can put it directly into an Integer64
  11.     _MEMGET m, m.OFFSET, ConvertOffset&& 'Get the contents of the memblock and put the values there directly into ConvertOffset&&
  12.     'However, on 32 bit OSes, an OFFSET is only 4 bytes.  We need to put it into a LONG variable first
  13.     _MEMGET m, m.OFFSET, temp& 'Like this
  14.     ConvertOffset&& = temp& 'And then assign that long value to ConvertOffset&&
  15. _MEMFREE m 'Free the memblock
  16.  
  17.  

See the difference in the offset convertor above, and yours.  I imagine there’s your issue (4 vs 8 bytes).
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 #57 on: January 04, 2021, 01:53:42 pm »
Thank you, Steve. This solved all. Now all works under all versions.

You can test it with this new effect, named as "When you shoot a turntable"

Code: QB64: [Select]
  1. 'program create speed - up track and then play it
  2. INPUT "Insert sound file name:", snd$
  3. DIM Left AS _MEM
  4. DIM Right AS _MEM
  5. DIM NewTrack AS _MEM
  6. DIM SL AS LONG, SR AS LONG
  7.  
  8. snd = _SNDOPEN(snd$)
  9. Left = _MEMSOUND(snd, 1)
  10. Right = _MEMSOUND(snd, 2)
  11. IF Right.SIZE = 0 THEN PRINT "Program need stereo track!": END
  12. NewTrack = _MEMNEW(Left.SIZE * 2)
  13. R = 0
  14. DO UNTIL p& >= Left.SIZE - R
  15.     IF p& MOD 88200 = 0 THEN R = R + 2
  16.     IF p& + R > Left.SIZE THEN EXIT DO
  17.     SL = 0
  18.     SR = 0
  19.     FOR SLUC = 1 TO R
  20.         _MEMGET Left, Left.OFFSET + p& + R, S
  21.         SL = SL + S
  22.         _MEMGET Right, Right.OFFSET + p& + R, S
  23.         SR = SR + S
  24.     NEXT SLUC
  25.  
  26.     SL = SL \ R
  27.     SR = SR \ R
  28.     _MEMPUT NewTrack, NewTrack.OFFSET + i&, SL
  29.     _MEMPUT NewTrack, NewTrack.OFFSET + i& + 2, SR
  30.  
  31.     p& = p& + R
  32.     i& = i& + 4
  33.  
  34. SAVESOUND16S NewTrack, "eff2.wav"
  35. _SNDPLAYFILE ("eff2.wav")
  36.  
  37.  
  38. SUB SAVESOUND16S (arr AS _MEM, file AS STRING)
  39.  
  40.     TYPE head16
  41.         chunk AS STRING * 4 '       4 bytes  (RIFF)
  42.         size AS LONG '              4 bytes  (file size)
  43.         fomat AS STRING * 4 '       4 bytes  (WAVE)
  44.         sub1 AS STRING * 4 '        4 bytes  (fmt )
  45.         subchunksize AS LONG '      4 bytes  (lo / hi), $00000010 for PCM audio
  46.         format AS INTEGER '         2 bytes  (0001 = standard PCM, 0101 = IBM mu-law, 0102 = IBM a-law, 0103 = IBM AVC ADPCM)
  47.         channels AS INTEGER '       2 bytes  (1 = mono, 2 = stereo)
  48.         rate AS LONG '              4 bytes  (sample rate, standard is 44100)
  49.         ByteRate AS LONG '          4 bytes  (= sample rate * number of channels * (bits per channel /8))
  50.         Block AS INTEGER '          2 bytes  (block align = number of channels * bits per sample /8)
  51.         Bits AS INTEGER '           2 bytes  (bits per sample. 8 = 8, 16 = 16)
  52.         subchunk2 AS STRING * 4 '   4 bytes  ("data")  contains begin audio samples
  53.         lenght AS LONG '            4 bytes  Data block size
  54.     END TYPE '                     44 bytes  total
  55.     DIM H16 AS head16
  56.     ch = FREEFILE
  57.  
  58.     H16.chunk = "RIFF"
  59.     H16.size = 44 + ConvertOffset&&(arr.SIZE) / _SNDRATE / 4 'two channels, it create 16 bit, stereo wav file, one sample use 2 bytes to one channel
  60.  
  61.     H16.fomat = "WAVE"
  62.     H16.sub1 = "fmt "
  63.     H16.subchunksize = 16
  64.     H16.format = 1
  65.     H16.channels = 2
  66.     H16.rate = 44100
  67.     H16.ByteRate = 44100 * 2 * 16 / 8
  68.     H16.Block = 4
  69.     H16.Bits = 16
  70.     H16.subchunk2 = "data"
  71.     '  $IF 32BIT THEN
  72.     '      H16.lenght = ConvertOffset&&(arr.SIZE) - 2
  73.     '  $ELSE
  74.     H16.lenght = ConvertOffset&&(arr.SIZE)
  75.     ' $END IF
  76.     IF _FILEEXISTS(file$) THEN KILL file$
  77.  
  78.     Audio$ = SPACE$(ConvertOffset&&(arr.SIZE))
  79.     _MEMGET arr, arr.OFFSET, Audio$
  80.  
  81.     OPEN file$ FOR BINARY AS #ch
  82.     PUT #ch, , H16
  83.     PUT #ch, , Audio$
  84.     Audio$ = ""
  85.  
  86.     CLOSE ch
  87.  
  88.  
  89.  
  90. FUNCTION ConvertOffset&& (value AS _OFFSET)
  91.     DIM m AS _MEM 'Define a memblock
  92.     m = _MEM(value) 'Point it to use value
  93.     $IF 64BIT THEN
  94.         'On 64 bit OSes, an OFFSET is 8 bytes in size.  We can put it directly into an Integer64
  95.         _MEMGET m, m.OFFSET, ConvertOffset&& 'Get the contents of the memblock and put the values there directly into ConvertOffset&&
  96.     $ELSE
  97.         'However, on 32 bit OSes, an OFFSET is only 4 bytes.  We need to put it into a LONG variable first
  98.         _MEMGET m, m.OFFSET, temp& 'Like this
  99.         ConvertOffset&& = temp& 'And then assign that long value to ConvertOffset&&
  100.     $END IF
  101.     _MEMFREE m 'Free the memblock
  102.  

a little better version:

Code: QB64: [Select]
  1. 'program create speed - up track and then play it
  2. INPUT "Insert sound file name:", snd$
  3. DIM Left AS _MEM
  4. DIM Right AS _MEM
  5. DIM NewTrack AS _MEM
  6. DIM SL AS LONG, SR AS LONG
  7.  
  8. snd = _SNDOPEN(snd$)
  9. Left = _MEMSOUND(snd, 1)
  10. Right = _MEMSOUND(snd, 2)
  11. IF Right.SIZE = 0 THEN PRINT "Program need stereo track!": END
  12. NewTrack = _MEMNEW(Left.SIZE)
  13. R = 0
  14. DO UNTIL p& >= Left.SIZE - R
  15.     IF i& \ 4 MOD 88200 = 0 THEN R = R + 2
  16.     IF p& + R > Left.SIZE THEN EXIT DO
  17.     SL = 0
  18.     SR = 0
  19.     FOR SLUC = 1 TO R
  20.         _MEMGET Left, Left.OFFSET + p& + R, S
  21.         SL = SL + S
  22.         _MEMGET Right, Right.OFFSET + p& + R, S
  23.         SR = SR + S
  24.     NEXT SLUC
  25.  
  26.     SL = SL \ R
  27.     SR = SR \ R
  28.     _MEMPUT NewTrack, NewTrack.OFFSET + i&, SL
  29.     _MEMPUT NewTrack, NewTrack.OFFSET + i& + 2, SR
  30.  
  31.     p& = p& + R
  32.     i& = i& + 4
  33.  
  34. 'DO UNTIL S = 0
  35.  
  36.  
  37. SAVESOUND16S NewTrack, "eff2.wav"
  38. _SNDPLAYFILE ("eff2.wav")
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48. SUB SAVESOUND16S (arr AS _MEM, file AS STRING)
  49.  
  50.     TYPE head16
  51.         chunk AS STRING * 4 '       4 bytes  (RIFF)
  52.         size AS LONG '              4 bytes  (file size)
  53.         fomat AS STRING * 4 '       4 bytes  (WAVE)
  54.         sub1 AS STRING * 4 '        4 bytes  (fmt )
  55.         subchunksize AS LONG '      4 bytes  (lo / hi), $00000010 for PCM audio
  56.         format AS INTEGER '         2 bytes  (0001 = standard PCM, 0101 = IBM mu-law, 0102 = IBM a-law, 0103 = IBM AVC ADPCM)
  57.         channels AS INTEGER '       2 bytes  (1 = mono, 2 = stereo)
  58.         rate AS LONG '              4 bytes  (sample rate, standard is 44100)
  59.         ByteRate AS LONG '          4 bytes  (= sample rate * number of channels * (bits per channel /8))
  60.         Block AS INTEGER '          2 bytes  (block align = number of channels * bits per sample /8)
  61.         Bits AS INTEGER '           2 bytes  (bits per sample. 8 = 8, 16 = 16)
  62.         subchunk2 AS STRING * 4 '   4 bytes  ("data")  contains begin audio samples
  63.         lenght AS LONG '            4 bytes  Data block size
  64.     END TYPE '                     44 bytes  total
  65.     DIM H16 AS head16
  66.     ch = FREEFILE
  67.  
  68.     H16.chunk = "RIFF"
  69.     H16.size = 44 + ConvertOffset&&(arr.SIZE) / _SNDRATE / 4 'two channels, it create 16 bit, stereo wav file, one sample use 2 bytes to one channel
  70.  
  71.     H16.fomat = "WAVE"
  72.     H16.sub1 = "fmt "
  73.     H16.subchunksize = 16
  74.     H16.format = 1
  75.     H16.channels = 2
  76.     H16.rate = 44100
  77.     H16.ByteRate = 44100 * 2 * 16 / 8
  78.     H16.Block = 4
  79.     H16.Bits = 16
  80.     H16.subchunk2 = "data"
  81.     '  $IF 32BIT THEN
  82.     '      H16.lenght = ConvertOffset&&(arr.SIZE) - 2
  83.     '  $ELSE
  84.     H16.lenght = ConvertOffset&&(arr.SIZE)
  85.     ' $END IF
  86.     IF _FILEEXISTS(file$) THEN KILL file$
  87.  
  88.     Audio$ = SPACE$(ConvertOffset&&(arr.SIZE))
  89.     _MEMGET arr, arr.OFFSET, Audio$
  90.  
  91.     OPEN file$ FOR BINARY AS #ch
  92.     PUT #ch, , H16
  93.     PUT #ch, , Audio$
  94.     Audio$ = ""
  95.  
  96.     CLOSE ch
  97.  
  98.  
  99.  
  100. FUNCTION ConvertOffset&& (value AS _OFFSET)
  101.     DIM m AS _MEM 'Define a memblock
  102.     m = _MEM(value) 'Point it to use value
  103.     $IF 64BIT THEN
  104.         'On 64 bit OSes, an OFFSET is 8 bytes in size.  We can put it directly into an Integer64
  105.         _MEMGET m, m.OFFSET, ConvertOffset&& 'Get the contents of the memblock and put the values there directly into ConvertOffset&&
  106.     $ELSE
  107.         'However, on 32 bit OSes, an OFFSET is only 4 bytes.  We need to put it into a LONG variable first
  108.         _MEMGET m, m.OFFSET, temp& 'Like this
  109.         ConvertOffset&& = temp& 'And then assign that long value to ConvertOffset&&
  110.     $END IF
  111.     _MEMFREE m 'Free the memblock
  112.  
  113.  
  114.  
  115.  
  116. FUNCTION OFFSETasI64&& (OffsetVal AS _OFFSET) 'convert OFFSET value to _INTEGER64 value -> 8 byte lenght to 8 byte lenght
  117.     DIM o AS _INTEGER64, mo AS _MEM
  118.     mo = _MEM(o)
  119.     _MEMPUT mo, mo.OFFSET, OffsetVal
  120.     _MEMFREE mo
  121.     OFFSETasI64&& = o
  122.  
  123.  

The reverse effect can be achieved by adding more samples between the existing samples (always the mathematical average of two adjacent samples), thus achieving a deceleration effect.
« Last Edit: January 04, 2021, 02:04:20 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 #58 on: January 04, 2021, 02:58:21 pm »
But the previous version is too rough. So, here's a way to do it better. The music will gradually speed up. This is done by omitting samples. To make this transition smoother, the transition is always supplemented by one sample to the place where the samples were omitted.
The more samples you insert, the more you slow down the acceleration and smooth the transition.

Code: QB64: [Select]
  1. 'speed - up track and then play it
  2. INPUT "Insert sound file name:", snd$
  3. DIM Left AS _MEM
  4. DIM Right AS _MEM
  5. DIM NewTrack AS _MEM
  6.  
  7. snd = _SNDOPEN(snd$)
  8. Left = _MEMSOUND(snd, 1)
  9. Right = _MEMSOUND(snd, 2)
  10. IF Right.SIZE = 0 THEN PRINT "Program need stereo track!": END
  11. NewTrack = _MEMNEW(Left.SIZE * 2)
  12. R = 0
  13. DO UNTIL p& >= Left.SIZE
  14.     IF p& MOD 22050 = 0 THEN
  15.         skip& = skip& + 10: p& = p& + skip& 'speed up by 10 samples per half second.  This is linear, but it can be exponencial...
  16.         OSL = SL
  17.         OSR = SR
  18.         IF p& > Left.SIZE - 2 THEN EXIT DO
  19.         _MEMGET Left, Left.OFFSET + p&, SL
  20.         _MEMGET Right, Right.OFFSET + p&, SR
  21.         SL = (OSL + SL) \ 2
  22.         SR = (OSR + SR) \ 2
  23.         _MEMPUT NewTrack, NewTrack.OFFSET + i&, SL
  24.         _MEMPUT NewTrack, NewTrack.OFFSET + i& + 2, SR
  25.         i& = i& + 4
  26.     ELSE p& = p& + 2 'all this values must be dividible by two (integer)
  27.     END IF
  28.     IF p& > Left.SIZE - 2 THEN EXIT DO
  29.     _MEMGET Left, Left.OFFSET + p&, SL
  30.     _MEMGET Right, Right.OFFSET + p&, SR
  31.     _MEMPUT NewTrack, NewTrack.OFFSET + i&, SL
  32.     _MEMPUT NewTrack, NewTrack.OFFSET + i& + 2, SR
  33.     i& = i& + 4
  34.  
  35. SAVESOUND16S NewTrack, "eff2.wav"
  36. _SNDPLAYFILE ("eff2.wav")
  37.  
  38.  
  39. SUB SAVESOUND16S (arr AS _MEM, file AS STRING)
  40.     TYPE head16
  41.         chunk AS STRING * 4 '       4 bytes  (RIFF)
  42.         size AS LONG '              4 bytes  (file size)
  43.         fomat AS STRING * 4 '       4 bytes  (WAVE)
  44.         sub1 AS STRING * 4 '        4 bytes  (fmt )
  45.         subchunksize AS LONG '      4 bytes  (lo / hi), $00000010 for PCM audio
  46.         format AS INTEGER '         2 bytes  (0001 = standard PCM, 0101 = IBM mu-law, 0102 = IBM a-law, 0103 = IBM AVC ADPCM)
  47.         channels AS INTEGER '       2 bytes  (1 = mono, 2 = stereo)
  48.         rate AS LONG '              4 bytes  (sample rate, standard is 44100)
  49.         ByteRate AS LONG '          4 bytes  (= sample rate * number of channels * (bits per channel /8))
  50.         Block AS INTEGER '          2 bytes  (block align = number of channels * bits per sample /8)
  51.         Bits AS INTEGER '           2 bytes  (bits per sample. 8 = 8, 16 = 16)
  52.         subchunk2 AS STRING * 4 '   4 bytes  ("data")  contains begin audio samples
  53.         lenght AS LONG '            4 bytes  Data block size
  54.     END TYPE '                     44 bytes  total
  55.     DIM H16 AS head16
  56.     ch = FREEFILE
  57.  
  58.     H16.chunk = "RIFF"
  59.     H16.size = 44 + ConvertOffset&&(arr.SIZE) / _SNDRATE / 4 'two channels, it create 16 bit, stereo wav file, one sample use 2 bytes to one channel
  60.  
  61.     H16.fomat = "WAVE"
  62.     H16.sub1 = "fmt "
  63.     H16.subchunksize = 16
  64.     H16.format = 1
  65.     H16.channels = 2
  66.     H16.rate = 44100
  67.     H16.ByteRate = 44100 * 2 * 16 / 8
  68.     H16.Block = 4
  69.     H16.Bits = 16
  70.     H16.subchunk2 = "data"
  71.     H16.lenght = ConvertOffset&&(arr.SIZE)
  72.     IF _FILEEXISTS(file$) THEN KILL file$
  73.     Audio$ = SPACE$(ConvertOffset&&(arr.SIZE))
  74.     _MEMGET arr, arr.OFFSET, Audio$
  75.     OPEN file$ FOR BINARY AS #ch
  76.     PUT #ch, , H16
  77.     PUT #ch, , Audio$
  78.     Audio$ = ""
  79.     CLOSE ch
  80.  
  81.  
  82.  
  83. FUNCTION ConvertOffset&& (value AS _OFFSET)
  84.     DIM m AS _MEM 'Define a memblock
  85.     m = _MEM(value) 'Point it to use value
  86.     $IF 64BIT THEN
  87.         'On 64 bit OSes, an OFFSET is 8 bytes in size.  We can put it directly into an Integer64
  88.         _MEMGET m, m.OFFSET, ConvertOffset&& 'Get the contents of the memblock and put the values there directly into ConvertOffset&&
  89.     $ELSE
  90.         'However, on 32 bit OSes, an OFFSET is only 4 bytes.  We need to put it into a LONG variable first
  91.         _MEMGET m, m.OFFSET, temp& 'Like this
  92.         ConvertOffset&& = temp& 'And then assign that long value to ConvertOffset&&
  93.     $END IF
  94.     _MEMFREE m 'Free the memblock
  95.  

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 #59 on: January 05, 2021, 01:37:14 pm »
Next example. Sound "ping - pong". Take two different songs (to make the effect stand out more) and have the sound sent from the right speaker to the left, with the second song going opposite. Sound position is changed continuously during playback. It's best to listening it on headphones.

Code: QB64: [Select]
  1. DIM left AS _MEM
  2. DIM Right AS _MEM
  3. DIM AudioL AS INTEGER
  4. DIM AudioR AS INTEGER
  5. DIM NewSound AS _MEM
  6. _TITLE "Sound ping - pong"
  7. INPUT "Insert music file name"; snd$
  8. INPUT "Insert music file name2"; snd2$
  9.  
  10.     snd = _SNDOPEN(snd$)
  11.     PRINT "File 1 opened"
  12.     snd2 = _SNDOPEN(snd2$)
  13.     PRINT "File 2 opened"
  14.  
  15.     left = _MEMSOUND(snd, 1)
  16.     Right = _MEMSOUND(snd2, 1)
  17.     IF Right.SIZE > left.SIZE THEN Size = left.SIZE ELSE Size = Right.SIZE
  18.     PRINT "Size: "; Size
  19.     NewSound = _MEMNEW(Size * 2)
  20.     DO UNTIL s& = Size
  21.         _MEMGET left, left.OFFSET + s&, AudioL
  22.         _MEMGET Right, Right.OFFSET + s&, AudioR
  23.         L = (AudioL * ABS(SIN(sinus)) + AudioR * ABS(COS(sinus2))) / 2
  24.         R = (AudioR * ABS(SIN(sinus2)) + AudioL * ABS(COS(sinus))) / 2
  25.         _MEMPUT NewSound, NewSound.OFFSET + t&, L
  26.         _MEMPUT NewSound, NewSound.OFFSET + t& + 2, R
  27.         sinus = sinus + .00001
  28.         sinus2 = sinus + _PI
  29.         s& = s& + 2
  30.         t& = t& + 4
  31.     LOOP
  32.     PRINT "Some file not exists."
  33.     END
  34. PRINT "Saving WAV"
  35. SAVESOUND16S NewSound, "TestEff3.wav"
  36. PRINT "Playing"
  37. _SNDPLAYFILE "TestEff3.wav"
  38. _MEMFREE Right
  39. _MEMFREE NewSound
  40.  
  41.  
  42.  
  43. SUB SAVESOUND16S (arr AS _MEM, file AS STRING)
  44.  
  45.     TYPE head16
  46.         chunk AS STRING * 4 '       4 bytes  (RIFF)
  47.         size AS LONG '              4 bytes  (file size)
  48.         fomat AS STRING * 4 '       4 bytes  (WAVE)
  49.         sub1 AS STRING * 4 '        4 bytes  (fmt )
  50.         subchunksize AS LONG '      4 bytes  (lo / hi), $00000010 for PCM audio
  51.         format AS INTEGER '         2 bytes  (0001 = standard PCM, 0101 = IBM mu-law, 0102 = IBM a-law, 0103 = IBM AVC ADPCM)
  52.         channels AS INTEGER '       2 bytes  (1 = mono, 2 = stereo)
  53.         rate AS LONG '              4 bytes  (sample rate, standard is 44100)
  54.         ByteRate AS LONG '          4 bytes  (= sample rate * number of channels * (bits per channel /8))
  55.         Block AS INTEGER '          2 bytes  (block align = number of channels * bits per sample /8)
  56.         Bits AS INTEGER '           2 bytes  (bits per sample. 8 = 8, 16 = 16)
  57.         subchunk2 AS STRING * 4 '   4 bytes  ("data")  contains begin audio samples
  58.         lenght AS LONG '            4 bytes  Data block size
  59.     END TYPE '                     44 bytes  total
  60.     DIM H16 AS head16
  61.     ch = FREEFILE
  62.  
  63.     H16.chunk = "RIFF"
  64.     H16.size = 44 + ConvertOffset&&(arr.SIZE) / _SNDRATE / 4 'two channels, it create 16 bit, stereo wav file, one sample use 2 bytes to one channel
  65.     H16.fomat = "WAVE"
  66.     H16.sub1 = "fmt "
  67.     H16.subchunksize = 16
  68.     H16.format = 1
  69.     H16.channels = 2
  70.     H16.rate = 44100
  71.     H16.ByteRate = 44100 * 2 * 16 / 8
  72.     H16.Block = 4
  73.     H16.Bits = 16
  74.     H16.subchunk2 = "data"
  75.     H16.lenght = ConvertOffset&&(arr.SIZE)
  76.     ' $END IF
  77.     IF _FILEEXISTS(file$) THEN KILL file$
  78.     Audio$ = SPACE$(ConvertOffset&&(arr.SIZE))
  79.     _MEMGET arr, arr.OFFSET, Audio$
  80.     OPEN file$ FOR BINARY AS #ch
  81.     PUT #ch, , H16
  82.     PUT #ch, , Audio$
  83.     Audio$ = ""
  84.     CLOSE ch
  85.  
  86.  
  87.  
  88. FUNCTION ConvertOffset&& (value AS _OFFSET)
  89.     DIM m AS _MEM 'Define a memblock
  90.     m = _MEM(value) 'Point it to use value
  91.     $IF 64BIT THEN
  92.         'On 64 bit OSes, an OFFSET is 8 bytes in size.  We can put it directly into an Integer64
  93.         _MEMGET m, m.OFFSET, ConvertOffset&& 'Get the contents of the memblock and put the values there directly into ConvertOffset&&
  94.     $ELSE
  95.         'However, on 32 bit OSes, an OFFSET is only 4 bytes.  We need to put it into a LONG variable first
  96.         _MEMGET m, m.OFFSET, temp& 'Like this
  97.         ConvertOffset&& = temp& 'And then assign that long value to ConvertOffset&&
  98.     $END IF
  99.     _MEMFREE m 'Free the memblock
  100.  
  101.