sub cat_waves(@){ my ($out, @list)=@_; my $me = whoami(); # $me is like "Util::cat_waves", i.e "this" subroutine name my $BUFSIZE = 8 * 2**10; myprint ("$me: Creating \"$out\" using ".scalar@list." input \".wav\" files..."); unless ( (defined ($out)) && (@list >0) ){ showfailed( "$me - Internal Error: not enough arguments supplied"); return; } # The final output file format will be: # "RIFF" (4 bytes) # riff size (4 bytes) (total bytes that follow from here) # voice format info (42 bytes) #some weird voodoo is in here # "data" (4 bytes) # data size (4 bytes) (voice bytes that follow from here) # all of the voice data (n bytes), must be word aligned. # EOF # 4 byte integers are Intel, VAX "little endian" convention. # Some of the standard company voice edited .wav files contain other # weird segments after the voice data segment. These will be deleted in # the final concatentated .wav file. my ($new_data_size, @data_file_info) = get_data_sizes(@list); my $new_riff_size = $new_data_size + 42+8; #allow for wave format info + DATA header myprint ("New File: \"$out\" will be created now..."); myprint (" total file size = ",$new_riff_size + 8); myprint (" RIFF segment size = $new_riff_size"); myprint (" DATA segment size = $new_data_size"); open (OUTBIN, ">$out") || showfailed("$me: unable to open $out"); binmode(OUTBIN) || showfailed("$me: unable to set binmode $out"); my $buff; # write the new RIFF header to the output file. my $header_file = $list[0]; #"steal" the header from first input file myprint ("Using header info from file: $header_file"); open(INBIN, "<$header_file") || showfailed("$me: unable to open $header_file"); binmode(INBIN) || showfailed("$me: unable to set binmode $header_file"); my $n_bytes = read(INBIN, $buff, $BUFSIZE); ($n_bytes > 58) || showfailed("$me: too few bytes ($n_bytes) in $header_file"); my $rsize = pack("V4", $new_riff_size); # "V4" means Vax or Intel "little endian" substr($buff,4,4) = substr($rsize,0,4); my $data_size = pack("V4", $new_data_size); substr($buff,54,4)= substr($data_size,0,4); print OUTBIN substr($buff,0,58); close INBIN || showfailed("$me: unable to close $header_file"); #now just extract the data from all the .wav files and append to OUTBIN while (@data_file_info){ my ($wave, $xfer) = @data_file_info; open(INBIN, "<$wave") || showfailed ("$me: unable to open $wave"); binmode(INBIN) || showfailed ("$me: unable to set binmode $wave"); myprint ("Appending voice data from $wave..."); my $i_buf_low=58; #don't transfer the initial header stuff in the RIFF files. while ($xfer>0){ my $n_buf_bytes = read(INBIN, my $buff, $BUFSIZE); my $n = $n_buf_bytes - $i_buf_low; if ($xfer-$n <0 ){$n = $xfer;} #don't xfer past the end of current data segment. $xfer -= $n; print OUTBIN substr($buff,$i_buf_low,$n); $i_buf_low = 0; } close (INBIN) || showfailed ("$me: unable to close $wave"); } #end of while (@data_file_info) close(OUTBIN) || showfailed ("$me: unable to close $out"); myprint ("$me: Success \"$out\" has been created!"); return; } #end of cat_waves()