Audio-Nama

 view release on metacpan or  search on metacpan

bin/nama  view on Meta::CPAN

375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
Marks in Nama are similar to those in other audio editing
software. One limitation is that mark positions are relative
to the beginning of an Ecasound chain setup. If your project
involves a single track, and you will be shortening the
stream by setting a region to play, set any marks you need
I<after> defining the region.
 
=head2 Regions
 
The C<region> command allows you to define endpoints for a
portion of an audio file.  You can then use the C<shift>
command to move the region to the desired time position.
 
If you use named marks as endpoints, the region will change
if the mark's position is adjusted.
 
Each track can have one region definition. To create
multiple regions, the C<new-region> command takes a pair of
marks to create a read-only copy of the current track with
the specified region definition.
 
You can control this region as you would any other other
track, shifting the start time, applying effects, adjusting volume, etc.

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

2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
        1;}
remove_mark: _remove_mark {
        return unless (ref $Audio::Nama::this_mark) =~ /Mark/;
        $Audio::Nama::this_mark->remove;
        1;}
add_mark: _add_mark ident { Audio::Nama::drop_mark $item{ident}; 1}
add_mark: _add_mark {  Audio::Nama::drop_mark(); 1}
next_mark: _next_mark { Audio::Nama::next_mark(); 1}
previous_mark: _previous_mark { Audio::Nama::previous_mark(); 1}
loop: _loop someval(s) {
        my @new_endpoints = @{ $item{"someval(s)"}};
        $Audio::Nama::mode->{loop_enable} = 1;
        @{$Audio::Nama::setup->{loop_endpoints}} = (@new_endpoints, @{$Audio::Nama::setup->{loop_endpoints}});
        @{$Audio::Nama::setup->{loop_endpoints}} = @{$Audio::Nama::setup->{loop_endpoints}}[0,1];
        1;}
noloop: _noloop { $Audio::Nama::mode->{loop_enable} = 0; 1}
name_mark: _name_mark ident {$Audio::Nama::this_mark->set_name( $item{ident}); 1}
list_marks: _list_marks {
        my $i = 0;
        my @lines = map{        my $pre $_->{time} == $Audio::Nama::this_mark->{time} ? q(*) : q();
                                                $pre . join " ", $i++, sprintf("%.1f", $_->{time}), $_->name, "\n"
                } @Audio::Nama::Mark::all;
        my $start = my $end = "undefined";
        push @lines, "now at ". sprintf("%.1f\n", Audio::Nama::ecasound_iam("getpos"));

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

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
        if ( ! $eattr->{chain_id} and ! $vattr->{chain_id} ){
                my $n = $eattr->{n} || $vattr->{n};
                $eattr->{chain_id} = jumper_count($n);
        }
        my @direction = qw(input output);
        map{
                my $direction = shift @direction;
                my $class = Audio::Nama::IO::get_class($_, $direction);
                my $attrib = {%$vattr, %$eattr};
                $attrib->{endpoint} //= $_ if Audio::Nama::Graph::is_a_loop($_);
                logpkg(__FILE__,__LINE__,'debug',"non-track: $_, class: $class, chain_id: $attrib->{chain_id},","device_id: $attrib->{device_id}");
                my $io = $class->new($attrib ? %$attrib : () ) ;
                $g->set_edge_attribute(@$edge, $direction, $io);
                $io;
        } @$edge;
}
 
{
### counter for jumper chains
#

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

352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
        my $track_index = shift;
        my $try1 = $prefix . $track_index;
        $used{$try1}++, return $try1 unless $used{$try1};
        $try1 . $counter++;
}
}
sub dispatch { # creates an IO object from a graph edge
        my $edge = shift;
        return non_track_dispatch($edge) if not grep{ $tn{$_} } @$edge ;
        logpkg(__FILE__,__LINE__,'debug','dispatch: ',join ' -> '@$edge);
        my($name, $endpoint, $direction) = decode_edge($edge);
        logpkg(__FILE__,__LINE__,'debug',"name: $name, endpoint: $endpoint, direction: $direction");
        my $track = $tn{$name};
        my $class = Audio::Nama::IO::get_class( $endpoint, $direction );
                # we need the $direction because there can be
                # edges to and from loop,Main_in
                 
        my @args = (track => $name,
                                endpoint => massaged_endpoint($track, $endpoint, $direction),
                                chain_id => $tn{$name}->n, # default
                                override($name, $edge));   # priority: edge > node
        #say "dispatch class: $class";
        my $io = $class->new(@args);
 
        $g->set_edge_attribute(@$edge, $direction => $io );
        $io
}
sub massaged_endpoint {
        my ($track, $endpoint, $direction) = @_;
        if ( $endpoint =~ /^(loop_in|loop_out)$/ ){
                my $final = ($direction eq 'input' $track->source_id : $track->send_id );
                $final =~ s/^loop,//;
                $final         
        } else { $endpoint }
}
sub decode_edge {
        # assume track-endpoint or endpoint-track
        # return track, endpoint
        my ($a, $b) = @{$_[0]};
        #say "a: $a, b: $b";
        my ($name, $endpoint) = $tn{$a} ? @{$_[0]} : reverse @{$_[0]} ;
        my $direction = $tn{$a} ? 'output' : 'input';
        ($name, $endpoint, $direction)
}
sub override {
        # data from edges has priority over data from vertexes
        # we specify $name, because it could be left or right
        # vertex
        logsub((caller(0))[3]);
        my ($name, $edge) = @_;
        (override_from_vertex($name), override_from_edge($edge))
}
        

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

443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
        set_edit_mode();
        $this_edit->host_alias_track->set(rw => PLAY); # all
        $edit_actions{$action}->();
        request_setup();
 
#   TODO: looping
#       my $is_setup = generate_setup();
#       return unless $is_setup;
#       if ($action !~ /record/){
#               $mode->{loop_enable}++;
#               @{$setup->{loop_endpoints}} = (0,$setup->{audio_length} - 0.05);
#               #  and transport_start()
#       }
#       connect_transport();
}
}
 
sub end_edit_mode       {
 
        # regenerate fades
        

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

133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# from the last fade to the track (or region) end
 
# - If the first fade is a fade-in, the straight
#   segment will be at zero-percent level
#   (otherwise 100%)
#
# - If the last fade is fade-out, the straight
#   segment will be at zero-percent level
#   (otherwise 100%)
 
# although we can get the precise start and endpoints,
# I'm using 0 and $track->shifted_playat_time + track length
 
sub initial_level {
        # return 0, 1 or undef
        # 0: track starts silent
        # 1: track starts at full volume
        my $track_name = shift;
        my @fades = fades($track_name) or return undef;
        # if we fade in we'll hold level zero from beginning
        (scalar @fades and $fades[0]->type eq 'in') ? 0 : 1

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

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
### 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.
        

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

415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
}
 
{
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} }
}
{

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

573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
}
{
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}");
}
}
{
use v5.36;
our $VERSION = 1.0;
our @ISA = 'Audio::Nama::IO';
}

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

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
        $project->{track_comments}
        $project->{bunch}
        $project->{current_op}
        $project->{current_param}
        $project->{current_stepsize}
        $project->{playback_position}
        $project->{sample_rate}
        $project->{waveform}
        @project_effect_chain_data
        $fx->{id_counter}
        $setup->{loop_endpoints}
        $mode->{loop_enable}
        $mode->{mastering}
        $mode->{preview}
        $mode->{midi_transport_sync}
        $gui->{_seek_unit}
        $text->{command_history}
        $text->{command_index}
        $this_track_name
        $this_op
);

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

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
        my $mark = shift;
        Audio::Nama::previous_mark();
}
 
# -- Class Methods
 
sub all { sort { $a->{time} <=> $b->{time} }@all }
 
sub loop_start {
        my @points = sort { $a <=> $b }
        grep{ $_ } map{ mark_time($_)} @{$setup->{loop_endpoints}}[0,1];
        #print "points @points\n";
        $points[0];
}
sub loop_end {
        my @points =sort { $a <=> $b }
                grep{ $_ } map{ mark_time($_)} @{$setup->{loop_endpoints}}[0,1];
        $points[1];
}
sub time_from_tag {
        my $tag = shift;
        $tag or $tag = '';
        #print "tag: $tag\n";
        my $mark;
        if ($tag =~ /\./) { # we assume raw time if decimal
                #print "mark time: ", $tag, $/;
                return $tag;

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

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
        $Audio::Nama::tn{$self->{items}->[$index - 1]};
}
sub list_output {
        my $self = shift;
        my $i;
        join "\n","Sequence $self->{name} clips:",
                map { join " ",
                                ++$i,
                                $Audio::Nama::tn{$_}->n,
                                $_,
                                sprintf("%.3f %.3f", $Audio::Nama::tn{$_}->duration, $Audio::Nama::tn{$_}->endpoint),
                } @{$self->items}
}
sub remove {
        my $sequence = shift;
 
        # delete all clips
        map{$Audio::Nama::tn{$_}->remove } $by_name{$sequence->name}->tracks;
 
        # delete clip array
        delete $sequence->{items};

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

487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
        $self->sequence->clip($self->index - 1)
}
sub duration {
        my $self = shift;
        $self->{duration}
                ? Audio::Nama::Mark::duration_from_tag($self->{duration})
                : $self->is_region
                        ? $self->region_end_time - $self->region_start_time
                        : $self->wav_length;
}
sub endpoint {
        my $self = shift;
        $self->duration + ( $self->predecessor ?  $self->predecessor->endpoint : 0 )
}
sub playat_time {
        my $self = shift;
        my $previous = $self->predecessor;
        $previous ? $previous->endpoint : 0
}
sub rec_status { $_[0]->version ? PLAY : OFF }
 
# we currently are not compatible with offset run mode
# perhaps we can enforce OFF status for clips under
# offset run mode
 
} # end package
{

t/12_nama.t  view on Meta::CPAN

92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
  class: from_wav
  args:
    playat_output: playat,5
    select_output: select,1,4
    modifiers:
    full_path: test_dir/sax_1.wav
  ecs_string: -i:playat,5,select,1,4,test_dir/sax_1.wav
-
  class: from_loop
  args:
    endpoint: sax_in
  ecs_string: -i:loop,sax_in
-
  class: to_loop
  args:
    endpoint: sax_out
  ecs_string: -o:loop,sax_out
-
  class: to_alsa_soundcard_device
  ecs_string: -o:alsa,default
-
  class: from_alsa_soundcard_device
  ecs_string: -i:alsa,default
-
  class: from_soundcard
  args:

t/12_nama.t  view on Meta::CPAN

470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
# The tests are exhaustive, all possible
# combinations are covered.
#
# The numbers indicate time positions.
 
# asterisk (*) indicates that no output is available
# for that specific field
 
{
 
$ENV{NAMA_VERBOSE_TEST_OUTPUT} and diag "Edit mode playat$ENV{NAMA_VERBOSE_TEST_OUTPUT} region endpoints adjustment";
my @tests = split "\n",<<TEST_DATA;
1 12 5 15 4   8  *  *  * 30 out_of_bounds_near region
2 12 5 15 23 26  *  *  * 30 out_of_bounds_far region
3 12 5 15 10 17  2  5 10 30 play_start_during_playat_delay region
4 12 5 15 13 21  0  6 14 30 play_start_within_region region
5 12 5 15 21 26  0 14 19 30 play_start_within_region region
6  0 5 15  5  9  0 10 14 30 play_start_within_region region
7  0 0  0  5  9  0  5  9 30 no_region_play_start_after_playat_delay no_playat
8  2 0  0  5  9  0  3  7 30 no_region_play_start_after_playat_delay
9  6 0  0  5  9  1  0  3 30 no_region_play_start_during_playat_delay



( run in 0.317 second using v1.01-cache-2.11-cpan-55f5a4728d2 )