Tech Tidbits - Ruby, Ruby On Rails, Merb, .Net, Javascript, jQuery, Ajax, CSS...and other random bits and pieces.

Showing posts with label Perl. Show all posts
Showing posts with label Perl. Show all posts

Friday, May 25, 2007

Audio file conversion

Here's a collection of small scripts for converting audio file formats using lame, mpg123, and mplayer.

wav2mp3.pl

#!/usr/bin/perl
use strict;
use warnings;

my $in = "/home/doug/music/somedir/";
my $out = $in;

opendir DH_IN, $in || die "Can't open $in: $!";
foreach my $name (sort readdir(DH_IN)) {
next unless $name =~ /\.wav$/;
print "NAME: $name\n";
my($base_name) = ($name =~ /^(.*)\.wav$/);
my $in_file = "${in}$base_name.wav";
my $out_file = "${out}$base_name.mp3";
`lame -b 192 $in_file $out_file`;
}
close DH_IN;


wav2mp3.sh

#!/bin/sh
bitrate="192"
for wavfile in *.wav
do
echo "input: $wavfile"
mp3file=`echo $wavfile | sed s/\\.wav/.mp3/`
echo "output: $mp3file"
lame -b $bitrate $wavfile $mp3file
done


mp32wav.sh

#!/bin/sh
for mp3file in *.mp3
do
echo "input: $mp3file"
wavfile=`echo $mp3file | sed s/\\.mp3/.wav/`
echo "output: $wavfile"
mpg123 -w $wavfile $mp3file
done


wma2mp3.sh

#!/bin/sh

if [ -z "$1" ]
then
echo "Usage: wma2mp3 "
exit 1
fi

name=`echo $1 | tr ' ' '_' | tr '[A-Z]' '[a-z]'`

name="`basename "$name" .wma`.mp3"

cp "$1" $name

mplayer -vo null -vc dummy -af resample=44100 -ao pcm:waveheader $name && lame -m s -h --vbr-new audiodump.wav -o $name


m4a2mp3.sh

#!/bin/sh

MPLAYER=mplayer
LAME=lame

for m4a in *.m4a
do

mp3=`echo "$m4a" | sed -e 's/m4a$/mp3/'`
wav="$m4a.wav"

if [ ! -e "$mp3" ]; then
[ -e "$wav" ] && rm "$wav"
mkfifo "$wav" || exit 255
mplayer "$m4a" -ao pcm:file="$wav" &>/dev/null &
lame "$wav" "$mp3"
[ -e "$wav" ] && rm "$wav"
fi
done

Finding installed Perl modules

I don't recall where I came across this little script, but it's quite handy for finding installed Perl modules along with their versions.


#!/usr/bin/perl
use strict;

use ExtUtils::Installed;
my $instmod = ExtUtils::Installed->new();
foreach my $module ($instmod->modules()) {
my $version = $instmod->version($module) || "???";
print "$module -- $version\n";
}

Saturday, April 28, 2007

Perl - DateTime

Our servers were recently switched from using local time to UTC. This had an affect on our content, causing it to show several hours early since content availability is based on local time. In the past we had relied on Date::Calc on other various date manipulations using epoch seconds. Having recently worked on two projects with Catalyst, I had become familiar with the Perl module DateTime. Not only was converting UTC to local time a breeze, DateTime required far fewer lines of code, not to mention the ease and readability of date manipulations.

The standard Unix date command shows the server is on UTC:

kl93@oiche/home/kl93:$ date
Sat Apr 28 13:10:15 UTC 2007


or in Perl:

my $date = localtime(time);
print "$date\n";


returns

2007-04-28T13:16:29


Now, using DateTime module:

#!/usr/bin/perl
use strict;
use DateTime;
my $dt = DateTime->now();
print $dt->datetime(), "\n";


Output:

kl93@oiche:/home/kl93$ perl datetime1.pl
2007-04-28T13:23:15


To get local time, you can either set the desired time zone when you create the DateTime object:

#!/usr/bin/perl
use strict;
use DateTime;
my $dt = DateTime->now(time_zone => 'America/Chicago');
print $dt->datetime(), "\n";


or set it after you've created the object:

#!/usr/bin/perl
use strict;
use DateTime;
my $dt = DateTime->now();
$dt->set_time_zone('America/Chicago');
print $dt->datetime(), "\n";


Now we have local time for US Central:

kl93@oiche:/home/kl93$ perl datetime2.pl
2007-04-28T08:29:56


Using a named time zone like 'America/Chicago' is nice, as it will calculate DST changes. However, it's not recommended for dates far in the future (read the Pod).

You can also use "today" in place of "now," which will only initialize the date, not the time:


#/usr/bin/perl
use strict;
use DateTime;
my $dt1 = DateTime->today();
print "dt1: ", $dt1->datetime(), "\n";
my $dt2 = DateTime->now();
print "dt2: ", $dt2->datetime(), "\n";



kl93@oiche:/home/kl93$ perl datetime3.pl
dt1: 2007-04-28T00:00:00
dt2: 2007-04-28T17:53:32


You can also initialize the DateTime object to any valid date by passing passing parameters to the constructor:

#!/usr/bin/perl
use strict;
use DateTime;
my $dt = DateTime->new( year => 2001,
month => 4,
day => 23,
hour => 10,
minute => 45,
second => 30,
time_zone => 'America/Chicago',
);
print $dt->datetime(), "\n";


We can see that the date has been initialized to April 23, 2005 at 10:45:30 (am):

kl93@oiche:/home/kl93$ perl datetime4.pl
2001-04-23T10:45:30


There are several accessors - a quick perusal of the Pod shows:

$dt->year;
$dt->month; # 1-12 - also mon
$dt->day; # 1-31 - also day_of_month, mday
$dt->day_of_week; # 1-7 (Monday is 1) - also dow, wday
$dt->hour; # 0-23
$dt->minute; # 0-59 - also min
$dt->second; # 0-61 (leap seconds!) - also sec
$dt->day_of_year; # 1-366 (leap years) - also doy
$dt->day_of_quarter; # 1.. - also doq
$dt->quarter; # 1-4


I won't cover everything, that's what the Pod is for, but a few handy features include easy date formating and date calculations.

A few formatting built-ins:

$dt->ymd; # 2007-04-28
$dt->ymd('/'); # 2007/04/28
$dt->ymd('') # 20070428

$dt->mdy; # 04-28-2007
$dt->mdy('/'); # 04/28/2007
$dt->mdy(''); # 04282007

$dt->dmy; # 28-04-200
$dt->dmy('/'); # 28/04/2007
$dt->dmy(''); # 28042007

$dt->hms; # 12:33:45


And if you need it, you can use 'strftime' for further formatting:

$dt->strftime("%A, %B %d, %Y"); # Saturday, April 28, 2007


A few date manipulations:

You can update an existing DateTime object to another date:

#!/usr/bin/perl
use strict;
use DateTime;
my $dt = DateTime->new( year => 2001,
month => 4,
day => 23,
hour => 10,
time_zone => 'America/Chicago',
);
print $dt->ymd, "\n";

$dt->set( year => 2007 );
$dt->set( month => 11 );
$dt->set( day => 30 );
print $dt->ymd, "\n";


We can see that the date was changed from 2001-04-23 to 2007-11-30:

kl93@oiche:/home/kl93$ perl datetime5.pl
2001-04-23
2007-11-30


You can find x number of years, months, days from a date by using "add" and "subtract" on your DateTime object.

To find one month from today:

#!/usr/bin/perl
use strict;
use DateTime;
my $dt = DateTime->now();
print $dt->datetime(), "\n";
print $dt->add(months => 1), "\n";


Output:

kl93@oiche:/home/kl93$ perl datetime6.pl
2007-04-28T14:05:35
2007-05-28T14:05:35


Or one month previous:

#!/usr/bin/perl
use strict;
use DateTime;
my $dt = DateTime->now();
print $dt->datetime(), "\n";
print $dt->subtract(months => 1), "\n";


Output:

kl93@oiche:/home/kl93$ perl datetime7.pl
2007-04-28T14:07:42
2007-03-28T14:07:42


One note - DateTime objects are hash references, so if you want to keep your original DateTime object unchanged, you need to clone your object and then use "add" or "subtract" to get the calculated date.

Here we simply copy $dt1 and update $dt2.

#/usr/bin/perl
use strict;
use DateTime;
my $dt1 = DateTime->now();
print "dt1: ", $dt1->datetime(), "\n";
my $dt2 = $dt1;
$dt2->add(months => 1), "\n";
print "dt2: ", $dt2->datetime(), "\n";
print "dt1: ", $dt1->datetime(), "\n";


Note that once $dt2 is modified, $dt1 is modified as well (they both "point" to the same DateTime object:

kl93@oiche:/home/kl93$ perl datetime8.pl
dt1: 2007-04-28T17:19:46
dt2: 2007-05-28T17:19:46
dt1: 2007-05-28T17:19:46


To prevent this, use the clone method to create a totally new DateTime object:

#/usr/bin/perl
use strict;
use DateTime;
my $dt1 = DateTime->now();
print "dt1: $dt1->datetime(), "\n";
my $dt2 = $dt1->clone;
$dt2->add(months => 1), "\n";
print "dt2: ", $dt2->datetime(), "\n";
print "dt1: ", $dt1->datetime(), "\n";


Now $dt1 remains unchanged:

kl93@oiche:/home/kl93$ perl datetime9.pl
dt1: 2007-04-28T17:23:39
dt2: 2007-05-28T17:23:39
dt1: 2007-04-28T17:23:39


Find out more about the DateTime module at the Perl DateTime Wiki or at CPAN (written by Dave Rolsky)

Saturday, April 21, 2007

Java/Perl - Command-line arguments

Command-line arguments are passed to a Perl program in the array @ARGV.

Perl

#!/usr/bin/perl
use strict;
use warnings;

my $num_args = @ARGV;
print "Length of \@ARGV array: $num_args\n";
for(my $i = 0; $i %lt; $num_args; $i++) {
print "Argument $i = |$ARGV[$i]|\n";
}

# another way to loop through arguments
my $count = 0;
for my $arg(@ARGV) {
print "Argument $count = |$arg|\n";
$count++;
}


Output:


[kl93@localhost ]$ perl args.pl Eeyore Piglet "Pooh Bear"
Argument 0 = |Eeyore|
Argument 1 = |Piglet|
Argument 2 = |Pooh Bear|
Length of @ARGV array: 3
Argument 0 = |Eeyore|
Argument 1 = |Piglet|
Argument 2 = |Pooh Bear|


Command-line arguments are passed to main method in a Java program. The arguments are passed as a String array called args (or whatever you may choose to call it).

Java

public class Args
{
public static void main(String[] args)
{
System.out.println("Length of args array: "
+ args.length);

for(int i = 0; i < args.length; i++)
{
System.out.println("Argument " + i + " = |" + args[i] + "|");
}
}
}


Output:


[kl93@localhost ]$ java Args Eeyore Piglet "Pooh Bear"
Length of args array: 3
Argument 0 = |Eeyore|
Argument 1 = |Piglet|
Argument 2 = |Pooh Bear|

Java/Perl - String comparison (eq)

In Perl, comparison operators are used when comparing either numbers or strings. For comparing strings, the comparison operator for equality is 'eq.' Unlike Java, Perl doesn't have a String class as Perl is a "typeless" language. However, Perl scalar variables can contain numbers or strings, so there isn't much difference between 999 (number) or '999' (string). So comparing strings in Perl for equality is fairly straight forward.

Perl

#!/usr/bin/perl
use strict;
use warnings;

my $string1 = 'Eeyore';
my $string2 = 'Eeyore';

if($string1 eq $string2) {
print "True\n";
} else {
print "False\n";
}


The output is:

True


In Java, strings are objects. In most cases when an equality comparison is made between two strings, it is the value of the two strings that we want to compare. To check if two strings have the same value, the 'equals' method is used.

Java

public class Equals
{
public static void main(String[] args)
{
String string1 = "Eeyore";
String string2 = "Eeyore";
if(string1.equals(string2))
System.out.println("True");
else
System.out.println("False");
}
}


The output is:

True


Note that with Java, there are two ways to create a new string.

  1. String string1 = "Eeyore";
  2. // informal method
  3. String string2 = new String("Eeyore");
  4. // formal method


There is a subtle difference. With the the informal method, String objects are created and the JVM places them in the "literal pool," an area in JVM memory that allows shared access to String objects. In this case, before a new String object is created, the literal pool is checked to see if an identical string already exists, and if so it is reused. If not, a new String is created and added to the literal pool. That way, if several strings are created with the same value, they all point to the same String object.

With the formal method, a new String object is created even if the same string already exists. In this case the String object is placed in the JVM general memory.

To check if two Strings point to the same object, the '==' operator is used.


public class Equals2
{
public static void main(String[] args)
{
String string1 = "Eeyore";
String string2 = "Eeyore";
String string3 = new String("Eeyore");

if(string1.equals(string2))
System.out.println("True");
else
System.out.println("False");

if(string1.equals(string3))
System.out.println("True");
else
System.out.println("False");

if(string1 == string2)
System.out.println("True");
else
System.out.println("False");

if(string1 == string3)
System.out.println("True");
else
System.out.println("False");
}
}


The output is:

True
True
True
False


This shows that string1 and string2 have the same value and point to the same String object. This also shows that while string1 and string3 have the same value, they point to different String objects.

Java/Perl - split

split breaks up (or splits) a string into "tokens" or substrings according to a separator. split uses a regular expression as the separator.

Perl


#!/usr/bin/perl
use strict;
use warnings;

my @fields = split /:/, "jim:bob:frank:steve";
foreach my $field (@fields) {
print "$field\n";
}

my $string = "one two three four\tfive";
my @array = split /\s+/, $string;
foreach my $el(@array) {
print "$el\n";
}


Output:

jim
bob
frank
steve
one
two
three
four
five


Java 1.4 added the split() method to the String class.

Java


public class Split
{
public static void main(String[] args)
{
String string1 = "jim:bob:frank:steve";
String[] names = string1.split(":");
for(int i=0; i<names.length; i++)
System.out.println(names[i]);

String string2 = "one two three four\tfive";
String[] words = string2.split("\\s+");
for(int i=0; i<words.length; i++)
System.out.println(words[i]);
}
}


It is also possible to use the java.util.StringTokenizer to break a string into tokens.


import java.util.StringTokenizer;

public class StringToke
{
public static void main(String[] args)
{
String string1 = "jim:bob:frank:steve";
StringTokenizer st1 = new StringTokenizer(string1,":");
while(st1.hasMoreTokens())
System.out.println(st1.nextToken());

String string2 = "one two three four\tfive";
StringTokenizer st2 = new StringTokenizer(string2);
while(st2.hasMoreTokens())
System.out.println(st2.nextToken());
}
}


Output:

jim
bob
frank
steve
one
two
three
four
five


If no regular expression pattern is used, split defaults to using white space as the separator. (both in Perl and Java)

Java/Perl - Directory handles

With Perl, one way to get a list of names in a given directory is to use a directory handle. On my Fedora box, Perl displays "." and ".." while Java does not.

Perl

#!/usr/bin/perl
use strict;
use warnings;

my $dir = '/home/kl93';
opendir DH, $dir or die "Cannot open $dir: $!";
foreach my $file (readdir DH) {
next if $file =~ /^\.\.?$/; # skip . and ..
print "$file\n";
}
close DH;


Java

import java.io.*;

public class ReadDir
{
public static void main(String[] args) throws Exception
{

File file = new File("/home/kl93");

if( !file.exists() || !file.canRead() )
{
System.out.println("Can't read " + file);
return;
}

if( file.isDirectory() ) {
String[] files = file.list();
for(int i=0; i<files.length; i++)
System.out.println(files[i]);
}
else {
System.out.println(file + " is not a directory");
}
}
}


If you want to display filenames based on some sort of criteria - like all files with the .java extension for example - then it's often easiest to use a regular expression.

Perl

#!/usr/bin/perl
use strict;
use warnings;

my $dir = '/home/kl93';
opendir DH, $dir or die "Cannot open $dir: $!";
foreach my $file (readdir DH) {
next unless $file =~ /\.java$/;
print "$file\n";
}
close DH;


Java

import java.io.*;
import java.util.regex.*;

public class ReadDir2
{
public static void main(String[] args) throws Exception
{

File file = new File("/home/kl93");

if( !file.exists() || !file.canRead() )
{
System.out.println("Can't read " + file);
return;
}

if( file.isDirectory() ) {
String[] files = file.list();
for(int i=0; i<files.length; i++)
{
if(files[i].matches("^.*\\.java$"))
System.out.println(files[i]);
}
}
else {
System.out.println(file + " is not a directory");
}
}
}


Or


import java.io.*;
import java.util.regex.*;

public class ReadDir3
{
public static void main(String[] args) throws Exception
{

File file = new File("/home/kl93");

if( !file.exists() || !file.canRead() )
{
System.out.println("Can't read " + file);
return;
}

if( file.isDirectory() ) {
String[] files = file.list();
Pattern pattern = Pattern.compile("\\.java$");
Matcher matcher;
for(int i=0; i<files.length; i++)
{
matcher = pattern.matcher(files[i]);
if(matcher.find())
System.out.println(files[i]);
}
}
else {
System.out.println(file + " is not a directory");
}
}
}


Sort (ascending)

Perl

#!/usr/bin/perl
use strict;
use warnings;

my $dir = '/home/kl93';
opendir DH, $dir or die "Cannot open $dir: $!";
foreach my $file (sort readdir(DH)) {
print "$file\n";
}
close DH;


Sort desending


#!/usr/bin/perl
use strict;
use warnings;

my $dir = '/home/kl93';
opendir DH, $dir or die "Cannot open $dir: $!";
foreach my $file (reverse(sort readdir(DH))) {
print "$file\n";
}
close DH;

About Me

My photo
Developer (Ruby on Rails, iOS), musician/composer, Buddhist, HSP, Vegan, Aspie.

Labels