back

Nomo.pl

This one is a fun, if slightly odd one. It will create a new wave from sinewaves using data thats interpreted from either an image or another wave file. Uses code from Audio::Wav readme.

Here are some example sounds - wave example (25s - 505kb), jpeg example 1 (1m07s - 1.3mb), jpeg example 2 (1s - 38kb) and jpeg example 3 (<1s - 23kb).

usage: perl nomo.pl input output
#!usr/bin/perl

# nomo.pl
#
# 01.05.2008	-	d.shaw
#
#	program to create a sound from an image
#
#	rough idea is
#					load in the image
#					parse through the data, getting the r,g,b data for each pixel
#					create a sineware with the frequency of r, the amplitude of g and the phase of b
#					write the data as either a .wav
#
#	towards the middle of may	-	added function to create a wave from a wave.  only uses the left side if it's a stereo.  gets the r value starting at
#									the beginning of the wave moving forwards, gets the g value from the end and works backwards
#
#	current usage - nomo (picture|wave) output.wav (0|1)	# last parameter is the debug on/off - defaults to off
#	
# Audio::Wav and some of the code below is (C) Nick Peskett and Kurt George Gjerde


use GD::Image;
use Audio::Wav;
use Math::Trig;

$ver = "nomo v1.0 - (C) d.shaw 2008\n";

&print_header;

&check_file();

exit(0);

###########################################################################################################################

sub print_header() {

	print "$ver";
}

###########################################################################################################################


sub load_file() {							# this one allows us to open any supported file
	
	$open_filename = $_[0];
	
	if (!$open_filename) {
		print "Need an input filename!\n";
		exit(0);
	}
	
	if ( !open( OPENHANDLE, $open_filename ) ) {
        print "Cannot open $open_filename for reading - $!\n";
		exit(0);
    }

	$image = GD::Image->new(*OPENHANDLE);
    close(OPENHANDLE);
    
    &open_wave_file($outputfile);
	&do_something();
	&close_wave_file();
}

###########################################################################################################################


sub load_file_jpeg () {						# this one only opens jpeg images

	$open_filename = $ARGV[0];
	
	if (!$open_filename) {
		print "Need an input filename!\n";
		exit(0);
	}
	
	$image = GD::Image->newFromJpeg($open_filename);

} 

###########################################################################################################################


sub do_something () {

	($width , $height) = $image->getBounds();
	if ($debug) { print "filename - $open_filename\nwidth = $width" . "px" . " height = $height" . "px" . "\n"; }

	$space = $width * $height;
	
	if ($debug) { print "samples = $space\n"; }
	
	$count = 0;

	for ($y = 0; $y < $height; $y++) {
	
		for ($x = 0; $x < $width; $x++) {
		
			($r , $g , $b) = $image->rgb($image->getPixel($x,$y));
			
			if ($debug) {
				if ( $count % 250 == 0 ) { print sprintf( "%06d" , $count) . " $r : $g\n"; }
			}
			
			&me_sine( $r, $g, $b );
				
			$count++;
		}
	}
}

###########################################################################################################################


sub write_file () {

	$write_filename = $ARGV[1];
	
	if (!$write_filename) {
		print "Need an output filename!\n";
		exit(0);
	}
	
	if ( !open( WRITEHANDLE, ">" . $write_filename ) ) {
        print "Cannot open $write_filename for reading - $!\n";
		exit(0);
    }

	binmode WRITEHANDLE;
	print WRITEHANDLE @data;
    close(WRITEHANDLE);
}

###########################################################################################################################


sub open_wave_file () {
	
	$write_filename = $_[0];
	$out_wav = new Audio::Wav;

	$sample_rate = 44100;
	$bits_sample = 16;
	
	$details = {
    	'bits_sample'   => $bits_sample,
    	'sample_rate'   => $sample_rate,
    	'channels'      => 1,
    	# if you'd like this module not to use a write cache, uncomment the next line
    	#'no_cache'     => 1,

	};

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

###########################################################################################################################


sub close_wave_file () {

	$write -> finish();
	print "Done.\n";

}
###########################################################################################################################


sub add_sine {

    my $hz = shift;
    my $length = shift;
    my $pi = ( 22 / 7 ) * 2;
    $length *= $sample_rate;
    my $max_no =  ( 2 ** $bits_sample ) / 2;
    for my $pos ( 0 .. $length ) {
        $time = $pos / $sample_rate;
        $time *= $hz;
        my $val = sin $pi * $time;
        my $samp = $val * $max_no;
        $write -> write( $samp );
	}
}

###########################################################################################################################


sub me_sine {
	
	$this_r = $_[0];
	$this_g = $_[1];
	$this_b = $_[2];
	
	$stepvalue = 360 / $this_r;
	$steppointer = 0;
	
	$this_r = $this_r;
	
	$this_g = $this_g * 128;				#	16 bit values so need to multiply by 128 (+/- 15 bit)
	
	for $lp ( 0 .. $this_r) {
	
		$samp = sin ( deg2rad( $steppointer ) ) * $this_g;		# sin() take the parameter in radians
		
		$write -> write( $samp );
		$steppointer = $steppointer + $stepvalue;
	}
}

###########################################################################################################################


sub check_file {
		
		$checkfilename = $ARGV[0];
		
		$outputfile = $ARGV[1];
		
		$debug = $ARGV[2];
		
		$cfn_len = length ( $checkfilename );
		
		$extension = substr ( $checkfilename , $cfn_len-4 , 4 );
		
		$extension = lc ( $extension );
		
		if ($debug) { print "cfn_len = $cfn_len extension = $extension\n"; }

		if ( $extension =~ ".wav") {
			if ($debug) { print "it\'s a wave!\n"; }
			&load_wave ( $checkfilename );
			}
		else {
			if ($debug) { print "it\'s an image!\n"; }
			&load_file ( $checkfilename ) ;
		}
}

###########################################################################################################################


sub load_wave {

	$open_filename = $_[0];
	
	if (!$open_filename) {
		print "Need an input filename!\n";
		exit(0);
	}
	
	if ($debug) { print "$open_filename\n"; }
	
	$in_wav = new Audio::Wav;
	$in_read = $in_wav -> read( $open_filename );
   
    &open_wave_file($outputfile);
	&do_something_waveinput();
	&close_wave_file();
}

###########################################################################################################################


sub do_something_waveinput {

	$length = $in_read -> length();
	if ($debug) { print "length = $length\n"; }
	
	for $lp ( 0 .. $length) {

		@lr = $in_read -> read();
		$value = $lr[0];
		$value = $value + 32768;					# 2^15 = 32768
		$value = ($value / 256) ;					# need to divide by 256 as we're using 16 bit value, not signed 15 bit
		
		$value = int ( $value );
		
		if ( $value == 0 ) { $value++ };
		
		# get the amp value by going backward through the file.
			
		$amp_point = $length - $lp;
		$in_read -> move_to( $amp_point );
		@lr = $in_read -> read();
		$amp_value = $lr[0];
		$amp_value = $amp_value + 32768;					# 2^15 = 32768
		$amp_value = ($amp_value / 256) ;					# need to divide by 256 as we're using 16 bit value, not signed 15 bit
		
	 	$amp_value = int ( $amp_value );
		
		if ( $amp_value == 0 ) { $amp_value++ };
		
		&me_sine ( $value , $amp_value , 1 );
				
		$in_read -> move_to( $lp );
		
		if ($debug) {
			if ( $lp % 250 == 0 ) { print sprintf( "%06d" , $lp) . " $value : $amp_value\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