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