back

tlp.pl - Time-Lapse Phonography

Most people are familiar with Time-Lapse Photography, whereby a collection of images taken a specified time apart are combined to make a video. This software does something similar but with sound.

There are generally two main methods of created a Time-Lapse with images. The first is to use an intervalometer to take a specific number of photos a specifc period of time apart. The other is to take a frame (or frames) from an existing video at a specified interval. This is the method that I've chosen to use for my Time-Lapse Phonography implementation.

There are two main parameters that are used by TLP, the interval to keep and the interval to skip. The image below shows an example.




usage: perl tlp.pl input.wav output.wav interval-1 interval-2

	input.wav is the source audio
	output.wav is the edited / truncated data and will match the specifications of the input wave
	interval-1 is the time in seconds of the data to keep
	interval-2 is the amount of time to skip

#!usr/bin/perl

# tlp.pl	-	Time Lapse Phonography
# (C)		-	Darren Shaw
# date		-	10th - 17th May 2012
#
# Synopsis	-	Using a process similar to taking time lapse photographs (using an intervalometer) this script with take a wave file as the input
#			and iterate through the data keeping the length of data specified and then skipping over until the next one.
#
#			For example this could be used to create a new waveform from just for first second in the minute for the length of a track.  
#			So a 5 minute track would be condensed down into 5 seconds of audio.
#
#			It will create an output wave file that matches the parameters of the input wave file (specifically sample rate, bit depth and 
#			number of channels).
#
# Overview	-	load the close the wave
#			parse the wave for it's paramaters - bit depth, sample frequency, channels, length
#			allocate a new output wave with the parameters of the input
#			calculate how many 'keepers' we'll need ( length / (interval-1 + interval-2) )
#			iterate through the input, copying the data to the output
#			write / close the output wave
#
# todo		-	sort out a cross fade to avoid the clicks where the samples join
#			make it quicker
#			put in some error checking / sanity checks
#			- current bug is that if the int-2 time is longer than the sample then it just exits after writing the .wav header
#			  but that's to be expected because it the number_of_keepers is less than one and reduces to either 1 or 0 as an int()


use Audio::Wav;

$ver = "Time Lapse Phonography " . "v1.0 " . "(C) Darren Shaw 2012" . "\n";

$debug = 0;

print $ver;

# Alocate my variables from the command line

$input_filename = $ARGV[0];
$output_filename = $ARGV[1];
$interval_one = $ARGV[2];
$interval_two = $ARGV[3];

if ($debug) { print "$input_filename $output_filename $interval_one $interval_two\n";}


&load_wave ( $input_filename );
&create_output_wav ( $output_filename) ;
&iterate ();
&close_output_wave () ;

exit(0);

###################################################################################################
####
#### Load the input wave and parse the parameters
####

sub load_wave {

	$open_filename = $_[0];
	
	$in_wav = new Audio::Wav;						# Create and Wave object
	$in_data = $in_wav -> read( $open_filename );	# Read the file
	$in_length = $in_data -> length_samples();		# Get it's length in ** SAMPLES **
	
}

###################################################################################################
####
#### Create the output wave file - uses parameters from the input wave file
####

sub create_output_wav {
	
	$write_filename = $_[0];
	$out_wav = new Audio::Wav;

	$sample_rate = $in_data -> details -> {sample_rate};
	$bits_sample = $in_data -> details -> {bits_sample};
	$audio_channels = $in_data -> details -> {channels};
	
	$interval_one_samples = $interval_one * $sample_rate;
	$interval_two_samples = $interval_two * $sample_rate;
	
	print "Details - $sample_rate" . "hz" . " / " . "$bits_sample" . "bit" . " / " . "$audio_channels" ." channel";
	if ( $audio_channels > 1 ) { print "s"; }			# lets be grammatically correct, eh?
	print "\n";
	
	$details = {
    	'bits_sample'   => $bits_sample,
    	'sample_rate'   => $sample_rate,
    	'channels'      => $audio_channels,
    	# if you'd like this module not to use a write cache, uncomment the next line
    	#'no_cache'     => 1,

	};

	$out_write = $out_wav -> write( $write_filename, $details );
}

###################################################################################################
####
#### Closed the output wave file
####

sub close_output_wave () {

	$out_write -> finish();
	print "\nDone.\n";

}


###################################################################################################
####
#### Iterate throught the input and copy the data to the output wave
####

sub iterate () {
	
	$| =1;		# This sets the autoflush to be true which means that the terminal output doesn't get buffered
	 
	$number_of_keepers = $in_length / ( $interval_one_samples + $interval_two_samples );
	if ($debug) { print "number_of_keepers = $number_of_keepers\n"; }
	
	$number_of_keepers = int ( $number_of_keepers );
	if ($debug) { print "number_of_keepers = $number_of_keepers\r"; }

	
	$current_position = 0;	
	
	for $counter ( 1 .. $number_of_keepers ) {		# for each interval_one do this little loop to copy it
	
		print "Working - $counter / $number_of_keepers\r";
		
		for $anothercounter ( 0 .. $interval_one_samples ) {
		
			$in_data -> move_to_sample ( $current_position );	# move within the input wave to the new start location
			
			# @lr = $in_data -> read();					# get the array of values at the current location
			# $out_write -> write( @lr );				# write it to the output file
			
			$out_write -> write( $in_data -> read() ) ;	# the above lines can be joined together in this one for an approx 3% speed increase
			
			$current_position++;
		}
	
		$current_position = $current_position + $interval_two_samples;	# move to the new start of the keeper
		if ($debug) { print "current_position = $current_position\n"; }
	}
		
}

All this code is © 2006 - 2015, except for the noted pieces which are © to their authors as noted. Feel free to use anything you find here, I'm not that precious about it. Take it, improve it, make lots of cash with it, it's a gift.

back