Unbuffered I/O problem

D

Dave Saville

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 ...................

while(1)
{
# 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.
 
R

Rainer Weikusat

Dave Saville said:
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 ...................

while(1)
{
# 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;

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.
 
R

Rainer Weikusat

Rainer Weikusat said:
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.

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?
 
G

gamo

El 23/03/14 16:42, Dave Saville escribió:
open my $PACAT, '|pacat ...................
my $old_fh = select $PACAT; $| = 1; select $old_fh;

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.
 
R

Rainer Weikusat

gamo said:
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.

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]),

http://stackoverflow.com/questions/196754/what-does-selectselects-10-do-in-perl
 
X

Xho Jingleheimerschmidt

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 ...................

while(1)
{
# 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.

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
concealing.

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

Xho
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,479
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top