Audio-Nama
view release on metacpan or search on metacpan
lib/Audio/Nama/TrackIO.pm view on Meta::CPAN
package Audio::Nama::TrackIO;
use Role::Tiny;
use v5.36;
our $VERSION = 1.0;
use Audio::Nama::Globals qw(:all);
use File::Slurp qw(write_file);
use File::Copy;
use Audio::Nama::Util qw(dest_string dest_type join_path freq);
use Audio::Nama::Log qw(logpkg logsub);
sub is_used {
my $track = shift; # Track is used if:
my $bus = $track->bus; #
$track->send_type # It's sending its own signal
or $track->{rw} eq REC # It's recording its own signal
or $track->used_by_another_track
or ($bus and $bus->can('wantme') and $bus->wantme) # A bus needs my signal
}
sub rec_status {
# logsub((caller(0))[3]);
my $track = shift;
my $bus = $track->bus;
return OFF if 0 # ! ($track->engine_group eq $Audio::Nama::this_engine->name)
or $track->{rw} eq OFF
or ! $track->is_used
and ! ($mode->doodle and ! $mode->eager and $setup->{tracks_with_duplicate_inputs}->{$track->name} );
if ($track->{rw} ne PLAY) # e.g. MON or REC
{
return OFF if $track->source_type eq 'jack_client'
and not $jack->{clients}->{$track->{source_id}};
return $track->{rw}
}
my $v = $track->playback_version;
{
no warnings 'uninitialized';
logpkg(__FILE__,__LINE__,'debug', "track: $track->{name}, source: $track->{source_id}, playback version: $v");
}
no warnings 'uninitialized';
return maybe_playback($track, $v);
}
sub maybe_playback { # ordinary sub, not object method
my ($track, $playback_version) = @_;
return PLAY if $track->targets->{$playback_version} and ! $mode->doodle;
return OFF;
}
sub rec_status_display {
my $track = shift;
my $rs = $track->rec_status;
my $status;
$status .= $rs;
$status .= ' v'.$track->current_version if $rs eq REC;
$status
}
### object methods for text-based commands
# Reasonable behavior whether 'source' and 'send' commands
# are issued in JACK or ALSA mode.
sub set_io {
my $track = shift;
my ($direction, $id, $type) = @_;
# $direction: send | source
# unless we are dealing with a simple query,
# by the end of this routine we are going to assign
# the following fields using the values in the
# $type and $id variables:
#
# source_type
# source_id
#
# -OR-
#
# send_type
lib/Audio/Nama/TrackIO.pm view on Meta::CPAN
sub output_object_text { # text for user display
my $track = shift;
$track->object_as_text('send');
}
sub source_status {
my $track = shift;
no warnings 'uninitialized';
return $track->current_wav if $track->play;
my $bus = $bn{$track->source_id};
return join " ", $bus->name, $bus->display_type if $track->source_type eq 'bus';
return "track ".$track->source_id if $track->source_type eq 'track';
return 'jack client '.$track->source_id if $track->source_type eq 'jack_client';
if($track->source_type eq 'soundcard')
{
my $ch = $track->source_id;
my @channels;
push @channels, $_ for $ch .. ($ch + $track->width - 1);
return 'CH '. join '/', @channels
}
"type: $track->{source_type} id: $track->{source_id}"
if $track->{source_id} =~ /\S/
or $track->{source_type} =~ /\S/;
}
sub destination {
my $track = shift;
return if $track->off;
# display logic
# always show the bus
# except for tracks that belongs to the bus null.
# in that case, show the specific source.
#
# for these mix tracks, we use the
# track's own send_type/send_id
my $out;
$out .= (join " ", $track->group, $track->bus->display_type) unless $track->group =~ /^(Null)$/;
my $send_id = $track->send_id;
my $send_type = $track->send_type;
return $out if ! $send_type;
$out .= ', ' if $out;
$out .= dest_string($send_type, $send_id, $track->width);
$out
}
sub set_rec {
my $track = shift;
if (my $t = $track->target){
my $msg = $track->name;
$msg .= qq( is an alias to track "$t");
$msg .= q( in project ") . $track->project . q(")
if $track->project;
$msg .= qq(.\n);
$msg .= "Can't set a track alias to REC.\n";
Audio::Nama::throw($msg);
return;
}
$track->set_rw(REC);
}
sub rw_set {
my $track = shift;
logsub((caller(0))[3]);
my ($bus, $rw) = @_;
$track->set_rec, return if $rw eq REC;
$track->set_rw($rw);
}
sub set_rw {
my ($track, $setting) = @_;
#my $already = $track->rw eq $setting ? " already" : "";
$track->set(rw => $setting);
my $status = $track->rec_status();
Audio::Nama::pagers("Track ",$track->name, " set to $setting",
($status ne $setting ? ", but current status is $status" : ""));
}
sub has_insert { $_[0]->prefader_insert or $_[0]->postfader_insert }
sub prefader_insert { Audio::Nama::Insert::get_id($_[0],'pre') }
sub postfader_insert { Audio::Nama::Insert::get_id($_[0],'post') }
sub inserts { [ # return array ref
map{ $Audio::Nama::Insert::by_index{$_} }grep{$_}
map{ Audio::Nama::Insert::get_id($_[0],$_)} qw(pre post)
]
}
sub soundcard_channel { $_[0] // 1 }
sub import_audio {
my $track = shift;
Audio::Nama::throw($track->name.": Cannot import audio to system track"),
return if ! $track->is_user_track;
my ($path, $frequency) = @_;
$path = Audio::Nama::expand_tilde($path);
my $version = $track->last + 1;
if ( ! -r $path ){
Audio::Nama::throw("$path: non-existent or unreadable file. No action.\n");
return;
}
my ($depth,$width,$freq) = split ',', Audio::Nama::wav_format($path);
Audio::Nama::pager_newline("format: ", Audio::Nama::wav_format($path));
$frequency ||= $freq;
if ( ! $frequency ){
Audio::Nama::throw("Cannot detect sample rate of $path. Skipping.",
"Maybe 'import_audio <path> <frequency>' will help.");
return
}
my $desired_frequency = freq( $config->{raw_to_disk_format} );
my $destination = join_path(Audio::Nama::this_wav_dir(),$track->name."_$version.wav");
if ( $frequency == $desired_frequency and $path =~ /.wav$/i){
Audio::Nama::pager_newline("copying $path to $destination");
copy($path, $destination) or die "copy failed: $!";
} else {
my $format = Audio::Nama::signal_format($config->{raw_to_disk_format}, $width);
Audio::Nama::pager_newline("importing $path as $destination, converting to $format");
Audio::Nama::teardown_engine();
my $ecs = qq(-f:$format -i:resample-hq,$frequency,"$path" -o:$destination);
my $path = join_path(Audio::Nama::project_dir()."convert.ecs");
write_file($path, $ecs);
Audio::Nama::load_ecs($path) or Audio::Nama::throw("$path: load failed, aborting"), return;
Audio::Nama::ecasound_iam('start');
Audio::Nama::sleeper(0.2);
sleep 1 while $this_engine->running();
( run in 0.492 second using v1.01-cache-2.11-cpan-5a3173703d6 )