Author Topic: Sound Recorder with additional tracks?  (Read 2544 times)

0 Members and 1 Guest are viewing this topic.

Offline Richard

  • Seasoned Forum Regular
  • Posts: 364
    • View Profile
Sound Recorder with additional tracks?
« on: June 10, 2021, 05:04:29 am »
Does anyone have a QB64 sound recording program and can it also incorporate a time stamp?

The epoch (say) timestamp should not interfere with the audio but it would be acceptable to have say

time stamp - x seconds audio - time stamp - x seconds audio - time stamp ....

Ideally the program is compact (very few features) and the recording can be played on "free" software or another QB64 program.

Any choice on audio dynamic range (8 bits .... 64 bits)?

Availablity to record two audios, not necessarily stereo, would be a plus.

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Sound Recorder with additional tracks?
« Reply #1 on: June 10, 2021, 12:06:05 pm »
You'd have to learn the MCI commands so you can take advantage of some more advanced features but here is a recording application I made in QB64 using the WINMM DLL. It opens up a wav file and writes to it until you press a key. It saves the recording and then plays it back. The code also uses Fellippe's code showcasing MEMSOUND to show waveforms of audio.

Code: QB64: [Select]
  1.  
  2. _Title "mciSendString Record Test"
  3.  
  4. Dim x, y
  5. StartRecording
  6.  
  7. x = Timer(0.01)
  8.     y = Timer(0.01)
  9.     Cls
  10.     Print "Recording...Press any key to stop"
  11.     Print y - x
  12.     _Display
  13.  
  14. StopRecording
  15. SaveRecording ("test.wav")
  16.  
  17. _Title "Waveform Display"
  18. ShowWaveForm "test.wav"
  19.  
  20.     Function mciSendString& Alias "mciSendStringA" (lpstrCommand As String, lpstrReturnString As String, Byval uReturnLength As _Unsigned Long, Byval hwndCallback As Long)
  21.     Function mciGetErrorString& Alias "mciGetErrorStringA" (ByVal dwError As Long, lpstrBuffer As String, Byval uLength As _Unsigned Long)
  22.  
  23. Sub StartRecording
  24.     Dim As Long a
  25.     a = mciSendString("open new type waveaudio alias capture" + Chr$(0), "", 0, 0)
  26.     If a Then
  27.         Dim As Long x
  28.         Dim As String MCIError
  29.         MCIError = Space$(255)
  30.         x = mciGetErrorString(a, MCIError, Len(MCIError))
  31.         Print MCIError
  32.         End
  33.     Else
  34.         a = mciSendString("set capture time format ms bitspersample 16 channels 2 samplespersec 48000 bytespersec 192000 alignment 4" + Chr$(0), "", 0, 0)
  35.         a = mciSendString("record capture" + Chr$(0), "", 0, 0)
  36.     End If
  37.  
  38. Sub StopRecording
  39.     Dim As Long a
  40.     a = mciSendString("stop capture" + Chr$(0), "", 0, 0)
  41.  
  42. Sub SaveRecording (file As String)
  43.     Dim a As Long
  44.     a = mciSendString("save capture " + Chr$(34) + file + Chr$(34) + Chr$(0), "", 0, 0)
  45.     a = mciSendString("close capture" + Chr$(0), "", 0, 0)
  46.  
  47. Sub ShowWaveForm (file As String)
  48.     Const true = -1, false = 0
  49.  
  50.     Dim theSound As Long, x0 As Long, i As _Offset, j As _Offset
  51.     Dim a%, c~&, k&, trackerHeight As Integer
  52.     Dim y0 As Long, y1 As Long
  53.     Dim mouseDown As _Byte, f$, mouseDownOn As Integer
  54.     Dim sleft As _MEM, sright As _MEM
  55.     Dim stereo As _Byte
  56.     Dim stereoScreen As Long, monoScreen As Long
  57.  
  58.     stereoScreen = _NewImage(882, 400, 32)
  59.     monoScreen = _NewImage(882, 200, 32)
  60.     Screen monoScreen
  61.  
  62.  
  63.     f$ = file
  64.  
  65.     Print "Loading '"; f$; "'..."
  66.     theSound = _SndOpen(f$)
  67.     If theSound = 0 Then Print "Load failed.": End
  68.  
  69.     loaded:
  70.     sleft = _MemSound(theSound, 1)
  71.     sright = _MemSound(theSound, 2)
  72.  
  73.     If sright.SIZE > 0 Then
  74.         Screen stereoScreen
  75.         stereo = true
  76.         y0 = _Height / 4
  77.         y1 = _Height - _Height / 4
  78.     Else
  79.         Screen monoScreen
  80.         stereo = false
  81.         y0 = _Height / 2
  82.     End If
  83.  
  84.     trackerHeight = 50
  85.     _SndPlay theSound
  86.     _SndPause theSound
  87.  
  88.     Do
  89.         While _MouseInput: Wend
  90.         If _MouseButton(1) Then
  91.             If mouseDown = false Then
  92.                 mouseDown = true
  93.                 If _MouseY < _Height - trackerHeight Then
  94.                     mouseDownOn = 1 'plot area
  95.                 Else
  96.                     mouseDownOn = 2 'track area
  97.                 End If
  98.             Else
  99.                 If mouseDownOn = 2 And _SndPlaying(theSound) = 0 Then
  100.                     _SndSetPos theSound, map(_MouseX, 0, _Width, 0, _SndLen(theSound))
  101.                 End If
  102.             End If
  103.         Else
  104.             If mouseDown Then
  105.                 'toggle play
  106.                 If mouseDownOn = 1 Then
  107.                     toggleSoundState theSound
  108.                 ElseIf mouseDownOn = 2 Then
  109.                     _SndSetPos theSound, map(_MouseX, 0, _Width, 0, _SndLen(theSound))
  110.                 End If
  111.                 mouseDown = false
  112.                 mouseDownOn = 0
  113.             End If
  114.         End If
  115.  
  116.         k& = _KeyHit
  117.         If k& = 32 Then toggleSoundState theSound
  118.  
  119.         If _TotalDroppedFiles > 0 Then
  120.             If _FileExists(_DroppedFile$(1)) Then
  121.                 _SndStop theSound
  122.                 _SndClose theSound
  123.                 theSound = 0
  124.                 f$ = _DroppedFile$(1)
  125.                 _PrintString (_Width / 2 - _PrintWidth("Loading...") / 2, _Height / 2 - _FontHeight), "Loading..."
  126.                 _Display
  127.                 theSound = _SndOpen(f$)
  128.                 If theSound Then
  129.                     _FinishDrop
  130.                     GoTo loaded
  131.                 Else
  132.                     Print "Load failed."
  133.                     End
  134.                 End If
  135.             End If
  136.             _FinishDrop
  137.         End If
  138.  
  139.         Dim alpha As Integer
  140.         alpha = 50 'IF _SNDPLAYING(theSound) THEN alpha = 40 ELSE alpha = 20
  141.         Line (0, 0)-(_Width - 1, _Height - 1), _RGB32(0, alpha), BF
  142.         GoSub render
  143.         If _SndPlaying(theSound) = 0 Then _PrintString (_Width / 2 - 16, _Height / 2 - _FontHeight), Chr$(221) + Chr$(222)
  144.  
  145.         _Display
  146.         _Limit 60
  147.     Loop
  148.  
  149.     render:
  150.     Dim o As _Offset
  151.     o = Int((_SndGetPos(theSound)) * _SndRate)
  152.     While o Mod 2 <> 0: o = o + 1: Wend
  153.     i = sleft.OFFSET + o
  154.     If stereo Then j = sright.OFFSET + o
  155.     For x0 = 0 To _Width
  156.         _MemGet sleft, i, a%
  157.         If a% < 0 Then
  158.             c~& = _RGB32(67, 150, 33, map(a%, 0, -32767, 80, 255))
  159.         Else
  160.             c~& = _RGB32(67, 150, 33, map(a%, 0, 32767, 80, 255))
  161.         End If
  162.         Line (x0, y0)-Step(0, map(a%, -32768, 32767, -_Height / 4, _Height / 4)), c~&, BF
  163.  
  164.         If stereo Then
  165.             _MemGet sright, j, a%
  166.             If a% < 0 Then
  167.                 c~& = _RGB32(67, 150, 33, map(a%, 0, -32767, 80, 255))
  168.             Else
  169.                 c~& = _RGB32(67, 150, 33, map(a%, 0, 32767, 80, 255))
  170.             End If
  171.             Line (x0, y1)-Step(0, map(a%, -32768, 32767, -_Height / 4, _Height / 4)), c~&, BF
  172.         End If
  173.  
  174.         i = i + 2
  175.         If stereo Then j = j + 2
  176.         If i + 2 >= sleft.OFFSET + sleft.SIZE Then Exit For
  177.     Next
  178.  
  179.     'tracker:
  180.     Line (0, _Height - trackerHeight / 3)-Step(map(_SndGetPos(theSound), 0, _SndLen(theSound), 0, _Width), -trackerHeight / 3), _RGB32(255, 180), BF
  181.     If _MouseY > _Height - trackerHeight Then
  182.         Line (0, _Height - trackerHeight)-Step(_Width, trackerHeight), _RGB32(255, 30), BF
  183.     End If
  184.  
  185.     Return
  186.  
  187. Function map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  188.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  189.  
  190. Sub toggleSoundState (theSound As Long)
  191.     If _SndPlaying(theSound) Then
  192.         _SndPause theSound
  193.     Else
  194.         Dim i As Integer
  195.         For i = -20 To 20
  196.             Line (_Width / 2 + 20, _Height / 2 - 5)-Step(-40, i)
  197.         Next
  198.         _SndLoop theSound
  199.     End If
« Last Edit: June 16, 2021, 09:21:39 am by SpriggsySpriggs »
Shuwatch!

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Sound Recorder with additional tracks?
« Reply #2 on: June 10, 2021, 01:56:38 pm »
Nice snippet, @SpriggsySpriggs.  Just hit me running that, wow a multi-track recorder app CAN be made in QB64.

- Dav