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 20:00:10 -0800
User-agent: Mutt/1.5.6i

On Wed, Nov 30, 2005 at 09:56:26PM -0500, Michael Dickens wrote:
> On Nov 30, 2005, at 6:20 PM, Eric Blossom wrote:
> >On Wed, Nov 30, 2005 at 05:41:42PM -0500, Michael Dickens wrote:
> >>BTW> In examples/audio, it seems like the "dst" in "multi_...",
> >>"dial_...", and "mono..." generate way too much data.  I don't think
> >>this is a clock mismatch ... I haven't had time to look further;
> >>maybe some who knows these things better than I could take a gander.
> >
> >The sources generate an unbounded amount of data.
> >Got a problem with that?   ;)
> 
> Protected memory is a good thing; my first implementation used an  
> unbounded list, which quickly took up all available memory and  
> crashed the application.  My second implementation bounds the list  
> (FIFO ring) to a default of 20 items,

Q: how big is an item?  A single floating point sample?

> but is a user option when instantiated; it works much better for
> memory, but drops old inputs quickly and thus the output sound can
> be undesirable.  My third implementation will try to force a slower
> data rate by (optionally) blocking if the queue gets too large or
> dropping as before (it not blocking).

In "ok to block mode", you probably want to keep no more than 4
transfers in flight, where a transfer is something on the order of a
millisecond's worth of samples.  I assume there's some way to block
and wait for outstanding transfers to complete.

> >These are cases where the audio sink needs to set the pacing.
> 
> I am still learning about GR's code, so I don't see why the sink  
> needs to set the pace here when the source shouldn't be generating so  
> much data.  

Playing Devil's Advocate, how *would* the source set the pace?  What
if it were reading from a file?  Should the average disk i/o
throughput set the pace?  What would you use as the "master clock"?

GNU Radio is fundamentally a data flow architecture.  Blocks fire when
data is available and there's room for the output.  Thus, a block can
block (sorry about that) if there's no input available, or if there's
no room for it to write its output.  Therefore, flow control occurs
from both ends.

Perfectly legitimate GNU Radio flow graph: 

  src = gr.file_source(gr.sizeof_char, "/boot/vmlinux")
  dst = gr.file_sink(gr.sizeof_char, "/tmp/my-copy-of-vmlinux")
  fg.connect (src, dst)
  fg.run()

Note the complete absence of anything having to do with sample rates.

> Is there no way to have the source cut back on data generation?

Nope.

In the dial_tone example, the audio_sink controls the ultimate rate at
which the pipeline runs.

>  Aren't there interrupts or timers available to go off  
> every 10 ms & the source would generate 1/100 (or 100 ms and 1/10,  
> etc.) of the sample rate's worth of data?

Nope.  It all depends on the data rate through the sources and sinks,
over which the sources and sinks have complete control.

> Yes, it's easier for the  
> source to generate unbounded data, but doesn't that take a big part  
> of the point out of a sampling rate?  The source does seem to take  
> the sampling rate as its first argument ...

The gr.sig_source_f takes a sampling rate just so that you don't have to
specify frequencies normalized to 1 or pi, or whatever.  It doesn't
have anything to do with how often or fast it runs.

> Either way, the sink needs to handle the "too much data" in some  
> fashion (either drop or block).  Thus:
> 
> >do_block
> 
> This will be trivial to add to my code (it's in there but commented  
> out, as it won't compile due to inheritance issues) ... once an  
> "work" API is agreed upon for the parent class "gr_sync_block".

I'm not going to change work's calling sequence for this.  There's no
need.  How would the code that calls work figure out whether to pass
true or false to the work method?  Remember, "ok to block" is an
attribute of the audio source or sink.  You just make it an instance
variable of audio_osx_sink/source.

> So, again, yes, a "bool do_block" or "bool dont_block" seems  
> necessary to have in "work" for both source and sink.  I -think- I  
> can make the necessary changes to the code to allow for this ...  
> should I just go ahead and do it and submit the patches?  Or are we  
> not in enough agreement yet?

You don't have to change any of the existing GNU Radio code.
You can do it all in the new code.  Something vaguely along these lines:

int
audio_osx_sink::work (int noutput_items,
                      gr_vector_const_void_star &input_items,
                      gr_vector_void_star &output_items)
{
  const float  *f0, *f1;
  
  switch (input_items.size ()){

  case 1:               // mono input

    // blah...

    break;

  case 2:               // stereo input

    f0 = (const float *) input_items[0];
    f1 = (const float *) input_items[1];

    for (int i = 0; i < noutput_items; i += d_chunk_size){
      for (int j = 0; j < d_chunk_size; j++){
        // interleave, or whatever is required to meet AudioCore's API
        d_buffer[j] = some function of (f0[j], f1[j]);
      }

      if (ok_to_block())        // private method of audio_osx_sink

        issue_blocking_write_to_audio_core (d_buffer, d_chunk_size,...);

      else {    // not allowed to block

        // Determine (somehow) how much free buffer room there is in AudioCore.

        int free_space_in_audio_core = some_magic_call_to_audio_core();

        // FWIW, I suspect that a total buffer size equivalent to 2 ms
        //  worth of samples would be fine.

        int nsamples_to_write = std::min(d_chunk_size, 
free_space_in_audio_core);
        issue_non_blocking_write_to_audio_core (d_buffer, nsamples_to_write);
      }

      f0 += d_chunk_size;
      f1 += d_chunk_size;
    }
    break;
  }

  return noutput_items;
}




reply via email to

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