Discussion:
[Portaudio] How to set the volume on a PortAudio stream
Brant Sears
2006-08-03 20:00:01 UTC
Permalink
Hi. I have a question. What is the best way to set the volume on a
PortAudio stream? I've read about PortMixer, but I wasn't able to
find its website.

What method is best? Obviously I would like something that works
cross platform.
Eric Wachsmann
2006-08-03 20:21:02 UTC
Permalink
Multiplication can be used to scale a stream. Simply scale each buffer by a
value between 0 and 1.0. Now if you are trying to set the volume on the
device, I don't think you're going to find a cross platform solution for
that.


Eric Wachsmann
FlexRadio Systems
-----Original Message-----
Sent: Thursday, August 03, 2006 1:59 PM
Subject: [Portaudio] How to set the volume on a PortAudio stream
Hi. I have a question. What is the best way to set the volume on a
PortAudio stream? I've read about PortMixer, but I wasn't able to
find its website.
What method is best? Obviously I would like something that works
cross platform.
_______________________________________________
Portaudio mailing list
http://music.columbia.edu/mailman/listinfo/portaudio
Brant Sears
2006-08-03 21:44:01 UTC
Permalink
Post by Eric Wachsmann
Multiplication can be used to scale a stream. Simply scale each buffer by a
value between 0 and 1.0.
OK. Should I be treating the output stream as a pointer to float?
I'm trying the following code:

...write audio data...

if (fReduceVolume) {
int f;
float * fptr = (float*)out;
for (f = 0;f < (outputBytes / sizeof(float));++f) {
fptr[f] *= 0.5;
}
}

I toggle fReduceVolume during playback. When I set it to true, I just
get a lot of distortion and crackling. However, if I use fptr[f] =
0;, then I do get silence. It probably something stupid.
Phil Burk
2006-08-03 22:05:01 UTC
Permalink
Hello Brant,
Post by Brant Sears
OK. Should I be treating the output stream as a pointer to float?
Only if you have defined it as paFloat32 format when you opened the stream.
Otherwise you will just get noise.

If you are already using floats then gain control is easy. But if you are using
short 16 bit data then you can use fixed-point gain control. For example:


long gain = 0x4000; // equivalent to 0.5 in 1.15 fixed point format

long sample = *data++;

long result = (gain * sample) > 15; // fixed point multiple

*out++ = (short) result;

Phil Burk
Mikael Magnusson
2006-08-03 21:02:01 UTC
Permalink
Post by Brant Sears
Hi. I have a question. What is the best way to set the volume on a
PortAudio stream? I've read about PortMixer, but I wasn't able to find
its website.
You find one fork of PortMixer in the iaxclient subversion repository.

Mikael
Eric Wachsmann
2006-08-03 22:11:01 UTC
Permalink
It would depend on what kind of sample format you chose when you opened the
stream. If you are using Float32, then this code should be fine. If you
are using paInt32 (or 24/16/8), then you need to make sure to cast back to
an int (or a short, char, etc) after you do the multiplication. So your
code would look like this:

=============================
if (fReduceVolume) {
int i;
int * out_ch1_ptr = (int*)out;
for (i = 0;i < (outputBytes / sizeof(float));++i) {
fptr[i] = (int)(fptr[i]*0.5);
}
}
=============================

If you are using v19, you can use the frameCount callback parameter instead
of havint the outputBytes / sizeof(float)) in there.
-----Original Message-----
Sent: Thursday, August 03, 2006 3:44 PM
To: Eric Wachsmann
Subject: Re: [Portaudio] How to set the volume on a PortAudio stream
Post by Eric Wachsmann
Multiplication can be used to scale a stream. Simply scale each
buffer by a
value between 0 and 1.0.
OK. Should I be treating the output stream as a pointer to float?
...write audio data...
if (fReduceVolume) {
int f;
float * fptr = (float*)out;
for (f = 0;f < (outputBytes / sizeof(float));++f) {
fptr[f] *= 0.5;
}
}
I toggle fReduceVolume during playback. When I set it to true, I just
get a lot of distortion and crackling. However, if I use fptr[f] =
0;, then I do get silence. It probably something stupid.
Brant Sears
2006-08-03 22:15:02 UTC
Permalink
Post by Eric Wachsmann
It would depend on what kind of sample format you chose when you opened the
stream.
I said it was probably something stupid. I was wrong - it was
something REALLY stupid. I opened the stream as a paInt16. So, I
changed it to a short and it works fine.

Thanks.
Reed Hedges
2006-08-07 14:14:01 UTC
Permalink
Post by Brant Sears
Hi. I have a question. What is the best way to set the volume on a
PortAudio stream? I've read about PortMixer, but I wasn't able to find
its website.
You can get PortMixer from the Audacity source code. Or I can send you some code
(that I modified a bit).

Would PortAudio be willing to host a PortMixer section on its website? It's
really a trivial library, should only need one page and minimal maintainence.

Reed
d***@websurfer.co.za
2006-08-08 07:37:01 UTC
Permalink
Hello there,

Did you modify the PortMixer to be compatible with v19 of PortAudio ?

I personally think that it would be nice to have something like PortMixer
that comes together (or is referenced on the same site) with PortAudio.

Most people would want to be able to change volume in hardware, enable
playthrough, etc.
Post by Reed Hedges
Post by Brant Sears
Hi. I have a question. What is the best way to set the volume on a
PortAudio stream? I've read about PortMixer, but I wasn't able to find
its website.
You can get PortMixer from the Audacity source code. Or I can send you some code
(that I modified a bit).
Would PortAudio be willing to host a PortMixer section on its website? It's
really a trivial library, should only need one page and minimal maintainence.
Reed
_______________________________________________
Portaudio mailing list
http://music.columbia.edu/mailman/listinfo/portaudio
Reed Hedges
2006-08-09 14:43:01 UTC
Permalink
I don't use portmixer, but I know I would be more likely to if it was
included in PA. Does portMixer integrate well with v19? Does it make
sense to merge to projects altogether?
I don't know how it interactis with V19. For WMME it needs a pointer to the PA
stream. For OSS it works independently. There is no ALSA support in the
version I have but maybe it's been added in other forks. I also have mac_core
support but I've never tried it.

Yes, it might make sense to integrate mixer/volume control into PA, if the
various maintainers of the platform implementations don't mind supporting it.
Generally it ought to be pretty easy to implement mixer control, just a few
functions (if we simplify PortMixer API from what it is now).

The API looks like this, it could probably be simplified a lot. Normally all you
care about is 2 levels: output and input. If each is associated with a PA
stream, then you can just create multiple PxMixer* handles for each stream (i.e.
each input/output channel set), then you wouldn't need the functions to select
different input channels etc. RecordLevel and InputGain should be merged into
one, as should the different output volume functions (maybe retaining master
volume to adjust the global system volume).

typedef void PxMixer;

typedef float PxVolume; /* 0.0 (min) --> 1.0 (max) */
typedef float PxBalance; /* -1.0 (left) --> 1.0 (right) */


PxMixer *Px_OpenMixer( void *pa_stream, int i );
void Px_CloseMixer(PxMixer *mixer);

// I added this function, for OSS you can use a NULL pa_stream in
// Px_OpenMixer(): (-reed)
int Px_PortAudioStreamRequired();

// never used these: (-reed)
int Px_GetNumMixers( void *pa_stream );
const char *Px_GetMixerName( void *pa_stream, int i );

// I use these functions a lot: (-reed)
PxVolume Px_GetMasterVolume( PxMixer *mixer );
void Px_SetMasterVolume( PxMixer *mixer, PxVolume volume );

// I use these too. The two concepts (RecordLevel and InputGain) could
// maybe be merged into one. I use RecordLevel if supported, else InputGain.
// (-reed)
int Px_SupportsRecordLevel(PxMixer *mixer);
PxVolume Px_GetRecordLevel(PxMixer *mixer);
void Px_SetRecordLevel(PxMixer *mixer, PxVolume volume);
int Px_SupportsInputGain(PxMixer *mixer);
PxVolume Px_GetInputGain(PxMixer *mixer);
void Px_SetInputGain(PxMixer *mixer, PxVolume volume);

// I don't use these, they seem sort of redundant or maybe platform-specific
// compared to the above functions, and could be merged in with the above
// functions or removed (the user will always have operating system tools to
// do things like set playthrough, and the information about input sources
// can be via PortAudio): (-reed)
PxVolume Px_GetPCMOutputVolume( PxMixer *mixer );
void Px_SetPCMOutputVolume( PxMixer *mixer, PxVolume volume );
int Px_SupportsPCMOutputVolume( PxMixer* mixer ) ;
int Px_GetNumOutputVolumes( PxMixer *mixer );
const char *Px_GetOutputVolumeName( PxMixer *mixer, int i );
PxVolume Px_GetOutputVolume( PxMixer *mixer, int i );
void Px_SetOutputVolume( PxMixer *mixer, int i, PxVolume volume );
int Px_GetNumInputSources( PxMixer *mixer );
const char *Px_GetInputSourceName( PxMixer *mixer, int i);
int Px_GetCurrentInputSource( PxMixer *mixer ); /* may return -1 == none */
void Px_SetCurrentInputSource( PxMixer *mixer, int i );
PxVolume Px_GetInputVolume( PxMixer *mixer );
void Px_SetInputVolume( PxMixer *mixer, PxVolume volume );
int Px_SupportsOutputBalance( PxMixer *mixer );
PxBalance Px_GetOutputBalance( PxMixer *mixer );
void Px_SetOutputBalance( PxMixer *mixer, PxBalance balance );
int Px_SupportsPlaythrough( PxMixer *mixer );
PxVolume Px_GetPlaythrough( PxMixer *mixer );
void Px_SetPlaythrough( PxMixer *mixer, PxVolume volume );


Reed
Reed Hedges
2006-08-09 14:50:01 UTC
Permalink
Post by Reed Hedges
Normally
all you care about is 2 levels: output and input. If each is associated
with a PA stream, then you can just create multiple PxMixer* handles for
each stream (i.e. each input/output channel set), then you wouldn't need
the functions to select different input channels etc.
I should have also said this, though: the fact that mixer control in OSS is
independent of the PA stream is actually really convenient. In my application, I
want to set up UI for controlling the mixer before setting up the PA stream,
because I only open the PA stream when it's required by the application (and
there is some runtime configuration about how to open it that the application
only finds out about after starting up). On Windows (where I use WMME), it
seems to need the PA stream to get a handle on the mixer to open, so I use a
temporary PA stream and then close it after PortMixer opens the mixer.

So maybe, instead, we should remove any dependency on PA form PortMixer, if
possible?

Reed
Ross Bencina
2006-08-09 23:47:01 UTC
Permalink
Hi Guys

First thing first: this has been discussed before and the resolution was to
add host-api specific extensions to PA to export any data that PortMixer
needed so that there wouldn't be any strong coupling between the two
modules. This is the approach that should be taken with V19. Keep in mind
that I only care about V19 so don't misconstrue my comments to be talking
about anything else ;-)

I think it's best to keep PortMixer as a separate project, but if we can
support its development somehow we probably should.
On Windows (where I use WMME), it seems to need the PA stream to get a
handle on the mixer to open, so I use a temporary PA stream and then close
it after PortMixer opens the mixer.
So maybe, instead, we should remove any dependency on PA form PortMixer,
if possible?
I think PortMixer probably needs the handle so it knows which mixer to open
(or perhaps if a stream is open it can't open the mixer without the handle,
just guesses really). So perhaps some kind of dependency needs to exist (at
least as an optional one)... but it could certainly be achieved in a less
intrusive fashion.

I don't have the PortMixer code handy to comment further.

Best wishes

Ross.
Bjorn Roche
2006-08-10 02:07:01 UTC
Permalink
Post by Ross Bencina
Hi Guys
First thing first: this has been discussed before and the resolution was to
add host-api specific extensions to PA to export any data that PortMixer
needed so that there wouldn't be any strong coupling between the two modules.
This is the approach that should be taken with V19. Keep in mind that I only
care about V19 so don't misconstrue my comments to be talking about anything
else ;-)
I think it's best to keep PortMixer as a separate project, but if we can
support its development somehow we probably should.
On Windows (where I use WMME), it seems to need the PA stream to get a
handle on the mixer to open, so I use a temporary PA stream and then close
it after PortMixer opens the mixer.
So maybe, instead, we should remove any dependency on PA form PortMixer, if
possible?
I think PortMixer probably needs the handle so it knows which mixer to open
(or perhaps if a stream is open it can't open the mixer without the handle,
just guesses really). So perhaps some kind of dependency needs to exist (at
least as an optional one)... but it could certainly be achieved in a less
intrusive fashion.
I don't have the PortMixer code handy to comment further.
I agree that PortMixer should be separate for now, if for no other reason
than the fact that PortMixer is behind PortAudio in development.

However, there are a number of projects that seem to be built on or
around PortAudio and they are all maintained by different people on their
own web-sites. There are things like port mixer, language bindings and
probably more. What about adding a "contrib" directory where authors of
these projects can store and work on their source?

Just a thought...


bjorn


-------------
Bjorn Roche
Check out my CD Mastering Software
for Mac OS X : http://www.xowave.com
Ross Bencina
2006-08-10 09:39:01 UTC
Permalink
Post by Bjorn Roche
I agree that PortMixer should be separate for now, if for no other reason
than the fact that PortMixer is behind PortAudio in development.
However, there are a number of projects that seem to be built on or around
PortAudio and they are all maintained by different people on their own
web-sites. There are things like port mixer, language bindings and
probably more. What about adding a "contrib" directory where authors of
these projects can store and work on their source?
We already have a /bindings directory. Currently PaCpp is the only one
there. We can/could include others.. and this hasn't really been discussed
so I'm thinking out loud here.. but for us to include them I think they
would have to conform to some standards:
- close/exact adherence to the PA naming conventions (within reason for the
given language)
- close/exact mapping of the PA API (within language conventions, see pacpp
for an example of a C++ style interface)
- support for most/all of the PA API where it makes sense
- someone who is prepared to maintain the binding

So the binding would need to be that: a binding, not just some kind of
foreign language audio api built with C++, but other than that I think we'd
accept things from the other people...

perhaps putting it into a contrib directory is not such a bad idea though...

thoughs?

Ross.
Leland
2006-08-10 00:27:01 UTC
Permalink
Post by Ross Bencina
Hi Guys
First thing first: this has been discussed before and the resolution was to
add host-api specific extensions to PA to export any data that PortMixer
needed so that there wouldn't be any strong coupling between the two
modules. This is the approach that should be taken with V19. Keep in mind
that I only care about V19 so don't misconstrue my comments to be talking
about anything else ;-)
I think it's best to keep PortMixer as a separate project, but if we can
support its development somehow we probably should.
I would be happy to work up a first run at this if y'all don't mind. I've
already done a bit of research on it and would like to take it further as
the way we (Audacity) do it now (copying bits of portaudio source into
portmixer) is a little tedious.

Portmixer will actually need access to a little more info than just the
device handle. The other main item it will need is which interface is being
used if portmixer is to know which API it must use. Right now it can only
be compiled for one interface (WMMME, DSOUND, ALSA, OSS, ...) at a time.

Leland
Ross Bencina
2006-08-10 11:45:02 UTC
Permalink
Hil Leland
Post by Leland
I would be happy to work up a first run at this if y'all don't mind. I've
already done a bit of research on it and would like to take it further as
the way we (Audacity) do it now (copying bits of portaudio source into
portmixer) is a little tedious.
Great!
Post by Leland
Portmixer will actually need access to a little more info than just the
device handle. The other main item it will need is which interface is being
used if portmixer is to know which API it must use. Right now it can only
be compiled for one interface (WMMME, DSOUND, ALSA, OSS, ...) at a time.
Perhaps we should extend PaStreamInfo to include the deviceIndex then you
could do stuff like:

switch( Pa_GetHostApiInfo( Pa_GetDeviceInfo(
Pa_GetStreamInfo(stream)->deviceIndex )->hostApi )->type ){
case paMME:
//mme stuff
case paDirectSound:
//direct sound stuff
};


...

thoughts?

Ross.
Leland
2006-08-10 14:00:01 UTC
Permalink
Post by Ross Bencina
Perhaps we should extend PaStreamInfo to include the deviceIndex then you
switch( Pa_GetHostApiInfo( Pa_GetDeviceInfo(
Pa_GetStreamInfo(stream)->deviceIndex )->hostApi )->type ){
//mme stuff
//direct sound stuff
};
Exactly, something like that would be perfect. And how do you feel about
breaking out the private stream structs into separate headers so that we
wouldn't have to copy them into the portmixer code?

Leland
Ross Bencina
2006-08-10 14:17:01 UTC
Permalink
Post by Leland
And how do you feel about
breaking out the private stream structs into separate headers so that we
wouldn't have to copy them into the portmixer code?
I think there should be a clean interface that does not expose PortAudio
implementation internals. We already have a convention of host-api specific
header files. To these I would add functions for querying for device handles
or whatever information is needed.

For example, pa_win_wmme.h already provides the info you need (hopefully):
http://www.portaudio.com/docs/v19-doxydocs/pa__win__wmme_8h-source.html

00115 int PaWinMME_GetStreamInputHandleCount( PaStream* stream );
00116
00117
00128 HWAVEIN PaWinMME_GetStreamInputHandle( PaStream* stream, int
handleIndex );
00129
00130
00140 int PaWinMME_GetStreamOutputHandleCount( PaStream* stream );
00141
00142
00153 HWAVEOUT PaWinMME_GetStreamOutputHandle( PaStream* stream, int
handleIndex );

Similar extensions should be written for the other APIs

The advantage here is that there is no dependency on the data layout of
PaStream...

Best wishes

Ross.
David Viens
2006-08-10 14:25:02 UTC
Permalink
Hello

Would it be interesting for you guys to be able to call pa_initialise(int mask)
with a mask that specify which host api you want,
and use 0xffffffff, when you want "all thats available for my platform". (or something
more intelligent)

There are LOTS of bugs in drivers that are due to opening mme, then ds then ASIO's
version of that driver (handle count bugs on lower level api-common dlls).
I think Ross does that in his version in AudioMulch if im not mistaken?

Cheers
--
David Viens, Plogue Art et Technologie Inc,
Montreal. http://www.plogue.com
Ross Bencina
2006-08-11 07:45:01 UTC
Permalink
Post by David Viens
Would it be interesting for you guys to be able to call
pa_initialise(int mask)
with a mask that specify which host api you want,
and use 0xffffffff, when you want "all thats available for my platform".
(or something more intelligent)
There are LOTS of bugs in drivers that are due to opening mme, then ds then ASIO's
version of that driver (handle count bugs on lower level api-common dlls).
I think Ross does that in his version in AudioMulch if im not mistaken?
Hi David

In AudioMulch I reimplemented the host API initialisation iteration to only
initialise certain host APIs depending on user settings.

Your suggestion seems reasonable to me. One way we could implement it is to
make host API Ids a bit-mask rather than a sequential enumeration. This
would limit us to 32 host apis in the future, but I sincerely hope we will
never get to the point of supporting 32 host APIs anyway.

I guess we could do one of 3 things:

1. - break all existing code by adding a parameter to Pa_Initialize()
2. - add a Pa_Initialize2 method (or something) which takes the apis as a
parameter
3. - Pa_SetHostApiInitializationMask() <- call this before calling
Pa_Initialize()

I like 3. Truly portable code shouldn't have to know about host apis at all.

Ross.
David Viens
2006-08-11 13:24:02 UTC
Permalink
Hello
Post by Ross Bencina
1. - break all existing code by adding a parameter to Pa_Initialize()
2. - add a Pa_Initialize2 method (or something) which takes the apis as
a parameter
3. - Pa_SetHostApiInitializationMask() <- call this before calling
Pa_Initialize()
I like 3. Truly portable code shouldn't have to know about host apis at all.
3 sounds indeed very good to me too!

Cheers
--
David Viens, Plogue Art et Technologie Inc.
Montreal. http://www.plogue.com
Leland
2006-08-10 17:25:01 UTC
Permalink
Post by Ross Bencina
Post by Leland
And how do you feel about
breaking out the private stream structs into separate headers so that we
wouldn't have to copy them into the portmixer code?
I think there should be a clean interface that does not expose PortAudio
implementation internals. We already have a convention of host-api specific
header files. To these I would add functions for querying for device handles
or whatever information is needed.
http://www.portaudio.com/docs/v19-doxydocs/pa__win__wmme_8h-source.html
00115 int PaWinMME_GetStreamInputHandleCount( PaStream* stream );
00116
00117
00128 HWAVEIN PaWinMME_GetStreamInputHandle( PaStream* stream, int
handleIndex );
00129
00130
00140 int PaWinMME_GetStreamOutputHandleCount( PaStream* stream );
00141
00142
00153 HWAVEOUT PaWinMME_GetStreamOutputHandle( PaStream* stream, int
handleIndex );
Similar extensions should be written for the other APIs
The advantage here is that there is no dependency on the data layout of
PaStream...
Absolutely. That's even better. I will take that approach.

Thanks,

Leland
Leland
2006-08-27 22:55:01 UTC
Permalink
Hi all,

How does something like this look? If you think it's okay, I will continue
with the other host APIs.

http://www.homerow.net/portaudio/expose.diff

It adds 3 fields to the PaStreamInfo struct:

/** struct version 2 additions */

/** The well known unique identifier of this host API @see
PaHostApiTypeId */
PaHostApiTypeId hostType;

/** The input device for this stream. The value will be a device index
ranging from 0 to (Pa_GetDeviceCount()-1), paNoDevice if no input
device is associated or paUseHostApiSpecificDeviceSpecification if
host device specification is in effect.
*/
PaDeviceIndex inputDevice;

/** The output device for this stream. The value will be a device index
ranging from 0 to (Pa_GetDeviceCount()-1), paNoDevice if no input
device is associated or paUseHostApiSpecificDeviceSpecification if
host device specification is in effect.
*/
PaDeviceIndex outputDevice;

And changes the WMME, DirectSound, and CoreAudio host APIs to populate them.
But, when change PortMixer to take advantage of these, I found that the only
necessary one was hostType since PortMixer needed the host specific device
interface.

It also adds host API specific functions to CoreAudio and Dsound that
provide the necessary device info so PortMixer can get at the correct
device.

The include/pa_mac_core.h header needed to be changed a little more than I
wanted since there were multiply defined symbol problems when included into
PortMixer.

If you want, I can also post a diff to the current PortMixer that adds
multiple host API and DirectSound support. (Taking advantage of the above
changes.)

Leland
Post by Ross Bencina
Post by Leland
And how do you feel about
breaking out the private stream structs into separate headers so that we
wouldn't have to copy them into the portmixer code?
I think there should be a clean interface that does not expose PortAudio
implementation internals. We already have a convention of host-api specific
header files. To these I would add functions for querying for device handles
or whatever information is needed.
http://www.portaudio.com/docs/v19-doxydocs/pa__win__wmme_8h-source.html
00115 int PaWinMME_GetStreamInputHandleCount( PaStream* stream );
00116
00117
00128 HWAVEIN PaWinMME_GetStreamInputHandle( PaStream* stream, int
handleIndex );
00129
00130
00140 int PaWinMME_GetStreamOutputHandleCount( PaStream* stream );
00141
00142
00153 HWAVEOUT PaWinMME_GetStreamOutputHandle( PaStream* stream, int
handleIndex );
Similar extensions should be written for the other APIs
The advantage here is that there is no dependency on the data layout of
PaStream...
Best wishes
Ross.
Ross Bencina
2006-08-29 04:15:02 UTC
Permalink
Hi Leland

I'm having some problems with my email right now so I'm not sure when you'll
get this.. however, some comments:

This all seems to be going in a good direction... thanks a lot for this
Leland, I think it's a great this is being worked on... What do others
think?

Bjorn: see below for some comments re pa_mac_core.h
Post by Leland
How does something like this look? If you think it's okay, I will continue
with the other host APIs.
http://www.homerow.net/portaudio/expose.diff
/** struct version 2 additions */
Since we havn't released V19 yet we might get away with expanding the API
without creating a new struct version.... not sure what other's think about
this.. Another way to make this a binary compatible change would be to add a
Pa_GetStreamHostApiType() function, that wouldn't break the struct layout
(assuming we put hostApiType at the top of the struct.
Post by Leland
PaHostApiTypeId */
PaHostApiTypeId hostType;
This should definitely be called "hostApiType" -- that would be consistent
with "PaHostErrorInfo."


If the following aren't needed don't add them.
Post by Leland
/** The input device for this stream. The value will be a device index
ranging from 0 to (Pa_GetDeviceCount()-1), paNoDevice if no input
device is associated or paUseHostApiSpecificDeviceSpecification if
host device specification is in effect.
*/
PaDeviceIndex inputDevice;
/** The output device for this stream. The value will be a device index
ranging from 0 to (Pa_GetDeviceCount()-1), paNoDevice if no input
device is associated or paUseHostApiSpecificDeviceSpecification if
host device specification is in effect.
*/
PaDeviceIndex outputDevice;
This also raises the question of whether it would be better to embed
PaStreamParameters instances inside PaStreamInfo instead. I argued against
this saying that the client could cache that information for themselves.
Post by Leland
And changes the WMME, DirectSound, and CoreAudio host APIs to populate them.
But, when change PortMixer to take advantage of these, I found that the only
necessary one was hostType since PortMixer needed the host specific device
interface.
Make sure you update pa_skeleton.c to be consistent too.
Post by Leland
The include/pa_mac_core.h header needed to be changed a little more than I
wanted since there were multiply defined symbol problems when included into
PortMixer.
Bjorn: it seems like pa_mac_core.h doesn't follow standard PortAudio naming
conventions, to be consistent with other apis and portaudio.h:

- structs should begin with "PaMacCore" (not "paMacCore")
- functions should begin with PaMacCore_
- flags/constants should begin with paMacCore (no trailing underscore)


Best wishes

Ross.
Bjorn Roche
2006-08-29 13:22:01 UTC
Permalink
Post by Ross Bencina
Bjorn: it seems like pa_mac_core.h doesn't follow standard PortAudio naming
- structs should begin with "PaMacCore" (not "paMacCore")
- functions should begin with PaMacCore_
- flags/constants should begin with paMacCore (no trailing underscore)
Sorry must have been staring at apple code too long. That stuff isn't even
consistant with itself. I don't have time to fix and test it now, so I
made a ticket. I have several major deadlines approching so I probably
won't be good for much of anything 'till after october.

bjorn


-------------
Bjorn Roche

XO Wave
Audio Production and Post-Production Software for Mac OS X
http://www.xowave.com
Robert Bielik
2006-08-29 18:18:02 UTC
Permalink
Hi all,

I'm using the v19 release of portaudio in an application (44.1kHz
stereo) and I have the problem that even with no processing code
whatsoever in the callback, the CPU usage is still about 10 - 15 % (AMD
Athlon 1.2 GHz). I use only MME at the moment. How can the overhead be
so much ?

TIA
/Rob
Chris Parsons
2006-08-29 18:55:01 UTC
Permalink
It could be sample rate conversion in MME. MME through WDM drivers go
through the Windows kernel mixer which usually locks on to the device
at it's preferred sample rate. All MME/DirectSound sounds to the
device go through at that sample rate. So if the Windows kernel mixer
is communicating with your audio device at 48kHz, and you are
communicating with the kernel mixer at 44.1kHz, internal resampling
will occur.

Two things you can try.
Use the ASIO interface if it is available, or use a virtual ASIO
driver that wraps the kernel streaming interface. This will allow you
connect at a native rate without SRC as it avoids the kernel mixer
entirely.
Try another sample rate in an attempt to match the Windows rate.
There's no accurate way to know what this is, so it's not as effective
as the first option. It's usually 48kHz for devices that support
48kHz.

-Chris
Post by Leland
Hi all,
I'm using the v19 release of portaudio in an application (44.1kHz
stereo) and I have the problem that even with no processing code
whatsoever in the callback, the CPU usage is still about 10 - 15 % (AMD
Athlon 1.2 GHz). I use only MME at the moment. How can the overhead be
so much ?
TIA
/Rob
_______________________________________________
Portaudio mailing list
http://music.columbia.edu/mailman/listinfo/portaudio
Bjorn Roche
2006-08-29 13:13:02 UTC
Permalink
Post by Leland
Hi all,
How does something like this look? If you think it's okay, I will continue
with the other host APIs.
http://www.homerow.net/portaudio/expose.diff
I'm afraid I don't have time to look at this in detail at the moment, but
here are som quick observations:

- I don't see wht a number of const variables have been replaced with
#defines.

- I agree with Ross's suggestion about Pa_GetStreamHostApiType()

everything else looks fine at first glance.

bjorn

-------------
Bjorn Roche

XO Wave
Audio Production and Post-Production Software for Mac OS X
http://www.xowave.com
Leland
2006-08-29 04:58:01 UTC
Permalink
Post by Ross Bencina
Post by Leland
/** struct version 2 additions */
Since we havn't released V19 yet we might get away with expanding the API
without creating a new struct version.... not sure what other's think about
this.. Another way to make this a binary compatible change would be to add a
Pa_GetStreamHostApiType() function, that wouldn't break the struct layout
(assuming we put hostApiType at the top of the struct.
I like the Pa_GetStreamHostApiType() idea since it wouldn't be left to the
individual APIs to set or return it. The API type "could" be stored in
PaUtilStreamRepresentation and then the function could just return the value
without calling the API.
Post by Ross Bencina
Post by Leland
PaHostApiTypeId */
PaHostApiTypeId hostType;
This should definitely be called "hostApiType" -- that would be consistent
with "PaHostErrorInfo."
Will do, if hostApiType stays in PaStreamInfo.
Post by Ross Bencina
If the following aren't needed don't add them.
Gotcha.
Post by Ross Bencina
This also raises the question of whether it would be better to embed
PaStreamParameters instances inside PaStreamInfo instead. I argued against
this saying that the client could cache that information for themselves.
Well, as far as PortMixer goes, I haven't needed any info from
PaStreamParameters. I still have a redo of OSS support and new ALSA support
coming, so that may change.

That brings up a question about which portaudio APIs are currently in
working order? I'll add code to each for the PaStreamInfo changes (if
needed), but I won't necessarily be able to add API specific functions to
get at the low-level device...which really isn't all that necessary until
it's truly needed.
Post by Ross Bencina
Post by Leland
And changes the WMME, DirectSound, and CoreAudio host APIs to populate
them.
But, when change PortMixer to take advantage of these, I found that the
only
necessary one was hostType since PortMixer needed the host specific device
interface.
Make sure you update pa_skeleton.c to be consistent too.
Will do, but if we don't add it to PaStreamInfo, then we won't have to
modify any of the hostApis other than to add API specific functions to get
at the devices.

Leland
Leland
2006-08-29 14:17:01 UTC
Permalink
Post by Bjorn Roche
- I don't see wht a number of const variables have been replaced with
#defines.
The linker complained of multiply defined symbols, but I'm suspecting that
it has something to do with the way I'm linking. I just tried it with a
very simple test case and I did not have the same problem. I will attempt
to recreate it this evening in the larger project.

Leland
Bjorn Roche
2006-08-29 22:23:01 UTC
Permalink
Post by Leland
Post by Bjorn Roche
- I don't see wht a number of const variables have been replaced with
#defines.
The linker complained of multiply defined symbols, but I'm suspecting that
it has something to do with the way I'm linking. I just tried it with a
very simple test case and I did not have the same problem. I will attempt
to recreate it this evening in the larger project.
I can see where that would be a problem.... Perhaps we should deal with
that seperately from the PortMixer issue. Feel free to send me a patch or
post a new ticket and I'll take care of it when I can.

bjorn

-------------
Bjorn Roche

XO Wave
Audio Production and Post-Production Software for Mac OS X
http://www.xowave.com
Eric Wachsmann
2006-08-29 18:43:01 UTC
Permalink
Are you looking at the overall CPU% or just the usage for your process?
What size buffers are you using? In my experience, the CPU% can vary
greatly depending on the buffer setting and (probably more significantly)
the driver of your soundcard. Note that on some cards I get better
performance on MME. On others I get better performance on DirectSound. On
nearly all cards that support ASIO, I get the best performance using the
ASIO interface. We have used a program called ASIO4ALL in the past to add
ASIO support to cards that don't have a native ASIO driver. That may be an
option for you.

I hope this helps.


Eric Wachsmann
FlexRadio Systems
-----Original Message-----
Sent: Tuesday, August 29, 2006 12:17 PM
To: Untitled
Subject: [Portaudio] CPU usage
Hi all,
I'm using the v19 release of portaudio in an application (44.1kHz
stereo) and I have the problem that even with no processing code
whatsoever in the callback, the CPU usage is still about 10 - 15 % (AMD
Athlon 1.2 GHz). I use only MME at the moment. How can the overhead be
so much ?
TIA
/Rob
_______________________________________________
Portaudio mailing list
http://music.columbia.edu/mailman/listinfo/portaudio
Robert Bielik
2006-08-29 20:53:01 UTC
Permalink
Sorry, it seems I looked for problems in the wrong place, using AMD
CodeAnalyst I can see that portaudio is not the
cause of my excessive CPU usage. Sorry for bothering y'all!

Thanks for a great audio library!
/R
Post by Eric Wachsmann
Are you looking at the overall CPU% or just the usage for your process?
What size buffers are you using? In my experience, the CPU% can vary
greatly depending on the buffer setting and (probably more significantly)
the driver of your soundcard. Note that on some cards I get better
performance on MME. On others I get better performance on DirectSound. On
nearly all cards that support ASIO, I get the best performance using the
ASIO interface. We have used a program called ASIO4ALL in the past to add
ASIO support to cards that don't have a native ASIO driver. That may be an
option for you.
I hope this helps.
Eric Wachsmann
FlexRadio Systems
-----Original Message-----
Sent: Tuesday, August 29, 2006 12:17 PM
To: Untitled
Subject: [Portaudio] CPU usage
Hi all,
I'm using the v19 release of portaudio in an application (44.1kHz
stereo) and I have the problem that even with no processing code
whatsoever in the callback, the CPU usage is still about 10 - 15 % (AMD
Athlon 1.2 GHz). I use only MME at the moment. How can the overhead be
so much ?
TIA
/Rob
_______________________________________________
Portaudio mailing list
http://music.columbia.edu/mailman/listinfo/portaudio
_______________________________________________
Portaudio mailing list
http://music.columbia.edu/mailman/listinfo/portaudio
Leland
2006-09-02 18:08:01 UTC
Permalink
I've up'd a new version:

http://www.homerow.net/portaudio/expose.diff

It no longer adds any fields to PaStreamInfo and adds the suggested
Pa_GetStreamHostApiType() function instead.

It now includes CoreAudio, Dsound, OSS, and ALSA. I think that's as
probably as far as I'll take it since that's all I can really test.

I took a look at ASIO, but there doesn't seem to be a way to relate the ASIO
device to the Windows/Mac device for controlling.

Leland
Post by Leland
Hi all,
How does something like this look? If you think it's okay, I will continue
with the other host APIs.
http://www.homerow.net/portaudio/expose.diff
/** struct version 2 additions */
PaHostApiTypeId */
PaHostApiTypeId hostType;
/** The input device for this stream. The value will be a device index
ranging from 0 to (Pa_GetDeviceCount()-1), paNoDevice if no input
device is associated or paUseHostApiSpecificDeviceSpecification if
host device specification is in effect.
*/
PaDeviceIndex inputDevice;
/** The output device for this stream. The value will be a device index
ranging from 0 to (Pa_GetDeviceCount()-1), paNoDevice if no input
device is associated or paUseHostApiSpecificDeviceSpecification if
host device specification is in effect.
*/
PaDeviceIndex outputDevice;
And changes the WMME, DirectSound, and CoreAudio host APIs to populate them.
But, when change PortMixer to take advantage of these, I found that the only
necessary one was hostType since PortMixer needed the host specific device
interface.
It also adds host API specific functions to CoreAudio and Dsound that
provide the necessary device info so PortMixer can get at the correct
device.
The include/pa_mac_core.h header needed to be changed a little more than I
wanted since there were multiply defined symbol problems when included into
PortMixer.
If you want, I can also post a diff to the current PortMixer that adds
multiple host API and DirectSound support. (Taking advantage of the above
changes.)
Leland
Post by Ross Bencina
Post by Leland
And how do you feel about
breaking out the private stream structs into separate headers so that we
wouldn't have to copy them into the portmixer code?
I think there should be a clean interface that does not expose PortAudio
implementation internals. We already have a convention of host-api specific
header files. To these I would add functions for querying for device handles
or whatever information is needed.
http://www.portaudio.com/docs/v19-doxydocs/pa__win__wmme_8h-source.html
00115 int PaWinMME_GetStreamInputHandleCount( PaStream* stream );
00116
00117
00128 HWAVEIN PaWinMME_GetStreamInputHandle( PaStream* stream, int
handleIndex );
00129
00130
00140 int PaWinMME_GetStreamOutputHandleCount( PaStream* stream );
00141
00142
00153 HWAVEOUT PaWinMME_GetStreamOutputHandle( PaStream* stream, int
handleIndex );
Similar extensions should be written for the other APIs
The advantage here is that there is no dependency on the data layout of
PaStream...
Best wishes
Ross.
_______________________________________________
Portaudio mailing list
http://music.columbia.edu/mailman/listinfo/portaudio
Bjorn Roche
2006-09-03 00:03:01 UTC
Permalink
Post by Leland
http://www.homerow.net/portaudio/expose.diff
It no longer adds any fields to PaStreamInfo and adds the suggested
Pa_GetStreamHostApiType() function instead.
It now includes CoreAudio, Dsound, OSS, and ALSA. I think that's as
probably as far as I'll take it since that's all I can really test.
I took a look at ASIO, but there doesn't seem to be a way to relate the ASIO
device to the Windows/Mac device for controlling.
Leland,

thanks for this. It looks fine as far as the CoreAudio stuff goes
except that you have PaMacCore_GetStreamInputDevice twice instead of
PaMacCore_GetStreamOutputDevice. Do the need to be defined in
pa_mac_core.h?

The #defines I think are fine, though I prefer if the valies are in
parenthases like this:

#define paMacCore_ConversionQualityMin (0x0100)

since that can reduce errors later (though I don't know what the PA
convesions have to say about it).

bjorn

-------------
Bjorn Roche

XO Wave
Audio Production and Post-Production Software for Mac OS X
http://www.xowave.com
http://www.myspace.com/xowave
http://blog.bjornroche.com
Leland
2006-09-03 02:05:01 UTC
Permalink
Post by Ross Bencina
Post by Leland
http://www.homerow.net/portaudio/expose.diff
It no longer adds any fields to PaStreamInfo and adds the suggested
Pa_GetStreamHostApiType() function instead.
It now includes CoreAudio, Dsound, OSS, and ALSA. I think that's as
probably as far as I'll take it since that's all I can really test.
I took a look at ASIO, but there doesn't seem to be a way to relate the
ASIO
Post by Leland
device to the Windows/Mac device for controlling.
Leland,
thanks for this. It looks fine as far as the CoreAudio stuff goes
except that you have PaMacCore_GetStreamInputDevice twice instead of
PaMacCore_GetStreamOutputDevice. Do the need to be defined in
pa_mac_core.h?
Shame on me. The reason it was wrong was because I had to resolve a conflict
when I pulled down a fresh copy from SVN. I reworked the patch to fit, but
didn't actually run a test compile. And yes, they should be defined in
pa_mac_core.h. Sorry about that...

Leland

Loading...