add option to play audio before and after gap
[soepkiptng.git] / soepkiptng_detect_hidden_track
blob3f9dc353268155b0e9c7e1bebe62390b9da12b90
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 = DBI->connect("DBI:$conf{'db_type'}:$conf{'db_name'}:$conf{'db_host'}", $conf{'db_user'}, $conf{'db_pass'})
55 or die "can't connect to database";
57 FILE: foreach my $file (@ARGV) {
58 my $path = abs_path($file);
59 my $song = $dbh->selectrow_hashref("SELECT * FROM song WHERE filename = ?", undef, $path);
61 if(open(F, "-|") == 0) {
62 open STDERR, ">&STDOUT";
63 open STDOUT, ">/dev/null";
64 exec "sox", "-V3", $path, "-";
65 die "sox: $!\n";
67 my %prop;
68 while(<F>) {
69 /^([^:]+[^:\s])\s+:\s*(.*\S)/ and $prop{$1} = $2;
71 close F;
72 print Dumper(\%prop) if $opt_d;
73 my $ch = $prop{Channels}
74 or die "$file: number of channels not found\n";
75 my $srate = $prop{"Sample Rate"}
76 or die "$file: sample rate not found\n";
78 open F, "-|", "sox", $path, "-c2", "-traw", "-b16", "-esigned-integer", "-";
79 my ($buf, $off, $start, $len, %sil);
80 while(read F, $buf, 4096) {
81 foreach(unpack("s*", $buf)) {
82 if(abs($_) <= $opt_t) {
83 if(defined($start)) {
84 $len++;
85 } else {
86 $start = $off;
87 $len = 1;
89 } else {
90 $sil{$start} = $len if defined($start) && $len > 44100;
91 $start = undef;
93 $off++;
96 close F;
98 if(!%sil) {
99 print "$file: no gaps detected\n";
100 next;
102 #if(defined($start)) { $sil{$start} = $len; }
103 printf "%d %s", $off, Dumper(\%sil) if $opt_d;
105 my ($max, $max2) = sort { $sil{$b} <=> $sil{$a} } keys %sil;
106 if($sil{$max} < $sil{max2} * 2) {
107 print "no clear gap\n" . Dumper(\%sil);
109 my $siloff = $max;
110 my $sillen = $sil{$max};
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 (%d:%02d.%03d) length %d (%d:%02d.%03d)
125 $file,
126 $siloff, $siloff / $srate / 60, ($siloff / $srate) % 60, ($siloff / $srate * 1000) % 1000,
127 $sillen, $sillen / $srate / 60, ($sillen / $srate) % 60, ($sillen / $srate * 1000) % 1000;
129 next if $opt_n;
131 for(;;) {
132 print STDERR "y) split b) play last 10 sec before a) play after : ";
133 $_ = <STDIN>;
134 if(/b/i) {
135 system "play", "-V3", $path, "trim", sprintf("%ds", $siloff - 10 * $srate), 10;
136 } elsif(/a/i) {
137 system "play", "-V3", $path, "trim", sprintf("%ds", $siloff + $sillen);
138 } elsif(/y/i) {
139 last;
140 } else {
141 next FILE;
145 $dbh->do("UPDATE song SET length=?,trimstart=NULL,trimlength=? WHERE id=?", undef,
146 int($siloff / $srate), $siloff, $song->{id})
147 or die "can't do sql command: " . $dbh->errstr . "\n";
149 delete $song->{id};
150 delete $song->{last_played};
151 delete $song->{mtime};
152 delete $song->{time_added};
153 delete $song->{trimlength};
154 delete $song->{uuid};
155 $song->{title} = "(Bonus Track)";
156 $song->{track}++;
157 $song->{trimstart} = $siloff + $sillen;
158 $song->{length} = int((($off / $ch) - ($siloff + $sillen)) / $srate);
160 my @k = sort keys %$song;
161 $dbh->do(sprintf("INSERT INTO song (%s,time_added) VALUES (%s,now())",
162 join(",", @k), join(",", map { "?" } @k)), undef,
163 map { $song->{$_} } @k)
164 or die "can't do sql command: " . $dbh->errstr . "\n";