最近遇到一段有趣的代码,咋看一眼觉得无从入手,费了一些功夫才搞清楚它的真实意图,希望以后尽量不要再遇到这样子的代码。
一开始是没有注释的,后来我给它加上了注释:
UINT32 MidiTicksToSTCno ( UINT32 ticks, UINT32 tempo )
{
UINT32 STCnumber;
UINT16 frameCode, ticksPerFrame;
//printf("ticks : %4x timeFormat %d tempo %d",ticks,timeFormat,tempo);
STCnumber = 0;
if ( ( ( INT16 ) timeFormat ) > 0 )
{
UINT32 iTestUp, iTestDown, iTestTicks;
iTestUp = 9 * tempo;
iTestDown = timeFormat * 100;
iTestTicks = ( 0xfffffffe ) / iTestUp;
while ( ticks > iTestTicks )
{
iTestUp = iTestTicks * 9 * tempo;
STCnumber += ( iTestUp ) / iTestDown;
ticks = ticks - iTestTicks ;
}
STCnumber += ( ticks * 9 * tempo ) / iTestDown;
}
else
{
frameCode = - ( timeFormat >> 8 );
ticksPerFrame = timeFormat & 0xFF;
{
UINT32 iTestUp, iTestDown, iTestTicks;
iTestDown = frameCode * ticksPerFrame * 11;
iTestTicks = ( 0xfffffffe ) / 1000000;
while ( ticks > iTestTicks )
{
iTestUp = iTestTicks * 1000000;
STCnumber += iTestUp / iTestDown;
ticks -= iTestTicks;
}
STCnumber += ( ticks * 1000000 ) / iTestDown;
}
}
return (STCnumber);
}
要看懂这段代码首先要懂得MIDI的时间转换公式,然后要知道系统的STC clock是90kHz。
然后这段代码的功能就是输入事件的tick数和节奏值,返回对应于系统时钟的STC值。
最难懂的部分就是while那一段,一开始总想不通为何写成这样,但输入一些具体的值进去之后就比较明白了,
其实它是为了避免数据溢出而做的一种措施,等于把一个算式分开成多次来计算,然后把每次计算的结果累加起来得到最终结果。
UINT32 MidiTicksToSTCno ( UINT32 ticks, UINT32 tempo )
{
UINT32 STCnumber; //how many STC clock ??
UINT16 frameCode, ticksPerFrame;
//printf("ticks : %4x timeFormat %d tempo %d",ticks,timeFormat,tempo);
STCnumber = 0;
if ( ( ( INT16 ) timeFormat ) > 0 ) //it's conventional format, simply the ticks per beat
{
UINT32 iTestUp, iTestDown, iTestTicks;
iTestUp = 9 * tempo; //up is the numerator of a fraction
iTestDown = timeFormat * 100; //down is the denominator of a fraction
iTestTicks = ( 0xfffffffe ) / iTestUp;
while ( ticks > iTestTicks ) //in case that ticks is too long(> 795), we need to partially
//add it up,maybe it's a way of avoiding overflow
{
iTestUp = iTestTicks * 9 * tempo; //get the upper part
STCnumber += ( iTestUp ) / iTestDown; //accumulate
ticks = ticks - iTestTicks ; //decrease ticks by iTestTicks
}
STCnumber += ( ticks * 9 * tempo ) / iTestDown; //when ticks is less than iTestTicks.
}
else //the following is SMPTE code format
{
frameCode = - ( timeFormat >> 8 );
ticksPerFrame = timeFormat & 0xFF;
{
UINT32 iTestUp, iTestDown, iTestTicks;
iTestDown = frameCode * ticksPerFrame * 11;
iTestTicks = ( 0xfffffffe ) / 1000000;
while ( ticks > iTestTicks )
{
iTestUp = iTestTicks * 1000000;
STCnumber += iTestUp / iTestDown;
ticks -= iTestTicks;
}
STCnumber += ( ticks * 1000000 ) / iTestDown;
}
}
return (STCnumber);
}
一组用来计算的数值:
example value:
ticks = 120
tempo = 600,000
timeformat = 120
we get result:
STC = 54,000 clks