Audio::ESD - Perl extension for talking to the Enlightened Sound Daemon


Audio-ESD documentation Contained in the Audio-ESD distribution.

Index


Code Index:

NAME

Top

Audio::ESD - Perl extension for talking to the Enlightened Sound Daemon

SYNOPSIS

Top

  use Audio::ESD;
  my $stream = Audio::ESD->play_stream({ # these are the defaults
                                         sample_rate => 16000,
                                         channels => 1,
                                         fallback => 0,
                                         bits_sample => 16,
                                         encoding => 'linear' })
      or die "Failed to open ESD stream: $!\n";
  print $stream $data; # etcetera

DESCRIPTION

Top

This module provides a Perl wrapper around the Enlightened Sound Daemon's client library. Input, output, and monitoring streams are supported, as well as some (but not all) of the control functions. Samples are supported but untested.

AUDIO STREAMS

Top

Audio streams can be opened for playback, recording, monitoring, or filtering. There are separate `constructor' class methods for doing all of these things. All of these methods accept a single optional argument, which is a reference to a hash possibly containing the following stream parameters (defaults are supplied if the parameters are not present):

sample_rate

The sampling rate for audio written to and/or read from the stream, expressed in samples per second. Defaults to 16000

bits_sample

The sample size in bits. Currently acceptable values are 8 and 16. Defaults to 16.

channels

The number of channels (interleaved). Currently acceptable values are 1 and 2. Defaults to 1.

encoding

The audio encoding format used. The only currently acceptable value is 'linear' (which means linear PCM). Maybe someday Esound will support others.

To open a stream for playback, use play_stream:

  my $stream = Audio::ESD->play_stream(\%opts);

This method also supports an extra option, 'fallback'. If this is true, the Esound library will "fall back" to the local audio device if a connection to the ESD server could not be made (or so the documentation says, at least).

To open a stream for recording, use record_stream:

  my $stream = Audio::ESD->record_stream(\%opts);

This method also supports the 'fallback' option.

To open a stream for monitoring (i.e. capturing the mixed output stream from the server), use monitor_stream:

  my $stream = Audio::ESD->monitor_stream(\%opts);

To open a stream for filtering, use filter_stream:

  my $stream = Audio::ESD->filter_stream(\%opts);

Apparently, this allows you read blocks of data from the output stream, do some transformations on them, then write them back, and have ESD play them.

SERVER CONNECTIONS

Top

To open a general-purpose control connection to the ESD server, use the open_sound class method:

  my $esd = Audio::ESD->open_sound($hostname);

If $hostname is undefined, a local ESD will be contacted via a Unix domain socket.

As with the audio streams, you can read and write to this connection as if it were a normal filehandle (since, in fact, that is what it is...) and thus, if you want to take your chances with the "over-the-wire" protocol you are free to do so.

However, you most likely just want to use this connection to access various parameters in the server, and don't worry, there are some methods for that:

send_auth
  $esd->send_auth();

lock
  $esd->lock();

unlock
  $esd->unlock();

standby
  $esd->standby();

resume
  $esd->resume();

sample_cache
  $esd->sample_cache($format, $rate, $length, $name);

confirm_sample_cache
  $esd->confirm_sample_cache();

sample_getid
  my $sample_id = $esd->sample_getid($name);

sample_play
  $esd->sample_play($sample_id);

sample_loop
  $esd->sample_loop($sample_id);

sample_stop
  $esd->sample_stop($sample_id);

sample_free
  $esd->sample_free($sample_id);

set_stream_pan
  $esd->set_stream_pan($stream_id, $left_scale, $right_scale);

set_default_sample_pan
  $esd->set_default_sample($stream_id, $left_scale, $right_scale);

get_latency
  my $latency = $esd->get_latency();

get_standby_mode
  my $standby = $esd->get_standby_mode();

SERVER INFO

Top

get_server_info
  my $server_info = $esd->get_server_info();

get_all_info
  my $info = $esd->get_all_info();

print_server_info
  $server_info->print_server_info();

print_all_info
  $info->print_all_info();

EXPORTABLE CONSTANTS

Top

The following constants can be imported from Audio::ESD. They are mostly useful for the format argument to some functions. You can import all of them with the :standard tag.

	ESD_ADPCM
	ESD_BITS16
	ESD_BITS8
	ESD_BUF_SIZE
	ESD_DEFAULT_PORT
	ESD_DEFAULT_RATE
	ESD_ENDIAN_KEY
	ESD_KEY_LEN
	ESD_LOOP
	ESD_MASK_BITS
	ESD_MASK_CHAN
	ESD_MASK_FUNC
	ESD_MASK_MODE
	ESD_MONITOR
	ESD_MONO
	ESD_NAME_MAX
	ESD_PLAY
	ESD_RECORD
	ESD_SAMPLE
	ESD_STEREO
	ESD_STOP
	ESD_STREAM
	ESD_VOLUME_BASE

BUGS

Top

It probably leaks file descriptors or worse. Lots of stuff is untested and undocumented, and since the Esound API is full of happy surprises it's likely not to work.

AUTHOR

Top

David Huggins-Daines <dhd@cepstral.com>

SEE ALSO

Top

perl(1), esd(1).


Audio-ESD documentation Contained in the Audio-ESD distribution.

# -*- cperl -*-

# Audio::ESD - Perl interface to the Enlightened Sound Daemon
#
# Copyright (c) 2000 Cepstral LLC. All rights Reserved.
#
# This module is free software; you can redistribute it and/or modify
# it under the same terms as Perl itself.
#
# Written by David Huggins-Daines <dhd@cepstral.com>

package Audio::ESD;

use strict;
use Carp;
use IO::Socket;
use vars qw($VERSION @ISA %EXPORT_TAGS @EXPORT_OK $AUTOLOAD);

require Exporter;
require DynaLoader;
require AutoLoader;

@ISA = qw(Exporter DynaLoader IO::Handle);
# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.
@EXPORT_OK = qw(
	ESD_ADPCM
	ESD_BITS16
	ESD_BITS8
	ESD_BUF_SIZE
	ESD_DEFAULT_PORT
	ESD_DEFAULT_RATE
	ESD_ENDIAN_KEY
	ESD_KEY_LEN
	ESD_LOOP
	ESD_MASK_BITS
	ESD_MASK_CHAN
	ESD_MASK_FUNC
	ESD_MASK_MODE
	ESD_MONITOR
	ESD_MONO
	ESD_NAME_MAX
	ESD_PLAY
	ESD_RECORD
	ESD_SAMPLE
	ESD_STEREO
	ESD_STOP
	ESD_STREAM
	ESD_VOLUME_BASE
);
%EXPORT_TAGS = (standard => \@EXPORT_OK);
$VERSION = '0.02';

sub AUTOLOAD {
    # This AUTOLOAD is used to 'autoload' constants from the constant()
    # XS function.  If a constant is not found then control is passed
    # to the AUTOLOAD in AutoLoader.

    my $constname;
    ($constname = $AUTOLOAD) =~ s/.*:://;
    croak "& not defined" if $constname eq 'constant';
    my $val = constant($constname, @_ ? $_[0] : 0);
    if ($! != 0) {
	if ($! =~ /Invalid/) {
	    $AutoLoader::AUTOLOAD = $AUTOLOAD;
	    goto &AutoLoader::AUTOLOAD;
	}
	else {
		croak "Your vendor has not defined Audio::ESD macro $constname";
	}
    }
    no strict 'refs';
    if ($] >= 5.00561) {
	*$AUTOLOAD = sub () { $val };
    } else {
	*$AUTOLOAD = sub { $val };
    }
    goto &$AUTOLOAD;
}

bootstrap Audio::ESD $VERSION;

sub _get_format_bits {
    my ($channels, $bits, $encoding) = @_;

    $channels ||= 1;
    $bits ||= 16;
    $encoding ||= 'linear';

    my $fmt = 0;
    if ($channels == 1) {
	$fmt |= ESD_MONO(); # argh hate kill h2xs die die die
    } elsif ($channels == 2) {
	$fmt |= ESD_STEREO();
    } else {
	croak "Unsupported number of channels $channels\n";
    }

    if ($encoding eq 'linear') {
	if ($bits == 8) {
	    $fmt |= ESD_BITS8();
	} elsif ($bits == 16) {
	    $fmt |= ESD_BITS16();
	} else {
	    croak "Unsupporte sample size $bits\n"
	}
    } else {
	croak "Unsupported encoding $encoding\n";
    }

    return $fmt;
}

sub _make_esd_stream {
    my ($func, $fmt, $opts) = @_;

    $fmt |= _get_format_bits($opts->{channels}, $opts->{bits_sample},
			     $opts->{encoding});
    my $sps = $opts->{sample_rate} || $opts->{sps} || 16000;
    my $fd = $func->($fmt, $sps, $opts->{host}, $opts->{name})
	or return undef;
    return IO::Handle->new_from_fd($fd, "r+");
}

# Bizarro-constructors of various sorts.
#
# I'm not really sure what the bad side effects of reblessing an
# IO::Handle into Audio::ESD are, but it does seem to work okay.

sub play_stream {
    my ($this, $opts) = @_;
    my $class = ref $this || $this;

    $opts ||= {};
    my $func = ($opts->{fallback} ?
		\&esd_play_stream_fallback : \&esd_play_stream);
    my $fh = _make_esd_stream($func, ESD_PLAY(), $opts)
	or return undef;
    bless $fh, $class;
}

sub record_stream {
    my ($this, $opts) = @_;
    my $class = ref $this || $this;

    $opts ||= {};
    my $func = ($opts->{fallback} ?
		\&esd_record_stream_fallback : \&esd_record_stream);
    my $fh = _make_esd_stream($func, ESD_RECORD(), $opts)
	or return undef;
    bless $fh, $class;
}

sub monitor_stream {
    my ($this, $opts) = @_;
    my $class = ref $this || $this;

    $opts ||= {};
    my $fh = _make_esd_stream(\&esd_monitor_stream,
			      ESD_PLAY(), # ???
			      $opts) or return undef;
    bless $fh, $class;
}

sub filter_stream {
    my ($this, $opts) = @_;
    my $class = ref $this || $this;

    $opts ||= {};
    my $fh = _make_esd_stream(\&esd_filter_stream,
			      ESD_PLAY(), # ???
			      $opts) or return undef;
    bless $fh, $class;
}

sub open_server {
    my ($this, $host) = @_;
    my $class = ref $this || $this;

    my $fd = esd_open_sound($host)
	or return undef;
    my $sock = IO::Handle->new_from_fd($fd, "r+")
	or return undef;

    bless $sock, $class;
}

1;
__END__