YM2612 Algorithms - How do you phase modulate an operator?

For anything related to sound (YM2612, PSG, Z80, PCM...)

Moderator: BigEvilCorporation

Post Reply
sbroumley
Interested
Posts: 29
Joined: Wed Feb 11, 2009 11:23 pm

YM2612 Algorithms - How do you phase modulate an operator?

Post by sbroumley » Wed Feb 11, 2009 11:58 pm

Hi all,

I'm having troubles getting operator phase modulation working in my YM2612 core emulator.

Basically, I'm following the excellent information in this thread:

viewtopic.php?t=386&postdays=0&postorder=asc&start=150

The problem is I'm not sure how to combine the output of one operator (which is 14 bits) to modulate the phase input (10 bits) of another operator as required by the YM2612 "Alogorithms".

Do I need to perform any shifts/manipulation on the 14 bit output before adding it to the 10 bit phase input? I've tried everything under the sun, but I can't get anything to work - I keep getting wierd hissing/distortion sound as soon as I try to combine operators.

Can anyone explain the math on how to do this in the "perfect" device code taken from the mentioned thread (see below).

cheers,
Steve

Code: Select all

//attenuationBitCount = 10 
//phaseBitCount = 10 
//operatorOutBitCount = 14 
//phase = the output from the phase generator 
//attenuation = the output from the envelope generator 

//???????????????????????
// how do you modulate the 10 bit "phase" input by another operators 14 bit output?
// Something like this is not working for me:
//  phase += otherOperatorOutput; // Modulate
//  phase &= ( ( 1 << 10 ) -1 );      // Wrap
//???????????????????????

//Calculate the sine value 
double phaseNormalized = ((double)phase / ((1 << phaseBitCount) - 1)) 
double sinResult = sin(phaseNormalized * M_PI * 2); 

//Convert the attenuation to a linear representation of power 
double attenuationIndividualBitWeighting = 48.0 / (1 << attenuationBitCount); 
double attenuationInBels = (((double)attenuation * attenuationIndividualBitWeighting) / 10.0); 
double powerLinear = pow(10.0, -attenuationInBels); 

//Attenuate the result 
double resultNormalized = sinResult * powerLinear; 

//Calculate the 14-bit operator output 
unsigned int maxOperatorOutput = ((1 << (operatorOutBitCount - 1)) - 1); 
int result = (int)(resultNormalized * maxOperatorOutput);

Nemesis
Very interested
Posts: 791
Joined: Wed Nov 07, 2007 1:09 am
Location: Sydney, Australia

Post by Nemesis » Thu Feb 12, 2009 12:21 am

Yeah, I think I mentioned this part briefly somewhere, although not clearly enough since it's such an important part. From the comments in my core:

Code: Select all

//Convert the 14-bit operator unit output from the modulator into
//a 10-bit phase modulation input. Note that the bits are not
//mapped quite the way you might expect. The operator output is
//shifted down by 1 when it is mapped to the phase modulation
//input. The remaining upper 3 bits of the operator output are
//discarded.
//  ---------------------------------------------------------
//  |               Operator Output (14-bit)                |
//  |-------------------------------------------------------|
//  |13 |12 |11 |10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
//  ------------=========================================----
//              |       Modulation Input (10-bit)       |
//              |---------------------------------------|
//              | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
//              -----------------------------------------
In the case where multiple inputs feed into a single operator, just sum the two inputs.

sbroumley
Interested
Posts: 29
Joined: Wed Feb 11, 2009 11:23 pm

Post by sbroumley » Thu Feb 12, 2009 1:24 am

Thanks so much Nemesis! - my audio is sounding much *better* now, but still not quite like the genesis hardware yet (I think I have ADSR wrong now).

This is probably another topic, but did you ever do hardware tests and figure out how operator1 feedback and the global LFO works?

cheers,
Steve

Nemesis
Very interested
Posts: 791
Joined: Wed Nov 07, 2007 1:09 am
Location: Sydney, Australia

Post by Nemesis » Thu Feb 12, 2009 1:57 am

I'm currently in the process of performing tests on the LFO. I have performed tests on self-feedback, but I want to go back and re-test a few things. I'll post info on these areas when I'm confident the information is correct. I think it's more important I get my updated notes on the envelope generator out first however, since incorrect emulation of the envelope generator is still causing problems in some games.

sbroumley
Interested
Posts: 29
Joined: Wed Feb 11, 2009 11:23 pm

Post by sbroumley » Thu Feb 12, 2009 3:08 am

Awesome. I look forward to your findings.

cheers,
Steve.

Snake
Very interested
Posts: 206
Joined: Sat Sep 13, 2008 1:01 am

Post by Snake » Thu Feb 12, 2009 10:17 am

Steve Broumley? Small world ;)

TmEE co.(TM)
Very interested
Posts: 2440
Joined: Tue Dec 05, 2006 1:37 pm
Location: Estonia, Rapla City
Contact:

Post by TmEE co.(TM) » Thu Feb 12, 2009 12:42 pm

Who is Steve Broumley, other than someone who is writing something with YM2612 emulator :P ?
Mida sa loed ? Nagunii aru ei saa ;)
http://www.tmeeco.eu
Files of all broken links and images of mine are found here : http://www.tmeeco.eu/FileDen

Eke
Very interested
Posts: 885
Joined: Wed Feb 28, 2007 2:57 pm
Contact:

Post by Eke » Thu Feb 12, 2009 12:51 pm

google never let me down:

http://www.linkedin.com/pub/dir/steve/broumley

apparently, another former genesis developper who probably worked in the same company as Sir Snake :wink:

sbroumley
Interested
Posts: 29
Joined: Wed Feb 11, 2009 11:23 pm

Post by sbroumley » Thu Feb 12, 2009 4:37 pm

heh..yes it is indeed Steve Broumley here.

Holy crap - I recall meeting you (Snake) back in the early 90's over at Iguana UK - it is indeed a small world!

nice to meet everyone - this forum is awesome - especially for people trying to emulate the bloody YM2612!

cheers,
-Steve.

Post Reply