Audio-Nama

 view release on metacpan or  search on metacpan

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

{ 
package Audio::Nama::Effect;
use v5.36;
our $VERSION = 1.0;
use List::MoreUtils qw(first_index insert_after_string);
use Carp qw(carp cluck croak confess);
use Data::Dumper::Concise;
use Audio::Nama::Assign qw(json_out);
use Audio::Nama::Log qw(logsub logpkg);
use Audio::Nama::Util qw(timer start_event stop_event);
use Audio::Nama::Globals qw(
					$fx 
					$fx_cache 
					$ui 
					%ti 
					%tn 
					%bn 
					%en
					$config 
					$setup 
					$project
					$this_engine
					$this_track);


use Audio::Nama::Object qw(  
				id
				type
				chain
				class
				params
				params_log
				display
				parent
				owns
				bypassed
				name
				surname 
				predecessor

);
*this_op			= \&Audio::Nama::this_op;
*this_param			= \&Audio::Nama::this_param;
*this_stepsize		= \&Audio::Nama::this_stepsize;
our %by_id;
our $AUTOLOAD;
import_engine_subs();

sub initialize { 

	%by_id = () ;
	
	# effect variables - no object code (yet)
	$fx->{id_counter} = "A"; # autoincrement counter

	# volume settings
	$fx->{muted} = [];
}
sub AUTOLOAD {
	my $self = shift;
	#say "got self: $self", Audio::Nama::Dumper $self;
	die 'not object' unless ref $self;
	# get tail of method call
	my ($call) = $AUTOLOAD =~ /([^:]+)$/;
	# see if this can be satisfied by a field from
	# the corresponding effects registry entry
	$call = 'name' if $call eq 'fxname';
	$self->about->{$call}
}
sub DESTROY {}

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


		$is_track_error++, $result->{track}->{$name}->{orphan_vol} = $track->vol 
			if $track->vol and !  grep { $track->vol eq $_ } @ops;
		$is_track_error++,$result->{track}->{$name}->{orphan_pan} = $track->pan 
			if $track->pan and !  grep { $track->pan eq $_ } @ops;

		# we don't check for orphan latency ops as this is
		# allowed in order to keep constant $op_id over
		# time (slower incrementing of fx counter)
		
		#$is_track_error++,$result->{track}->{$name}->{orphan_latency_op} = $track->latency_op 
		#	if $track->latency_op and !  grep { $track->latency_op eq $_ } @ops;

		# check for undefined op ids 
		
		my @track_undef_op_pos;

		my $i = 0;
		map { defined $_ or push @track_undef_op_pos, $i; $i++ } @ops;
		$is_track_error++,$result->{track}->{$name}->{undef_op_pos}
			= \@track_undef_op_pos if @track_undef_op_pos;

		# remove undefined op ids from list
		
		@ops = grep{ $_ } @ops;

		# check for op ids without corresponding entry 

		my @uninstantiated_op_ids;
		map { fxn($_) or push @uninstantiated_op_ids, $_ } @ops;

		$is_track_error++, $result->{track}->{$name}->{uninstantiated_op_ids} 
			= \@uninstantiated_op_ids if @uninstantiated_op_ids;

		$result->{track}->{$name}->{is_error}++ if $is_track_error;
		$result->{is_error}++ if $is_track_error;
	} Audio::Nama::audio_tracks();

	# check for objects missing fields
	
	my @incomplete_entries = 
		grep { ! fxn($_)->params or ! fxn($_)->type or !  fxn($_)->chain } 
		grep { $_ } keys %Audio::Nama::Effect::by_id;

	if(@incomplete_entries)
	{
		$result->{incomplete_entries} = \@incomplete_entries;
		$result->{is_error}++
	}
	$result;
}

sub fade {
	my $self = shift;
	# parameter starts at one
	my ($param, $from, $to, $seconds) = @_;

	my $id = $self->id;
	# no fade without Time::HiRes
	# no fade unless engine is running
	if ( $this_engine->started() and $config->{hires_timer} )
	{
		my $steps = $seconds * $config->{fade_resolution};
		my $wink  = 1/$config->{fade_resolution};
		my $size = ($to - $from)/$steps;
		logpkg(__FILE__,__LINE__,'debug', "id: $id, param: $param, from: $from, to: $to, seconds: $seconds");
		# first step by step
		for (1..$steps - 1){
			$self->_modify_effect($param, $size, '+');
			sleeper( $wink );
		}		
	}
	$self->_modify_effect($param, $to)
}

sub plan_fade {
	return unless $this_engine->started();
	my $self = shift;
	my %args = @_;
	my $param   = $args{param}   || 1;
	my $from    = $args{from}    || 0;
	my $to	    = $args{to}      || 0;
	my $seconds = $args{seconds} || 1;
	my $in_future 	= $args{in_future};
	my $steps 	= $seconds * $config->{fade_resolution};
	my $wink  	= 1/$config->{fade_resolution};
	my $id 		= $self->id;
	my $size 	= ($to - $from)/$steps;
	logpkg(__FILE__,__LINE__,'debug', "id: $id, param: $param, from: $from, to: $to, seconds: $seconds");
	if ( not $in_future ){
		for (1..$steps - 1){
			$self->_modify_effect($param, $size, '+');
			sleeper( $wink );
		}		
		$self->_modify_effect($param, $to)
	}
	else {
		my $advance = $in_future;
		my $coderef = sub { $self->_modify_effect($param, $size, '+') };
		for (1..$steps - 1){
			$advance += $wink;
			schedule_fade($advance, $coderef)
		}		
		$advance += $wink;
		schedule_fade($advance, sub { $self->_modify_effect($param, $to) } );
		sub schedule_fade {
			my ($after, $sub) = @_;
			start_event("fade_".$setup->{fade_counter}++ => timer( $after, 0, $sub ));
		}
	}
}

sub fadein {
	my $self = shift;
	my $to = shift;
	my $from  = $config->{fade_out_level}->{$self->type};
	$self->_modify_effect(1, $from);
	$self->fade(1, $from, $to, $config->{engine_fade_length_on_start_stop});
}
sub fadeout {
	my $self = shift;
	my $from  =	$self->params->[0];
	my $to	  = $config->{fade_out_level}->{$self->type};
	$self->fade(1, $from, $to, $config->{engine_fade_length_on_start_stop} );
	$self->_modify_effect(1, $config->{mute_level}->{$self->type});
}
sub mute_level {
	my $self = shift;
	my $level = $config->{mute_level}->{$self->type};
	#defined $level or die $self->nameline .  " cannot be muted."
	$level
}
sub fade_out_level {
	my $self = shift;
	$config->{fade_out_level}->{$self->type}
}
sub ecasound_format {
	my $self = shift;
	my $cmd = '-'.$self->code;
	$cmd .= ':'.join ',' ,@{$self->{params}} if $self->{params} and @{$self->{params}} > 0;
	$cmd
}

} # end package Effect

1



( run in 2.652 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )