Unbuffered I/O problem

Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

Threaded View
I am playing with sending audio to stereo speakers as part of a bigger
project. At the moment I am just generating a sine wave that moves  
from left to right.

I pipe the data to pacat a sample at a time.

open my $PACAT, '|pacat ...................

  # generate $stuff - This is the angle sample value  
  print $PACAT $stuff; #  

This works but is a little jerky. Wondering if it were a buffering  
problem I tried to make it unbuffered.

open my $PACAT, '|pacat ...................
my $old_fh = select $PACAT; $| = 1; select $old_fh;

while (1)
  # generate $stuff  
  print $PACAT $stuff;

And it just sits there doing nothing - I assume something has blocked.

Dave Saville

Re: Unbuffered I/O problem

Quoted text here. Click to load it

This doesn't "make it unbuffered", it forces the buffer to be flushed
after every output operation. Considering that you're dealing with a
soft realtime problem, you shouldn't be using the implicit buffering
layer to begin with, but syswrite.

Re: Unbuffered I/O problem

Quoted text here. Click to load it

Expanding a little on that (I'm ignoring the 'STREAMS for perl' features
of PerlIO): The whole point of 'stdio-style, implicit buffering' is to
delay actual output until a 'large' amount of output data has been
accumulated in order to increase throughput/ decrease system resource
usage by decreasing the number of system calls necessary to perform the
actual output. This is already of somewhat dubious value in Perl because
Perl-code usually doesn't do 'I/O processing' in 'really small chunks'
aka 'char-by-char/ byte-by-byte' (I also suspect that the overhead of
calling a Perl subroutine is higher than that of a system call) but it
is (at best) totally useless for audio output: This implies that audio
data has to become available at a fixed bit rate/ byte rate. When the
next chunk of it is due, it must not be delayed and 'increasing
throughput' is useless because sending data faster than required only
means something else has to use an internal buffer in order to cope with
that (this is somewhat simplified).

Something similar is true for many other IPC scenarios which are not
supposed to do batch processing of data. And trying to work around that
by 'enabling autoflush' is just totally bizarre: It basically means "Oh
well, the implicit buffering is really harmful in my case, so I'll
always flush the buffer immediately after a totally redundant block
memory copy of my input data was made" --- but if the buffering isn'y
useful, why copy data from application buffer a to 'middleware buffer' b
to begin with?

Re: Unbuffered I/O problem

El 23/03/14 16:42, Dave Saville escribió:
Quoted text here. Click to load it

That could be wrong because, according to the documentation, $|=1
affects to the currently selected I/O, and you do a select after that.

        $|      If set to nonzero, forces a flush right away and after  
every write or print on the currently selected output channel.

Check that, moving the $|=1 to after the relevant last select.

Good luck.

Quoted text here. Click to load it


Re: Unbuffered I/O problem

Quoted text here. Click to load it

perldoc -f select contains this exact example:

    FILEHANDLE may be an expression whose value gives the name of
    the actual filehandle.  Thus:
                   $oldfh = select(STDERR); $| = 1; select($oldfh);

See also select((select(s),$|=1)[0]),


Re: Unbuffered I/O problem

On 03/23/14 08:42, Dave Saville wrote:
Quoted text here. Click to load it

Please post code that compiles and does something.

I'm willing you help you with perl, less willing to do extensive  
speculation about what the "...." and "# generate $stuff" might be  

In any case, it works for me if I remove the ..., balance the quotes,  
and just set my $stuff=random();


Site Timeline