jdkmidi class library documentation

Copyright © 2004 J.D. Koftinoff Software, Ltd.

Released under the GNU General Public License (GPL)




Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

src/jdkmidi_smpte.cpp

Go to the documentation of this file.
00001 /*
00002  *  libjdkmidi-2004 C++ Class Library for MIDI
00003  *
00004  *  Copyright (C) 2004  J.D. Koftinoff Software, Ltd.
00005  *  www.jdkoftinoff.com
00006  *  jeffk@jdkoftinoff.com
00007  *
00008  *  *** RELEASED UNDER THE GNU GENERAL PUBLIC LICENSE (GPL) April 27, 2004 ***
00009  *
00010  *  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU General Public License
00021  *  along with this program; if not, write to the Free Software
00022  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023 */
00024 /*
00025 **  Copyright 1986 to 1998 By J.D. Koftinoff Software, Ltd.
00026 **
00027 **  All rights reserved.
00028 **
00029 **  No one may duplicate this source code in any form for any reason
00030 **  without the written permission given by J.D. Koftinoff Software, Ltd.
00031 **
00032 */
00033 
00034 #include "jdkmidi/world.h"
00035 #include "jdkmidi/smpte.h"
00036 
00037 #ifndef DEBUG_MDSMPTE
00038 # define DEBUG_MDSMPTE  0
00039 #endif
00040 
00041 #if DEBUG_MDSMPTE
00042 # undef DBG
00043 # define DBG(a) a
00044 #else
00045 # undef DBG
00046 # define DBG(a)
00047 #endif
00048 
00049 namespace jdkmidi
00050 {
00051   
00052   const uchar smpte_max_frames[] =
00053   {
00054     24, 25, 30, 30, 30, 30
00055   };
00056   
00057   const double smpte_smpte_rates[] = 
00058   {
00059     24.0,
00060     25.0,
00061     29.97,
00062     29.97,
00063     30.0,
00064     30.0
00065   };
00066   
00067   const double smpte_smpte_rates_long[] = 
00068   {
00069     2400,
00070     2500,
00071     2997,
00072     2997,
00073     3000,
00074     3000
00075   };
00076   
00077   
00078   const double smpte_sample_rates[] =
00079   {
00080     32000.0,
00081     44055.9,
00082     44100.0,
00083     47952.0,
00084     48000.0,
00085     48048.0
00086   };
00087   
00088   const long smpte_sample_rates_long[] =
00089   {
00090     320000,
00091     440559,
00092     441000,
00093     479520,
00094     480000,
00095     480480
00096   };
00097   
00098   
00099   
00100   SMPTE::SMPTE(
00101     SMPTE_RATE smpte_rate_,
00102     SAMPLE_RATE sample_rate_
00103     )
00104     :
00105     smpte_rate( smpte_rate_ ),
00106     sample_rate( sample_rate_ ),
00107     sample_number( 0 ),
00108     hours(0),
00109     minutes(0),
00110     seconds(0),
00111     frames(0),
00112     sub_frames(0),
00113     sample_number_dirty(false)
00114   {
00115     
00116   }
00117   
00118   
00119   
00120   SMPTE::SMPTE(
00121     const SMPTE & s
00122     )
00123   {
00124     Copy(s);  
00125   }
00126   
00127   
00128   
00129   
00130   
00131   void  SMPTE::AddHours( char h )
00132   {
00133     AddSamples(  GetSampleRateLong()// samples per second times 10
00134                  * h *
00135                  (  60    // seconds per minute
00136                     * 60    // minutes per hour
00137                     / 10    // compensate for freq*10
00138                    )
00139       );
00140   }
00141   
00142   
00143   void  SMPTE::AddMinutes( char m )
00144   {
00145     AddSamples(
00146       GetSampleRateLong()
00147       * m * // samples per second times 10
00148       ( 60    // seconds per minute
00149         / 10 )  // compensate for freq*10
00150       );
00151   }
00152   
00153   
00154   void  SMPTE::AddSeconds( char s )
00155   {
00156     AddSamples(
00157       GetSampleRateLong() // samples per second times 10
00158       * s    // number of seconds
00159       / 10     // compensate for freq*10
00160       );
00161   }
00162   
00163   
00164   void  SMPTE::AddFrames( char f )
00165   {
00166     AddSamples(
00167       GetSampleRateLong()   // samples per second times 10
00168       * f       // number of frames
00169       * 10      // times 10
00170       / GetSMPTERateLong()  // divide by smpte rate (frames per second) times 100
00171       );
00172   }
00173   
00174   
00175   void  SMPTE::AddSubFrames( char sf )
00176   {
00177     AddSamples(
00178       GetSampleRateLong() // samples per second times 10
00179       * sf      // number of sub frames
00180       / GetSMPTERateLong()  // divide by smpte rate (frames per second) times 100
00181       / 10      // divide by 10 to get hundredths of a frame
00182       );      
00183   }
00184   
00185   
00186   
00187   void  SMPTE::SampleToTime()
00188   {
00189     //
00190     // make a temporary copy of the sample number
00191     //
00192     
00193     ulong tmp_sample=sample_number;
00194     
00195     
00196     //
00197     // keep track of the actual rates in use in doubles.
00198     //
00199     
00200     double the_smpte_rate = smpte_smpte_rates[ smpte_rate ];
00201     double the_sample_rate = smpte_sample_rates[ sample_rate ];
00202     
00203     //
00204     // keep track of the maximum frame number for this smpte format.
00205     //
00206     
00207     uchar max_frame = smpte_max_frames[ smpte_rate ];
00208     
00209     //
00210     // Calculate the number of samples per frame.
00211     //
00212     
00213     double samples_per_frame=smpte_sample_rates[ sample_rate ] / smpte_smpte_rates[ smpte_rate ];
00214     
00215     //
00216     // if the smpte rate is a drop frame type, calculate the number
00217     // of frames that must be dropped.
00218     //
00219     
00220     if( smpte_rate==SMPTE_RATE_30DF || smpte_rate==SMPTE_RATE_2997DF )
00221     {
00222       //
00223       // Calculate number of minutes that have gone by
00224       //
00225       
00226       // short num_minutes = (short)((double)tmp_sample/(smpte_sample_rates[sample_rate]))/60;
00227       int num_minutes = tmp_sample/(48000*60);
00228       
00229       DBG( printf( "num_minutes=%d\n", (int)num_minutes ) );
00230       
00231       //
00232       // Calculate the number of tens of minutes that have gone by, including minute 00
00233       //
00234       
00235       int ten_minutes = num_minutes/10;
00236       
00237       DBG( printf( "ten_minutes=%d\n", (int)ten_minutes) );
00238       
00239       //
00240       // Calculate the number of frames that are dropped by this
00241       // time.
00242       //
00243       
00244       int drops=(num_minutes - ten_minutes)*2;
00245       
00246       DBG( printf( "drops=%d\n", (int)drops ) );
00247       
00248       //
00249       // Offset the tmp_sample number by this amount of frames.
00250       //
00251       
00252       DBG( printf( "tmp_sample before drops=%ld\n", (long)tmp_sample ) );
00253       
00254       tmp_sample+=(ulong)(drops*samples_per_frame);
00255       
00256       DBG( printf( "tmp_sample after drops=%ld\n", (long)tmp_sample ) );
00257     }
00258     
00259     //
00260     // Calculate the time in sub frames, frames, seconds, minutes, hours
00261     //
00262     
00263     ulong rounded_sub_frames= (ulong)((tmp_sample*the_smpte_rate * 100)/the_sample_rate +.5);
00264     
00265     DBG( printf( "rounded_sub_frames = %ld\n", rounded_sub_frames ) );
00266     
00267     sub_frames = (uchar) ((rounded_sub_frames)%100);
00268     frames     = (uchar) ((rounded_sub_frames/100) % max_frame);
00269     seconds    = (uchar) ((rounded_sub_frames/(100L*max_frame)) % 60 );
00270     minutes    = (uchar) ((rounded_sub_frames/(100L*60L*max_frame)) % 60 );
00271     hours    = (uchar) ((rounded_sub_frames/(100L*60L*24L*max_frame)) % 24 );
00272     
00273   }
00274   
00275   
00276   void  SMPTE::TimeToSample()
00277   {
00278     
00279     //
00280     // keep track of the actual rates in use in doubles.
00281     //
00282     
00283     double the_smpte_rate = smpte_smpte_rates[ smpte_rate ];
00284     double the_sample_rate = smpte_sample_rates[ sample_rate ];
00285     
00286     //
00287     // optimize a coupla similiar double divides by calculating it once.
00288     //
00289     
00290     double samples_per_frame=the_sample_rate / the_smpte_rate;
00291     
00292     //
00293     // calculate the sample number
00294     //
00295     
00296     double tmp_sample = (double) (
00297       ( (hours    * the_sample_rate * (60 * 60) )
00298         + (minutes  * the_sample_rate * 60 )
00299         +   (seconds  * the_sample_rate )
00300         +   (frames   * samples_per_frame )
00301         + (sub_frames   * samples_per_frame * (1.0/100.0) ) +.5)
00302       );
00303     
00304     //
00305     // Now compensate for Drop Frame mode if we are in drop frame mode.
00306     //
00307     
00308     if( smpte_rate == SMPTE_RATE_30DF || smpte_rate==SMPTE_RATE_2997DF )
00309     {
00310       //
00311       // Calculate number of minutes that have gone by
00312       //
00313       
00314       int num_minutes = (int)((double)tmp_sample/(smpte_sample_rates[sample_rate]*60));
00315       
00316       DBG( printf( "num_minutes=%d\n", (int)num_minutes ) );
00317       
00318       //
00319       // Calculate the number of tens of minutes that have gone by, including minute 00
00320       //
00321       
00322       int ten_minutes = num_minutes/10;
00323       
00324       DBG( printf( "ten_minutes=%d\n", (int)ten_minutes) );
00325       
00326       //
00327       // Calculate the number of frames that are dropped by this
00328       // time.
00329       //
00330       
00331       int drops=(num_minutes - ten_minutes)*2;
00332       
00333       DBG( printf( "drops=%d\n", (int)drops ) );
00334       
00335       //
00336       // Offset the tmp_sample number by this amount of frames.
00337       //
00338       
00339       DBG( printf( "tmp_sample before drops=%ld\n", (long)tmp_sample ) );
00340       
00341       tmp_sample-=drops*samples_per_frame;
00342       
00343       DBG( printf( "tmp_sample after drops=%ld\n", (long)tmp_sample ) );
00344       
00345     }
00346     
00347     //
00348     // save the calculated sample number in self.
00349     //
00350     
00351     sample_number=(ulong)tmp_sample;
00352   }
00353   
00354   
00355   
00356   void  SMPTE::Copy( const SMPTE & s )
00357   {
00358     smpte_rate=s.smpte_rate;
00359     sample_rate=s.sample_rate;
00360     sample_number=s.sample_number;
00361     hours=s.hours;
00362     minutes=s.minutes;
00363     seconds=s.seconds;
00364     frames=s.frames;
00365     sub_frames=s.sub_frames;
00366     sample_number_dirty=s.sample_number_dirty;
00367   }
00368   
00369   
00370   int SMPTE::Compare( SMPTE & s )
00371   {
00372     ulong a = GetSampleNumber();
00373     ulong b = s.GetSampleNumber();
00374     
00375     if( a<b )
00376       return -1;
00377     if( a>b )
00378       return 1;
00379     
00380     return 0;
00381   }
00382   
00383   
00384   void  SMPTE::Add( SMPTE & s )
00385   {
00386     ulong a=GetSampleNumber();
00387     ulong b=s.GetSampleNumber();
00388     
00389     SetSampleNumber( a+b );
00390   }
00391   
00392   void  SMPTE::Subtract( SMPTE & s )
00393   {
00394     ulong a=GetSampleNumber();
00395     ulong b=s.GetSampleNumber();
00396     
00397     SetSampleNumber( a-b );
00398   }
00399   
00400   
00401   
00402   
00403   
00404 }