add connect_to_db() to soepkiptng.lib; set mysql_auto_reconnect (thx Roel)
[soepkiptng.git] / soepkiptng_detect_hidden_track
blob62abdcc26fdd1d3bf3e32739516ba0731cdb1e72
1 #!/usr/bin/perl
2 ############################################################################
3 # soepkiptng (c) copyright 2000 Eric Lammerts <eric@lammerts.org>.
4 ############################################################################
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License, version 2, as
7 # published by the Free Software Foundation.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # A copy of the GNU General Public License is available on the World Wide Web
15 # at `http://www.gnu.org/copyleft/gpl.html'. You can also obtain it by
16 # writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 # Boston, MA 02111-1307, USA.
18 ############################################################################
20 my $progdir;
21 BEGIN {
22 use Cwd qw'abs_path cwd';
24 # find program directory
25 $_ = $0;
26 while(-l) {
27 my $l = readlink or die "readlink $_: $!\n";
28 if($l =~ m|^/|) { $_ = $l; } else { s|[^/]*$|/$l|; }
30 m|(.*)/|;
31 $progdir = abs_path($1);
33 unshift @INC, "$progdir/lib";
35 require "$progdir/soepkiptng.lib";
36 $ENV{PATH} = "$progdir/bin:$ENV{PATH}";
38 use strict;
39 use Data::Dumper;
40 use DBI;
41 use Getopt::Std;
43 our ($opt_c, $opt_d, $opt_h, $opt_n, $opt_t);
45 getopts('c:dhnt:');
47 $opt_h and die <<EOF;
48 usage: soepkiptng_detect_hidden_track [-h] [-c configfile] [-t threshold]
49 EOF
51 my %conf;
52 read_configfile(\%conf, $opt_c);
54 my $dbh = connect_to_db(\%conf);
56 FILE: foreach my $file (@ARGV) {
57 my $path = abs_path($file);
58 my $song = $dbh->selectrow_hashref("SELECT * FROM song WHERE filename = ?", undef, $path);
60 if(open(F, "-|") == 0) {
61 open STDERR, ">&STDOUT";
62 open STDOUT, ">/dev/null";
63 exec "sox", "-V3", $path, "-";
64 die "sox: $!\n";
66 my %prop;
67 while(<F>) {
68 /^([^:]+[^:\s])\s+:\s*(.*\S)/ and $prop{$1} = $2;
70 close F;
71 print Dumper(\%prop) if $opt_d;
72 my $ch = $prop{Channels}
73 or die "$file: number of channels not found\n";
74 my $srate = $prop{"Sample Rate"}
75 or die "$file: sample rate not found\n";
77 open F, "-|", "sox", $path, "-c2", "-traw", "-b16", "-esigned-integer", "-";
78 my ($buf, $off, $start, $len, %sil);
79 while(read F, $buf, 4096) {
80 foreach(unpack("s*", $buf)) {
81 if(abs($_) <= $opt_t) {
82 if(defined($start)) {
83 $len++;
84 } else {
85 $start = $off;
86 $len = 1;
88 } else {
89 $sil{$start} = $len if defined($start) && $len > 44100;
90 $start = undef;
92 $off++;
95 close F;
97 if(defined($start)) { $sil{$start} = $len; }
98 if(!%sil) {
99 print "$file: no gaps detected\n";
100 next;
102 printf "%d %s", $off, Dumper(\%sil) if $opt_d;
104 my ($max, $max2) = sort { $sil{$b} <=> $sil{$a} } keys %sil;
105 if($sil{$max} < $sil{max2} * 2) {
106 print "no clear gap\n" . Dumper(\%sil);
108 my $siloff = $max;
109 my $sillen = $sil{$max};
110 my $trailing = $siloff + $sillen == $off;
111 if($ch > 1) {
112 $siloff = int($siloff / $ch);
113 my $p = $max % $ch;
114 if($p) {
115 $siloff++;
116 $sillen -= ($ch - $p) % $ch;
118 $sillen = int($sillen / $ch);
121 printf <<EOF,
123 Gap from %d length %d (%d:%02d.%03d - %d:%02d.%03d), trailing %ss
125 $file,
126 $siloff, $sillen,
127 $siloff / $srate / 60, ($siloff / $srate) % 60, ($siloff / $srate * 1000) % 1000,
128 ($siloff + $sillen) / $srate / 60, (($siloff + $sillen) / $srate) % 60, (($siloff + $sillen) / $srate * 1000) % 1000,
129 ($trailing? "n/a " : int(($off / $ch - ($siloff + $sillen)) / $srate));
131 next if $opt_n;
133 for(;;) {
134 print STDERR "y) split b) play last 10 sec before a) play after : ";
135 $_ = <STDIN>;
136 if(/b/i) {
137 system "play", "-V3", $path, "trim", sprintf("%ds", $siloff - 10 * $srate), 10;
138 } elsif(/a/i) {
139 system "play", "-V3", $path, "trim", sprintf("%ds", $siloff + $sillen);
140 } elsif(/y/i) {
141 last;
142 } else {
143 next FILE;
147 $dbh->do("UPDATE song SET length=?,trimstart=NULL,trimlength=? WHERE id=?", undef,
148 int($siloff / $srate), $siloff, $song->{id})
149 or die "can't do sql command: " . $dbh->errstr . "\n";
151 if(!$trailing) {
152 delete $song->{id};
153 delete $song->{last_played};
154 delete $song->{mtime};
155 delete $song->{time_added};
156 delete $song->{trimlength};
157 delete $song->{uuid};
158 $song->{title} = "(Bonus Track)";
159 $song->{track}++;
160 $song->{trimstart} = $siloff + $sillen;
161 $song->{length} = int((($off / $ch) - ($siloff + $sillen)) / $srate);
163 my @k = sort keys %$song;
164 $dbh->do(sprintf("INSERT INTO song (%s,time_added) VALUES (%s,now())",
165 join(",", @k), join(",", map { "?" } @k)), undef,
166 map { $song->{$_} } @k)
167 or die "can't do sql command: " . $dbh->errstr . "\n";