#!/usr/bin/perl -s our($c, $r,$rec,$h,$debug,$fluid,$out); use strict; use Data::Dumper; use IPC::Open3; my %client; $c ||= "c1"; my $OUT=""; if($out){ $OUT="-d hw:$out"; print "using $OUT\n"; } my $def_instrument = shift || 1 ; my ($R,$W,$E); my $fluidsynth = qq{fluidsynth -l -a jack -g 0.8 -j }; ## fluissynth -a pulseaudio -i -l -s /usr/share/soundfonts/fluidr3/FluidR3GM.SF2 my $pid = open3($W,$R,$E,$fluidsynth) || die("can open3"); my $current_sf={}; my $f=[ {file=>"FluidR3_GM", chan=>[[0,0],[0,7],[0,48],[0,19],[0,22],[0,68],[128,0]]}, {file=>"Diato", chan=>[[0,1],[0,2],[0,3],[0,4],[0,5]]}, {file=>"Blanchet-1720", chan=>[[1,1],[1,2],[1,3],[1,4]]}, {file=>"lute", chan=>[[0,24]]}, {file=>"erans-kvist-cello_sus_f", chan=>[[0,0]]}, {file=>'Natural_Oboe', chan=>[[0,0]]}, {file=>"bongos", chan=>[[0,0]]}, {file=>"drums_super_real_evandro", chan=>[[0,0]]}, {file=>"pianoChords", chan=>[[0,0],[0,1],[0,2],[0,3]]}, {file => '5334_ACCORDION', chan=>[[0,0]]}, {file => 'CampbellsHonerAccordian', chan=>[[0,0]]}, ]; my $i = shift // "FluidR3_GM"; my ($vip,$vop,$sp,$mtp); my %inst = ( corn => 'English_Horn_2', diato => 'Diato', orgao => 'Orgue_de_salon', acordeao => '5334_ACCORDION', guitarc => 'acoustic_guitar_chords', bongo => 'bongos', lute => 'lute', cello => 'erans-kvist-cello_sus_f', guitar => 'nylon_guitar_1', piano => 'wst25fstein_00sep22', # geral => 'default', FluidR3_GM => 'FluidR3_GM', oboe => 'Natural_Oboe', '8m' => '8MBGMSFX', ti => 'TimGM6mb', cravo => 'Blanchet-1720', drums => 'drums_super_real_evandro', sax => 'Tenor_Sax_1', music_box => 'Music_Box', #FluidR3_GM.sf2 #TimGM6mb.sf2 ); my $sfpath; # my $sfpath="/usr/share/soundfonts"; # my $sfpath="/usr/share/sounds/sf2"; # my $sfpath="/f18/usr/share/soundfonts"; my @sf2dir=qw( . /usr/share/soundfonts/sf2 /usr/share/soundfonts /usr/share/sounds/sf2/ ); if($h){ print "!available voices: \n\t", join("\n\t",sort keys %inst),"\n"; exit 0; } sys("killall -9 -q pulseaudio"); if($r){ ## reset!! sys("killall -q vmpk"); sys("killall -q qsynth"); sys("killall -9 -q fluidsynth"); sys("killall -9 -q jackd"); sys("killall -q qarecord"); exit 0; } my $sf2 ; ### = $sfpath. "/" . ($inst{$i} or $i).".sf2"; for(@sf2dir){next unless -d $_; if(-f "$_/$inst{$i}.sf2" ){$sf2 //= "$_/$inst{$i}.sf2"; $sfpath//=$_;}; if(-f "$_/$i.sf2" ){$sf2 //= "$_/$i.sf2" ; $sfpath//=$_;}; } die("Cant find basefont (try to install $i...where is it?)\n") unless $sf2; my $midiserver2 = qq{fluidsynth -a jack -g 1 -j $sf2 } ; ## fluidsynth --server --no-shell --a jack --connect-jack-outputs \ ## /usr/share/sounds/sf2/FluidR3_GM.sf2 \ ## 1>/tmp/fluidsynth.out 2>/tmp/fluidsynth.out & my $midiserver = $midiserver2 ; my $keyb = "cvmpk $c "; my $reccom = "qarecord --jack output"; die("$sf2 not found\n") unless -f $sf2; sys ("$reccom & ") if $rec; jackserver(); get_connections(); if($fluid) {midiserverfl( $sf2 );} ### {qq{$sfpath/$inst{$i}.sf2});} else {set_sf($def_instrument);} keyboard(); conets(); while(<>) { chomp; if (/^\s*(\d+)\s*$/){ set_sf($1,undef) } elsif (/^\s*(\d+)\.(\d+)\s*$/){ set_sf($1,$2) } elsif (/^\s*(h|help)\s*$/){ for(1..@$f){print "$_ -- $f->[$_-1]{file}\n"} for(keys %$current_sf){print "$_ -loaded as- $current_sf->{$_}\n"} } else {print $W "$_\n"; } } kill $pid; sub get_connections{ %client =(); $vop=$vip=$sp=$mtp=0; my $a = sys("aconnect -i -o -l","quiet"); print $a if $debug; if($a =~ /client\s*(\d+):\s*'VMPK Output/){$vop=$1} if($a =~ /client\s*(\d+):\s*'VMPK Input/ ){$vip=$1} if($a =~ /client\s*(\d+):\s*'FLUID Synth/){$sp=$1} if($a =~ /client\s*(\d+):\s*'Midi Through/){$mtp=$1} my $k; for ( split(/(?:^|\n)client\s*/,$a,1000)){ if(s/^(\d+):\s*'(.*?)'//){ $k=$1; $client{$1}{name}=$2;} else {next} if(s/Connect(?:ing|ed) (To|From):\s*(\S.*\S)//){ $client{$k}{$1}=$2;} else {next} if(s/Connect(?:ing|ed) (To|From):\s*(\S.*\S)//){ $client{$k}{$1}=$2;} else {next} if(s/Connect(?:ing|ed) (To|From):\s*(\S.*\S)//){ $client{$k}{$1}=$2;} else {next} } print Dumper \%client if $debug; } sub jackserver{ my $jstatus = `jack_wait -c 2> /dev/null`; if($jstatus !~ /^running/) { print "starting jack\n"; sys ("jackd -r --silent -d alsa $OUT -p 128 -r 44100 -s &"); print "waiting for jack\n"; sys ("jack_wait -w -t 10 2> /dev/null"); print "done\n"; } else{ print "jack already running\n"; } } sub keyboard{ my $sleep=1; my $timeout=15; if(not $vop) { print "starting VMPK\n"; sys ("$keyb & "); } get_connections(); while(not $vop) { print "sleeping $sleep\n"; sleep $sleep; get_connections(); if ($timeout < 0) { print "ERROR: VMPK timeout\n"; return;} $timeout -= $sleep; } print "done $vop\n"; } sub conets{ if(not $client{$vop}{To}) { if($vop and $sp){ print "connecting VMPK to SYNth...\n"; sys("aconnect $vop:0 $sp:0");} else{ print "ERROR: cant connect VMPK to midiserver...\n";} } if(not $client{$mtp}{To}) { if($mtp and $sp){ print "connecting midithrough to SYNth...\n"; sys("aconnect $mtp:0 $sp:0");} else{ print "ERROR: cant connect to midiserver...\n";} } } sub sys{ my $com = shift; my $quit = shift || 0; my $r=""; print "==> $com" unless $quit; if ($com =~ /\&/){ system($com); } else {$r=`$com`;} warn("\nError: $!\n") if $!; print "\n" unless $quit; $r; } #system ("jack_connect 'VMPK Output' system:playback_1 #system ("jack_connect aeolus:out.R system:playback_1 sub set_sf{ ## set soundfont (sf-number, [prog for channel 0]) my ($i,$opprog) = @_; my $voice ; if ($current_sf->{$i}) { $voice = $current_sf->{$i} } else { $voice = $current_sf->{$i} = (++$current_sf->{next}); print $W "load $sfpath/$f->[$i-1]{file}.sf2\n"; } preset($i,$voice,$opprog); } sub preset{ my($i,$voice,$prog)=@_; my @l=@{$f->[$i-1]{chan}}; my $n = 0; if($prog){ print "##### select 0 $voice $l[$prog][0] $l[$prog][1]\n"; print $W "select 0 $voice $l[$prog][0] $l[$prog][1]\n"; } else { for (0..@l-1){ print $W "select $_ $voice $l[$_][0] $l[$_][1]\n"; } } print $W "help batatas\n"; while(($a=<$R>) !~ /help help/) { next if $a =~ /^\n|FluidSynth version|Distributed under|Copyright|registered trademark|batatas|help topic/; chomp $a; print "{$a}\n"; } chomp $a; print "{$a}+\n"; } __END__