Generating Live Audio

Just starting out? Need help? Post your questions and find answers here.
User avatar
matalog
Enthusiast
Enthusiast
Posts: 301
Joined: Tue Sep 05, 2017 10:07 am

Generating Live Audio

Post by matalog »

I have asked a similar question before, just asking to see if anyone has a little example of Purebasic being used to generate an audio output live - and not saving to an audio file first.

To be honest I really just want to play a sine/square/triangle wave out of the PC speakers with the hope of making some type of PCM later.

I know idle mentioned that they had 97% completed something working after a full day of trying.

Does anyone have anything like this?
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Generating Live Audio

Post by wilbert »

Years ago I have used PortAudio for generating audio.
"miniaudio" can also used for something like this.
I hope Fred will add a PB command in the future for generating audio with a callback to supply the audio samples.
Especially since newer versions of PureBasic already use "miniaudio" internally.
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
idle
Always Here
Always Here
Posts: 5835
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Generating Live Audio

Post by idle »

Portaudio is the easiest I will post links later.
User avatar
Sicro
Enthusiast
Enthusiast
Posts: 559
Joined: Wed Jun 25, 2014 5:25 pm
Location: Germany
Contact:

Re: Generating Live Audio

Post by Sicro »

https://github.com/Dadido3/Audio
German forum thread: https://www.purebasic.fr/german/viewtopic.php?t=28447
There is no thread in this English forum.

I also have it in my code archive:
PB-CodeArchiv-Rebirth/Sound/AudioIN_OUT[Win]/
Image
Why OpenSource should have a license :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (syntax color scheme) :: RegEx-Engine (compiles RegExes to NFA/DFA)
Manjaro Xfce x64 (Main system) :: Windows 10 Home (VirtualBox) :: Newest PureBasic version
dfw1417
User
User
Posts: 16
Joined: Tue Mar 01, 2022 1:45 am

Re: Generating Live Audio

Post by dfw1417 »

:wink: Great Example Located:

Type "Awesome Audio Generator" into the Search.
Experience is what you get when you didn't get what you thought you wanted!
Acer TC895 32gb i5-2.9ghz Win10 1.5tb ssd Asus Gsyn 4k and Vizio 1080 hd monitors.
User avatar
matalog
Enthusiast
Enthusiast
Posts: 301
Joined: Tue Sep 05, 2017 10:07 am

Re: Generating Live Audio

Post by matalog »

dfw1417 wrote: Fri Dec 27, 2024 8:33 pm :wink: Great Example Located:

Type "Awesome Audio Generator" into the Search.
That actually is Awesome! Thanks for sharing it.
User avatar
matalog
Enthusiast
Enthusiast
Posts: 301
Joined: Tue Sep 05, 2017 10:07 am

Re: Generating Live Audio

Post by matalog »

Sicro wrote: Fri Dec 27, 2024 8:32 pm https://github.com/Dadido3/Audio
German forum thread: https://www.purebasic.fr/german/viewtopic.php?t=28447
There is no thread in this English forum.

I also have it in my code archive:
PB-CodeArchiv-Rebirth/Sound/AudioIN_OUT[Win]/
Hi Sicro, I have downloaded your Sound folder and the sine example is pretty awesome too! Thanks for sharing your work.
User avatar
matalog
Enthusiast
Enthusiast
Posts: 301
Joined: Tue Sep 05, 2017 10:07 am

Re: Generating Live Audio

Post by matalog »

matalog wrote: Fri Dec 27, 2024 9:12 pm
Sicro wrote: Fri Dec 27, 2024 8:32 pm https://github.com/Dadido3/Audio
German forum thread: https://www.purebasic.fr/german/viewtopic.php?t=28447
There is no thread in this English forum.

I also have it in my code archive:
PB-CodeArchiv-Rebirth/Sound/AudioIN_OUT[Win]/
Hi Sicro, I have downloaded your Sound folder and the sine example is pretty awesome too! Thanks for sharing your work.
Sicro, I have been amending your Sine example to become an LFO, when I set it to change frequency+1 each step it is smooth but slow. If I Set it to frequency+10 at each step it is faster and smoothish, and when I set it to frequency+100 it is fast but obviously low resolution.

I'm sure that PB can be fast enough to change the frequency speed fast enough, because I'm sure I have got a 16MHz Arduino to do it. What would I need to amend to make an LFO program run correctly to change the Frequency and update the change of Frequency faster?

This is what I have amended your Sine Example to as an example of fast enough, but not enough resolution:

The variable I change is called 'add' and it can be positive or negative to add or take away. It's as if the program will always only change the variable Frequency once every Frame or something, unlike graphics, audio could be required to be update faster.

Code: Select all

EnableExplicit

; ##################################################### Includes ####################################################

XIncludeFile "Includes/AudioOut.pbi"

; ##################################################### Prototypes ##################################################

; ##################################################### Structures ##################################################

; ##################################################### Constants ###################################################

#Samplerate = 44100
Global add=100
; ##################################################### Structures ##################################################

Structure Main
  *AudioOut
  
  Quit.i
EndStructure
Global Main.Main

Structure Main_Window
  ID.i
  
  TrackBar.i [10]
  TextG.i [10]
  Timer.i
EndStructure
Global Main_Window.Main_Window

; ##################################################### Variables ###################################################

Global Frequency.d = 1000
Global Amplitude.d = 0.25

; ##################################################### Procedures ##################################################

Procedure Main_Window_Open()
  Main_Window\ID = OpenWindow(#PB_Any, 0, 0, 800, 200, "AudioOut Example", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered)
  AddWindowTimer(Main_Window\ID,Main_Window\Timer,1)
  If Main_Window\ID
    
    Main_Window\TrackBar[0] = TrackBarGadget(#PB_Any, 10, 10, 780, 30, 0, 2000)
    Main_Window\TextG[0] = TextGadget(#PB_Any,10,40,780,30,"Freq = "+Str(Frequency))
    SetGadgetState(Main_Window\TrackBar[0], Frequency)
    
    Main_Window\TrackBar[1] = TrackBarGadget(#PB_Any, 10, 70, 780, 30, 0, 1000)
    SetGadgetState(Main_Window\TrackBar[1], Amplitude*1000)
    
  EndIf
EndProcedure

Procedure Notifier_CallBack(*AudioOut)
  Protected *Temp, Temp_Size.i
  Static Rotation.d
  
  While AudioOut::GetQueuedBlocks(*AudioOut) <= 3
    
    Temp_Size = AudioOut::GetBufferBlocksize(*AudioOut)
    If Temp_Size > 0
      *Temp = AllocateMemory(Temp_Size)
      
      Define Left.d, Right.d, i
      For i = 0 To Temp_Size / 4 - 1
        Left = Sin(Rotation) * Amplitude
        Right = Sin(Rotation) * Amplitude
        
        PokeW(*Temp + i*4    , Left*32767)
        PokeW(*Temp + i*4 + 2, Right*32767)
        
        Rotation + 2.0*#PI / #Samplerate * Frequency
      Next
      
      AudioOut::Write_Data(Main\AudioOut, *Temp, Temp_Size)
      
      FreeMemory(*Temp)
    EndIf
    
  Wend
EndProcedure

Procedure changefreq()
  Frequency=Frequency+add
  If Frequency>2000 Or Frequency<=0
    add=-add
  EndIf
  EndProcedure

; ##################################################### Initialisation ##############################################

Main_Window_Open()

AudioOut::GetDevices()

ForEach AudioOut::Device()
 ; Debug PeekS(AudioOut::@Device()\szPname)
Next

Main\AudioOut = AudioOut::Initialize(#WAVE_MAPPER, #Samplerate, 2, 16, @Notifier_CallBack())

If Not Main\AudioOut
 ; Debug AudioOut::GetError()
  End
EndIf

Notifier_CallBack(Main\AudioOut)

; ##################################################### Main ########################################################

Repeat
  
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_Timer
        changefreq()
      Case #PB_Event_Gadget
        Select EventGadget()
          Case Main_Window\TrackBar[0]
            Frequency = GetGadgetState(Main_Window\TrackBar[0])
            SetGadgetText(Main_Window\TextG[0],"Freq = "+Str(Frequency))
            
          Case Main_Window\TrackBar[1]
            Amplitude = GetGadgetState(Main_Window\TrackBar[1]) / 1000
            

            
            
        EndSelect
        
      Case #PB_Event_CloseWindow
        Main\Quit = #True
        
      Case 0
        Break
    EndSelect
  ForEver
  
Until Main\Quit

; ##################################################### End #########################################################

AudioOut::Deinitialize(Main\AudioOut)
pjay
Enthusiast
Enthusiast
Posts: 251
Joined: Thu Mar 30, 2006 11:14 am

Re: Generating Live Audio

Post by pjay »

It's not recommended to use event-based timers for any realtime work as they're low priority - Your 1ms timeout request could be only firing every 20ms or so.

Try placing your frequency change code directly into the main callback.
Post Reply