you can try the java soundcard mpg thingie, does the ppc have stereo inputs?
Code:
import java.awt.Color;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.text.NumberFormat;
import java.util.Properties;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.TargetDataLine;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Mpg extends Thread {
static String propFile = "./mpg.properties"; // place to persist confguration and trips.
//Will be created on first run if it doesnt exist.
static int injThreshold = Integer
.parseInt(getProperty("injThreshold", "-30")); // value above the noise
static int vssThreshold = Integer
.parseInt(getProperty("vssThreshold", "100")); // value above the noise
static double distanceFudge = Double.parseDouble(getProperty("distanceFudge", "3200.0"));
static double fuelFudge = Double.parseDouble(getProperty("fuelFudge", "8000000.00"));
static String dummyFile = getProperty("dummyFile", "");
// low level stats tracked in the "trip" class.
class Trip {
String name;
long sampleCount; // num samples, used to compute elapsed time, good
// for about 58 billion hours @ 44100hz
long injHi; // stores number of samples that were "HI" (injector was
// open)
long vssTot; // how many pulses from the vss, indication of distance
// travelled
public Trip(String _name) {
name = _name;
}
// real lightweight update process, gets called at end of audio chunk
public void Update(long _sampleCount, long _injHi, long _vssTot) {
sampleCount += _sampleCount;
injHi += _injHi;
vssTot += _vssTot;
}
public String toString() {
return "name=" + name + ";sampleCount=" + sampleCount + ";injHi="
+ injHi + ";vssTot=" + vssTot;
}
public void reset() {
sampleCount = 0;
injHi = 0;
vssTot = 0;
}
public Trip load() {
sampleCount = Long
.parseLong(getProperty(name + ".sampleCount", "0"));
injHi = Long.parseLong(getProperty(name + ".injHi", "0"));
vssTot = Long.parseLong(getProperty(name + ".vssTot", "0"));
return this;
}
public void save() {
properties.put(name + ".sampleCount", "" + sampleCount);
properties.put(name + ".injHi", "" + injHi);
properties.put(name + ".vssTot", "" + vssTot);
}
public double miles() {
return (double) vssTot / distanceFudge;
}
public double hours() {
return ((double) sampleCount) / (44100.0D * 3600.0D);
}
public double gallons() {
return (double) injHi / fuelFudge;
}
public double mpg() {
return gallons() > 0.0D ? (miles() / gallons())
: Double.POSITIVE_INFINITY;
}
}
class TripPanel extends JPanel {
Trip trip = null;
JLabel name = new JLabel("name");
JLabel miles = new JLabel("miles");
JLabel gallons = new JLabel("gallons");
JLabel mpg = new JLabel("mpg");
JLabel hours = new JLabel("gallons");
JLabel mph = new JLabel("mph");
JButton reset = new JButton("reset");
/** used for limiting numbers to 4 decimal places*/
NumberFormat fm = NumberFormat.getNumberInstance();
public TripPanel(Trip _trip) {
trip = _trip;
setLayout(new GridLayout(1, 8));
setBorder(BorderFactory.createLineBorder(Color.BLACK));
add(name);
add(miles);
add(gallons);
add(mpg);
add(hours);
add(mph);
add(reset);
reset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
trip.reset();
}
});
fm.setMaximumFractionDigits(4);
}
public void upDateLabels() {
name.setText(" " + trip.name);
miles.setText(fm.format(trip.miles()));
gallons.setText(fm.format(trip.gallons()));
mpg.setText(fm.format(trip.mpg()));
hours.setText(fm.format(trip.hours()));
mph.setText(fm.format(trip.miles() / trip.hours()));
}
}
private TargetDataLine m_line;
protected boolean m_bRecording = true;
Trip instant = new Trip("instant");
TripPanel instantPanel = new TripPanel(instant);
Trip current = new Trip("current");
TripPanel currentPanel = new TripPanel(current);
Trip tank = new Trip("tank").load();
TripPanel tankPanel = new TripPanel(tank);
public Mpg(TargetDataLine line, AudioFileFormat.Type targetType) {
m_line = line;
new Thread(new Runnable() {// thread to update the view every second
public void run() {
while (m_bRecording) {
instantPanel.upDateLabels();
instant.reset();// reset the instant trip after
// displaying it
currentPanel.upDateLabels();
tankPanel.upDateLabels();
try {
Thread.sleep(1000);
} catch (Exception e) {
}
}
}
}).start();
}
public void start() {
m_line.start();
super.start();
}
public void stopRecording() {
m_line.stop();
m_line.close();
m_bRecording = false;
System.out.println(" inj sampleCount = " + current.sampleCount
+ " inj hi = " + current.injHi + " inj vssTot = "
+ current.vssTot);
}
boolean ig = true;
boolean vg = true;
void processChunk(byte[] b, int c) {
long ih = 0;
long vt = 0;
for (int x = 0; x < c; x += 2) {
int val = ((int) b[x] & 255) - 127;
if (val > vssThreshold && vg) {
vt++;
System.out.println(" vss going hi "
+ (current.sampleCount + (x / 2)));
vg = false;
}
if (val < 0) {
vg = true;
}
val = ((int) b[x + 1] & 255) - 127;
if (val < injThreshold) {
ig = true;
}
if (val > 0)
ig = false;
if (ig)
ih++;
}
instant.Update(c / 2, ih, vt);
current.Update(c / 2, ih, vt);
tank.Update(c / 2, ih, vt);
}
public void realrun() {
byte[] buffer = new byte[m_line.getBufferSize()];
while (m_bRecording) {
int c = m_line.read(buffer, 0, m_line.available());
if (c != 0) {
processChunk(buffer, c);
}
}
}
public void run() {
if ("".equals(dummyFile))
realrun();
else
dummyrun();
}
public void dummyrun() {
try {
String strFilename = dummyFile;
File soundFile = new File(strFilename);
AudioInputStream audioInputStream = null;
audioInputStream = AudioSystem.getAudioInputStream(soundFile);
int nBytesRead = 0;
byte[] abData = new byte[44100];
while (nBytesRead != -1) {
nBytesRead = audioInputStream.read(abData, 0, abData.length);
if (nBytesRead >= 0) {
processChunk(abData, nBytesRead);
}
try {
Thread.sleep(1000);
} catch (Exception e) {
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
AudioFormat audioFormat = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED, 44100.0F, 8, 2, 2, 44100.0F,
false);
DataLine.Info info = new DataLine.Info(TargetDataLine.class,
audioFormat);
TargetDataLine targetDataLine = null;
targetDataLine = (TargetDataLine) AudioSystem.getLine(info);
targetDataLine.open(audioFormat);
AudioFileFormat.Type targetType = AudioFileFormat.Type.WAVE;
final Mpg recorder = new Mpg(targetDataLine, targetType);
JFrame j = new JFrame("MPG Monitor!!!");
j.setSize(640, 125);
Container c = j.getContentPane();
c.setLayout(new GridLayout(4, 1));
JPanel hd = new JPanel();
hd.setLayout(new GridLayout(1, 8));
hd.add(new JLabel(""));
hd.add(new JLabel("MILES"));
hd.add(new JLabel("GAL"));
hd.add(new JLabel("MPG"));
hd.add(new JLabel("HRS"));
hd.add(new JLabel("MPH"));
hd.add(new JLabel(""));
c.add(hd);
c.add(recorder.instantPanel);
c.add(recorder.currentPanel);
c.add(recorder.tankPanel);
j.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
recorder.stopRecording();
recorder.tank.save();//this just adds the trip fields to the properties object
try {
properties.store(new FileOutputStream(new File(propFile)),"");
} catch (Exception f) {
}
System.exit(0);
}
});
j.setVisible(true);
recorder.start();
}
static Properties properties;
static String getProperty(String tag, String dflt) {
String s = "";
try {
if (properties == null) {
properties = new Properties();
try {
properties.load(new FileInputStream(new File(propFile)));
} catch (Exception e) {
}
;
}
s = properties.getProperty(tag);
if (s == null) {
s = dflt;
properties.put(tag, s);// will propogate default values to the
// file
}
} catch (Exception e) {
}
return s;
}
}