Category: Software

Saving streaming audio on Linux

MONITOR=$(pactl list | egrep -A2 ‘^(\*\*\* )?Source #’ | grep ‘Name: .*\.monitor$’ | awk ‘{print $NF}’ | tail -n1)

goes to alsa_output.pci-0000_00_1b.0.analog-stereo.monitor on my system

LAMEOPTIONS=’ -s 44.1 –preset cbr 192′
FILENAME=foo.mp3

Record currently playing audio:
parec -d $MONITOR | lame $LAMEOPTIONS -r $FILENAME

Split into separate 1 hr files with a 3 sec overlap:
ffmpeg -ss 00:00:00 -t 01:00:03 -i foo.mp3 $1.01.mp3 -acodec copy
ffmpeg -ss 01:00:00 -t 01:00:03 -i foo.mp3 $1.02.mp3 -acodec copy

Commands from here

App game idea

Flip it

This game board is an array of tiles. The tiles have letters. The game play involves flipping a pair of letters, as if the two tiles can move through the screen on the axis that connects them. In any case, they move switches them. The goal is to rearrange the tiles to spell words.
Move:

cat --flip c:a--> act
dog ------------> dog

cat --flip c:d--> dat
dog ------------> cog

The game can be played different sized boards, and with boards with cutouts.
Variation 1: Have the tiles have both color and a letter, to distinguish common letters.
Variation 2: Have the tiles be two sided, so that flipping them exposes the other sides.

What is interesting about this is that it is a class of games easy to implement in the computer but which is hard or impossible to implement as a physical game. There is a whole class of variations on pen and pencil or board games that haven’t been tried because of this!

Postscript site

Here’s a site with a good Postscript library for drawing variable width lines.

To add a rounded end I added an arc command after the bolt function:
20 setlinewidth
newpath 0 0 moveto
0 -50 200 -150 200 0 rcurveto
currentpoint
reversepath bolt
5 0 179 arc
fill

I used two of these curves to draw a stylized pear.

L-system Iterator

I’ve put up a web site for exploring L-system images, L-system Iterator.

Well known L-systems

The snowflake shape is only one example of the pictures that can be drawn this way.

L-systems are simple iterated drawing rules. Simple rules for turning and drawing put together in this way make quite interesting and complicated patterns. The ones shown above are well known. From the the left, the Koch snowflake, the Sierpinski triangle, a kolam-like image, and a plant-like image. On the second row, the Heighway dragon, the Hilbert curve, and another plant.

The Heighway dragon has many interesting properties–for example, it can be tiled over the plane.

Some iterated objects are fractals–the Koch snowflake, Sierpinski triangle, and Hilbert curve are famous simple fractals.

L-systems can be quite complicated. The systems modeled on my web site use a single rotation angle and only one line width. More complicated models can make surprisingly realistic plants. Prusinkiewicz and Lindenmayer (the L in L-system) have developed detailed plant models.

The web site is based on the Perl code I wrote for my Biomorph evolution/selection web site. The images are generated using Postscript to draw the L-system, and then the ImageMagick convert program to change it to a PNG image. Images are given a file name that describes the L-system, effectively caching the image. The Prototype Javascript library is used to assist in making the popup boxes.

Each L-system variant has two changes from the current L-system. Some logic is used to keep the L-system in the same family–if there’s no Y equation, one isn’t added. Existing equations are grown or shrunk but not dropped. These images can take much longer to generate than the Biomorph images, so a number of limits are placed to keep the L-system from getting too complicated or taking too much CPU time.

The hardest part of the Postscript was getting the images scaled and centered appropriately. The images can extend in any direction and some are large, others small. The centering code generates the image twice, once to find out its dimensions and then a second time scaled and centered. Here’s the code to record the dimensions of each part of the image. It gets called before each stroke operation.

/max_path {
gsave initmatrix pathbbox grestore


ur_y false eq { /ur_y exch store } { dup ur_y gt { /ur_y exch store } { pop } ifelse } ifelse
ur_x false eq { /ur_x exch store } { dup ur_x gt { /ur_x exch store } { pop } ifelse } ifelse
ll_y false eq { /ll_y exch store } { dup ll_y lt { /ll_y exch store } { pop } ifelse } ifelse
ll_x false eq { /ll_x exch store } { dup ll_x lt { /ll_x exch store } { pop } ifelse } ifelse
} def

The ‘initmatrix’ command is required to reset things because of all the rotation operations.

The code for the site is linked on the L-system iterator home page.

Update: Added color variation as an option. And a reverse direction primitive.

Also, the code now runs under mod_perl.

Note for mod_perl users–mod_perl 2.0 has no way of handling alarms. select() doesn’t work either as a way of timing out pipes. The only usable method is prepending commands with ‘ulimit -t secs’ and letting the shell limit the system process.

To make the split color B&W images I used these ImageMagick commands:
convert -size 150x150 tile:color.png tile:bw.png ../temp/mask.png -composite split.png
using a half black, half white split image as the mask.

Then added the split line using:
convert -size 150x150 -fill white -stroke black -draw "line 0,0 150,150" split.png split_line.png

Putting video clips on my blog

Putting video clips on my blog was a bit harder than I expected. I first tried converting the .MOV files the camera writes into .avi files using ffmegX and posting them using <embed> tag code. The files showed up great on my Mac but not at all on a Windows computer.

Flash format files, .flv, are the easiest cross-platform way to post video clips. Flash does require that the site supply a Flash player. There are many Flash players available. I tried OS FLV and it worked nicely.

To edit video files I used avidemux, then ffmegX to convert them to .flv, and I put them on the site using the ‘noscript’ <embed> code suggested by OS FLV with the OS FLV player.swf.

Indie games

I ran across the independently produced game World of Goo. Fun game, the stylish graphics caught my eye.

So I wondered what was involved in creating a modern game. What’s done? Tech wise, graphics engine, physics engine, AI, etc. Art and sound. Looked around, found these two sites:

Indie Game Developer Links
Gamedev.net

Never found the a straightforward answer to my question though.

Addendum:

Reading the ‘how we made it’ articles on their site, it looks like World of Goo was made using the open source PopCap framework. PopCap includes two physics engines, the 2D Chipmonk Physics library and the 3D ODE physics library!

Spelunking partition tables with testdisk

I have my home directories on a separate drive from the OS, and after upgrading Fedora I went to remount my home directory and ran into problems. First off, the new Fedora had renamed hda as sda and so all the drive naming was off. I had my home directory disk mirrored in RAID 1, but some months ago one the the drives went bad and I dropped it from the array but left it plugged in until I had time to deal with it.

So I looked around for my home directory disk and mounted the one that had gone bad. It was working fine when I mounted it, so I didn’t notice until a few days later when it I noticed recently created files were missing and eventually figured it out.

So I could find the ‘good’ home directory disk and mount it, right? Not so easy, it turned out to have a small ext2 partition and a large LVM partition. Which is not the way it should be, it should have one partition. I mount the small one, and it throws ‘read past end of disk’ errors. It takes quite a while to figure out how to mount and read the LVM partitions. LVM is a really, really idea. The LVM tools couldn’t find a filesystem on the LVM partition, and after much hair pulling I realized that there really *wasn’t* one, that the partition shouldn’t exist. Because it was LVM, this took about 10X longer than it should have.

Now running with the hypothesis that the home directory disk had picked up a disk error in the partition table (Argg^&@$#@!), I made a backup image of the drive using dd:

dd if=/dev/hdc of=/data/hdc_copy.bin

Then I mounted the image as a loopback device:

losetup /dev/loop0 /data/hdc_copy.bin

And started working with the image to repair it. Looking around, testdisk seemed promising, so I installed it, ran it. Testdisk finds potential partitions on the disk, and lets you view the files in them to see if it has guessed right. After a few tries I found a testdisk partition that contained my home directories. At this point I used testdisk’s copy function to save the most critical recently (no backup) changed directories. This worked and I was hopeful. Then I had testdisk write the partition it had found to the disk image.

Now running fdisk on /dev/loop0 shows the single partition (/dev/loop0p1) spanning the whole disk as expected. /dev/loop0 can’t be mounted by itself as it is an image of the disk, not a file system (/dev/loop0p1 isn’t a device in /dev, just a fdisk label). So I had to mount the partition as a second loopback device using the info from fdisk to find the correct offset:


Disk /dev/loop0: 203.9 GB, 203928109056 bytes
1 heads, 1 sectors/track, 398297088 cylinders, total 398297088 sectors
Units = cylinders of 1 * 512 = 512 bytes
Disk identifier: 0x00000000

Device Boot Start End Blocks Id System
/dev/loop0p1 64 398283327 199141632 83 Linux

So I tried an offset of 64 * 512 = 32768:

losetup -o 32768 /dev/loop1 /dev/loop0

and then ran e2fsck on /dev/loop0. But e2fsck wasn’t happy, and none of the alternate superblocks worked either. Finally I found a reference to doing this that mentioned setting fdisk to sectors first:


Command (m for help): u
Changing display/entry units to sectors

Command (m for help): p

Disk /dev/loop0: 203.9 GB, 203928109056 bytes
1 heads, 1 sectors/track, 398297088 cylinders, total 398297088 sectors
Units = sectors of 1 * 512 = 512 bytes
Disk identifier: 0x00000000

Device Boot Start End Blocks Id System
/dev/loop0p1 63 398283326 199141632 83 Linux

Ah ha, the sector offset is *really* 63, so 63 * 512 = 32256 bytes, and after

losetup -o 32256 /dev/loop1 /dev/loop0

e2fsck now sees the file system and works! BTW sending e2fsck the SIGUSR1 signal makes it show a progress bar:

kill -s SIGUSR1 <e2fsck pid>

and after e2fsck completes I can mount the now good file system:

mount /dev/loop1 /mnt/home_recover
and it works!

With a good copy of the home directory filesystem I now was willing to risk changing the original drive, and ran testdisk and e2fsck on it following the same course. I was able to fix the partition table, clean the filesystem, and mount it! My home directories are all back!

Scanning and posting photos

I scanned in a bunch of family photos, fixed them up, added captions, and posted them on Google’s Picasa Web Album.

I used a flatbed scanner and filled it with photos each scan. This necessitated splitting and cropping each scan into separate images. To speed this along I wrote an AppleScript to call Photoshop’s “Crop and Straighten Photos” function and then save the images.

split_img Applescript

The script worked pretty well for about half the images. I went through and cropped/straightened each image. Then I automatically ran Auto Levels and Auto Contrast or Auto Colors on each image using a second Applescript.

adjust_img Applescript

I wanted to add captions and tags to each image using a list of captions I made when I scanned the photos. Jpg images can store this meta data in the file using the IPTC standard. Unfortunately, Google’s Picasa uploading applications terribly buggy and don’t work well with IPTC tags added by other programs like iPhoto or EXIFutils. So I couldn’t use Google’s Picasa software or plugins to upload the photos.

Google makes an API for interacting with their web sites available, and there is a Perl module, Net::Google::PicasaWeb, available that allows adding captions and tags when uploading pictures. Testing showed that it worked so I wrote a small Perl program to take a tab-delimited text file of images, the target album, the caption, and any tags and load the photos onto the Picasa Web Album site. I needed to use the most up to date version of Net::Google::PicasaWeb and make a one line change.

picasa_upload Perl program

My Picasa Web Album:

Old family photos (Jan. 2009)