1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
|
/*
* Modification History
*
* 2004-August-22 Jason Rohrer
* Created.
*
* 2004-August-26 Jason Rohrer
* Added parameter to control character of part.
*/
#include "MusicPart.h"
#include "LevelDirectoryManager.h"
#include <math.h>
MusicPart::MusicPart( MusicNoteWaveTable *inWaveTable,
RandomSource *inRandSource,
double inParameter )
: mWaveTable( inWaveTable ),
mNotes( new SimpleVector<MusicNote *>() ) {
int frequencyCount = inWaveTable->getFrequencyCount();
int lengthCount = inWaveTable->getLengthCount();
char error= false;
double musicChanceOfReversedNote =
LevelDirectoryManager::readDoubleFileContents(
"musicChanceOfReversedNote", &error, true );
if( error ) {
// default to all notes playing forward
musicChanceOfReversedNote = 0.0;
}
error = false;
double musicPartLength =
LevelDirectoryManager::readDoubleFileContents(
"musicPartLength", &error, true );
if( error ) {
// default to 10 second parts
musicPartLength = 10.0;
}
// populate our note vector with randomized notes, all of the same length
// decide note length using our parameter
int lengthIndex = (int)( rint( inParameter * ( lengthCount - 1 ) ) );
double totalLength = 0;
while( totalLength < musicPartLength ) {
// add another note
int frequencyIndex =
inRandSource->getRandomBoundedInt( 0, frequencyCount - 1 );
char noteReversed;
// flip a weighted coin to determine if this note should be played
// in reverse
if( inRandSource->getRandomDouble() < musicChanceOfReversedNote ) {
noteReversed = true;
}
else {
noteReversed = false;
}
mNotes->push_back(
new MusicNote( frequencyIndex, lengthIndex, noteReversed ) );
// add this note's length to our total
totalLength += inWaveTable->getLengthInSeconds( lengthIndex );
}
// note lengths sum to a total length that may be beyond the limit
if( totalLength > musicPartLength ) {
// drop the last note
int lastNoteIndex = mNotes->size() - 1;
delete *( mNotes->getElement( lastNoteIndex ) );
mNotes->deleteElement( lastNoteIndex );
// could do something more intelligent here...
// like drop the note that results in a total length that
// is closest to the musicPartLength
}
}
MusicPart::~MusicPart() {
int numNotes = mNotes->size();
for( int i=0; i<numNotes; i++ ) {
delete *( mNotes->getElement( i ) );
}
delete mNotes;
}
double MusicPart::getPartLengthInSeconds() {
return mPartLengthInSeconds;
}
int MusicPart::getNotesStartingInInterval(
double inStartTimeInSeconds,
double inLengthInSeconds,
MusicNote ***outNotes,
double **outNoteStartOffsetsInSeconds ) {
SimpleVector<MusicNote*> *returnNotes = new SimpleVector<MusicNote*>();
SimpleVector<double> *returnStartOffsets = new SimpleVector<double>();
double endTimeInSeconds = inStartTimeInSeconds + inLengthInSeconds;
// walk through notes looking for those that start in the interval
int numNotes = mNotes->size();
double currentNoteStartTime = 0;
for( int i=0;
i<numNotes && currentNoteStartTime <= endTimeInSeconds;
i++ ) {
MusicNote *note = *( mNotes->getElement( i ) );
double noteLength =
mWaveTable->getLengthInSeconds( note->mLengthIndex );
if( currentNoteStartTime >= inStartTimeInSeconds ) {
// add the note
returnNotes->push_back( note->copy() );
returnStartOffsets->push_back(
currentNoteStartTime - inStartTimeInSeconds );
}
// else skip the note
currentNoteStartTime += noteLength;
}
int numNotesReturned = returnNotes->size();
*outNotes = returnNotes->getElementArray();
*outNoteStartOffsetsInSeconds = returnStartOffsets->getElementArray();
delete returnNotes;
delete returnStartOffsets;
return numNotesReturned;
}
|