Author Topic: Upcoming feature (v1.5) - _MEMSOUND (Hi, Petr!)  (Read 16422 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 »

Marked as best answer by on Today at 09:18:49 am

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 »
  • Undo Best Answer
  • 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.