Audio-Nama

 view release on metacpan or  search on metacpan

lib/Audio/Nama/IO.pm  view on Meta::CPAN


# we will use the following to map from graph node names
# to IO class names

our %io_class = qw(
	null_in					Audio::Nama::IO::from_null
	null_out				Audio::Nama::IO::to_null
	soundcard_in 			Audio::Nama::IO::from_soundcard
	soundcard_out 			Audio::Nama::IO::to_soundcard
	soundcard_device_in 	Audio::Nama::IO::from_alsa_soundcard_device
	soundcard_device_out 	Audio::Nama::IO::to_alsa_soundcard_device
	wav_in 					Audio::Nama::IO::from_wav
	wav_out 				Audio::Nama::IO::to_wav
	loop_source				Audio::Nama::IO::from_loop
	loop_sink				Audio::Nama::IO::to_loop
	jack_manual_in			Audio::Nama::IO::from_jack_port
	jack_manual_out			Audio::Nama::IO::to_jack_port
	jack_ports_list_in		Audio::Nama::IO::from_jack_port
	jack_ports_list_out		Audio::Nama::IO::to_jack_port
	jack_multi_in			Audio::Nama::IO::from_jack_multi
	jack_multi_out			Audio::Nama::IO::to_jack_multi
	jack_client_in			Audio::Nama::IO::from_jack_multi
	jack_client_out			Audio::Nama::IO::to_jack_multi
	bus_in					Audio::Nama::IO::from_bus
	);
    #bus_out					Audio::Nama::IO::to_bus # 

### class descriptions

# === CLASS Audio::Nama::IO::from_jack_port ===
#
# is triggered by source_type codes: 
#
#  + jack_manual_in 
#  + jack_ports_list_in
#
# For track 'piano', the class creates an input similar to:
#
# -i:jack,,piano_in 
#
# which receives input from JACK node: 
#
#  + Nama:piano_in,
# 
# If piano is stereo, the actual ports will be:
#
#  + Nama:piano_in_1
#  + Nama:piano_in_2

# (CLASS Audio::Nama::IO::to_jack_port is similar)

### class definition

our $AUTOLOAD;

# add underscore to field names so that regular method
# access will go through AUTOLOAD

# we add an underscore to each key 

use Audio::Nama::Object qw(track_ chain_id_ endpoint_ format_ format_template_ width_ ecs_extra_ direction_ device_id_);

sub new {
	my $class = shift;
	my %vals = @_;
	my @args = map{$_."_", $vals{$_}} keys %vals; # add underscore to key 

	# note that we won't check for illegal fields
	# so we can pass any value and allow AUTOLOAD to 
	# check the hash for it.
	
	my $self = bless {@args}, $class;

	my $direction = $self->direction; # input or output

	# join IO objects to graph
	my $name;
	try{ $name  = $self->name }
	catch {};  # we do nothing

	{ no warnings 'uninitialized';
	Audio::Nama::logpkg(__FILE__,__LINE__,'debug',"I belong to track $name\n",
		sub{Audio::Nama::Dumper($self)} );
	}
	
	if($name){
		$by_name{$name}->{$direction} = $self;
	}
	$self
}

# latency stubs
sub capture_latency {
	my $self = shift;
	return unless $self->client;
	Audio::Nama::jack_port_latency('input', $self->client);
}
sub playback_latency {
	my $self = shift;
	return unless $self->client;
	Audio::Nama::jack_port_latency('output', $self->client);
}

# we need at least stubs for subclasses' methods 
# for AUTOLOAD to be happy - so we include

sub client {}

#### JACK related methods

# inherited by all, the methods defined below are called in 
# these classes: 
# 
#		to_jack_multi, 
#		from_jack_multi 
#		to_jack_client
#		from_jack_client
#
# They have no function in other classes.


lib/Audio/Nama/IO.pm  view on Meta::CPAN

{
package Audio::Nama::IO::to_null;
use v5.36;
our $VERSION = 1.0;
our @ISA = 'Audio::Nama::IO';
sub _device_id { 'null' }
}

{
package Audio::Nama::IO::from_rtnull;
use v5.36;
our $VERSION = 1.0;
our @ISA = 'Audio::Nama::IO';
sub _device_id { 'rtnull' }  
}

{
package Audio::Nama::IO::to_rtnull;
use v5.36;
our $VERSION = 1.0;
our @ISA = 'Audio::Nama::IO';
sub _device_id { 'rtnull' }  
}

{
package Audio::Nama::IO::from_wav;
use v5.36;
our $VERSION = 1.0;
our @ISA = 'Audio::Nama::IO';
sub device_id { 
	my $self = shift;
	my @modifiers;
	push @modifiers, $self->playat_output if $self->playat_output;
	push @modifiers, $self->select_output if $self->select_output;
	push @modifiers, split " ", $self->modifiers if $self->modifiers;
	push @modifiers, $self->full_path;
	join(q[,],@modifiers);
}
sub _format { $Audio::Nama::setup->{wav_info}->{$_[0]->full_path}->{format} };
sub ecs_extra { $_[0]->mono_to_stereo}
sub client { 'system' if $jack->{jackd_running} } 
sub ports { 'system:capture_1' }
}
{
package Audio::Nama::IO::to_wav;
use v5.36;
our $VERSION = 1.0;
our @ISA = 'Audio::Nama::IO';
sub device_id { $_[0]->full_path }
sub _format_template { $config->{raw_to_disk_format} } 
}

{
package Audio::Nama::IO::from_loop;
use v5.36;
our $VERSION = 1.0;
our @ISA = 'Audio::Nama::IO';
sub new {
	my $class = shift;
	my %vals = @_;
	$class->SUPER::new( %vals, device_id => "loop,$vals{endpoint}");
}
sub _format { 
	my $self = shift;
	return if $Audio::Nama::config->{opts}->{T}; # XX don't break tests
	Audio::Nama::signal_format($self->format_template, $config->{loop_chain_channel_width});
}
sub _format_template { $config->{cache_to_disk_format} } 
}
{
package Audio::Nama::IO::to_loop;
use v5.36;
our $VERSION = 1.0;
our @ISA = 'Audio::Nama::IO::from_loop';
}

{
package Audio::Nama::IO::from_soundcard;
use v5.36;
our $VERSION = 1.0;
our @ISA = 'Audio::Nama::IO';
sub new {
	shift; # throw away class
	my $class = $io_class{Audio::Nama::IO::soundcard_input_type_string()};
	$class->new(@_);
}
}
{
package Audio::Nama::IO::to_soundcard;
use v5.36;
our $VERSION = 1.0;
our @ISA = 'Audio::Nama::IO';
sub new {
	shift; # throw away class
	my $class = $io_class{Audio::Nama::IO::soundcard_output_type_string()};
	$class->new(@_);
}
}
{
package Audio::Nama::IO::to_jack_multi;
use v5.36;
our $VERSION = 1.0;
our @ISA = 'Audio::Nama::IO';
sub client { 
	my $self = shift;
#  	say "to_jack_multi: target_id: ",$self->target_id;
#  	say "to_jack_multi: rectified target_id: ",Audio::Nama::IO::rectified($self->target_id);
	Audio::Nama::IO::rectified($self->target_id)
}
sub device_id { 
	my $self = shift;
	Audio::Nama::IO::jack_multi_route($self->ports)
}
}

{
package Audio::Nama::IO::from_jack_multi;
use v5.36;
our $VERSION = 1.0;
our @ISA = 'Audio::Nama::IO::to_jack_multi';
sub ecs_extra { $_[0]->mono_to_stereo }

lib/Audio/Nama/IO.pm  view on Meta::CPAN

sub ecs_extra { $_[0]->mono_to_stereo}
sub client { Audio::Nama::IO::rectified($_[0]->source_id) }
}

{
package Audio::Nama::IO::from_alsa_soundcard_device;
use v5.36;
our $VERSION = 1.0;
our @ISA = 'Audio::Nama::IO';
sub ecs_extra { join ' ', $_[0]->rec_route, $_[0]->mono_to_stereo }
sub device_id { $config->{devices}->{$config->{alsa_capture_device}}->{ecasound_id} }
sub input_channel { $_[0]->source_id }
sub rec_route {
	# works for mono/stereo only!
	no warnings qw(uninitialized);
	my $self = shift;
	# needed only if input channel is greater than 1
	return '' if ! $self->input_channel or $self->input_channel == 1; 
	
	my $route = "-chmove:" . $self->input_channel . ",1"; 
	if ( $self->width == 2){
		$route .= " -chmove:" . ($self->input_channel + 1) . ",2";
	}
	return $route;
}
}
{
package Audio::Nama::IO::to_alsa_soundcard_device;
use v5.36;
our $VERSION = 1.0;
our @ISA = 'Audio::Nama::IO';
sub device_id { $config->{devices}->{$config->{alsa_playback_device}}{ecasound_id} }
sub ecs_extra {route($_[0]->width,$_[0]->output_channel) }
sub output_channel { $_[0]->send_id }
sub route2 {
	my ($from, $to, $width) = @_;
}
sub route {
	# routes signals (1..$width) to ($dest..$dest+$width-1 )
	
	my ($width, $dest) = @_;
	return '' if ! $dest or $dest == 1;
	# print "route: width: $width, destination: $dest\n\n";
	my $offset = $dest - 1;
	my $route ;
	for my $c ( map{$width - $_ + 1} 1..$width ) {
		$route .= " -chmove:$c," . ( $c + $offset);
	}
	$route;
}
}
{
package Audio::Nama::IO::from_bus;
use v5.36;
our $VERSION = 1.0;
our @ISA = 'Audio::Nama::IO';
sub new {
	my $class = shift;
	my %vals = @_;
	print "from_bus: ", Audio::Nama::Dumper \%vals;
	#$class->SUPER::new( %vals, device_id => "loop,$vals{endpoint}");
}
}
{
package Audio::Nama::IO::any;
use v5.36;
our $VERSION = 1.0;
our @ISA = 'Audio::Nama::IO';
}


1;
__END__



( run in 0.605 second using v1.01-cache-2.11-cpan-5735350b133 )