Exemple #1
0
SoundUsage scanSoundUsage( char *inString ) {
    SimpleVector<int> idVector;
    SimpleVector<double> volVector;

    int numParts = 0;

    char **parts = split( inString, "#", &numParts );
    

    for( int i=0; i<numParts; i++ ) {
        int id = -1;
        double vol = 1.0;
        
        sscanf( parts[i], "%d:%lf", &id, &vol );
        
        if( id != -1 && vol >=0 && vol <= 1.0 ) {
            idVector.push_back( id );
            volVector.push_back( vol );
            }
        delete [] parts[i];
        }
    delete [] parts;

    
    if( idVector.size() > 0 ) {
        
        if( idVector.size() == 1 &&
            idVector.getElementDirect( 0 ) == -1 ) {
            return blankSoundUsage;
            }

        SoundUsage u = { idVector.size(), idVector.getElementArray(),
                         volVector.getElementArray() };
        return u;
        }
    else {
        return blankSoundUsage;
        }
    }
MusicNoteWaveTable::MusicNoteWaveTable( unsigned long inSamplesPerSecond ){


    // read frequencies and lengths from files
    

    SimpleVector<double> *frequencyVector = new SimpleVector<double>();
    SimpleVector<double> *lengthVector = new SimpleVector<double>();
    
    FILE *musicNotePitchesFILE = NULL;
    FILE *musicNoteLengthsFILE = NULL;
    

    if( musicNotePitchesFILE != NULL ) {

        double readValue;
        int numRead = 1;

        while( numRead == 1 ) {
            numRead = fscanf( musicNotePitchesFILE, "%lf", &readValue );
            
            if( numRead == 1 ) {
                frequencyVector->push_back( readValue );
                }
            }

        fclose( musicNotePitchesFILE );
        }
    else {
        // default pitches

        // Note  N,, means N two octaves down
        // N'' means two octaves up

        /*
        // This one sounds pretty good
        // but not enough notes, too bland
        
        // A,,
        frequencyVector->push_back( 110 );

        // D,
        frequencyVector->push_back( 146.832 );

        // A,
        frequencyVector->push_back( 220 );

        // D
        frequencyVector->push_back( 293.665 );

        // G
        frequencyVector->push_back( 391.995 );

        // C'
        frequencyVector->push_back( 523.251 );

        // E'
        frequencyVector->push_back( 659.255 );

        // G'
        frequencyVector->push_back( 783.991 );
        */


        // Instead, use entire two-octaves from c-major scale
        // Problem:  there can be some discords.
        // However:  much more interesting sounding than the two-chord version
        // above

        
        // base note:  C,
        double baseNote = 130.8127827;

        int majorScaleSteps[7] = {2,2,1,2,2,2,1};

        int scaleIndex = 0;
        int notePower = 0;

        // two octaves
        while( notePower < 25 ) {
            frequencyVector->push_back(
                baseNote * pow( 2, notePower / 12.0 ) );

            notePower += majorScaleSteps[ scaleIndex ];

            scaleIndex ++;
            if( scaleIndex >= 7 ) {
                // wrap around
                scaleIndex = 0;
                }
            }
        
                
        /*
          // These are the notes from Transcend level 001
        frequencyVector->push_back( 220 );
        frequencyVector->push_back( 277.183 );
        frequencyVector->push_back( 329.628 );
        frequencyVector->push_back( 440 );
        frequencyVector->push_back( 554.365 );
        frequencyVector->push_back( 659.255 );
        */
        }

    

    if( musicNoteLengthsFILE != NULL ) {

        double readValue;
        int numRead = 1;

        while( numRead == 1 ) {
            numRead = fscanf( musicNoteLengthsFILE, "%lf", &readValue );
            
            if( numRead == 1 ) {
                lengthVector->push_back( readValue );
                }
            }

        fclose( musicNoteLengthsFILE );
        }
    else {
        // default lengths
        lengthVector->push_back( globalLongestNoteLength );
        lengthVector->push_back( globalShortestNoteLength );
        }


    mFrequencyCount = frequencyVector->size();
    mLengthCount = lengthVector->size();

    double *frequencies = frequencyVector->getElementArray();
    mLengthsInSeconds = lengthVector->getElementArray();

    delete frequencyVector;
    delete lengthVector;
    
    
    
    
    mSampleTable = new float**[ mFrequencyCount ];
    mSampleCounts = new unsigned long[ mLengthCount ];

    for( int F=0; F<mFrequencyCount; F++ ) {

        mSampleTable[F] = new float*[ mLengthCount ];

        
        for( int L=0; L<mLengthCount; L++ ) {
            
            // construct a sample table for this freqency/length pair
            unsigned long lengthInSamples =
                (unsigned long)( mLengthsInSeconds[L] * inSamplesPerSecond );

            mSampleTable[F][L] = new float[ lengthInSamples ];


            // setting this inside a double-loop will set the same
            // value repeatedly with the same value, but this makes the code
            // cleaner (other options:  a separate loop to set this value, or
            //  an if statement to ensure that it is set only once)
            mSampleCounts[L] = lengthInSamples;

            

            // populate the sample table with a linearly decaying sine wave
            double frequencyInCyclesPerSecond = frequencies[F];


            double frequencyInCyclesPerSample =
                frequencyInCyclesPerSecond / inSamplesPerSecond;

            // sine function cycles every 2*pi
            // adjust so that it cycles according to our desired frequency
            double adjustedFrequency =
                frequencyInCyclesPerSample * ( 2 * M_PI );

            // try to fade in for 100 samples to avoid a click
            // at the start of the note
            unsigned long numFadeInSamples = 100;
            if( numFadeInSamples > lengthInSamples ) {
                numFadeInSamples = lengthInSamples / 2;
                }

            // optimizations (found with profiler)
            // pull these out of inner loop
            float lengthInSamplesMinusOne = (float)lengthInSamples - 1.0f;
            float inv_lengthInSamplesMinusOne =
                1.0f / lengthInSamplesMinusOne;
            float *theseSamples = mSampleTable[F][L];
            
            for( unsigned long i=0; i<lengthInSamples; i++ ) {

                // decay loudness linearly
                float loudness =
                    ( lengthInSamplesMinusOne - i )
                    * inv_lengthInSamplesMinusOne;
                    
                // fade in for the first 100 samples to avoid
                // a click

                if( i < numFadeInSamples ) {

                    float fadeInFactor =
                        (float)( i ) / (float)( numFadeInSamples - 1 );

                    // optimization:
                    // only do this extra multiplication for notes that
                    // are fading in
                    loudness *= fadeInFactor;
                    }
                
                theseSamples[i] =
                    loudness * (float)sin( i * adjustedFrequency );
                }
            }
        }

    
    delete [] frequencies;
    }
Exemple #3
0
char  pathFind( int inMapH, int inMapW,
                char *inBlockedMap, 
                GridPos inStart, GridPos inGoal,
                int *outFullPathLength,
                GridPos **outFullPath ) {

    // watch for degen case where start and goal are equal
    if( equal( inStart, inGoal ) ) {
        
        if( outFullPathLength != NULL ) {
            *outFullPathLength = 0;
            }
        if( outFullPath != NULL ) {
            *outFullPath = NULL;
            }
        return true;
        }
        


    // insertion-sorted queue of records waiting to be searched
    pathSearchQueue recordsToSearch;

    
    // keep records here, even after we're done with them,
    // to ensure they get deleted
    SimpleVector<pathSearchRecord*> searchQueueRecords;


    SimpleVector<pathSearchRecord> doneQueue;
    
    
    int numFloorSquares = inMapH * inMapW;


    // quick lookup of touched but not done squares
    // indexed by floor square index number
    char *openMap = new char[ numFloorSquares ];
    memset( openMap, false, numFloorSquares );

    char *doneMap = new char[ numFloorSquares ];
    memset( doneMap, false, numFloorSquares );

            
    pathSearchRecord startRecord = 
        { inStart,
          inStart.y * inMapW + inStart.x,
          0,
          getGridDistance( inStart, inGoal ),
          getGridDistance( inStart, inGoal ),
          -1,
          NULL };

    // can't keep pointers in a SimpleVector 
    // (change as vector expands itself)
    // push heap pointers into vector instead
    pathSearchRecord *heapRecord = new pathSearchRecord( startRecord );
    
    searchQueueRecords.push_back( heapRecord );
    
    
    recordsToSearch.head = heapRecord;


    openMap[ startRecord.squareIndex ] = true;
    


    char done = false;
            
            
    //while( searchQueueRecords.size() > 0 && !done ) {
    while( recordsToSearch.head != NULL && !done ) {

        // head of queue is best
        pathSearchRecord bestRecord = *( recordsToSearch.head );
        
        recordsToSearch.head = recordsToSearch.head->nextSearchRecord;


        if( false )
            printf( "Best record found:  "
                    "(%d,%d), cost %d, total %f, "
                    "pred %d, this index %d\n",
                    bestRecord.pos.x, bestRecord.pos.y,
                    bestRecord.cost, bestRecord.total,
                    bestRecord.predIndex, doneQueue.size() );
        
        doneMap[ bestRecord.squareIndex ] = true;
        openMap[ bestRecord.squareIndex ] = false;

        
        doneQueue.push_back( bestRecord );

        int predIndex = doneQueue.size() - 1;

        
        if( equal( bestRecord.pos, inGoal ) ) {
            // goal record has lowest total score in queue
            done = true;
            }
        else {
            // add neighbors
            GridPos neighbors[4];
                    
            GridPos bestPos = bestRecord.pos;
                    
            neighbors[0].x = bestPos.x;
            neighbors[0].y = bestPos.y - 1;

            neighbors[1].x = bestPos.x;
            neighbors[1].y = bestPos.y + 1;

            neighbors[2].x = bestPos.x - 1;
            neighbors[2].y = bestPos.y;

            neighbors[3].x = bestPos.x + 1;
            neighbors[3].y = bestPos.y;
                    
            // one step to neighbors from best record
            int cost = bestRecord.cost + 1;

            for( int n=0; n<4; n++ ) {
                int neighborSquareIndex = 
                    neighbors[n].y * inMapW + neighbors[n].x;
                
                if( ! inBlockedMap[ neighborSquareIndex ] ) {
                    // floor
                    
                    char alreadyOpen = openMap[ neighborSquareIndex ];
                    char alreadyDone = doneMap[ neighborSquareIndex ];
                    
                    if( !alreadyOpen && !alreadyDone ) {
                        
                        // for testing, color touched nodes
                        // mGridColors[ neighborSquareIndex ].r = 1;
                        
                        // add this neighbor
                        double dist = 
                            getGridDistance( neighbors[n], 
                                             inGoal );
                            
                        // track how we got here (pred)
                        pathSearchRecord nRecord = { neighbors[n],
                                                     neighborSquareIndex,
                                                     cost,
                                                     dist,
                                                     dist + cost,
                                                     predIndex,
                                                     NULL };
                        pathSearchRecord *heapRecord =
                            new pathSearchRecord( nRecord );
                        
                        searchQueueRecords.push_back( heapRecord );
                        
                        insertSearchRecord( 
                            &recordsToSearch, heapRecord );

                        openMap[ neighborSquareIndex ] = true;
                        }
                    else if( alreadyOpen ) {
                        pathSearchRecord *heapRecord =
                            pullSearchRecord( &recordsToSearch,
                                              neighborSquareIndex );
                        
                        // did we reach this node through a shorter path
                        // than before?
                        if( cost < heapRecord->cost ) {
                            
                            // update it!
                            heapRecord->cost = cost;
                            heapRecord->total = heapRecord->estimate + cost;
                            
                            // found a new predecessor for this node
                            heapRecord->predIndex = predIndex;
                            }

                        // reinsert
                        insertSearchRecord( &recordsToSearch, heapRecord );
                        }
                            
                    }
                }
                    

            }
        }

    char failed = false;
    if( ! done ) {
        failed = true;
        }
    

    delete [] openMap;
    delete [] doneMap;
    
    for( int i=0; i<searchQueueRecords.size(); i++ ) {
        delete *( searchQueueRecords.getElement( i ) );
        }
    
    
    if( failed ) {
        return false;
        }
    

            
    // follow index to reconstruct path
    // last in done queue is best-reached goal node

    int currentIndex = doneQueue.size() - 1;
            
    pathSearchRecord *currentRecord = 
        doneQueue.getElement( currentIndex );

    pathSearchRecord *predRecord = 
        doneQueue.getElement( currentRecord->predIndex );
            
    done = false;

    SimpleVector<GridPos> finalPath;
    finalPath.push_back( currentRecord->pos );

    while( ! equal(  predRecord->pos, inStart ) ) {
        currentRecord = predRecord;
        finalPath.push_back( currentRecord->pos );

        predRecord = 
            doneQueue.getElement( currentRecord->predIndex );
        
        }

    // finally, add start
    finalPath.push_back( predRecord->pos );
    

    SimpleVector<GridPos> finalPathReversed;
    
    int numSteps = finalPath.size();
    
    for( int i=numSteps-1; i>=0; i-- ) {
        finalPathReversed.push_back( *( finalPath.getElement( i ) ) );
        }


    if( outFullPathLength != NULL ) {
        *outFullPathLength = finalPath.size();
        }
    if( outFullPath != NULL ) {
        *outFullPath = finalPathReversed.getElementArray();
        }
    
    
    return true;
    }
ParameterizedStereoSound::ParameterizedStereoSound( FILE *inFILE,
                                                    char *outError ) {

    char readError = false;

    // read the sound length
    int numRead = fscanf( inFILE, "%lf", &mSoundLengthInSeconds );

    if( numRead != 1 ) {
        readError = true;
        
        printf( "Error:  failed to read sound length from sound space.\n" );
        }
    
    SimpleVector<ParameterSpaceControlPoint *> *controlPoints =
        new SimpleVector<ParameterSpaceControlPoint*>();
    SimpleVector<double> *controlPointParameterAnchors =
        new SimpleVector<double>();

    // keep reading parameter anchors and control points until we
    // can read no more
    
    while( !readError ) {
        
        // read the parameter space anchor
        double anchor = 0;
        numRead = fscanf( inFILE, "%lf", &anchor );

        if( numRead != 1 ) {
            readError = true;
            }
        else {

            // read the control point
            StereoSoundParameterSpaceControlPoint *point =
                new StereoSoundParameterSpaceControlPoint( inFILE,
                                                      &readError );

            if( !readError ) {
                controlPointParameterAnchors->push_back( anchor );
                controlPoints->push_back( point );
                }
            else {
                delete point;
                }
            }
        }

    mNumControlPoints = controlPoints->size();
    mControlPoints = controlPoints->getElementArray();
    mControlPointParameterAnchors =
        controlPointParameterAnchors->getElementArray();

    delete controlPoints;
    delete controlPointParameterAnchors;

    if( mNumControlPoints >= 2 ) {
        *outError = false;
        }
    else {
        // we didn't read enough control points
        *outError = true;
        }
    }
Exemple #5
0
void saveCategoryToDisk( int inParentID ) {
    CategoryRecord *r = getCategory( inParentID );
    

    if( r == NULL ) {
        return;
        }
    
    File categoriesDir( NULL, "categories" );
            
    if( !categoriesDir.exists() ) {
        categoriesDir.makeDirectory();
        }
    
    if( ! categoriesDir.exists() || ! categoriesDir.isDirectory() ) {

        printf( "Failed to make categories directory\n" );
        
        return;
        }


    
    File *cacheFile = categoriesDir.getChildFile( "cache.fcz" );

    cacheFile->remove();
    
    delete cacheFile;


        
    char *fileName = autoSprintf( "%d.txt", inParentID );


    File *categoryFile = categoriesDir.getChildFile( fileName );

    if( r->objectIDSet.size() == 0 ) {
        // empty category, simply remove it
        
        categoryFile->remove();
        }
    else {
        // resave
    
        SimpleVector<char*> lines;
        
        lines.push_back( autoSprintf( "parentID=%d", inParentID ) );

        if( r->isPattern ) {
            lines.push_back( stringDuplicate( "pattern" ) );
            }
        else if( r->isProbabilitySet ) {
            lines.push_back( stringDuplicate( "probSet" ) );
            }
        
        // start with 0 objects in a new category
        lines.push_back( autoSprintf( "numObjects=%d", 
                                      r->objectIDSet.size() ) );
        
        for( int i=0; i<r->objectIDSet.size(); i++ ) {
            if( r->isProbabilitySet ) {
                lines.push_back( 
                    autoSprintf( "%d %f", 
                                 r->objectIDSet.getElementDirect(i),
                                 r->objectWeights.getElementDirect(i) ) );
                }
            else {
                lines.push_back( 
                    autoSprintf( "%d", r->objectIDSet.getElementDirect(i) ) );
                }
            }
        
        
        char **linesArray = lines.getElementArray();
        
        
        char *contents = join( linesArray, lines.size(), "\n" );
        
        categoryFile->writeToFile( contents );
        
        delete [] contents;

        delete [] linesArray;
        lines.deallocateStringElements();
        }    
    
        
            
    delete [] fileName;
    delete categoryFile;
    
    return;
    }