Tuesday, April 9, 2013

Using the Finite Difference Method to Simulate Acoustic Waves in a Leslie Rotary Speaker (Part 1, preliminary results)

I am currently enrolled in a numerical methods class where we have learned the Finite Difference and Finite Element methods for heat flow and seismic wave propagation. For my final project, I have decided to do something a little different and am modeling high frequency acoustic waves inside a Leslie rotary speaker. Leslie's are the famous speakers that give organs the swirly sound, and sound great with a guitar as well. Here is an example:


This has a few challenges when compared to seismic wave propagation, specifically that very high frequencies are needed. Current highest frequency wave propagation simulations done at my work are in the range of 1-10hz. For audio, we need frequencies as high as 5-10khz, an order of magnitude higher frequency. This means that the simulation meshes must be much finer which slows down calculations. The benefit is that we only need to simulate across a few meters. The most important part of the calculation are boundary conditions to prevent reflections from the boundary (the first waves hit the boundary after <0.005s), so I implemented an absorbing boundary condition from Clayton 1977.

Here are some preliminary results, all with my virtual leslie on "fast" at 8 revolutions per second.

880hz test tone

Here is an animated gif of a 0.15s high resolution simulation of a 880hz test tone. The rotating green "+" sign represents the speaker position (rotating counter clockwise), and the green triangles are my virtual microphones. All audio demos are from the furthest microphone.

Here is a 1.5s demo of an 880hz test tone (with a break in the middle to test the lack of reflections from the boundaries)"



I also did some tests with the intro to Pride And Joy to see how it handles the guitar spectrum, here is an audio sample:


Anyway this is all a work in progress, but it's a lot of fun!

Wednesday, May 11, 2011

Vacuum Tube Guitar Amps: One Electrician’s Trash is Another Guitarist’s Treasure

Here is an article I wrote as part of my Writing 340 class at USC in 2007.

TITLE: Vacuum Tube Guitar Amps: One Electrician’s Trash is Another Guitarist’s Treasure (2007)

ABSTRACT: The transistor is the backbone of modern digital technology, but most professional guitarists insist on only using amplifiers that use vintage vacuum tubes and mid-twentieth century technology. This article transposes the technological advantages of transistors with the physical and perceived benefits of using vacuum tubes in guitar amplifiers, from their emphasis of certain sound frequencies to their simplicity of design and the subculture of musicians who build them themselves.

KEYWORDS: Vacuum Tube, Transistor, Electric Guitar Amplifiers, Amps, Vintage, Boutique

Download PDF

Wednesday, December 15, 2010

How to run JUnit tests with a timeout

For my main project, OpenSHA, we have operational JUnit tests that test system status on an hourly basis (through cruise control). For these tests, we want to make sure that all core services are operational and responsive. To do this, I needed a way to run JUnit tests with a timeout.

For example, for a map making request, it should fail if it takes over 120 seconds (which is more than generous).

I didn't find a built in way to do this, so I created my own with threads and java reflection. To use it, you call a method like this:


@Test
public void doTest() throws Throwable {
TestUtils.runTestWithTimer("sleepTestMethod", this, 2);
}


where "sleepTestMethod" is the method that gets run as a JUnit test. Note that "sleepTestMethod" shouldn't have the @Test annotation, because then it will be run twice.

Here is an example failure:

junit.framework.AssertionFailedError: method 'runTest' exceeded timeout of 120 secs!
at util.TestUtils.runTestWithTimer(TestUtils.java:70)
at org.opensha.commons.mapping.gmt.TestGMT_Operational.testMakeMapUsingServletGMT_MapStringString(TestGMT_Operational.java:37)


Here is the code for TestUtils:


package util;

import static org.junit.Assert.fail;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestUtils {

private static class TestMethodThread implements Runnable {

private Method testMethod;
private Object testObj;

private Throwable exception;

public TestMethodThread(Method testMethod, Object testObj) {
this.testMethod = testMethod;
this.testObj = testObj;
}

@Override
public void run() {
try {
testMethod.invoke(testObj);
} catch (Throwable t) {
this.exception = t;
}
}

public Throwable getException() {
return exception;
}

}

/**
* This runs a JUnit 4 test method in a separate thread with a timer. If the timeout is
* exceeded, then the test fails.
*
* @param methodName the name of the test method
* @param testObj the object for which method methodName is to be called
* @param timeoutSeconds timeout in seconds until the test should fail
* @throws Throwable
*/
public static void runTestWithTimer(String methodName, Object testObj, int timeoutSeconds) throws Throwable {
// get the method
Method testMethod = testObj.getClass().getDeclaredMethod(methodName);

// make sure it's accessible (not private)
if (!testMethod.isAccessible())
testMethod.setAccessible(true);

// create the thread which will simply run this test
TestMethodThread testThread = new TestMethodThread(testMethod, testObj);
// start the thread
Thread t = new Thread(testThread);
t.start();
// record the start time in milis
long start = System.currentTimeMillis();

while (t.isAlive()) {
// seconds that the thread has been running
double timeSecs = (double)(System.currentTimeMillis() - start) / 1000d;
if (timeSecs > timeoutSeconds) {
// if we're here, then it's exceeded it's allotted time.
try {
// try calling interrupt to end any blocking operation
t.interrupt();
} catch (Throwable e) {
e.printStackTrace();
}
// now fail
fail("method '"+methodName+"' exceeded timeout of "+timeoutSeconds+" secs!");
}

// if we're here then it's still running, but within the time limit. Sleep for 500 milis
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// see if it ended with an exception, this exception might be an assertion failed exception
Throwable exception = testThread.getException();
if (exception != null) {
Throwable cause = exception.getCause();
// if it's an assertion error, throw that so the failure shows up nicely in JUnit as opposed
// to an error.
if (cause != null &&
(cause instanceof AssertionError || exception instanceof InvocationTargetException))
throw cause;
// otherwise it actually is an error (not a failure), throw the exception
throw exception;
}
}

}



I hope this is useful to someone!

Tuesday, October 26, 2010

Workaround for BASH twitter script with OAuth and SuperTweet.net

When twitter disabled basic authentication for OAuth, my BASH post-commit script for posting SVN commits to twitter was broken. I didn't feel like writing an OAuth bash client, and didn't want to install any 3rd party libraries, so I found this solution: http://www.supertweet.net/

Using supertweet, you create a password for supertweet and connect it to your twitter account. You can then perform command line status updates using curl without using OAuth. The best thing is that you never actually give supertweet your twitter password, and can disable it at any time. Here's the curl command (via http://mrblog.org/2010/05/20/an-answer-for-twitter-oauth-pacalypse/):

curl -u user:password -d "status=playing with cURL and the SuperTweet.net API" http://api.supertweet.net/1/statuses/update.xml

So with that in mind, I updated the SVN post commit script. I hope it helps!

Here is the new version:

#!/bin/bash

REPOS="$1"
REV="$2"

### USER SPECIFIC PROPERTIES...CHAGE THESE! ###
# this is the path to your SVN binaries, you'll probably have to change this
SVNDIR='/usr/local/subversion/default/bin/'
# this is the trac URL. be sure to excape special characters like ':' with '%3A' and '/' with '%2F'
TRAC_URL="https%3A%2F%2Fopensha.usc.edu%2Ftrac%2Fchangeset%2F${REV}"
# this is your bit.ly login name
BITLY_LOGIN="FILLMEIN!"
# this is your bit.ly API key
BITLY_API="FILLMEIN!"
# twitter usename
TWITTER_USERNAME="FILLMEIN!"
# password for supertweet.net
SUPERTWEET_PASSWORD="FILLMEIN!"

# ---------------------------------
# This gathers some info on the commit, and "tweets" it to the twitter account
# "opensha_svn" at: http://twitter.com/opensha_svn .
# This is half for fun, and half to make it easier for Kevin to track commits.
# ---------------------------------
COMMENT=`$SVNDIR/svnlook log -r${REV} ${REPOS}`
AUTHOR=`$SVNDIR/svnlook author -r${REV} ${REPOS}`
UP=`$SVNDIR/svnlook changed -r${REV} ${REPOS} | awk '{ print $1 }' | grep -c U`
ADD=`$SVNDIR/svnlook changed -r${REV} ${REPOS} | awk '{ print $1 }' | grep -c A`
DEL=`$SVNDIR/svnlook changed -r${REV} ${REPOS} | awk '{ print $1 }' | grep -c D`

numTrunk=`$SVNDIR/svnlook dirs-changed -r${REV} ${REPOS} | grep -c trunk`

if [[ $numTrunk -gt 0 ]];then
codebase="trunk"
else
codebase=`$SVNDIR/svnlook dirs-changed -r${REV} ${REPOS} | cut -f2 --delimiter="/" | head -n 1`
fi

tweet="$REV $AUTHOR $codebase (${UP}U, ${ADD}A, ${DEL}D): $COMMENT"

if [[ $TRAC_URL ]];then
bitly=`curl "http://api.bit.ly/v3/shorten?login=${BITLY_LOGIN}&apiKey=${BITLY_API}&uri=${TRAC_URL}&format=txt"`

bitlychars=`echo -n $bitly | wc --chars`
if [[ $bitlychars -gt 25 ]];then
bitlychars=0
bitly=""
fi
fi

if [[ `echo -n "$tweet $bitly" | wc -c` -gt 140 ]];then
let chars=136-$bitlychars
tweet="`echo -n $tweet | head -c $chars`... $bitly"
else
tweet="$tweet $bitly"
fi

echo "tweet of len `echo -n "$tweet" | wc -c`: $tweet"

curl --user ${TWITTER_USERNAME}:${SUPERTWEET_PASSWORD} --data status="${tweet}" http://api.supertweet.net/1/statuses/update.xml

Thursday, September 16, 2010

New OpenSHA web site/build process with Java Web Start

My primary project at the Southern California Earthquake Center is called OpenSHA, an open source framework for seismic hazard calculations. OpenSHA is a Java-based platform. Originally we used simple executable Jar files for our standalone applications, but we have recently migrated to using Java Web Start.

The benefits of Java Web Start include automatic download of updates, native desktop integration (Start Menu/Desktop shortcuts/Mac OS X dock).

We have two parallel releases, a stable release and nightly builds. The nightlies automatically built with Cruise Control. As many of our applications use both Apache Tomcat and Java RMI, we run parallel RMI registries and Tomcat contexts, one which is linked to the trunk of our repository, and one which uses the release branch for the current stable release. This allows for easy development of server based applications, without disrupting the stable releases.

The website is build with Drupal, a content management system.

Check out the new OpenSHA website here: http://www.opensha.org and try out an application!

Saturday, August 7, 2010

BASH post-commit script for posting SVN commits to twitter (with Trac /bit.ly link)

EDIT: Changes to the twitter API broke this script. See workaround and new script here: Workaround for BASH twitter script with OAuth and SuperTweet.net

Recently I got the idea of using twitter to follow commits to various SVN repositories. I thought this might be of interest to someone out there. It's free to use (under the Apache 2.0 license).

We have Trac pages set up for our projects, so I use bit.ly to shorten URLs to the changeset. If this isn't applicable to your project, you can remove it from the script. To get it working, simply place this script in the "hooks" directory of your SVN repository, and name it "post-commit". It must also be executable. I would recommend restricting read access to your user, and the apache user (or whatever SVN runs under).

Here's the format of the tweets: [revision number] [username] [branch] ([num files updated, added, delated]): [comment] [trac changeset url]

Tweets longer than 140 characters will be automatically shortened (without ruining the trac URL)

Here's an example:

opensha_svn 6920 kmilner releases (6U, 0A, 0D): merged from trunk: updated build version to 1.0.0 http://bit.ly/cVkq3W

Here's the code (don't forget to fill in the blanks with your information!):

#!/bin/bash

REPOS="$1"
REV="$2"

### USER SPECIFIC PROPERTIES...CHAGE THESE! ###
# this is the path to your SVN binaries, you'll probably have to change this
SVNDIR='/usr/local/subversion/default/bin/'
# this is the trac URL. be sure to excape special characters like ':' with '%3A' and '/' with '%2F'
# I left an example to help with formatting, you should fill it in!
TRAC_URL="https%3A%2F%2Fintensity.usc.edu%2Ftrac%2Fopensha%2Fchangeset%2F${REV}"
# this is your bit.ly login name
BITLY_LOGIN="FILLMEIN!"
# this is your bit.ly API key
BITLY_API="FILLMEIN!"
# twitter usename
TWITTER_USERNAME="FILLMEIN!"
# twitter password
TWITTER_PASSWORD="FILLMEIN!"

# ---------------------------------
# This gathers some info on the commit, and "tweets" it to the twitter account
# "opensha_svn" at: http://twitter.com/opensha_svn .
# This is half for fun, and half to make it easier for Kevin to track commits.
# ---------------------------------
COMMENT=`$SVNDIR/svnlook log -r${REV} ${REPOS}`
AUTHOR=`$SVNDIR/svnlook author -r${REV} ${REPOS}`
UP=`$SVNDIR/svnlook changed -r${REV} ${REPOS} | awk '{ print $1 }' | grep -c U`
ADD=`$SVNDIR/svnlook changed -r${REV} ${REPOS} | awk '{ print $1 }' | grep -c A`
DEL=`$SVNDIR/svnlook changed -r${REV} ${REPOS} | awk '{ print $1 }' | grep -c D`

numTrunk=`$SVNDIR/svnlook dirs-changed -r${REV} ${REPOS} | grep -c trunk`

if [[ $numTrunk -gt 0 ]];then
codebase="trunk"
else
codebase=`$SVNDIR/svnlook dirs-changed -r${REV} ${REPOS} | cut -f2 --delimiter="/" | head -n 1`
fi

tweet="$REV $AUTHOR $codebase (${UP}U, ${ADD}A, ${DEL}D): $COMMENT"

if [[ $TRAC_URL ]];then
bitly=`curl "http://api.bit.ly/v3/shorten?login=${BITLY_LOGIN}&apiKey=${BITLY_API}&uri=${TRAC_URL}&format=txt"`

bitlychars=`echo -n $bitly | wc --chars`
if [[ $bitlychars -gt 25 ]];then
bitlychars=0
bitly=""
fi
fi

if [[ `echo -n "$tweet $bitly" | wc -c` -gt 140 ]];then
let chars=136-$bitlychars
tweet="`echo -n $tweet | head -c $chars`... $bitly"
else
tweet="$tweet $bitly"
fi

echo "tweet of len `echo -n "$tweet" | wc -c`: $tweet"

curl --basic --user ${TWITTER_USERNAME}:${TWITTER_PASSWORD} --data status="${tweet}" https://twitter.com/statuses/update.xml

New Blog

I have a new blog! I had an old website for a while, but that was mostly just for learning php/linux server administration, but lately I've been wanting a place to post cool stuff that I come across. Most of it will probably be little tech tricks, rants on USC football, travel reports, etc. Anyway, I hope you enjoy it!