From bd40855aa0ea0cda169445ee351289579d03ec7b Mon Sep 17 00:00:00 2001 From: Ahmad Khalifa Date: Sat, 22 Feb 2025 17:07:37 +0000 Subject: [PATCH 1/2] examples: Add portaudio sine wave example PortAudio already has a FB header, this adds an example usage to play a sine wave from a buffer. --- examples/Makefile | 3 +- examples/sound/portaudio-sine.bas | 82 +++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 examples/sound/portaudio-sine.bas diff --git a/examples/Makefile b/examples/Makefile index 579b697002..61fd2c8d9f 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -46,7 +46,8 @@ NETWORK := $(subst .bas,,$(wildcard network/*.bas network/*/*.bas \ network/*/*/*.bas)) #OPTIMIZE := $(subst .bas,,$(wildcard OptimizePureAbstractTypes/*.bas)) #REGEX := $(subst .bas,,$(wildcard regex/*/*.bas)) -SOUND := $(subst .bas,,$(wildcard sound/*/*.bas)) +SOUND := $(subst .bas,,$(wildcard sound/*.bas)) \ + $(subst .bas,,$(wildcard sound/*/*.bas)) THREADS := $(subst .bas,,$(wildcard threads/*.bas)) \ threads/timer-lib/libtimer$(DLLEXT) threads/timer-lib/test UNICODE := $(subst .bas,,$(wildcard unicode/*.bas)) diff --git a/examples/sound/portaudio-sine.bas b/examples/sound/portaudio-sine.bas new file mode 100644 index 0000000000..3aa3e9cd8d --- /dev/null +++ b/examples/sound/portaudio-sine.bas @@ -0,0 +1,82 @@ +'' +'' PortAudio Sine wave example +'' +'' Requires libportaudio2 + +#include "portaudio.bi" + +Const Pi as Double = 3.14159265358979323846 +Const SampleRate as Integer = 44100 +Const SineSamples as Integer = SampleRate / 10 + +Type PlayPayload + frequency As Single +End Type + +Function PlayCallback (InputBuff as Const Any Ptr, OutputBuff as Any Ptr, _ + FrameCount as CUlong, TimeInfo as Const PaStreamCallbackTimeInfo Ptr, _ + StatusFlags as PaStreamCallbackFlags, UserData as Any ptr) as Long + + Dim as Long Ptr outBuff = OutputBuff + Dim as PlayPayload Ptr payload = UserData + Dim as Single frequency = payload->frequency + For i as Integer = 0 To FrameCount - 1 + outBuff[i] = CLng(&h7FFFFFFF * 0.5 * Sin(2 * Pi * frequency * i / SampleRate)) + Next + Function = paContinue +End Function + +Sub Play(Frequency as Single, Duration as Single) + Dim as PaError pe + Dim as PaStream Ptr stream + + Dim as PlayPayload payload + payload.frequency = Frequency + + pe = Pa_OpenDefaultStream(@stream, 0, 1, paInt32, SampleRate, SineSamples, @PlayCallback, @payload) + If pe <> paNoError Then + Print "Error: "; Pa_GetErrorText(pe) + End 1 + End If + + Print "Playing "; Frequency; "Hz for "; Duration; "ms" + pe = Pa_StartStream(stream) + If pe <> paNoError Then + Print "Error: "; Pa_GetErrorText(pe) + End 1 + End If + + 'Sleep 2 + Pa_Sleep(Duration) + + pe = Pa_StopStream(stream) + If pe <> paNoError Then + Print "Error: "; Pa_GetErrorText(pe) + End 1 + End If + + pe = Pa_CloseStream(stream) + If pe <> paNoError Then + Print "Error: "; Pa_GetErrorText(pe) + End 1 + End If +End Sub + +Dim as PaError pe +Print "Initialize PortAudio ("; *Pa_GetVersionText(); ")" + +pe = Pa_Initialize() +If pe <> paNoError Then + Print "Error: "; Pa_GetErrorText(pe) + End 1 +End If + +'' Play from A4 (440Hz) for 44ms until A2 (220Hz) for 22ms +For i as Integer = 440 to 220 Step -10 + Play(i, i / 10) +Next + +Print "Shutdown PortAudio" +Pa_Terminate() + +End 0 From 178c3decd86c1a233adccc0566e4e30afb29a548 Mon Sep 17 00:00:00 2001 From: Ahmad Khalifa Date: Mon, 3 Mar 2025 19:39:06 +0000 Subject: [PATCH 2/2] examples: fix portaudio on Win - Change duration to play notes for longer as 44ms duration was too small to play over stream initialisation on Win32 with MM API. - Print portaudio API and device names - Fix callback and error text dereferencing --- examples/sound/portaudio-sine.bas | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/examples/sound/portaudio-sine.bas b/examples/sound/portaudio-sine.bas index 3aa3e9cd8d..c116912868 100644 --- a/examples/sound/portaudio-sine.bas +++ b/examples/sound/portaudio-sine.bas @@ -13,7 +13,7 @@ Type PlayPayload frequency As Single End Type -Function PlayCallback (InputBuff as Const Any Ptr, OutputBuff as Any Ptr, _ +Function PlayCallback cdecl (InputBuff as Const Any Ptr, OutputBuff as Any Ptr, _ FrameCount as CUlong, TimeInfo as Const PaStreamCallbackTimeInfo Ptr, _ StatusFlags as PaStreamCallbackFlags, UserData as Any ptr) as Long @@ -35,14 +35,14 @@ Sub Play(Frequency as Single, Duration as Single) pe = Pa_OpenDefaultStream(@stream, 0, 1, paInt32, SampleRate, SineSamples, @PlayCallback, @payload) If pe <> paNoError Then - Print "Error: "; Pa_GetErrorText(pe) + Print "Error: "; *Pa_GetErrorText(pe) End 1 End If Print "Playing "; Frequency; "Hz for "; Duration; "ms" pe = Pa_StartStream(stream) If pe <> paNoError Then - Print "Error: "; Pa_GetErrorText(pe) + Print "Error: "; *Pa_GetErrorText(pe) End 1 End If @@ -51,13 +51,13 @@ Sub Play(Frequency as Single, Duration as Single) pe = Pa_StopStream(stream) If pe <> paNoError Then - Print "Error: "; Pa_GetErrorText(pe) + Print "Error: "; *Pa_GetErrorText(pe) End 1 End If pe = Pa_CloseStream(stream) If pe <> paNoError Then - Print "Error: "; Pa_GetErrorText(pe) + Print "Error: "; *Pa_GetErrorText(pe) End 1 End If End Sub @@ -67,13 +67,23 @@ Print "Initialize PortAudio ("; *Pa_GetVersionText(); ")" pe = Pa_Initialize() If pe <> paNoError Then - Print "Error: "; Pa_GetErrorText(pe) + Print "Error: "; *Pa_GetErrorText(pe) End 1 End If -'' Play from A4 (440Hz) for 44ms until A2 (220Hz) for 22ms -For i as Integer = 440 to 220 Step -10 - Play(i, i / 10) +Dim defdevice as Integer = Pa_GetDefaultOutputDevice() +If defdevice = paNoDevice Then + Print "Error: no default output device" + End 1 +End If + +Dim devinfo as const PaDeviceInfo Ptr = Pa_GetDeviceInfo(defdevice) +Dim apiinfo as const PaHostApiInfo Ptr = Pa_GetHostApiInfo(Pa_GetDefaultHostApi()) +Print "Using "; *apiinfo->name; " api on default output device: "; *devinfo->name + +'' Play from A4 (440Hz) for 440ms until A3 (220Hz) for 220ms +For i as Integer = 440 to 220 Step -110 + Play(i, i) Next Print "Shutdown PortAudio"