VOGONS


First post, by clearcase

User metadata
Rank Newbie
Rank
Newbie

Hello,
New around here. I'd like to decode some Roland PCM ROMs in a perfect, bit accurate way.
I'm currently using this code which is a combination of code posted on this forum modified a little:

for (int i = 0; i < file_size / 2; i++) {

int16_t raw_sample;
*(((int8_t *) &raw_sample) + 1) = fgetc(fp);
*(((int8_t *) &raw_sample) + 0) = fgetc(fp);

int16_t ordered_sample;

// the bits have to be moved to these positions
// 15, 06, 14, 13, 12, 11, 10, 09, 08, 05, 04, 03, 02, 01, 00, 07
// EG: bit 15 stays, bit 6 moves to 14, bit 14 moves to bit 13...
ordered_sample = raw_sample & 0x8000;
ordered_sample |= raw_sample << 8 & 0x4000;
ordered_sample |= raw_sample >> 1 & 0x3F80;
ordered_sample |= raw_sample << 1 & 0x007E;

// decode the data
double float_sample = pow(2.0f, (((ordered_sample & 0x7FFF) - 32767.0f) / 2048.0f));
sample_data[i] = (int16_t)(float_sample * 32768.0f * ((ordered_sample & 0x8000) ? -1.0f : 1.0f));
}

This code produces almost perfect results but not bit accurate.
sergm said in another thread that I'd need to loose the float calculations and use a LUT and pointed me to the Tables.cpp file in mt32emu. Not sure how to procede from there. Any help or hints would be welcome.

Reply 1 of 8, by 8bitbubsy

User metadata
Rank Member
Rank
Member

I noticed that on line 18, the "32767.0f" part is actually "32787.0f" in MUNT. Try to change it and see if it gets bit accurate now? Though tbh, that kinda looks like a typo in the MUNT code.
EDIT: Most likely not a typo! I see the same value in the integer LA32 code too.

Also how do you know if it's bit-exact or not? What kind of reference do you have?

386:
- CPU: 386DX-40 (128kB external L1 cache)
- RAM: 8MB (0 waitstates at 40MHz)
- VGA: Diamond SpeedSTAR VGA (ET4000AX 1MB ISA)
- Audio: SB Pro 2.0 + GUS 1MB
- ISA PS/2 mouse card + ISA USB card
- MS-DOS 6.22 + Win 3.1
- MR BIOS

Reply 3 of 8, by clearcase

User metadata
Rank Newbie
Rank
Newbie
8bitbubsy wrote on 2020-10-13, 19:34:

I noticed that on line 18, the "32767.0f" part is actually "32787.0f" in MUNT. Try to change it and see if it gets bit accurate now? Though tbh, that kinda looks like a typo in the MUNT code.
EDIT: Most likely not a typo! I see the same value in the integer LA32 code too.

Also how do you know if it's bit-exact or not? What kind of reference do you have?

I have the PCM ROM(s) from a D-50 synth. Roland also make a VST of this instrument and in the resources section of the dll is the original ROMs already decoded (or can get with a memory dump). Decoding the D-50 ROM with the code I posted above creates good results. However, if I open both in Sound Forge (audio editor) and invert the phase of one and merge it with the other (aligned to the exact sample) there is still a signal - albeit very, very low. I have to zoom right up vertically to see it in Sound Forge. If I recompile the code using 32787 and do the same, the remaining signal is higher (about -43dB as opposed to about -70dB with 32767). So 32767 wins in this case.

Last edited by clearcase on 2020-10-13, 20:06. Edited 2 times in total.

Reply 4 of 8, by clearcase

User metadata
Rank Newbie
Rank
Newbie
sergm wrote on 2020-10-13, 19:40:

Could you please elaborate to what extent do you observe differences from the reference samples?

P.S. If you care about portability, rows #4 and #5 could be slightly improved.

Thank's for the portability tip. It's really just a personal project but I may as well improve it where possible.
Hopefully the reply to 8bitbubsy answers the observe differences but if not, let me know and I'll post screenshot or audio of the difference or something.

Reply 5 of 8, by 8bitbubsy

User metadata
Rank Member
Rank
Member

I see.

One problem here is that you can't know for sure if the decoded D-50 PCM ROM in the VST is bit-accurate to how D-50 is decoding its encoded ROM in realtime. It's possible that the original D-50 is using tricks to save chip manufacturing costs or to make the decoding faster, while Roland decoded the ROM in a different way for the VST. Just a guess, anything is possible here when you don't have it confirmed...

Is the D-50 even operating in 16-bit PCM?

386:
- CPU: 386DX-40 (128kB external L1 cache)
- RAM: 8MB (0 waitstates at 40MHz)
- VGA: Diamond SpeedSTAR VGA (ET4000AX 1MB ISA)
- Audio: SB Pro 2.0 + GUS 1MB
- ISA PS/2 mouse card + ISA USB card
- MS-DOS 6.22 + Win 3.1
- MR BIOS

Reply 6 of 8, by clearcase

User metadata
Rank Newbie
Rank
Newbie

The difference between the decoded data from Roland and the self-decoded ROMs is so tiny that it makes me think it's just the decoding code that's not quite there. Maybe it's a rounding difference or something.

Reply 7 of 8, by sergm

User metadata
Rank Oldbie
Rank
Oldbie
clearcase wrote on 2020-10-13, 20:36:

The difference between the decoded data from Roland and the self-decoded ROMs is so tiny that it makes me think it's just the decoding code that's not quite there. Maybe it's a rounding difference or something.

Yeah, that's what I mean. Try to figure statistical data from the differences, like mean and std deviation. Excel-like spreadsheet should help 😀

If the differences are rather substantial, I'd not think about rounding errors but about Roland using a different technique when producing the VST data.

Reply 8 of 8, by clearcase

User metadata
Rank Newbie
Rank
Newbie

Thanks for all the help, I reckon the results are close enough and it's not known how the decoded data from the VST was derived anyway a you say. I had originally assumed they'd have access to the original data before encoding for the ROM rather than having to decode their own ROMs but you never know. It may have been lost after 30 years.

However, just in case it help you chaps, I tested again using the code from LA32FloatWaveGenerator::getPCMSample.

float sampleValue = EXP2F(((pcmSample & 32767) -32787.0f) / 2048.0f);

and also modified to

float sampleValue = EXP2F(((pcmSample & 32767) - 32767.0f) / 2048.0f);

When inverted and overlayed with the VST data, 32767 gave much better results .

I'm not so sure about rounding errors now, if you normalise the data you can see and hear it is the original data (albeit very noisy of course). Almost like there was a slight volume difference between the two but I don't really know.
However, I just post that in case it's useful.
Thanks for all the help again.