- 论坛徽章:
- 0
|
先发布源代码,再说明干什么用,免得烂在我的硬盘里。
- #!/usr/bin/env perl
- # This program splits a wav file that contains multiple tracks into multiple wav
- # files, each of which contains one track based on indices provided by a cue file.
- # Written by Shufeng Tan <shufengtan@gmail.com> January, 2007
- # It is assumed that the cue file is in the same directory with the wav file.
- # The cue file with the same basename with the wav file will be picked.
- # Failing that, the program will pick the first cue file listed by DirHandle.
- use strict;
- use Audio::Wav;
- use Data::Dumper;
- use DirHandle;
- use FileHandle;
- use File::Basename;
- my $wavfile = shift;
- die "Usage: $0 file.wav\n" unless $wavfile;
- die "File $wavfile not found.\n" unless -f $wavfile;
- my $cuefile = find_cue_file($wavfile);
- warn "CUE file not found for $wavfile\n" unless $cuefile;
- my $WAV = new Audio::Wav;
- my $read = $WAV->read($wavfile);
- my $details = $read->details;
- my $Track_Details = {
- bits_sample => $details->{bits_sample},
- sample_rate => $details->{sample_rate},
- channels => $details->{channels},
- };
- exit unless $cuefile;
- my @tracks = parse_cue_file($cuefile, $read);
- print "$#tracks tracks from $cuefile\n";
- my $Max_Buf_Len = 1048576;
- foreach my $i (0 .. ($#tracks-1)) {
- my $track_info = $tracks[$i];
- my $track = $track_info->{TRACK};
- my $name = $track_info->{TITLE};
- my $artist = $track_info->{PERFORMER};
- my $track_file = "${track}_$name.wav";
- $track_file =~ tr|/:| |;
- my @pos = @{$track_info->{POS}};
- my $track_len = $tracks[$i+1]->{POS}->[0] - $pos[0];
- print "TRACK $track '$name' by '$artist' $track_len bytes POS=[@pos]\n";
- my $write = $WAV->write($track_file, $Track_Details);
- $write->set_info('software' => 'Audio::Wav', 'artist' => $artist, 'name' => $name);
- $read->move_to($pos[0]);
- my $read_len = 0;
- while($read_len < $track_len) {
- my $remain = $track_len - $read_len;
- my $buf_len = $remain >= $Max_Buf_Len ? $Max_Buf_Len : $remain;
- my $buf = $read->read_raw($buf_len);
- my $buf_len2 = length($buf);
- $read_len += $buf_len2;
- $write->write_raw($buf, $buf_len2);
- if ($buf_len != $buf_len2) {
- print "Last track: $read_len out of $track_len bytes\n";
- last;
- }
- }
- $write->finish();
- }
- exit;
- sub find_cue_file {
- my ($file) = @_;
- if ($file =~ s/\.\w+$/.cue/) {
- return $file if -f $file;
- $file =~ s/\.cue$/.CUE/;
- return $file if -f $file;
- }
- my $dir = dirname($file);
- my $dh = new DirHandle $dir;
- if (defined $dh) {
- while(my $f = $dh->read) {
- return "$dir/$f" if $f =~ /\.cue$/i;
- }
- }
- }
- sub parse_cue_file {
- my ($cuefile, $wav_in) = @_;
- my $cueh = new FileHandle $cuefile;
- return unless defined $cueh;
- my $wav_data = $wav_in->{data};
- print Data::Dumper->Dump([$wav_data]);
- return unless defined $wav_data;
- my $wav_sec = $wav_data->{length};
- my $wav_offset = $wav_data->{data_start};
- my $wav_bps = $wav_data->{bytes_sec};
- my (@tracks, $href);
- while(<$cueh>) {
- chomp;
- s/\r$//;
- if (/^\s*TRACK\s+(\d+)/i) {
- push(@tracks, $href) if defined $href;
- $href = { TRACK => $1 };
- } elsif (/^\s*INDEX\s+\d+\s+0?(\d+):0?(\d+):0?(\d+)/i) {
- my $pos = $wav_offset + ($1*60 + $2) * $wav_bps + $3*$wav_bps/75;
- $href->{POS} = exists($href->{POS}) ? [@{$href->{POS}}, $pos] : [$pos];
- } elsif (/^\s*(\w+)\s*(\S.*)/) {
- my ($key, $val) = ($1, $2);
- $val =~ s/^"//;
- $val =~ s/"$//;
- $href->{$key} = $val if defined $href;
- }
- }
- if (defined $href) {
- push @tracks, $href;
- push @tracks, { POS => [$wav_data->{total_length}] };
- }
- return @tracks;
- }
复制代码 |
|