- Main Page
- Classes
- Files

- File List
- File Members

# C:/Users/Public/AGS Final Folder/BFLETCHER D4010283/Source/Game/Source/Song.cpp

Go to the documentation of this file.

    00001 #include "Song.h"
    00002 #include "DebugUtil.h"
    00003
    00004 #include <iostream>
    00005 //#include <string>
    00006 #include <math.h>
    00007
    00008 #include "SDL.h"
    00009
    00010 #include "SoundManager.h"
    00011 #include "SineTable.h"
    00012
    00013 float* SongSection::m_pTrackDegreesOnWave = new float[MAX_TRACKS];
    00014
    00015 using std::cout;
    00016 using std::endl;
    00017
    00018 SongSection::SongSection()
    00019 : m_pTracks(0), m_numTracks(0)
    00020 {
    00021
    00022 }
    00023
    00024 SongSection::~SongSection()
    00025 {
    00026         if(m_pTracks)
    00027                 delete[] m_pTracks;
    00028 }
    00029
    00030 bool SongSection::Initialise(const UInt &bpm, const UInt &length)
    00031 {
    00032         //srand(timeGetTime());
    00033
    00034         for(int i = 0; i < MAX_TRACKS; i++)
    00035                 m_pTrackDegreesOnWave[i] = 180.0f;
    00036
    00037         //C - Eb - F - Gb - G - Bb - C Blues scale in C
    00038         float scale[NUM_SCALES][SCALE_LENGTH] =
    00039         {
    00040 //              {
    00041 //                      16.35f,   //C0
    00042 //                      19.45f,   //Eb0
    00043 //                      21.83f,   //F0
    00044 //                      23.12f,   //Gb0
    00045 //                      24.50f,   //G0
    00046 //                      29.14f,   //Bb0
    00047 //                      32.70f    //C1
    00048 //              },
    00049                 {
    00050                         32.70f,   //C1
    00051                                 38.89f,   //Eb1
    00052                                 43.65f,   //F1
    00053                                 46.25f,   //Gb1
    00054                                 49.00f,   //G1
    00055                                 58.27f,   //Bb1
    00056                                 65.41f    //C2
    00057                 },
    00058                 {
    00059                         32.70f,   //C1
    00060                         38.89f,   //Eb1
    00061                         43.65f,   //F1
    00062                         46.25f,   //Gb1
    00063                         49.00f,   //G1
    00064                         58.27f,   //Bb1
    00065                         65.41f    //C2
    00066                 },
    00067                 {
    00068                         65.41f,   //C2
    00069                         77.78f,   //Eb2
    00070                         87.31f,   //F2
    00071                         92.50f,   //Gb2
    00072                         98.00f,   //G2
    00073                         116.54f,  //Bb2
    00074                         130.81f   //C3
    00075                 },
    00076                 {
    00077                         65.41f,   //C2
    00078                                 77.78f,   //Eb2
    00079                                 87.31f,   //F2
    00080                                 92.50f,   //Gb2
    00081                                 98.00f,   //G2
    00082                                 116.54f,  //Bb2
    00083                                 130.81f   //C3
    00084                 },
    00085                 {
    00086                         130.81f,  //C3
    00087                                 155.56f,  //Eb3
    00088                                 174.61f,  //F3
    00089                                 185.00f,  //Gb3
    00090                                 196.00f,  //G3
    00091                                 233.08f,  //Bb3
    00092                                 261.63f   //C4
    00093                 },
    00094                 {
    00095                         130.81f,  //C3
    00096                                         155.56f,  //Eb3
    00097                                         174.61f,  //F3
    00098                                         185.00f,  //Gb3
    00099                                         196.00f,  //G3
    00100                                         233.08f,  //Bb3
    00101                                         261.63f   //C4
    00102                 },
    00103                 {
    00104                         261.63f,  //C4
    00105                                 311.13f,  //Eb4
    00106                                 349.23f,  //F4
    00107                                 369.99f,  //Gb4
    00108                                 392.00f,  //G4
    00109                                 466.16f,  //Bb4
    00110                                 523.25f   //C5
    00111                 }//,
    00112 //              {
    00113 //                      523.25f,  //C5
    00114 //                      622.25f,  //Eb5
    00115 //                      698.46f,  //F5
    00116 //                      739.99f,  //Gb5
    00117 //                      783.99f,  //G5
    00118 //                      932.33f,  //Bb5
    00119 //                      1046.50f  //C6
    00120 //              }/*,*/
    00121 //              {
    00122 //                      1046.50f, //C6
    00123 //                      1244.51f, //Eb6
    00124 //                      1396.91f, //F6
    00125 //                      1479.98f, //Gb6
    00126 //                      1567.98f, //G6
    00127 //                      1864.66f, //Bb6
    00128 //                      2093.00f  //C7
    00129 //              }
    00130         };
    00131
    00132
    00133
    00134         UInt barsPerSection = length / static_cast<UInt>((static_cast<double>(bpm) / 60.0f) * 1000.0f);
    00135
    00136         //m_numTracks = (rand() % MAX_TRACKS) + 1;
    00137         m_numTracks = MAX_TRACKS;
    00138         //m_pTrackDegreesOnWave = new double[MAX_TRACKS];
    00139         m_pTracks = new STrack[m_numTracks];
    00140         m_timePerSection = length;
    00141
    00142         int scaleIndex = rand() % NUM_SCALES;
    00143
    00144         for(size_t i = 0; i < m_numTracks; i++)
    00145         {
    00146         //      srand(timeGetTime());
    00147                 m_pTrackDegreesOnWave[i] = 0; //Init degrees
    00148                 m_pTracks[i].numUniqueBars = ((rand() % MAX_BARS) / 2) + 2; //The number of unique bars
    00149                 //m_pTracks[i].numUniqueBars = MAX_BARS;
    00150
    00151
    00152                 int newScaleIndex = rand() % NUM_SCALES;
    00153                 while(scaleIndex == newScaleIndex && NUM_SCALES > 1) //Makes the scale be at least different from the previous track's
    00154                         newScaleIndex = rand() % NUM_SCALES;                     //but it could be the same as another track in the song section.
    00155
    00156                 scaleIndex = newScaleIndex;
    00157
    00158                 m_pTracks[i].pUniqueBars = new SBar[m_pTracks[i].numUniqueBars];
    00159                 UInt noteLength = rand() % eNumNotesTypes;
    00160
    00161                 for(size_t j = 0; j < m_pTracks[i].numUniqueBars; j++)
    00162                 {
    00163                         SBar* pBar = &(m_pTracks[i].pUniqueBars[j]);
    00164                         switch(noteLength)
    00165                         {
    00166                         default:
    00167                         case eOneNote:
    00168                                 pBar->numFreqs = 1;
    00169                                 break;
    00170                         case eTwoNotes:
    00171                                 pBar->numFreqs = 2;
    00172                                 break;
    00173                         case eFourNotes:
    00174                                 pBar->numFreqs = 4;
    00175                                 break;
    00176                         case eEightNotes:
    00177                                 pBar->numFreqs = 8;
    00178                                 break;
    00179                         }
    00180
    00181                         pBar->timePerFreq = (UInt)(((double)bpm / 60.0f) * (1000.0f)) / pBar->numFreqs;
    00182
    00183                         pBar->pFrequencies = new float[pBar->numFreqs];
    00184
    00185                         for(size_t k = 0; k < pBar->numFreqs; k++)
    00186                         {
    00187                                 int idx = rand() % SCALE_LENGTH;
    00188                                 pBar->pFrequencies[k] = scale[scaleIndex][idx]; //scale[idx]; //Get note from scale. FIX
    00189                         }
    00190
    00191                         noteLength = rand() % eNumNotesTypes;
    00192                 }
    00193
    00194                 m_pTracks[i].numBars = barsPerSection;
    00195                 m_pTracks[i].pBars = new SBar*[barsPerSection];
    00196                 m_pTracks[i].timePerBar = length / barsPerSection;
    00197
    00198                 for(size_t j = 0; j < barsPerSection; j++)
    00199                 {
    00200                         m_pTracks[i].pBars[j] = &(m_pTracks[i].pUniqueBars[rand() % m_pTracks[i].numUniqueBars]);
    00201                 }
    00202         }
    00203
    00204         return true;
    00205 }
    00206
    00207 Sint16* SongSection::GetBuffer(const UInt &position, const int &len)
    00208 {
    00209         Sint16** pStreams = new Sint16*[m_numTracks];
    00210         Sint16* pMixedStream = 0;
    00211
    00212         SDL_AudioSpec* pSpec = SoundManager::getSingleton()->GetAudioSpec();
    00213
    00214         float secsPerSampleset = (float)pSpec->samples / (float)pSpec->freq;
    00215
    00216         for(size_t i = 0; i < m_numTracks; i++)
    00217         {
    00218                 pStreams[i] = new Sint16[len];
    00219                 UInt barIndex = position / m_pTracks[i].timePerBar;
    00220
    00221                 SBar* pBar = m_pTracks[i].pBars[barIndex];
    00222                 UInt timeWithinBar = position - (m_pTracks[i].timePerBar * barIndex);
    00223
    00224                 UInt freqIndex = timeWithinBar / pBar->timePerFreq;
    00225                 float freq = pBar->pFrequencies[freqIndex];
    00226
    00227                 int channelLen = len / pSpec->channels;
    00228
    00229                 for(int j = 0; j < channelLen; j++)
    00230                 {
    00231                         m_pTrackDegreesOnWave[i] += secsPerSampleset * freq;
    00232
    00233                         //DebugUtil::outputDebugText("Track Degrees: %f\n", m_pTrackDegreesOnWave[i]);
    00234
    00235                         float val = SineTable::getSingleton()->Sin(m_pTrackDegreesOnWave[i]) * VOLUME_AMPLITUDE;
    00236
    00237                         pStreams[i][j] = static_cast<Sint16>(val);
    00238
    00239                         if(m_pTrackDegreesOnWave[i] > 360.0f)
    00240                                 m_pTrackDegreesOnWave[i] = 0;
    00241                 }
    00242
    00243                 if(pSpec->channels > 1)
    00244                 {
    00245                         for(int c = 0; c < pSpec->channels - 1; c++)
    00246                         {
    00247                                 int startPoint = c * channelLen;
    00248                                 size_t sz = channelLen * sizeof(Sint16);
    00249                                 memcpy(&(pStreams[i][startPoint + channelLen]), &(pStreams[i][startPoint]), sz);
    00250                         }
    00251                 }
    00252
    00253
    00254                 if(pMixedStream == 0)
    00255                 {
    00256                         pMixedStream = new Sint16[len];
    00257                         memcpy(pMixedStream, pStreams[i], len * sizeof(Sint16));
    00258                 }
    00259                 else
    00260                 {
    00261                         SoundManager::MixBuffers(pMixedStream, pStreams[i], len);
    00262                         //SDL_MixAudio((Uint8*)pMixedStream, (Uint8*)(pStreams[i]), len * sizeof(Sint16), SDL_MIX_MAXVOLUME);
    00263                 }
    00264                 delete[] pStreams[i];
    00265         }
    00266
    00267         delete[] pStreams;
    00268
    00269         return pMixedStream;
    00270 }
    00271
    00272 void SongSection::Output()
    00273 {
    00274         for(size_t i = 0; i < m_numTracks; i++)
    00275         {
    00276                 cout << endl;
    00277                 cout << "Track " << i << ": " << endl;
    00278                 cout << "Number of bars: " << m_pTracks[i].numBars;
    00279                 for(size_t j = 0; j < m_pTracks[i].numBars; j++)
    00280                 {
    00281                         SBar* pBar = m_pTracks[i].pBars[j];
    00282
    00283                         cout << endl;
    00284                         cout << "Bar " << j << ": " << endl;
    00285                         cout << "Number of Frequencies: " << pBar->numFreqs << endl;
    00286                         cout << "Time per frequency: " << pBar->timePerFreq << endl;
    00287
    00288                         for(size_t k = 0; k < pBar->numFreqs; k++)
    00289                         {
    00290                                 cout << pBar->pFrequencies[k] << " ";
    00291                         }
    00292
    00293                         cout << endl;
    00294                 }
    00295         }
    00296 }
    00297
    00298 Song::Song()
    00299 : m_pSongSections(0), m_bpm(0), m_numSections(0), m_pUniqueSections(0), m_length(0),
    00300   m_timePerSection(0), m_lastPointPlayed(0), m_bIsPreCreated(false), m_pSongData(0), m_lastBufferRequested(0)
    00301 {
    00302 }
    00303
    00304 Song::~Song()
    00305 {
    00306         if(m_pSongSections)
    00307                 delete[] m_pSongSections;
    00308
    00309         if(m_pSongData)
    00310                 delete[] m_pSongData;
    00311 }
    00312
    00313 void Song::Initialise(const bool &bPreCreate, const UInt &bpm, const UInt &numUniqueSections, const UInt &lengthInSections, const UInt &timePerSection)
    00314 {
    00315         srand(SDL_GetTicks());
    00316         m_bpm = bpm;
    00317         m_numSections = lengthInSections;
    00318         m_timePerSection = timePerSection;
    00319         m_length = lengthInSections * m_timePerSection;
    00320         m_pSongSections = new SongSection*[lengthInSections];
    00321
    00322         m_pUniqueSections = new SongSection[numUniqueSections];
    00323
    00324         for(size_t i = 0; i < numUniqueSections; i++)
    00325                 m_pUniqueSections[i].Initialise(bpm, timePerSection);
    00326
    00327         for(size_t i = 0; i < lengthInSections; i++)
    00328         {
    00329                 int idx = rand() % numUniqueSections;
    00330                 m_pSongSections[i] = &m_pUniqueSections[idx];
    00331         }
    00332
    00333         if(bPreCreate)
    00334         {
    00335                 SDL_AudioSpec* pSpec = SoundManager::getSingleton()->GetAudioSpec();
    00336                 UInt lengthInWords = static_cast<UInt>((static_cast<float>(m_length) / 1000.0f) * static_cast<float>(SoundManager::getSingleton()->GetAudioSpec()->freq));
    00337                 m_numSampleSets = lengthInWords / pSpec->samples;
    00338                 m_pSongData = new Sint16*[m_numSampleSets];
    00339
    00340
    00341                 UInt msPerSampleSet = static_cast<UInt>(((static_cast<float>(pSpec->samples) / static_cast<float>(pSpec->freq)) * 1000.0f) + 1);
    00342                 UInt numSetsPerSection = (timePerSection / msPerSampleSet);
    00343
    00344 //              UInt arrIdx = 0;
    00345 //              for(int j = 0; j < lengthInSections; j++)
    00346 //              {
    00347 //                      for(int i = 0; i < numSetsPerSection; i++)
    00348 //                      {
    00349 //                              m_pSongData[arrIdx] = new Sint16[pSpec->samples];
    00350 //                              UInt pos = (arrIdx * msPerSampleSet) % m_pSongSections[j]->GetSectionLength();
    00351 //                              memcpy(&(m_pSongData[arrIdx][0]), m_pSongSections[j]->GetBuffer(pos, pSpec->samples), pSpec->samples * sizeof(Sint16));
    00352 //                              arrIdx++;
    00353 //                      }
    00354 //              }
    00355
    00356
    00357                 for(size_t i = 0; i < m_numSampleSets; i++)
    00358                 {
    00359 //                      UInt section = ((((float)i / (float)m_numSampleSets) * (float)m_length) / m_length);
    00360 //                      UInt pos = ( - (idx * m_timePerSection));
    00361
    00362                         UInt pos = i * msPerSampleSet;
    00363                         if(pos >= m_length)
    00364                                 pos = m_length - 1;
    00365                         m_pSongData[i] = GetDynamicBuffer(pos, pSpec->samples);
    00367                 }
    00368
    00369                 m_bIsPreCreated = true;
    00370         }
    00371 }
    00372
    00373 void Song::Output()
    00374 {
    00375         cout << "Music data output: " << endl;
    00376 //      cout << "Song: " << m_name << endl;
    00377         cout << "BPM: " << m_bpm << endl;
    00378         cout << "Length in MS: " << m_length << endl;
    00379
    00380         for(size_t i = 0; i < m_numSections; i++)
    00381         {
    00382                 cout << endl;
    00383                 cout << "Song Section " << i << ": " << endl;
    00384                 m_pSongSections[i]->Output();
    00385         }
    00386 }
    00387
    00388 Sint16* Song::GetBuffer(const UInt &position, const int &len, bool isLooping)
    00389 {
    00390         UInt relTime = 0;
    00391         if(isLooping)
    00392         {
    00393                 relTime = position % m_length;//If it's looping
    00394         }
    00395         else
    00396         {
    00397                 if(position > m_length)
    00398                         return 0;
    00399                 else
    00400                         relTime = position;
    00401         }
    00402
    00403         if(m_bIsPreCreated)
    00404         {
    00405 //              int idx = ((float)relTime / (float)m_length) * (float)m_numSampleSets;
    00406 //              if(idx >= m_numSampleSets)
    00407 //                      idx = m_numSampleSets - 1;
    00408 // //           if(m_pSongData[idx] == (Sint16*)0xcdcdcdcd)
    00409 // //                   return 0;
    00410
    00411                 ++m_lastBufferRequested;
    00412                 if(m_lastBufferRequested >= m_numSampleSets)
    00413                         m_lastBufferRequested = 0;
    00414                 return m_pSongData[m_lastBufferRequested];
    00415         }
    00416         else
    00417         {
    00418                 return GetDynamicBuffer(relTime, len);
    00419         }
    00420 }
    00421
    00422 Sint16* Song::GetDynamicBuffer(const UInt &pos, const int &len)
    00423 {
    00424         int idx = pos / m_timePerSection;
    00425         UInt sectionPos = (pos - (idx * m_timePerSection));
    00426         return m_pSongSections[idx]->GetBuffer(sectionPos, len);
    00427 }