Main Page | Class Hierarchy | Compound List | File List | Compound Members | File Members | Related Pages

samples.cpp

Go to the documentation of this file.
00001 //
00002 // 1997/10/01 23:55:11
00003 // 
00004 
00005 #include "samples.h"
00006 #include "6581_.h"
00007 #include "6510_.h"
00008 
00009 
00010 //extern ubyte* c64mem1;
00011 //extern ubyte* c64mem2;
00012 
00013 
00014 
00015 
00016 // ---
00017 
00018 
00019 //
00020 // constant data
00021 //
00022 
00023 // Sample Order Modes.
00024 static const ubyte SO_LOWHIGH = 0;
00025 static const ubyte SO_HIGHLOW = 1;
00026 
00027 static const sbyte galwayNoiseTab1[16] =
00028 {
00029         0x80u,0x91u,0xa2u,0xb3u,0xc4u,0xd5u,0xe6u,0xf7u,
00030         0x08u,0x19u,0x2au,0x3bu,0x4cu,0x5du,0x6eu,0x7fu
00031 };
00032 
00033 static const sbyte sampleConvertTab[16] =
00034 {
00035 //  0x81,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff,
00036 //  0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x7f
00037         0x81u,0x90u,0xa0u,0xb0u,0xc0u,0xd0u,0xe0u,0xf0u,
00038         0x00u,0x10u,0x20u,0x30u,0x40u,0x50u,0x60u,0x70u
00039 };
00040 
00041 
00042 //
00043 // implementation of Sample
00044 //
00045 
00046 Sample::Sample(C6510* a6510)
00050         {
00051         CTOR(Sample);
00052 
00053         sampleEmuRout = &Sample::sampleEmuSilence;
00054 
00055         c64mem1 = a6510->c64mem1;
00056         c64mem2 = a6510->c64mem2;
00057         }
00058 
00059 
00060 Sample::~Sample()
00064         {
00065         DTOR(Sample);
00066         }
00067 
00068 
00069 void Sample::channelReset(sampleChannel& ch)
00070 {
00071         ch.Active = false;
00072         ch.Mode = FM_NONE;
00073         ch.Period = 0;
00074 #if defined(DIRECT_FIXPOINT)
00075         ch.Pos_stp.l = 0;
00076 #elif defined(PORTABLE_FIXPOINT)
00077         ch.Pos_stp = (ch.Pos_pnt = 0);
00078 #else
00079         ch.Pos_stp = 0;
00080 #endif
00081 }
00082 
00083 inline void Sample::channelFree(sampleChannel& ch, const uword regBase)
00084         {
00085         ch.Active = false;
00086         ch.Mode = FM_NONE;
00087         c64mem2[regBase+0x1d] = 0x00;
00088         }
00089 
00090 inline void Sample::channelTryInit(sampleChannel& ch, const uword regBase)
00091 {
00092         if ( ch.Active && ( ch.Mode == FM_GALWAYON ))
00093                 return;
00094 
00095         ch.VolShift = ( 0 - (sbyte)c64mem2[regBase+0x1d] ) >> 1;
00096         c64mem2[regBase+0x1d] = 0x00;
00097         ch.Address = readLEword(c64mem2+regBase+0x1e);
00098         ch.EndAddr = readLEword(c64mem2+regBase+0x3d);
00099         if (ch.EndAddr <= ch.Address)
00100         {
00101                 return;
00102         }
00103         ch.Repeat = c64mem2[regBase+0x3f];
00104         ch.RepAddr = readLEword(c64mem2+regBase+0x7e);
00105         ch.SampleOrder = c64mem2[regBase+0x7d];
00106         uword tempPeriod = readLEword(c64mem2+regBase+0x5d);
00107         if ( (ch.Scale=c64mem2[regBase+0x5f]) != 0 )
00108         {
00109                 tempPeriod >>= ch.Scale;
00110         }
00111         if ( tempPeriod == 0 )
00112         {
00113                 ch.Period = 0;
00114 #if defined(DIRECT_FIXPOINT) 
00115                 ch.Pos_stp.l = (ch.PosAdd_stp.l = 0);
00116 #elif defined(PORTABLE_FIXPOINT)
00117                 ch.Pos_stp = (ch.Pos_pnt = 0);
00118                 ch.PosAdd_stp = (ch.PosAdd_pnt = 0);
00119 #else
00120                 ch.Pos_stp = (ch.PosAdd_stp = 0);
00121 #endif
00122                 ch.Active = false;
00123                 ch.Mode = FM_NONE;
00124         }
00125         else
00126         {         
00127                 if ( tempPeriod != ch.Period ) 
00128                 {
00129                         ch.Period = tempPeriod;
00130 #if defined(DIRECT_FIXPOINT) 
00131                         ch.Pos_stp.l = sampleClock / ch.Period;
00132 #elif defined(PORTABLE_FIXPOINT)
00133                         udword tempDiv = sampleClock / ch.Period;
00134                         ch.Pos_stp = tempDiv >> 16;
00135                         ch.Pos_pnt = tempDiv & 0xFFFF;
00136 #else
00137                         ch.Pos_stp = sampleClock / ch.Period;
00138 #endif
00139                 }
00140 #if defined(DIRECT_FIXPOINT) 
00141                 ch.PosAdd_stp.l = 0;
00142 #elif defined(PORTABLE_FIXPOINT)
00143                 ch.PosAdd_stp = (ch.PosAdd_pnt = 0);
00144 #else
00145                 ch.PosAdd_stp = 0;
00146 #endif
00147                 ch.Active = true;
00148                 ch.Mode = FM_HUELSON;
00149         }
00150 }
00151 
00152 inline ubyte Sample::channelProcess(sampleChannel& ch, const uword regBase)
00153 {
00154 #if defined(DIRECT_FIXPOINT) 
00155         uword sampleIndex = ch.PosAdd_stp.w[HI] + ch.Address;
00156 #elif defined(PORTABLE_FIXPOINT)
00157         uword sampleIndex = ch.PosAdd_stp + ch.Address;
00158 #else
00159         uword sampleIndex = (ch.PosAdd_stp >> 16) + ch.Address;
00160 #endif
00161     if ( sampleIndex >= ch.EndAddr )
00162         {
00163                 if ( ch.Repeat != 0xFF )
00164                 { 
00165                         if ( ch.Repeat != 0 )  
00166                                 ch.Repeat--;
00167                         else
00168                         {
00169                                 channelFree(ch,regBase);
00170                                 return 8;
00171                         }
00172                 }
00173                 sampleIndex = ( ch.Address = ch.RepAddr );
00174 #if defined(DIRECT_FIXPOINT) 
00175                 ch.PosAdd_stp.l = 0;
00176 #elif defined(PORTABLE_FIXPOINT)
00177                 ch.PosAdd_stp = (ch.PosAdd_pnt = 0);
00178 #else
00179                 ch.PosAdd_stp = 0;
00180 #endif
00181                 if ( sampleIndex >= ch.EndAddr )
00182                 {
00183                         channelFree(ch,regBase);
00184                         return 8;
00185                 }
00186         }  
00187   
00188         ubyte tempSample = c64mem1[sampleIndex];
00189         if (ch.SampleOrder == SO_LOWHIGH)
00190         {
00191                 if (ch.Scale == 0)
00192                 {
00193 #if defined(DIRECT_FIXPOINT) 
00194                         if (ch.PosAdd_stp.w[LO] >= 0x8000)
00195 #elif defined(PORTABLE_FIXPOINT)
00196                         if ( ch.PosAdd_pnt >= 0x8000 )
00197 #else
00198                     if ( (ch.PosAdd_stp & 0x8000) != 0 )
00199 #endif
00200                         {
00201                             tempSample >>= 4;
00202                         }
00203                 }
00204                 // AND 15 further below.
00205         }
00206         else  // if (ch.SampleOrder == SO_HIGHLOW)
00207         {
00208                 if (ch.Scale == 0)
00209                 {
00210 #if defined(DIRECT_FIXPOINT) 
00211                         if ( ch.PosAdd_stp.w[LO] < 0x8000 )
00212 #elif defined(PORTABLE_FIXPOINT)
00213                     if ( ch.PosAdd_pnt < 0x8000 )
00214 #else
00215                     if ( (ch.PosAdd_stp & 0x8000) == 0 )
00216 #endif
00217                         {
00218                             tempSample >>= 4;
00219                         }
00220                         // AND 15 further below.
00221                 }
00222                 else  // if (ch.Scale != 0)
00223                 {
00224                         tempSample >>= 4;
00225                 }
00226         }
00227         
00228 #if defined(DIRECT_FIXPOINT) 
00229         ch.PosAdd_stp.l += ch.Pos_stp.l;
00230 #elif defined(PORTABLE_FIXPOINT)
00231         udword temp = (udword)ch.PosAdd_pnt + (udword)ch.Pos_pnt;
00232         ch.PosAdd_pnt = temp & 0xffff;
00233         ch.PosAdd_stp += ( ch.Pos_stp + ( temp > 65535 ));
00234 #else
00235         ch.PosAdd_stp += ch.Pos_stp;
00236 #endif
00237         
00238         return (tempSample&0x0F);
00239 }
00240 
00241 // ---
00242 
00243 void Sample::sampleEmuReset(sidEmu* aTheSidEmu)
00247 {
00248         channelReset(ch4);
00249         channelReset(ch5);
00250 //      sampleClock = (udword) (((C64_clockSpeed / 2.0) / PCMfreq) * 65536UL); // original - calls __fixunsdfsi
00251 //      sampleClock = (sdword) (((C64_clockSpeed / 2.0) / PCMfreq) * 65536UL); //ALFRED - 
00252         sampleClock = (udword) (((aTheSidEmu->C64_clockSpeed / 2) / aTheSidEmu->PCMfreq) * 65536L);
00253         sampleEmuRout = &Sample::sampleEmuSilence;
00254         if ( c64mem2 != 0 )
00255         {
00256                 channelFree(ch4,0xd400);
00257                 channelFree(ch5,0xd500);
00258         }
00259 }
00260 
00261         ;      
00262 
00263 void Sample::sampleEmuInit(sidEmu* aTheSidEmu)
00267 {
00268         int k = 0;
00269         for ( int i = 0; i < 16; i++ )
00270         {
00271                 int l = 0;
00272                 for ( int j = 0; j < 64; j++ )
00273                 {
00274                         galwayNoiseTab2[k++] = galwayNoiseTab1[l];
00275                         l = (l+i) & 15;
00276                 }
00277         }
00278         sampleEmuReset(aTheSidEmu);
00279 }
00280 
00281 sbyte Sample::sampleEmuSilence()
00282 {
00283         return 0;
00284 }
00285 
00286 inline void Sample::sampleEmuTryStopAll()
00287 {
00288         if ( !ch4.Active && !ch5.Active )
00289         {
00290                 sampleEmuRout = &Sample::sampleEmuSilence;
00291         }
00292 }
00293 
00294 void Sample::sampleEmuCheckForInit()
00295 {
00296         // Try first sample channel.
00297         switch ( c64mem2[0xd41d] ) 
00298         {
00299          case 0xFF:
00300          case 0xFE:
00301                 channelTryInit(ch4,0xd400);
00302                 break;
00303          case 0xFD:
00304                 channelFree(ch4,0xd400);
00305                 break;
00306          case 0xFC:
00307                 channelTryInit(ch4,0xd400);
00308                 break;
00309          case 0x00:
00310                 break;
00311          default:
00312                 GalwayInit();
00313                 break;
00314         }
00315         
00316         if (ch4.Mode == FM_HUELSON)
00317         {
00318                 sampleEmuRout = &Sample::sampleEmu;
00319         }
00320         
00321         // Try second sample channel.
00322         switch ( c64mem2[0xd51d] ) 
00323         {
00324          case 0xFF:
00325          case 0xFE:
00326                 channelTryInit(ch5,0xd500);
00327                 break;
00328          case 0xFD:
00329                 channelFree(ch5,0xd500);
00330                 break;
00331          case 0xFC:
00332                 channelTryInit(ch5,0xd500);
00333                 break;
00334          default:
00335                 break;
00336         }
00337         
00338         if (ch5.Mode == FM_HUELSON)
00339         {
00340                 sampleEmuRout = &Sample::sampleEmuTwo;
00341         }
00342         sampleEmuTryStopAll();
00343 }
00344 
00345 sbyte Sample::sampleEmu()
00346 {
00347         // One sample channel. Return signed 8-bit sample.
00348         if ( !ch4.Active )
00349                 return 0;
00350         else
00351                 return (sampleConvertTab[channelProcess(ch4,0xd400)]>>ch4.VolShift);
00352 }
00353 
00354 sbyte Sample::sampleEmuTwo()
00355 {
00356         sbyte sample = 0;
00357         if ( ch4.Active )
00358                 sample += (sampleConvertTab[channelProcess(ch4,0xd400)]>>ch4.VolShift);
00359         if ( ch5.Active )
00360                 sample += (sampleConvertTab[channelProcess(ch5,0xd500)]>>ch5.VolShift);
00361         return sample;
00362 }
00363 
00364 // ---
00365   
00366 inline void Sample::GetNextFour()
00367 {
00368         uword tempMul = (uword)(c64mem1[ch4.Address+(uword)ch4.Counter])
00369                 * ch4.LoopWait + ch4.NullWait;
00370         ch4.Counter--;
00371 #if defined(DIRECT_FIXPOINT)
00372         if ( tempMul != 0 )
00373                 ch4.Period_stp.l = sampleClock / tempMul;
00374         else
00375                 ch4.Period_stp.l = 0;
00376 #elif defined(PORTABLE_FIXPOINT)
00377         udword tempDiv; 
00378         if ( tempMul != 0 )
00379                 tempDiv = sampleClock / tempMul;
00380         else
00381                 tempDiv = 0;
00382         ch4.Period_stp = tempDiv >> 16;
00383         ch4.Period_pnt = tempDiv & 0xFFFF;
00384 #else
00385         if ( tempMul != 0 )
00386                 ch4.Period_stp = sampleClock / tempMul;
00387         else
00388                 ch4.Period_stp = 0;
00389 #endif
00390         ch4.Period = tempMul;
00391 }
00392 
00393 void Sample::GalwayInit()
00394 {
00395         if (ch4.Active) 
00396                 return;
00397         
00398         sampleEmuRout = &Sample::sampleEmuSilence;
00399   
00400         ch4.Counter = c64mem2[0xd41d];  
00401         c64mem2[0xd41d] = 0; 
00402   
00403         if ((ch4.Address=readLEword(c64mem2+0xd41e)) == 0)
00404                 return;
00405   
00406         if ((ch4.LoopWait=c64mem2[0xd43f]) == 0)
00407                 return;
00408   
00409         if ((ch4.NullWait=c64mem2[0xd45d]) == 0)
00410                 return;
00411   
00412         if (c64mem2[0xd43e] == 0)
00413                 return;
00414         ch4.SamAddr = ((uword)c64mem2[0xd43e]&15) << 6;
00415   
00416         if ( c64mem2[0xd43d] == 0 )
00417                 return;
00418         ch4.SamLen = (((uword)c64mem2[0xd43d])+1) & 0xfffe;
00419   
00420         ch4.Active = true;
00421         ch4.Mode = FM_GALWAYON;
00422   
00423         //GalwayFourStart:
00424 #if defined(DIRECT_FIXPOINT)
00425         ch4.Pos_stp.l = 0;
00426 #elif defined(PORTABLE_FIXPOINT)
00427         ch4.Pos_stp = 0;
00428         ch4.Pos_pnt = 0;
00429 #else
00430         ch4.Pos_stp = 0;
00431 #endif
00432         //SelectNewVolume();
00433         GetNextFour();
00434         ch4.Counter++;
00435   
00436         sampleEmuRout = &Sample::GalwayReturnSample;
00437 }
00438 
00439 sbyte Sample::GalwayReturnSample()
00440 {
00441 #if defined(DIRECT_FIXPOINT)
00442         sbyte tempSample = galwayNoiseTab2[ ch4.SamAddr + (ch4.Pos_stp.w[HI] & 15) ];
00443 #elif defined(PORTABLE_FIXPOINT)
00444         sbyte tempSample = galwayNoiseTab2[ ch4.SamAddr + ( ch4.Pos_stp & 15 )];
00445 #else
00446         sbyte tempSample = galwayNoiseTab2[ ch4.SamAddr + ((ch4.Pos_stp >> 16) & 15) ];
00447 #endif
00448         
00449 #if defined(DIRECT_FIXPOINT)
00450         ch4.Pos_stp.l += ch4.Period_stp.l;
00451 #elif defined(PORTABLE_FIXPOINT)
00452         udword temp = (udword)ch4.Pos_pnt;
00453         temp += (udword)ch4.Period_pnt;
00454         ch4.Pos_pnt = temp & 0xffff;
00455         ch4.Pos_stp += ( ch4.Period_stp + ( temp > 65535 ));
00456 #else
00457         ch4.Pos_stp += ch4.Period_stp;
00458 #endif
00459 
00460 #if defined(DIRECT_FIXPOINT)
00461         if ( ch4.Pos_stp.w[HI] >= ch4.SamLen )
00462 #elif defined(PORTABLE_FIXPOINT)
00463         if ( ch4.Pos_stp >= ch4.SamLen )
00464 #else
00465         if ( (ch4.Pos_stp >> 16) >= ch4.SamLen )
00466 #endif
00467         {
00468 #if defined(DIRECT_FIXPOINT)
00469                 ch4.Pos_stp.w[HI] = 0;
00470 #elif defined(PORTABLE_FIXPOINT)
00471                 ch4.Pos_stp = 0;
00472 #else
00473                 ch4.Pos_stp &= 0xFFFF;
00474 #endif
00475         //GalwayFour:
00476         GetNextFour();
00477         if ( ch4.Counter == 0xff )  {
00478           //GalwayFourEnd:
00479           //SelectVolume();
00480           ch4.Active = false;
00481           ch4.Mode = FM_GALWAYOFF;
00482           sampleEmuRout = &Sample::sampleEmuSilence;
00483         }
00484   }
00485   return tempSample;
00486 }
00487 
00488 //static void SelectVolume()
00489 //{
00490 //      (c64mem2[0xd418] & 15) << 2;
00491 //}
00492 
00493 //static void SelectNewVolume()
00494 //{
00495 //      if (( c64mem2[0xd418] & 15 ) < 12 )
00496 //      {
00497 //      }
00498 //}

Generated on Tue Feb 8 04:13:59 2005 for Esidplay by doxygen 1.3.3