I've worked out most of the PiyoPiyo file format.
Enough that a player can be written, at least.
So I figured I should post it here, since it's useful for those that want to use PiyoPiyo outside Ikachan.

Note that "int32-le" is a 32-bit Little Endian integer.

First 4 bytes are "PMD" followed by 0x80.
The next 4 bytes are an int32-le for position in file of Track 1 data.
The next 4 bytes are an int32-le for the "music wait"(milliseconds per frame)
The next 4 bytes are an int32-le for the "loop start".
The next 4 bytes are an int32-le for the "loop end".
The next 4 bytes are an int32-le for the amount of 4-byte records per track.
Track Header Data(20 bytes followed by 256 bytes, then 64 bytes):
The first byte is the "Octave" field
The second byte is the "Icon" field.
The next 2 bytes are unknown.
The next 4 bytes are an int32-le for the "Length" field(time envelope is spread over, assume to be 11025==1 second)
The next 4 bytes are an int32-le for the "Volume" field.
The next 8 bytes are unknown.
The next 0x100 bytes are the waveform(8-bit, apparently unsigned. The sample rate is handled, for me at least, by changing the sample rate entered into the calculation below.)
The next 0x40 bytes are the envelope(also 8-bit, also apparently unsigned)
(This repeats 3 times, track P doesn't have this data)

Finally, there's an int32-le for Track P's volume.
That's the end of the header.

Then, at the offset mentioned, the track data begins.
The track data is not interleaved-it's Track 1 followed by Track 2 followed by Track 3 followed by Track P.
All the tracks are made of 4-byte records.
The 4-byte records are:
First 3 bytes are a bitfield(lowest bit/first byte is lowest pitch),
last byte is the Pan.(0 for no change, else 1 to 7)
The amount of these records per track is in the header.

The calculation you need to turn the note position and octave into the relative pitch is:
First, pos must be 0-based, with higher pitches being higher values.
Then add the octave * 12 to pos.

Run it through this:
double relativePitch=8363d*Math.pow(2.0d,pos/12.0d)/sample_rate;
And you have the relative pitch(where 1.0d is to play at normal speed,2.0d is to play at double speed,0.5d is to play at half speed, you get the idea)!
(Thanks to liborganya, which is where I got that calculation from)

You'll probably see these put to use later today.
--gamemanj
