diff options
-rwxr-xr-x | bsgrep | 454 | ||||
l--------- | bsjoin | 1 | ||||
-rwxr-xr-x | find_key | 48 | ||||
-rw-r--r-- | image_diff.pl | 58 | ||||
-rwxr-xr-x | tunebass | 83 | ||||
-rw-r--r-- | unifmt.pl | 3 | ||||
-rwxr-xr-x | ztunekey | 76 | ||||
-rw-r--r-- | ztunekey.desktop | 9 | ||||
-rw-r--r-- | ztunekey.png | bin | 0 -> 55391 bytes |
9 files changed, 716 insertions, 16 deletions
@@ -0,0 +1,454 @@ +#!/usr/bin/perl -w + +$VERSION = "0.0.1"; + +use Getopt::Std; +use File::Find; + +($self = $0) =~ s,.*/,,; + +%printed = (); + +$SIG{__WARN__} = sub { + my $m = shift; + + # don't include the line number in warnings. + $m =~ s/ at \S+ line \d+\.$//; + + # File::Find seems to use double newlines for its warnings.. + $m =~ s/\n\n+/\n/; + + # warnings that don't start with $self: are e.g. file access errors + # from the 'while(<>)' or File::Find. + if($m !~ /^$self:/) { + $m = "$self: $m"; + $ret = 2 unless $opt{q}; + } + + print STDERR $m unless $opt{s}; +}; + +sub grep_options { + my @nargv; + my $was_e; + + # first, grab all the -e options and remove them from @ARGV, + # because Getopt::Std doesn't support multiple occurrences of + # a flag with different args. probably it would be better to + # use Getopt::Long, but for now this works. + for(@ARGV) { + if($was_e) { + push @patterns, $_; + $was_e = 0; + } elsif($_ eq '-e') { + $was_e = 1; + } elsif($_ =~ /-e(.*)/) { + push @patterns, $1; + } else { + push @nargv, $_; + } + } + @ARGV = @nargv; + + getopts('d:FiklnNqrsvwz', \%opt) || exit 1; +} + +sub print_line { + print "$ARGV:" if $filecount > 1; + print "$start_line:" if $opt{n}; + print $_[0]; + print $opt{z} ? "\0" : "\n"; +} + +sub join_options { + getopts('d:knwz', \%opt) || exit 1; +} + +sub handle_line { + my $match = 0; + + for my $pat (@patterns) { + if($opt{v}) { + $match++ if $out !~ /$pat/; + } else { + $match++ if $out =~ /$pat/; + } + } + + return unless $match; + + if($opt{N}) { + return unless $match == @patterns; + } + + $ret = 0 if $ret == 1; + return if $opt{q}; + + if($opt{l}) { + if(!$printed{$ARGV}++) { + print "$ARGV\n"; + } + } else { + print_line($out); + } +} + +### main() +# TODO: do we need 'use locale'? +# also, why does reading iso-8859-1 text auto-convert to utf-8? +for (qw/LANG LC_CTYPE LC_ALL/) { + if(($ENV{$_} // "") =~ /utf-?8/i) { + binmode(\*STDIN, ':utf8'); + binmode(\*STDOUT, ':utf8'); + last; + } +} + +if(defined($ARGV[0])) { + if($ARGV[0] =~ /-help/) { + exec "perldoc $0"; + exit(1); + } elsif($ARGV[0] eq '--man') { + exec "pod2man --stderr -s1 -cUrchlaysStuff -r$VERSION -u $0"; + exit(1); + } elsif($ARGV[0] eq '--version') { + print "bsgrep $VERSION\n"; + exit(0); + } +} + +if($self =~ /join/) { + join_options(); + push @patterns, '^'; # every string has a beginning... +} else { + grep_options(); + + if(!@patterns) { + if(!($patterns[0] = shift)) { + grep_usage(); + die("$self: missing required pattern argument\n"); + } + } + + map { $_ = quotemeta } @patterns if $opt{F}; + map { $_ = "(?i)$_" } @patterns if $opt{i}; +} + +if($opt{r}) { + @ARGV = (".") unless @ARGV; + for(@ARGV) { + if(-d $_) { + find({ + wanted => sub { push @nargv, $_ if -f _; }, + follow => 0, + no_chdir => 1 }, + $_); + } else { + push @nargv, $_; + } + } + + @ARGV = @nargv; +} + +$ret = 1; # return value from main(), set to 0 if anything matched. + +$filecount = @ARGV; # used to decide whether to print filename prefixes. + +$cont = quotemeta($opt{d} // '\\'); + +$/ = "\0" if $opt{z}; + +while(<>) { + chomp; + if(s/\r//) { + if(!$cr_warning) { + warn "$self: $ARGV: stripping carriage returns\n" unless $opt{s}; + $cr_warning = 1; + } + } + if(/$cont\s+$/) { + warn "$self: $ARGV:$.: whitespace after continuation, malformed input?\n" unless $opt{s}; + } + s/^\s+// if $out && $opt{w}; + $start_line = $. unless defined $out; + $out .= $_; + if(/$cont$/) { + if(!$opt{k}) { + $out =~ s/$cont$//; + } + } else { + handle_line(); + undef $out; + } +} continue { + # reset $. on each new file (perldoc -f eof) + if(eof) { + if($out) { + warn "$self: $ARGV:$.: last line ends with continuation\n" unless $opt{s}; + handle_line(); + undef $out; + } + close ARGV; + $cr_warning = 0; + } +} + +exit $ret; + +### rest of file is the docs + +=pod + +=head1 NAME + +bsgrep - search for strings in files with backslash continuation + +bsjoin - join lines with backslash continuation + +=head1 SYNOPSIS + +bsgrep [B<[-FiklnNqrsvwz]> B<-d> I<char> I<...>] [B<-e> I<pattern> ... | I<pattern>] [I<file> I<...>] + +bsjoin [B<[-knwz]> B<-d> I<char> I<...>] [I<file> I<...>] + +=head1 DESCRIPTION + +B<bsgrep> (backslash grep) uses a regular expression to search for +strings in a file, much like B<grep>(1). The main difference is, +B<bsgrep> joins together lines that use the backslash for continuation +(e.g. as B<sh>(1) does). + +Other differences: B<bsgrep> doesn't support the full set of B<grep> +options, and it uses Perl regular expressions rather than POSIX. + +Input is read from one or more files, or standard input if no files +are given. Output goes to standard output. + +The search is done after lines are joined together, so the regex can +match text split across continuation lines. + +If B<bsgrep> is run as B<bsjoin> (via symbolic or hard link, or just +copying the executable), it will simply join together continued lines +without searching for anything. In this mode, only the B<-k>, B<-n>, +B<-w>, B<--version>, and B<--help> options are supported. + +=head1 OPTIONS + +These options work with both B<bsgrep> and B<bsjoin>: + +=over 4 + +=item -d I<char> + +Use I<char> as the continuation character, rather than a backslash. +Actually, there's no law that says it has to be a single character, +if you can think of a use for a string here... though it's treated as +a fixed string, not a regular expression. This option does not exist +in B<grep>. + +=item -k + +Keep the continuation characters when joining continued lines together. +This option does not exist in B<grep>. + +=item -n + +Prefix output lines with line numbers (same as B<grep>). For lines +that are split with continuation characters, the line number will be +that of the first line in the set. Same as B<grep>. + +=item -w + +For continuation lines, remove any leading whitespace. This option is +specific to B<bsgrep>. The B<grep> B<-w> option can be simulated with +the Perl B<\b> syntax in the regex. + +=item -z + +Use zero bytes (ASCII NUL) rather than newlines for line terminators, +for both input and output. Same as B<grep>. + +=item --version + +Print the version of B<bsgrep> and exit. + +=item --help + +Prints this help text, via B<perldoc>(1). + +=item --man + +Prints this help text as a man page, via B<pod2man>(1). Suggested use: + + bsgrep --man > bsgrep.1 + +=back + +These options are only supported by B<bsgrep>: + +=over 4 + +=item -e I<pattern> + +Use I<pattern> as the pattern. May be used multiple times, in which case +they are ORed together (a line that matches any I<pattern> is a match)... unless +the B<-N> option is used, q.v. Same as B<grep>. + +=item -F + +Treat pattern(s) as fixed strings, not regular expression(s). Same as B<grep>. + +=item -i + +Case-insensitive search (same as B<grep>). + +=item -l + +Instead of printing lines that match, print only the names of files +that contain matches (same as B<grep>). + +=item -N + +When multiple patterns are given with multiple B<-e> options, only +select lines that match all of the patterns; the default is to select +lines that match any of the patterns. This option doesn't exist +in B<grep>. + +=item -q + +Quiet: don't write to standard output. Exit status will be zero if +a match was found, even if there were errors. This doesn't prevent +warnings/errors being printed to standard error; use B<-s> to silence +those. Same as B<grep>. + +=item -r + +Recursively read all files under each directory, following symlinks +only if they're on the command line. If no files or directories are +given, reads the current directory. Same as B<grep>. + +=item -s + +Silence warnings (same as B<grep>). This includes error messages +about unreadable files as well as warnings about the input (see +B<DIAGNOSTICS>, below). + +=item -v + +Print only lines that do I<not> match (same as B<grep>). + +=back + +=head1 EXAMPLE + +Given the file B<trs80-roms.info> (which comes from SlackBuilds.org), containing: + + PRGNAM="trs80-roms" + VERSION="20230516" + HOMEPAGE="https://sdltrs.sourceforge.net/docs/index.html" + DOWNLOAD="https://www.filfre.net/misc/trs_roms.zip \ + http://cpmarchives.classiccmp.org/trs80/mirrors/www.discover-net.net/~dmkeil/trs80/files/trs80-62.zip \ + https://www.tim-mann.org/trs80/ld4-631.zip \ + https://archive.org/download/mame-0.250-roms-split_202212/MAME%200.250%20ROMs%20%28split%29/trs80m4p.zip \ + http://www.tim-mann.org/trs80/xtrs-4.9d.tar.gz \ + https://www.classic-computers.org.nz/system-80/disks/NEWDOS_80sssd_jv1.DSK" + MD5SUM="ecd2c47c0624885fbcfb17889241f0ed \ + 9b342f4401801bbc947e303cbeb9902f \ + f2678aa45b76d935a34a0cd2b108925d \ + 8a0f1567df8f166f4056a6a71ef7dce5 \ + 8bb7cf88a3bc1da890f1f29398120bf3 \ + 6f624bdbf4b410cfbe8603fa3bef44fa" + DOWNLOAD_x86_64="" + MD5SUM_x86_64="" + REQUIRES="" + MAINTAINER="B. Watson" + EMAIL="urchlay@slackware.uk" + +We can extract all the download URLs from the file with: + + $ bsgrep '^DOWNLOAD=' trs80-roms + + DOWNLOAD="https://www.filfre.net/misc/trs_roms.zip http://cpmarchives.classiccmp.org/trs80/mirrors/www.discover-net.net/~dmkeil/trs80/files/trs80-62.zip https://www.tim-mann.org/trs80/ld4-631.zip https://archive.org/download/mame-0.250-roms-split_202212/MAME%200.250%20ROMs%20%28split%29/trs80m4p.zip http://www.tim-mann.org/trs80/xtrs-4.9d.tar.gz https://www.classic-computers.org.nz/system-80/disks/NEWDOS_80sssd_jv1.DSK" + DOWNLOAD_x86_64="" + +All the URLs are listed as one long line (apologies for the ugly formatting). +Note that the whitespace that indents the continuation lines is +preserved. In this case, the whitespace is all spaces, but tabs would +be treated the same way. To compress the whitespace into a single space, +use the B<-w> option. + +=head1 DIAGNOSTICS + +Unless disabled with the B<-s> option, B<bsgrep> may print these messages +on standard error: + + bsgrep: <file>: stripping carriage returns + +The input file has MS-DOS/Windows CRLF line endings. B<bsgrep>'s +output will have these removed. Note that other Unix-flavored tools +that understand continuation lines will generally fail when fed CRLF +files. + + bsgrep: <file>, line <line>: whitespace after continuation, malformed input? + +In shell scripts (and most other uses of backslash continuation), a +line that ends with whitespace after the backslash is not treated as a +continuation line. This is a very easy error to create, when manually +editing files. The above warning will help you avoid this. As usual, +it can be ignored if you know exactly what you're doing. + + bsgrep: <file>: last line ends with continuation + +This warning is self-explanatory. There's nothing for the last line +to continue onto, so this is almost certainly an error. + +The above warnings don't affect the exit status. + +=head1 ENVIRONMENT + +B<bsgrep> doesn't define any environment variables of its own, but +it does pay attention to B<LANG>, B<LC_ALL>, and B<LC_CTYPE>. If any +of these contain the string I<UTF-8>, the input and output will be +read/written as Unicode, encoded as UTF-8. If the input turns out not +to be Unicode, it will be assumed ISO-8859-1, and converted to Unicode. + +=head1 EXIT STATUS + +0 if there were any matches, 1 if there were none, or 2 if there +were errors (e.g. nonexistent file). However, with B<-q>, the exit +status will be 0 or 1 even if there were errors. This is the same as +B<grep>'s exit status. + +=head1 LIMITATIONS + +B<bsgrep> doesn't detect binary files like B<grep> does. It can and +will print them to your terminal instead of "binary file matches". + +Not all B<grep> options are supported. Options that aren't implemented +but might be someday include B<--color>, B<-a>, B<-A>, B<-B>, B<-C>, B<-o>. +I don't intend to implement every single option B<grep> has, there are +too many of them. + +There are no long options other than B<--help> and B<--version>. + +B<bsgrep> does not comply with the POSIX (or any other) standard for +B<grep>, and does not intend do. + +Locale support isn't quite the same as B<grep>: in a UTF-8 locale, +if the input isn't plain ASCII or valid UTF-8, it will be treated +as ISO-8859-1, internally converted to Unicode, and output will be +UTF-8. This isn't intended; it's a side-effect of how Perl UTF-8 +filehandles work. In non-UTF-8 locales, things should work as +expected. I hope. + +=head1 AUTHOR + +B<bsgrep> was written by B. Watson <urchlay@slackware.uk> and released +under the WTFPL: Do WTF you want with this. + +=head1 SEE ALSO + +B<grep>(1), B<perl>(1) + +=cut @@ -0,0 +1 @@ +bsgrep
\ No newline at end of file @@ -55,8 +55,9 @@ $0: Find key of music in audio (or maybe video) files. Usage: $0 [-m|-M] file.wav [file.wav ...] --m: Force major keys to relative minor --M: Force minor keys to relative major +-q: Quiet, only output the most likely key. +-m: Force major keys to relative minor. +-M: Force minor keys to relative major. EOF exit 0; } @@ -70,6 +71,9 @@ for(@ARGV) { $fold_major = 0; $fold_minor = 1; next; + } elsif(/^-q/) { + $quiet++; + next; } my $sec; @@ -79,22 +83,23 @@ for(@ARGV) { $sf = Audio::SndFile->open("<", $_); }; if($@) { - warn "Extracting to tmp.wav\n"; - system("mplayer -vo null -ao pcm:fast:file=tmp.wav \"$_\""); + my $rq = $quiet ? "-really-quiet" : ""; + warn "Extracting to tmp.wav\n" unless $quiet; + system("mplayer $rq -vo null -ao pcm:fast:file=tmp.wav \"$_\""); $sf = Audio::SndFile->open("<", "tmp.wav"); $_ = "tmp.wav"; } $sec = ($sf->frames) * (1 / $sf->samplerate); } - printf "file is %03.2f sec\n", $sec; + printf "file is %03.2f sec\n", $sec unless $quiet; my $oldstamp = -1; my $oldkey = -1; - my $got = `vamp-simple-host qm-vamp-plugins:qm-keydetector "$_" 2`; + my $got = `vamp-simple-host qm-vamp-plugins:qm-keydetector "$_" 2 2>/dev/null`; die "Analysis failed\n" unless defined $got; - print "\n"; + print "\n" unless $quiet; my @got = split "\n", $got; ## for my $line (@got) { @@ -122,24 +127,25 @@ for(@ARGV) { } elsif($fold_minor) { $key = get_relative_minor($key); } - if($key =~ /m$/) { - $relkey = get_relative_major($key); - } else { - $relkey = get_relative_minor($key); - } + $relkey = get_relative_key($key); if($oldstamp != -1) { $times{$oldkey} += ($stamp - $oldstamp); } $oldstamp = $stamp; $oldkey = $key; - print "$stamp: $key ($relkey)\n"; + print "$stamp: $key ($relkey)\n" unless $quiet; } $times{$oldkey} += ($sec - $oldstamp); - print "\n"; - for(sort { $times{$b} <=> $times{$a} } keys %times) { - printf "%3s: %4.2f sec, %4.2f%%\n", $_, $times{$_}, $times{$_} / $sec * 100; + print "\n" unless $quiet; + my @sorted = sort { $times{$b} <=> $times{$a} } keys %times; + if($quiet) { + print $sorted[0] . " (" . get_relative_key($sorted[0]) . ")\n"; + } else { + for(@sorted) { + printf "%3s: %4.2f sec, %4.2f%%\n", $_, $times{$_}, $times{$_} / $sec * 100; + } } } @@ -153,6 +159,16 @@ sub get_relative_minor { return $relative_minors{$key} || $key; } +sub get_relative_key { + my $key = shift || die "missing key"; + if($key =~ /m$/) { + $relkey = get_relative_major($key); + } else { + $relkey = get_relative_minor($key); + } + return $relkey; +} + __END__ Output of plugin: - Estimated key (from C major = 1 to B major = 12 and C minor = 13 to B minor = 24) diff --git a/image_diff.pl b/image_diff.pl new file mode 100644 index 0000000..9199f61 --- /dev/null +++ b/image_diff.pl @@ -0,0 +1,58 @@ +#!/usr/bin/perl -w + +# given 2 images of the same size, create a 3rd image, with the pixel +# at each (x,y) transparent if it's the same RGB color in both images, +# or set to the color in the 2nd image if they're different. + +# the 2nd image should be an edited version of the 1st image, and the +# output image can be displayed overlaid on the 1st image to show what +# the 2nd image looked like. + +use Image::Magick; + +sub die_usage { + die "usage: $0 <input-image1> <input-image2> <output-image>]\n"; +} + +sub readimage { + my $file = shift; + my $i = new Image::Magick; + my $r = $i->Read($file); + die "$r\n" if $r; + warn "read $file, OK\n"; + return $i; +} + +die_usage() if @ARGV != 3; +$a = readimage(shift); +$b = readimage(shift); + +$w = $a->Get('width'); +$h = $a->Get('height'); + +if($w != $b->Get('width') || $h != $b->Get('height')) { + die "input images are not the same pixel size\n"; +} + +$out = Image::Magick->new(size => $w . 'x' . $h); +$r = $out->ReadImage('xc:transparent'); +die "$r\n" if $r; + +# this is rather slow... +for($y = 0; $y < $h; $y++) { + for($x = 0; $x < $w; $x++) { + my @ap = $a->GetPixel(map => "RGB", x => $x, y => $y); + my @bp = $b->GetPixel(map => "RGB", x => $x, y => $y); + if($ap[0] != $bp[0] || $ap[1] != $bp[1] || $ap[2] != $bp[2]) { + push @bp, 65535; # fully opaque + } else { + @bp = (0, 0, 0, 0); # transparent (and black) + } + $r = $out->SetPixel(map => "RGBA", x => $x, y => $y, color => \@bp); + die "$r\n" if $r; + } +} + +$r = $out->Write($ARGV[0]); +die "$r\n" if $r; +warn "wrote to $ARGV[0]\n"; diff --git a/tunebass b/tunebass new file mode 100755 index 0000000..5394abc --- /dev/null +++ b/tunebass @@ -0,0 +1,83 @@ +#!/bin/bash + +# Ear tuner for guitar and bass. Install tunebass on your $PATH, and +# symlink it to tunegtr. + +# this used to be a one-liner: +#play -n synth 2 pluck ${1:-A2} repeat 99999 + +case "$0" in + *gtr*|*guit*) + notes="E4 B3 G3 D3 A2 E2" + note=6 + lastnote=6 + ;; + *) + notes="G2 D2 A1 E1" + note=4 + lastnote=4 + ;; +esac + +prompt="Space: next string, BkSpc: prev string, 1-$lastnote: strings, q: quit, ?: help" + +# these seem like they ought to be the arrow keys, but they're actually +# \n and \b... kcud1 and kcub1 are the 'application mode' versions, which +# doesn't do us any good here. +#down="$( tput cud1 )" +#left="$( tput cub1 )" + +# these are correct for xterm and derivatives, and for the linux console. +down="$( printf "\x1b\x5bB" )" +left="$( printf "\x1b\x5bD" )" + +up="$( tput cuu1 )" +right="$( tput cuf1 )" +pageup="$( tput kpp )" +pagedown="$( tput knp )" + +esc="$( printf "\x1b" )" +enter=' +' + +oldnote= +pid= +echo "$prompt" +while true; do + narg="$( echo $notes | cut -d' ' -f $note )" + if [ "$oldnote" != "$note" ]; then + [ "$pid" != "" ] && kill "$pid" + echo -e -n "\rString: $note Note: $narg" + tput el + play --buffer 1024 -qn synth 2 pluck $narg repeat - &>/dev/null & + pid="$!" + oldnote="$note" + fi + key= + read -rs -N5 -t 0.1 key + if [ "$key" != "" ]; then + case "$key" in + [1-9]) + [ "$key" -le "$lastnote" ] && note=$key ;; + a|A|h|H|||$left|$pageup) + note=$(( note + 1 )); [ $note -gt $lastnote ] && note=1 ;; + d|D|l|L|' '|' '|$right|$enter|$pagedown) + note=$(( note - 1 )); [ $note = 0 ] && note=$lastnote ;; + s|S|j|J|$down) + note=$lastnote ;; + w|W|k|K|$up) + note=1 ;; + \?) + echo + cat <<EOF +Use space + backspace, arrow keys, pageup/down, WASD, HJKL, or numbers +1 to $lastnote to pick a string. Tune your strings to the notes you hear. +Press Q or Escape to exit. +EOF + ;; + $esc|q|Q) break ;; + esac + fi +done +kill "$pid" +echo @@ -1,5 +1,8 @@ #!/usr/bin/perl +# TODO: +# Braille. + # to read the docs outside of irssi: perldoc /path/to/unifmt.pl # in irssi, "/script load unifmt.pl", then "/unifmt_help" diff --git a/ztunekey b/ztunekey new file mode 100755 index 0000000..61eb9e6 --- /dev/null +++ b/ztunekey @@ -0,0 +1,76 @@ +#!/bin/sh + +# icon from: +# https://vectorified.com/images/guitar-tuner-icon-28.jpg +# ...installed via: +# convert guitar-tuner-icon-28.jpg .local/share/icons/hicolor/256x256/apps/ztunekey.png + +if [ "$1" = "--help" ]; then + cat <<EOF +ztunekey: show tuning and key of an audio file, using a zenity-based UI. + +Usage: ztunekey [file] + +[file] is an audio file, in any format supported by mplayer (since +mplayer is used to convert it to a .wav file for processing). + +With no [file], ztunekey queries audacious (using audtool) to get the +currently playing file. This will fail if audacious isn't running. + +The tuning (in cents relative to A440) and the detected key (and +relative key, e.g. G (Em) or A (F#m)) are shown in a window, after the +file is analyzed. +EOF + exit 0 +fi + +ICON=ztunekey +ZOPT='--width 300 --height 100 --title Tuning/Key' +file="$1" + +if [ "$file" = "" ]; then + file="$( audtool --current-song-filename )" + if [ "$file" = "" ]; then + zenity --error $ZOPT --text="Audacious is not running, or no song is playing." + exit 1 + fi +fi + +if [ ! -e "$file" ]; then + zenity --error $ZOPT --text="No such file:\\n$file" + exit 1 +fi + +bn="$( basename "$file" )" +tmpfile=/tmp/ztunekey.$$.wav + +keyfile=/tmp/key.$$ +tunefile=/tmp/tuning.$$ +( mplayer -really-quiet -benchmark -vo null -ao pcm:fast:file=$tmpfile "$file" + find_tuning -q "$tmpfile" > $tunefile & + find_key -q "$tmpfile" > $keyfile & + wait ) | zenity --progress --no-cancel $ZOPT --icon-name=ztunekey --text="$bn" --pulsate --auto-close + +TUNING="$( cat $tunefile )" +KEY="$( cat $keyfile )" +rm -f $keyfile $tunefile + +zenity --question $ZOPT --icon-name=ztunekey --text="$bn\\nTuning: $TUNING cents\\nKey: $KEY )\\n\\nRetune to standard?" +[ "$?" = 1 ] && exit 1 + +zenity --scale $ZOPT --icon-name=ztunekey --text="Semitones to transpose?\\n0 = original key." --min-value=-12 --max-value=12 --value=0 > /tmp/semi.$$ + +S="$( cat /tmp/semi.$$ )" +rm -f /tmp/semi.$$ +P="$( perl -MPOSIX=round -e "printf '%+2.2f', round(100 * ($S - $TUNING / 100)) / 100" )" +newfile="$( echo "$bn" | sed 's,\.[^.]*$,'$P'.wav,' )" + +mkdir -p ~/retuned +cd ~/retuned +rubberband --pitch $P $tmpfile "$newfile" | zenity --progress --no-cancel $ZOPT --icon-name=ztunekey --text "Retuning $bn by $P semitones." --pulsate --auto-close +flacfile="$( basename "$newfile" .wav )".flac +flac -f --delete-input-file -o "$flacfile" "$newfile" | zenity --progress --no-cancel $ZOPT --icon-name=ztunekey --text "Encoding $flacfile" --pulsate --auto-close +id3cp "$file" "$flacfile" +id3 -2 -t "%|%t||%_f|? (Retuned $P)" "$flacfile" +audtool --playlist-addurl-to-new-playlist ~/retuned/"$flacfile" + diff --git a/ztunekey.desktop b/ztunekey.desktop new file mode 100644 index 0000000..184792e --- /dev/null +++ b/ztunekey.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Version=1.0 +Name=Tuning/Key +Type=Application +Exec=/home/urchlay/bin/ztunekey %f +Icon=ztunekey +Terminal=false +StartupNotify=false +Hidden=false diff --git a/ztunekey.png b/ztunekey.png Binary files differnew file mode 100644 index 0000000..d152c37 --- /dev/null +++ b/ztunekey.png |