Unbuffered I/O problem

Discussion in 'Perl Misc' started by Dave Saville, Mar 23, 2014.

  1. Dave Saville

    Dave Saville Guest

    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, Mar 23, 2014
    1. Advertisements

  2. 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.
    Rainer Weikusat, Mar 23, 2014
    1. Advertisements

  3. 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?
    Rainer Weikusat, Mar 23, 2014
  4. Dave Saville

    gamo Guest

    El 23/03/14 16:42, Dave Saville escribió:
    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.
    gamo, Mar 26, 2014
  5. 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]),

    Rainer Weikusat, Mar 26, 2014
  6. 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();

    Xho Jingleheimerschmidt, Mar 27, 2014
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.