view release on metacpan or search on metacpan
375376377378379380381382383384385386387388389390391392393394395396397398Marks 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
245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473
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
319320321322323324325326327328329330331332333334335336337338339
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
352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
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
443444445446447448449450451452453454455456457458459460461462463
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
133134135136137138139140141142143144145146147148149150151152153# 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
8687888990919293949596979899100101102103104105106### 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
415416417418419420421422423424425426427428429430431432433434435}
{
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;
lib/Audio/Nama/IO.pm view on Meta::CPAN
573574575576577578579580581582583584585586587588589590591}
{
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
=
@_
;
"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'
;
}
lib/Audio/Nama/Initializations.pm view on Meta::CPAN
747576777879808182838485868788899091929394
$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
93949596979899100101102103104105106107108109110111112113114115116117118119
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
676869707172737475767778798081828384858687
$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
487488489490491492493494495496497498499500501502503504505506507508509510511512513514
$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
{
package
Audio::Nama::Spacer;
t/12_nama.t view on Meta::CPAN
9293949596979899100101102103104105106107108109110111112113114115116117
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
470471472473474475476477478479480481482483484485486487488489490# 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