Chris Lacy's Software Engineering Blog
object translators
in the year 2000, the buzz will be object translators, aka, property editors, aka closures, aka un/marshallers, aka de/serializers, aka reflected methods, etc. and everyone will conform to a standard api
we'll have libraries of translators, too; and we'll define the rules by which a given translator is chosen for conversion between types. and we'll have translators that don't have return values, and translators that take multiple values, etc
and what we'll do, is, we'll pipe data between these translators and translator libraries. REST will be piping data from a web request to a translator that converts http messages to sql (with maybe JSON or XML or AMF in between, plus validation/exception handling and security)
but we'll add these "plus" features (exception handling, security, caching, etc) with aop and additional translators/libraries
Posted at 08:35PM Jun 26, 2010 by chris in General |
music test
package net.chrislacy.music.test;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
public class MusicTest {
private static final double[] NOTES = { 261.626, 293.665, 329.628, 349.228, 391.995, 440.000, 493.883, 523.251 };
private static final Set<Integer> INCLUDE = new HashSet<Integer>();
private static final double VOLUME = 0.03;
private static final long LENGTH_MS = 1500;
static {
INCLUDE.add(1);
INCLUDE.add(3);
//INCLUDE.add(4);
INCLUDE.add(5);
//INCLUDE.add(8);
}
public static void main(String[] args) throws Throwable {
// TODO add fails to "more often test" list
// print solution after x (3) wrong guesses
while(true) {
List<Integer> notes = playRandomPhrase(3, VOLUME);
InputStreamReader converter = new InputStreamReader(System.in);
BufferedReader in = new BufferedReader(converter);
boolean shouldRepeat = true;
while(shouldRepeat) {
String line = in.readLine();
int index = 0;
boolean passed = true;
inner:
for(Integer n : notes) {
if(line.length() != notes.size() || Integer.parseInt(line.charAt(index++) + "") != n) {
System.out.println("nope");
playPhrase(VOLUME, createSimilarNotes(LENGTH_MS, 100, hertzFromOneBased(notes)));
passed = false;
break inner;
}
}
shouldRepeat = !passed;
}
}
}
private static double[] hertzFromOneBased(List<Integer> oneBased) {
double[] hertzs = new double[oneBased.size()];
int index = 0;
for(Integer oneB : oneBased) {
hertzs[index++] = NOTES[oneB - 1];
}
return hertzs;
}
private static List<Integer> playRandomPhrase(int length, double volume) {
List<Integer> result = new LinkedList<Integer>();
double[] hertzs = new double[length];
result.add(1);
hertzs[0] = NOTES[0];
for(int ii=1; ii<length; ii++) {
int cur = randomIntLessThan(NOTES.length);
int oneBasedCur = cur + 1;
while(!INCLUDE.contains(oneBasedCur)) {
cur = randomIntLessThan(NOTES.length);
oneBasedCur = cur + 1;
}
result.add(oneBasedCur);
hertzs[ii] = NOTES[cur];
}
playPhrase(volume, createSimilarNotes(LENGTH_MS, 100, hertzs));
return result;
}
private static int randomIntLessThan(int max) {
double r = Math.random();
return (int) Math.round(r * max);
}
private static ComplexNote[] createSimilarNotes(long length, int relativeVolume, double... hertz) {
ComplexNote[] result = new ComplexNote[hertz.length];
for(int ii=0; ii<hertz.length; ii++) {
result[ii] = new ComplexNote(hertz[ii], length, relativeVolume);
}
return result;
}
private static byte[] createOneWave(int numberOfBytes, double maxHeight) {
byte[] oneWave = new byte[numberOfBytes];
for(int i=0; i<numberOfBytes; i++) {
double fractionalPos = ((double)i*2) / numberOfBytes;
double angle = fractionalPos * Math.PI;
double sineVal = Math.sin(angle);
Double volSine = sineVal * maxHeight;
byte b = volSine.byteValue();
oneWave[i] = b;
}
return oneWave;
}
private static byte[] makeWaveTwoChannel(byte[] oneWave) {
byte[] stereoWave = new byte[oneWave.length * 2];
for(int i=0; i<oneWave.length; i++) {
int stereoPos = i*2;
stereoWave[stereoPos] = stereoWave[stereoPos+1] = oneWave[i];
}
return stereoWave;
}
private static byte[] repeatWave(byte[] original, int numberOfWaves) {
byte[] multipleStereoWaves = new byte[original.length * numberOfWaves];
for(int i=0; i < numberOfWaves; i++) {
System.arraycopy(original, 0, multipleStereoWaves, original.length * i, original.length);
}
return multipleStereoWaves;
}
private static byte[] createMultipleStereoWaves(int bytesPerWave, double volume, int numberOfWaves) {
byte[] oneWave = createOneWave(bytesPerWave, volume);
byte[] stereoWave = makeWaveTwoChannel(oneWave);
return repeatWave(stereoWave, numberOfWaves);
}
private static Clip createClip(AudioInputStream ais) {
Clip clip;
try {
clip = AudioSystem.getClip();
clip.open(ais);
clip.setFramePosition(0);
}
catch (Exception e) {
throw new RuntimeException(e);
}
return clip;
}
/**
* @param volume 1.000104 min vol headphones @ 220 hz
*/
private static AudioInputStream createAudioInputStream(double volume, ComplexNote... notes) {
float bytesPerSecond = 48000f;
AudioFormat af = new AudioFormat(bytesPerSecond,
8, // sample size in bits
2, // channels
true, // signed
false // bigendian
);
List<byte[]> waveList = new LinkedList<byte[]>();
int finalLength = 0;
for(ComplexNote note : notes) {
Double bpw = bytesPerSecond/note.getHertz();
int bytesPerWave = bpw.intValue();
int numberOfWaves = 800/bpw.intValue() + 5; // 763
byte[] multipleStereoWaves = createMultipleStereoWaves(bytesPerWave, note.getRelativeVolume() * volume, numberOfWaves);
int numBytesNeeded = ((Float) (bytesPerSecond * (note.getLength()/1000))).intValue();
byte[] noteBuffer = new byte[numBytesNeeded];
int repeatNum = numBytesNeeded / multipleStereoWaves.length;
int ii=0;
for(; ii<repeatNum; ii++) {
System.arraycopy(multipleStereoWaves, 0, noteBuffer, multipleStereoWaves.length * ii, multipleStereoWaves.length);
}
System.arraycopy(multipleStereoWaves, 0, noteBuffer, multipleStereoWaves.length * ii, numBytesNeeded % multipleStereoWaves.length);
waveList.add(noteBuffer);
finalLength += noteBuffer.length;
}
byte[] finalBa = new byte[finalLength];
int index = 0;
for(byte[] cur : waveList) {
System.arraycopy(cur, 0, finalBa, index, cur.length);
index = index + cur.length;;
}
return new AudioInputStream(new ByteArrayInputStream(finalBa), af, finalBa.length/2);
}
private static void playPhrase(double volume, ComplexNote... notes) {
Clip clip = createClip(createAudioInputStream(volume, notes));
clip.loop(0);
clip.drain();
clip.flush();
clip.close();
}
}
Posted at 12:31PM Jun 26, 2010 by chris in Java |