00001 #include "Song.h"
00002 #include "DebugUtil.h"
00003
00004 #include <iostream>
00005
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
00033
00034 for(int i = 0; i < MAX_TRACKS; i++)
00035 m_pTrackDegreesOnWave[i] = 180.0f;
00036
00037
00038 float scale[NUM_SCALES][SCALE_LENGTH] =
00039 {
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 {
00050 32.70f,
00051 38.89f,
00052 43.65f,
00053 46.25f,
00054 49.00f,
00055 58.27f,
00056 65.41f
00057 },
00058 {
00059 32.70f,
00060 38.89f,
00061 43.65f,
00062 46.25f,
00063 49.00f,
00064 58.27f,
00065 65.41f
00066 },
00067 {
00068 65.41f,
00069 77.78f,
00070 87.31f,
00071 92.50f,
00072 98.00f,
00073 116.54f,
00074 130.81f
00075 },
00076 {
00077 65.41f,
00078 77.78f,
00079 87.31f,
00080 92.50f,
00081 98.00f,
00082 116.54f,
00083 130.81f
00084 },
00085 {
00086 130.81f,
00087 155.56f,
00088 174.61f,
00089 185.00f,
00090 196.00f,
00091 233.08f,
00092 261.63f
00093 },
00094 {
00095 130.81f,
00096 155.56f,
00097 174.61f,
00098 185.00f,
00099 196.00f,
00100 233.08f,
00101 261.63f
00102 },
00103 {
00104 261.63f,
00105 311.13f,
00106 349.23f,
00107 369.99f,
00108 392.00f,
00109 466.16f,
00110 523.25f
00111 }
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 };
00131
00132
00133
00134 UInt barsPerSection = length / static_cast<UInt>((static_cast<double>(bpm) / 60.0f) * 1000.0f);
00135
00136
00137 m_numTracks = MAX_TRACKS;
00138
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
00147 m_pTrackDegreesOnWave[i] = 0;
00148 m_pTracks[i].numUniqueBars = ((rand() % MAX_BARS) / 2) + 2;
00149
00150
00151
00152 int newScaleIndex = rand() % NUM_SCALES;
00153 while(scaleIndex == newScaleIndex && NUM_SCALES > 1)
00154 newScaleIndex = rand() % NUM_SCALES;
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];
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
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
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
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 for(size_t i = 0; i < m_numSampleSets; i++)
00358 {
00359
00360
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
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;
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
00406
00407
00408
00409
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 }