Audio-Nama

 view release on metacpan or  search on metacpan

bin/nama  view on Meta::CPAN

=head2 Setup commands

=head4 B<limit-run-time> (lr) - Stop recording after the last audio file finishes playing. Can be turned off with limit-run-time_off.

=over 8

limit-run-time [ <float:additional_seconds> ]

=back

=head4 B<limit-run-time-off> (lro) - Disable the recording stop timer.

=over 8

limit-run-time-off 

=back

=head4 B<offset-run> (ofr) - Record/play from a mark, rather than from the start, i.e. 0.0 seconds.

=over 8

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

  what: Re-read the user customizations file 'custom.pl'.
  short: ruc
  parameters: none
limit_run_time:
  type: setup
  what: Stop recording after the last audio file finishes playing. Can be turned off with limit-run-time_off.
  short: lr
  parameters: [ <float:additional_seconds> ]
limit_run_time_off:
  type: setup
  what: Disable the recording stop timer.
  short: lro
  parameters: none
offset_run:
  type: setup
  what: Record/play from a mark, rather than from the start, i.e. 0.0 seconds.
  short: ofr
  parameters: <string:mark_name>
offset_run_off:
  type: setup
  what: Turn back to starting from 0.

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

	Audio::Nama::setup_user_customization(); 1
}
limit_run_time: _limit_run_time sign(?) dd { 
	my $sign = $item{'sign(?)'}->[-1]; 
	$Audio::Nama::setup->{runtime_limit} = $sign
		? eval "$Audio::Nama::setup->{audio_length} $sign $item{dd}"
		: $item{dd};
	Audio::Nama::pager( "Run time limit: ", Audio::Nama::heuristic_time($Audio::Nama::setup->{runtime_limit})); 1;
}
limit_run_time_off: _limit_run_time_off { 
	Audio::Nama::pager( "Run timer disabled");
	Audio::Nama::disable_length_timer();
	1;
}
offset_run: _offset_run markname {
	Audio::Nama::set_offset_run_mark( $item{markname} ); 1
}
offset_run_off: _offset_run_off {
	Audio::Nama::pager( "no run offset.");
	Audio::Nama::disable_offset_run_mode(); 
}
view_waveform: _view_waveform { 

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

    attach MIDI device ``filename'' as device number ``devnum''; ``filename'' is a quoted string. The ``mode'' argument is the name of the mode, it can be on if the following:

        ``ro'' - read-only, for input only devices
        ``wo'' - write-only, for output only devices
        ``rw'' - read and write. 

    If midish is configured to use ALSA (default on Linux systems) then ``filename'' should contain the ALSA sequencer port, as listed by ``aseqdump -l'', (eg. ``28:0'', ``FLUID Synth (qsynth)''). If ``nil'' is given instead of the path, then the por...
ddel devnum
    detach device number ``devnum'' 
dmtcrx devnum
    use device number ``devnum'' as MTC source. In this case, midish will relocate, start and stop according to incoming MTC messages. Midish will generate its clock ticks from MTC, meaning that it will run at the same speed as the MTC device. This i...
dmmctx { devnum1 devnum2 ... }
    Configure the given devices to transmit MMC start, stop and relocate messages. Useful to control MMC-capable audio applications from midish. By default, devices transmit MMC. 
dclktx { devnum1 devnum2 ... }
    Configure the given devices to transmit MIDI clock information (MIDI ticks, MIDI start and MIDI stop events). Useful to synchronize an external sequencer to midish. 
dclkrx devnum
    set device number ``devnum'' to be the master MIDI clock source. It will give midish MIDI ticks, MIDI start and MIDI stop events. This useful to synchronize midish to an external sequencer. If ``devnum'' is ``nil'', then the internal clock will b...
dclkrate devnum ticrate
    set the number of ticks in a whole note that are transmitted to the MIDI device (if dclktx was called for it). Default value is 96 ticks. This is the standard MIDI value and its not recommended to change it. 
dinfo devnum
    Print some information about the MIDI device. 

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

    read and executes the script from a file, ``filename'' is a quoted string. The execution of the script is aborted on error. If the script executes an exit statement, only the script is terminated. 
debug flag val
    set debug-flag ``flag'' to (integer) value ``val''. It's a developer knob. If ``val=0'' the corresponding debug-info are turned off. ``flag'' can be:

        ``filt'' - show events passing through the current filter
        ``mididev'' - show raw MIDI traffic on stderr
        ``mixout'' - show conflicts in the output MIDI merger
        ``norm'' - show events in the input normalizer
        ``pool'' - show pool usage on exit
        ``song'' - show start/stop events
        ``timo'' - show timer internal errors
        ``mem'' - show memory usage 

version
    Display midish version. 
panic
    Cause the sequencer to core-dump, useful to developpers. 
proclist
    Return the list of all user defined procs. 
builtinlist
    Return a list of all builtin commands. 

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

# -------- CacheTrack ------
package Audio::Nama;
use v5.36;
use Storable 'dclone';
use Try::Tiny;
use Audio::Nama::Globals qw(:all);
use Audio::Nama::Util qw(timer start_event stop_event);

# The $args hashref passed among the subroutines in this file
# has these fields:

# track
# additional_time
# processing_time
# original_version
# output_wav
# orig_volume

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

	
	revise_prompt(" "); 

	# we try to set processing time this way
	ecasound_iam("cs-set-length $args->{processing_time}"); 

	ecasound_iam("start");

	# ensure that engine stops at completion time
	$setup->{cache_track_args} = $args;
 	start_event(poll_engine => timer(1, 0.5, \&poll_progress));
}
sub complete_caching {
	logsub((caller(0))[3]);
	my $args = shift;	
	my $name = $args->{track}->name;
	my @files = grep{/$name/} new_files_were_recorded();
	if (@files ){ 
		
		update_cache_map($args);	
		caching_cleanup($args);

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


	remove_temporary_tracks(); # we will generate them again
	$setup->{audio_length} = 0;  
	@io = (); 			# IO object list
	Audio::Nama::IO::initialize();
	$g = Graph->new(); 	
	%inputs = %outputs = %post_input = %pre_output = ();
	%is_ecasound_chain = ();
	@input_chains = @output_chains = @post_input = @pre_output = ();
	undef $chain_setup;
	Audio::Nama::disable_length_timer();
	reset_aux_chain_counter();
	unlink $file->chain_setup;
	$g;
}
sub ecasound_chain_setup { $chain_setup } 
sub is_ecasound_chain { $is_ecasound_chain{$_[0]} }

sub engine_tracks { Audio::Nama::audio_tracks() } 
sub engine_wav_out_tracks {
	grep{$_->rec} engine_tracks();

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

package Audio::Nama::EcasoundRun;
use Role::Tiny;
use v5.36;
our $VERSION = 1.0;
use Audio::Nama::Globals qw(:all);
use Audio::Nama::Log qw(logpkg logsub);
use Audio::Nama::Util qw(timer start_event stop_event);
sub start { 
	package Audio::Nama;
	my $self = shift; 

	$self->valid_setup
		or throw("\nAudio engine is not configured. Cannot start.\n"),return;


	# use gradual unmuting to avoid pop on start
	# 

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

	#

	pager("\n\nStarting at ". current_position()) unless $quiet;
	schedule_wraparound();
	mute();
	$self->start_command;
	$self->{started}++;
	start_midi_transport() if midi_run_ready();

	# limit engine run time if we are in mixdown or edit mode, 
	# or if requested by user, set timer to specified time
	# defaulting to the result of cs-get-length
	limit_processing_time( ($setup->{runtime_limit} || $setup->{audio_length}) + $setup->{extra_run_time}) 
		if mixing_only() 
		or edit_mode() 
		or defined $setup->{runtime_limit};
		# TODO and live processing
 	#$project->{events}->{post_start_unmute} = timer(0.5, 0, sub{unmute()});
	sleeper(0.5);
	unmute();
	sleeper(0.5);
	$ui->set_engine_mode_color_display();
	start_heartbeat();
	engine_status() unless $quiet;
}
sub stop {
	package Audio::Nama;
	my $self = shift;
	if ($self->running())
	{
	# Since the playback position advances slightly during
	# the fade, we restore the position to exactly where the
	# stop command was issued.
	
	my $pos;
	$pos = $self->ecasound_iam('getpos') if ! Audio::Nama::ChainSetup::really_recording();
	mute();
	$self->stop_command;
	disable_length_timer();
	if ( ! $quiet ){
		sleeper(0.5);
		engine_status(current_position(),2,0);
	}
	unmute();
	stop_heartbeat();
	$ui->project_label_configure(-background => $gui->{_old_bg});

	# restore exact position transport stop command was issued
	

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

}
sub engine_status { 
	my ($pos, $before_newlines, $after_newlines) = @_;
	pager("\n" x $before_newlines, engine_is($pos), "\n" x $after_newlines);
}
sub current_position { 
	my $pos = $this_engine->ecasound_iam("getpos"); 
	colonize(int($pos || 0)) 
}
sub start_heartbeat {
 	start_event(poll_engine => timer(0, 1, \&Audio::Nama::heartbeat));
	$ui->setup_playback_indicator();
}
sub stop_heartbeat {
	# the following test avoids double-tripping rec_cleanup()
	# following manual stop
	return unless $project->{events}->{poll_engine};
	stop_event('poll_engine');
	stop_event('update_playback_position_display');
	$ui->reset_engine_mode_color_display();
	rec_cleanup() 

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

		cancel_wraparound();
	} elsif ( $diff < 3 ) { #schedule the move
		wraparound($diff, $start);
	}
}
sub cancel_wraparound {
	stop_event('wraparound');
}
sub limit_processing_time {
	my $length = shift;
 	start_event(processing_time => timer($length, 0, sub { Audio::Nama::stop_transport(); print prompt() }));
}
sub disable_length_timer {
	stop_event('processing_time');
	undef $setup->{runtime_limit};
}
sub wraparound {
	my ($diff, $start) = @_;
	#print "diff: $diff, start: $start\n";
	stop_event('wraparound');
	start_event(wraparound => timer($diff,0, sub{set_position($start)}));
}
sub stop_do_start {
	my ($coderef, $delay) = @_;
	$this_engine->started() ?  _stop_do_start( $coderef, $delay)
					 : $coderef->()

}
sub _stop_do_start {
	my ($coderef, $delay) = @_;
		$this_engine->stop_command();

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

	sleeper(0.2);
	Audio::Nama::pager(q(Press the "P" key three times to mark positions for:
    + play-start
    + record-start
    + record-end

Press "Q" to quit.

Engine will start in 2 seconds.));
	initialize_edit_points();
 	$project->{events}->{set_edit_points} = timer(2, 0, 
	sub {
		reset_input_line();
		detect_keystroke_p();
		ecasound_iam('start');
		Audio::Nama::pager("\n\nEngine is running\n");
		print prompt();
	});
}
sub transfer_edit_points {
	Audio::Nama::throw("Use 'set_edit_points' command to specify edit region"), return

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 

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

}

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 );
		}		

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

		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});

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

	map{ $_->n } @selected_user_tracks;
}

sub flash_ready {

	my $color = engine_mode_color();
	logpkg(__FILE__,__LINE__,'debug', "flash color: $color");
	$ui->length_display(-background => $color);
	$ui->project_label_configure(-background => $color) unless $mode->{preview};
	# TODO update for preview mode
 	start_event(heartbeat =>  timer(5, 0, \&reset_engine_mode_color_display));
}
sub reset_engine_mode_color_display { $ui->project_label_configure(
	-background => $gui->{_nama_palette}->{OffBackground} )
}
sub set_engine_mode_color_display { $ui->project_label_configure(-background => engine_mode_color()) }
sub group_gui {  
	my $ui = shift;
	my $group = $bn{Main}; 
	my $dummy = $gui->{track_frame}->Label(-text => ' '); 
	$gui->{group_label} = 	$gui->{track_frame}->Label(

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

	$gui->{seek_unit}->configure( -text => $gui->{_seek_unit} == 1 ? q(Sec) : q(Min) )
}
sub destroy_marker {
	my $ui = shift;
	my $pos = shift;
	$gui->{marks}->{$pos}->destroy; 
}

sub setup_playback_indicator {
	my $ui = shift;
	start_event(update_playback_position_display => timer(0, 0.1, \&update_indicator));
} 	
sub update_indicator {
	$gui->{wwcanvas}->delete('playback-indicator');
	my $pos = Audio::Nama::ecasound_iam("getpos");
	my $xpos = int( $pos * $config->{waveform_pixels_per_second} );
	$gui->{wwcanvas}->createLine(
			$xpos,0,
			$xpos,$config->{waveform_canvas_y},
			-fill => 'red',
			-width => 1,

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

#
#
#  These routines are executed once on program startup
#
#

package Audio::Nama;
use v5.36; use Carp;
use vars '$VERSION';
use Socket qw(getnameinfo NI_NUMERICHOST) ;
use Audio::Nama::Util qw(timer start_event stop_event);

sub is_test_script { $config->{opts}->{J} }
	# if we are using fake JACK client data, 
	# probably a test script is running

sub apply_test_args {

	push @ARGV, qw(-f /dev/null), # force to use internal namarc

				qw(-t), # set text mode 

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

		$class = 'Audio::Nama::NetEngine';
	}
	$class->new(%args);
}



sub choose_sleep_routine {
	if ( can_load(modules => {'Time::HiRes'=> undef} ) ) 
		 { *sleeper = *finesleep;
			$config->{hires_timer}++; }
	else { *sleeper = *select_sleep }
}
sub finesleep {
	my $sec = shift;
	Time::HiRes::usleep($sec * 1e6);
}
sub select_sleep {
   my $seconds = shift;
   select( undef, undef, undef, $seconds );
}

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

	wav_off
	strip_all
	strip_blank_lines
	strip_comments
	remove_spaces
	expand_tilde
	resolve_path
	dumper
	route_output_channels

	timer
	start_event
	stop_event

) ] );

our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );

our @EXPORT = ();


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

	remote_control
	jack_polling
	command_output
);
my %events = map{ $_ => 1} @events;
sub check_event_type ($type) {
	confess "illegal event type: $type"
	unless $events{$type}
}

sub timer ($delay, $interval, $coderef ) {
	my $timer;
	if ($interval == 0){
		$timer = IO::Async::Timer::Countdown->new(
			delay => $delay,
			on_expire => $coderef, 
		);
	}
	else {
		$timer = IO::Async::Timer::Periodic->new(
			interval => $interval,
			on_tick => $coderef,
		);
	}
	$timer->start;
	$text->{loop}->add($timer);
	$timer
}
sub stop_event ($label) {
	check_event_type($label);
	my $event = $Audio::Nama::project->{events}->{$label};
	$event->stop if defined $event 
}
sub start_event ($label, $async) {
	check_event_type($label);
	$Audio::Nama::project->{events}->{$label} = $async
}



( run in 3.465 seconds using v1.01-cache-2.11-cpan-6c8682c6c89 )