discuss-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Discuss-gnuradio] Changes to Audio Sink / Source ?


From: Eric Blossom
Subject: Re: [Discuss-gnuradio] Changes to Audio Sink / Source ?
Date: Wed, 30 Nov 2005 14:19:39 -0800
User-agent: Mutt/1.5.6i

On Wed, Nov 30, 2005 at 12:32:13PM -0500, Michael Dickens wrote:
> I have an gr-audio-osx sink which works in the basic sense of working  
> - no frills -, let's call it v0.1 since there are still some changes  
> I need to make before it works well enough to be released into the  
> wild.  In doing so, I've come up with some possible changes to the  
> audio sink & sink API ... thought I'd throw them out & see what  
> others think. - MLD
> 
> A) the API for "new" (e.g. audio_alsa_sink::audio_alsa_sink, audio- 
> osx-sink::audio-osx-sink) varies from type to type.  For OSS and (at  
> least for now) OSX, the parameters are:
>  * int sampling_freq
>  * const std::string dev
> 
> While for ALSA they are:
>  * int sampling_freq
>  * const std::string device_name
>  * double period_time
>  * int nperiods
> 
> Given that the audio source is determined "on the fly" by audio.py,  
> in the order {ALSA, OSS, OSX, WINDOWS}, there is no real way to  
> "know" that your program will be using one API or another.

FWIW, this may change.  Perhaps via a config file.

> Hence the  audio API needs to be fixed for all audio output types.  Here is 
> what  
> I would propose:
>
>  * int sampling_freq
>  * const std::string device_name
>  * double period_time
>  * int nperiods
>  * int &channel_config
>  * int n_buffers
> 
> The extra inputs would be set to 0 by default, so as to provide  
> backwards compatibility for current programs.


One problem with the existing strategy and this one, is that there is
no way to query the capabilities of the card, and then make a decision.

Another strategy may be to just supply the device name to the
constructor, and then provide methods to query the capabilities, and
then some more methods that will set them.

On the other hand, we now have a very nice rational resampler.  This
would allow us to always run the card in its best configuration (most
bits/sample, highest rate), and then resample as required behind the
user's back.  (Hierarchical block implementation needs refactoring to
support dynamically connecting and reconnecting).  Would still need to
query and handle varying numbers of channels.

> The first 2 are the same; the next 2 are same as for ALSA; the last 2  
> are:
> 1* int &channel_config     .... or something similar which describes  
> the type of audio output such as an enum including "mono", "stereo",  
> "5 channel stereo", "5.1 surround", or whatever.  Leaves options for  
> future expansion, and also allows the configuration to setup  
> appropriate buffers for exactly the number of channels (as opposed to  
> worst case).  The "&" is so that the audio_sink can change the value  
> to whatever it can support, and report that back to the calling  
> program (to check, presumedly).

With ALSA and JACK the number of audio channels and their capabilities
is pretty much open ended.  The user provides the "device name" which
maps through a highly indirect path down to either virtual or physical
hardware, the capabilities of which may then be queried.

FYI, non-const pointers are really ugly to wrap in SWIG.  Much easier
to add a method that returns the revised value.

> 2* int n_buffers     .... the number of buffer slots in the list  
> ("ring") before overrun occurs.  Not sure if this is really needed,  
> as there is probably a way to determine this number dynamically.  But  
> I think it would be nice for users to override that computation.

Life would be better if the interface just "did the right thing".
The only reason they're in their now is that it made experimenting from
Python much quicker than having to recompile everything.  The defaults
are reasonable.

> B) in "work" (e.g. audio-osx-sink::work ) for both source and sink,  
> right now the input parameters are:
>  * int noutput_items
>  * gr_vector_const_void_star &input_items,
>  * gr_vector_void_star &output_items
> 
> I would propose to add another parameter:
>  * bool do_block     ... which would tell "work" to block (TRUE) or  
> not (FALSE) until enough data is available to fill the buffer(s) (for  
> source) or to play synchronously (for sink).

No need to change the interface to work.  Just have an additional
instance attribute for those who care.  The do_block attribute is set
for a given source or sink based on a policy decision.  It depends on
the graph the user is building.

> This parameter may be ignored by some OS's (e.g. OSX would ignore
> for the sink, because it turns out to always play asynchronously
> with respect to how GnuRadio operates).

I've failed to make clear the problem with multiple clock domains in
the earlier message.  Just because OSX plays asynchronously, the
problem is not solved.  For example, if the audio clock is is 0.1%
slower than the USRP clock, we will be building a huge backlog of data
headed for the audio sink.  After 100 seconds, we'll be 0.1 second
behind, which is horrible, and only gets worse.  The dont block option
would permit the audio sink to explicity manage the queue to or from
the audio device, such that latency was minimized.

> So, yes, Eric, IMHO the audio API would benefit from allowing it to  
> block or not depending on who wants to control data flow.  All of  
> these could be added with default values, for backward compatibility  
> for current programs ... but allowing future programs the benefit of  
> the new options.

Thanks for your ideas and effort.  I think this is going to be a two
phase solution.  The first one would be to get OSX audio working
with...

  * double sampling_rate (in an ideal world the type would be rational...)
  * const std::string device_name
  * bool do_block

...args to the constructor (possibly ignoring the don't block case),
then in phase II we rework the API for all the audio interfaces.  It's
easy enough to add the do_block arg to all of them now.  We can make
the non blocking case work a bit later.

OS/X question: does CoreAudio resample for you, or are you restricted to
the rates that the card supports natively?  As I recall, most macs
only support a couple of rates.

Eric




reply via email to

[Prev in Thread] Current Thread [Next in Thread]