Page 3 of 3

Re: Playing a simple tone with PureBasic and PortAudio

Posted: Wed Nov 02, 2011 10:17 pm
by Trond
I recompiled the dll with support for WASAPI (Windows Vista/7 audio). It seems to work.
http://anotherprophecy.com/system/scrip ... 110326.zip

Edit: Actually it seems not to work... :?

Re: Playing a simple tone with PureBasic and PortAudio

Posted: Thu Nov 03, 2011 6:31 am
by doctornash
Infratec, I only used a textfile to scan through the data to ensure it was in right format and bounds before loading it into the purebasic ‘proof of concept’ app. But you’re right, it is not efficient to do this in practice. Re portaudio support for different audio API’s (including WASAPI support which Trond is working on), I’ve never experienced this luxury before, as till now i have been building functionality not just on directsound, but on a specific VERSION of directsound which happened to be native in winxp, needed to be installed on win2000, but was incompatible with win7. But just so i understand, what is the relationship between the devices which show up as available/installed on a user’s system, with the actual underlying APIs which portaudio supports? Does the act of selecting a particular device, also select the API path through portaudio, or can one programmatically CHOOSE which of the API’s to use :?:

Basically, if you are able to shed some light on the inter-relationship between eg the devices which show up on my win7 acer below (any of these use wasapi?), and all the api’s enumerated in portaudio.pb:

Image

Code: Select all

Enumeration ; PaHostApiTypeId
  #paInDevelopment=0 ; /* use While developing support For a new host API */
  #paDirectSound=1
  #paMME=2
  #paASIO=3
  #paSoundManager=4
  #paCoreAudio=5
  #paOSS=7
  #paALSA=8
  #paAL=9
  #paBeOS=10
  #paWDMKS=11
  #paJACK=12
  #paWASAPI=13
EndEnumeration

Re: Playing a simple tone with PureBasic and PortAudio

Posted: Thu Nov 03, 2011 7:40 am
by wilbert
I think what you might want is this

Code: Select all

XIncludeFile "PortAudio.pb"

Procedure ErrorCheck(err)
  If err <> #paNoError
    MessageRequester("", PeekS(Pa_GetErrorText(err), -1, #PB_Ascii))
    End
  EndIf
EndProcedure

ErrorCheck(Pa_Initialize()) 

numDevices = Pa_GetDeviceCount()

Dim deviceNames.s(numDevices - 1)

For device = 0 To numDevices - 1
  
  *deviceInfo.PaDeviceInfo = Pa_GetDeviceInfo(device)
  
  ioCapable.s = " ["
  If *deviceInfo\maxInputChannels : ioCapable + "I" : EndIf
  If *deviceInfo\maxOutputChannels : ioCapable + "O" : EndIf
  ioCapable + "]"
    
  deviceNames(device) = Str(device) + " " + PeekS(*deviceInfo\name, -1, #PB_Ascii) + ioCapable
  
  Debug deviceNames(device)
  
Next

Debug ""
Debug "Default input : " + deviceNames(Pa_GetDefaultInputDevice())
Debug "Default output : " + deviceNames(Pa_GetDefaultOutputDevice())

Pa_Terminate()
You can just select a specific input or output device and PortAudio takes care of the rest.
As far as I understand you only need to know the host api if you want to use specific functions for that type but that will break cross platform if it isn't available.

Have you looked at this page ?
http://portaudio.com/docs/v19-doxydocs/ ... io_8h.html
It contains a lot of useful information.

Re: Playing a simple tone with PureBasic and PortAudio

Posted: Thu Nov 03, 2011 10:59 am
by Trond
About the devices:
PortAudio uses the device enumeration of each API and then adds all results together in a list. So the ones with (MME) are the devices on your system, as recognized by MME. The ones with (DirectSound) are the devices on your system, as recognized by DirectSound. In most cases, DirectSound and MME will recognize the same devices, but not always (it depends on the drivers). Also, many apis have a special device called default, primary or mapper device, which is just an alias for one of the other devices (so it's easier to know which one to choose).

When using PortAudio, the underlying API is hidden, so you only think about the PortAudio API. The main difference for you is that the different APIs provide different latency.

There is more information on PortAudio.com.

Re: Playing a simple tone with PureBasic and PortAudio

Posted: Thu Nov 03, 2011 9:42 pm
by doctornash
Had a read through the documentation at portaudio.com. Any code tips for playing more than one sound simultaneously? (something the sequencer part of my application needs to do, and which I previously accomplished by defining, loading and playing more than one directsound secondary buffer)? So if one has two filled arrays of sound, does one need to open multiple pa streams to the same device to play them?

Re: Playing a simple tone with PureBasic and PortAudio

Posted: Thu Nov 03, 2011 9:52 pm
by Trond
You need to mix them in the callback. (Mixing two streams just means adding the sample values.)

Re: Playing a simple tone with PureBasic and PortAudio

Posted: Fri Nov 04, 2011 12:00 pm
by doctornash
You need to mix them in the callback. (Mixing two streams just means adding the sample values.)
but the way i implemented my application with directsound is illustrated below. the application has 10 channels, and in each channel i can load a wav file (and process it once loaded) or load a sound synthesized from scratch. each channel is an independent directsound buffer. Once sounds have been thus loaded into the channels, the sequencer part of the application can trigger play of each buffer independently (and if another trigger arrives to play while a sound is still playing, the buffer plays from the start again, which of course is what one wants from a sequencer), and directsound makes available methods on each buffer to allow the user to change the level, pan and frequency of the sound in the buffer 'on the fly' while the sequence is playing. a new sound can be loaded into any buffer or an existing sound in a buffer further processed while the sequence is playing, by the 'synth' part of the application. as you can see, there is no 'mix all the sounds prior and stream through one object' technique here. I was wondering how to do similar with purebasic->portaudio
Image

Re: Playing a simple tone with PureBasic and PortAudio

Posted: Fri Nov 04, 2011 12:31 pm
by Trond
I think you need to program the sound buffer objects yourself and mix and pan them yourself.

See: http://www.portaudio.com/faq.html#two

Re: Playing a simple tone with PureBasic and PortAudio

Posted: Tue Dec 06, 2011 11:35 pm
by audioguy
Has anyone written a Purebasic-compatible Portaudio calling library in C?

I encapsulated a fairly small part of the PortAudio API for a VB6 app in a Windows DLL (written using MSVC 2010) a few months ago, but am looking for the best way to access PortAudio from a cross-platform Windows/Linux PureBasic app.

I'm a raw PureBasic beginner, but a 30-year audio/DSP engineer and developer.

Thanks,
--jim

Re: Playing a simple tone with PureBasic and PortAudio

Posted: Sun Apr 29, 2012 9:55 am
by doctornash
I've successfully used the sound playback techniques discussed here in a couple of non-realtime synth apps I've released (both relied on play of pre-filled sound arrays). Now I'm working on a 'real time' synth. So far, I've got midi notes from the keyboard to dynamically change the Freq value in the below procedure, causing the tone pitch to change according to the note being played, and also to dynamically filter the waveform with sliders while it is playing. What I'd like some help with is how to get the playing waveform to dynamically change amplitude (level). For example, let us say when the waveform starts playing, we want the amplitude of the sound to rise from 0 to 1 over 2 seconds. This means, for every sample t, the instantaneous amplitude would be given by a= t/(#SampleRate*2). How to multiply this factor with Sin(#PI2 * WaveFormFn(Phase)) in the procedure to obtain the desired result?

Code: Select all

ProcedureC PaStreamCallback(*in, *output.Float, frameCount, *timeInfo.PaStreamCallbackTimeInfo, statusFlags, *userData)
  PhaseAdd = Freq / #SampleRate
  While frameCount
    *output\f = Sin(#PI2 * WaveFormFn(Phase))
    Phase + PhaseAdd
    If Phase > 1 : Phase = Phase - 1 : EndIf
    *output + 4
    frameCount - 1 
  Wend
EndProcedure