您的位置:首页 > 编程语言

一段有趣的代码的分析

2014-12-29 19:20 218 查看
最近遇到一段有趣的代码,咋看一眼觉得无从入手,费了一些功夫才搞清楚它的真实意图,希望以后尽量不要再遇到这样子的代码。

一开始是没有注释的,后来我给它加上了注释:

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: