float AlgorhythmicAudioIO::PlayDoubleArray(double * array, int size)//, int swapaindex, int swapbindex)
{
    mzsortdata.approxEvals+=size;
    
    if(array!=mzsortdata.doubleArray || size != mzsortdata.doubleArraySize)
    {
        LockSortData();
        mzsortdata.doubleArray=array;
        mzsortdata.doubleArraySize=size;
        unLockSortData();
    }
    
    if(mzsortdata.durationsSize<size)
    {
        LockSortData();
        if(mzsortdata.durationsSize)
            delete [] mzsortdata.durations;
        mzsortdata.durationsSize=size;
        //durations needs one greater for the noise seperator duration.
        mzsortdata.durations = new double[size+1];
        
        unLockSortData();
    }
	mzsortdata.sampleCursor=0;
	mzsortdata.phase=0;
	mzsortdata.usedouble=true;
    
    mzsortdata.lastNoteIndex=0;
    float secDuration = 0.0;
    
    int min = INT_MAX;
    int max = INT_MIN;
    for(int i=0;i<size;i++)
    {
        min = mymin(array[i],min);
        max = mymax(array[i],max);
    }
    
    
    //make up some durations based on the number.
    for(int i=0;i< size;i++)
    {
        //calculate the delay per note,
        //      mzsortdata.durations[i] = (((int)array[i])%20)/20.0 + 0.05 ;
        
        //short notes
        //      {
        //         int chop;
        //         chop = (int)array[i];
        //         mzsortdata.durations[i] = 0.05;
        //         while(fabs(chop) > 0)
        //         {
        //            mzsortdata.durations[i] *= 1.75;
        //            chop = chop/3;
        //         }
        //      }
        {
            float cursor;
            cursor = (array[i] - min)/(max-min);
            cursor = 1.0-cursor;
            cursor = exp2cursor(cursor,7);
            mzsortdata.durations[i] =m_speed;//(0.05 + cursor * (0.45) )* m_speed;
        }
        
        //we sum up the durations
        secDuration += mzsortdata.durations[i];
    }
    //duration of break
    mzsortdata.durations[size] = 0.0;//(m_seperatorOn?1.0:0.0) *m_speed;
    secDuration += mzsortdata.durations[size];
    mzsortdata.duration=secDuration;
	return secDuration;
}
示例#2
0
//at start time it should retun 1.0 at end time mEndCoef
//the second parameter is for recursive calls since this uses incompatable static variables
double Interpolation::ValueAtTime(double time)
{
   double cursor =mymin(mymax(0.0,time-mStartTime)/mDuration,1.0);
   double phase;
   double ret;
    
   __thread static InterpolationMetaData *meta;
    if (!meta) {
        meta = new InterpolationMetaData; /*TODO:leak*/
    }
   //get the list of our local parameters and copy them.
    std::vector<double> &instantParams = meta->instantParams;
   bool &instantParamsCleared = meta->instantParamsCleared;
   
   if(instantParamsCleared)
   {
      for(int i =0;i<mInterpParams.GetNumParameters();i++)
         instantParams.push_back(mInterpParams.GetValue((Parameter)i));
      instantParamsCleared=false;
   }
   else
   {
      for(int i =0;i<mInterpParams.GetNumParameters();i++)
         instantParams[i]=mInterpParams.GetValue((Parameter)i);   
   }
   
   //check to see if we have metaInterps attached to us and apply them.
   for(int i=0;i<mAttachedMetaInterps.size();i++)
   {
	//caution - MetaInterpolation::Apply uses ValueAtTime 
      mAttachedMetaInterps[i]->Apply(time,&instantParams);
   }
   
//   assert(mStartTime <=time);
//   assert(mStartTime+mDuration>=time);
//   


   switch(mType)
   {
      
      case eLinear:
        ret= cursor*(mEndCoef-1.0) + 1.0;
        break;
      case eExp2:
         ret= exp2cursor(cursor)*mEndCoef+(1.0-exp2cursor(cursor));
         break;
	  case eStep:
          ret= (mEndCoef-1.0)*((float)(floor((cursor+0.001) * floor(instantParams[eInterpTypeVariable]))))/floor(instantParams[eInterpTypeVariable]) + 1.0;
          break;
	  case eExp2Step:
          ret= (mEndCoef-1.0)*exp2cursor(((float)(floor((cursor+0.001) * floor(instantParams[eInterpTypeVariable]))))/floor(instantParams[eInterpTypeVariable]))+1.0;
          break;
     case eSquare:
     //need to implement some fading to bandlimit the square.
//         while(phase>2*3.141592)
//            phase-=2*3.141592;
//         if(phase>(2*3.141592*interpTypeVariable) <kSquareTransitSamples/44100.0)
//            return (mEndCoef-1.0) + 1.0;
         phase=modf(     (2 * cursor * (floor(instantParams[eInterpTypeVariable])/**mDuration*/+0.5 ) - 0.5)/2.0,&phase);//we just clober the intpart with the return value
         phase = 3.141592*2* phase;
         ret= phase<3.141592?1.0:mEndCoef;
         break;
     
     case ePeriodic:
		//sinusoid that starts at -1 (-pi/2) and continues for (n+0.5)periods to end up at +1 (pi/2)
		//we also shrink it down soo that -pi/2 comes to 1.0 and pi/2 comes to mEndCoef. 
      phase=modf(     (2 * cursor * (floor(instantParams[eInterpTypeVariable])/**mDuration*/+0.5 ) - 0.5)/2.0,&phase);//we just clober the intpart with the return value
      phase = 3.141592*2* phase;
		ret=  (sin(phase)*(mEndCoef-1.0)/2.0)+(mEndCoef-1.0)/2.0 + 1.0;
		break;
      
     default:
       assert(1==0);//shouldn't reach here.
       break;
   }
   return ret;
}
/* This routine will be called by the PortAudio engine when audio is needed.
 ** It may called at interrupt level on some machines so don't do anything
 ** that could mess up the system like calling malloc() or free().
 */
static int SortingPortAudioCallback( const void *inputBuffer, void *outputBuffer,
                                    unsigned long framesPerBuffer,
                                    const PaStreamCallbackTimeInfo* timeInfo,
                                    PaStreamCallbackFlags statusFlags,
                                    void *userData )
{
    int noisefactor;
    noisefactor = 1;
    
    float vol = AlgorhythmicAudioIO::Instance()->GetVolume();
    float freqMin = AlgorhythmicAudioIO::Instance()->GetFreqMin();
    float freqRange = AlgorhythmicAudioIO::Instance()->GetFreqMax() - freqMin;
    bool notesOn = AlgorhythmicAudioIO::Instance()->IsNotesOn();
    bool sepOn   = AlgorhythmicAudioIO::Instance()->IsSeperatorOn();
    bool click = false;
    
    for( int z = 0; z < NUM_CHANNELS; z++ )
        memset(((float*)outputBuffer)+framesPerBuffer*z, 0, framesPerBuffer*sizeof(float));
    
    //sonify stuff
	struct ssortdata* dataa = AlgorhythmicAudioIO::Instance()->GetSortData();
	int index;
	
	if(dataa->usedouble)
	{
        AlgorhythmicAudioIO::Instance()->LockSortData();
        
        //if this is a fresh array
        if(!dataa->seperatorPlayed)
        {
            click = true;
            nb_samples_left = nb_samples_total = dataa->duration * SAMPLE_RATE/8;
            dataa->seperatorPlayed=true;
        }
        
		//double array.
        //duration is for the entire array.
        //get the index of the number we are interested in by looking at how much we've played back so far.
        if(dataa->durations && dataa->lastNoteIndex< dataa->durationsSize && dataa->sampleCursor > dataa->durations[dataa->lastNoteIndex] * SAMPLE_RATE)
        {
            dataa->sampleCursor=0;
            dataa->lastNoteIndex++;
        }
		index = dataa->lastNoteIndex;
        ComputeCurrentIndex(index);
        
		if(dataa->doubleArray && index <= dataa->doubleArraySize && dataa->durations && dataa->durations[dataa->lastNoteIndex]* SAMPLE_RATE> dataa->sampleCursor)
		{
            float pan = 0.5f;
			float freq = 0.0f;
            if(index < dataa->doubleArraySize)
            {
                freq =  (dataa->doubleArray[index] + 100) / 200.0; //hack - values range from -100 to 100
                freq = freqRange*exp2cursor(freq, (logf(freqRange+freqMin)/logf(2) - logf(freqMin)/logf(2)))+freqMin;
                pan = ((float)index)/dataa->doubleArraySize;
			}
            
            if(sepOn && nb_samples_left) {
                nb_freq = 10000/(dataa->seperatorDepth + 1);
                
                NoiseBandFillFrame((float*) outputBuffer, framesPerBuffer, vol);
                for(int i=0;i<framesPerBuffer;i++) {
                    ((float*)outputBuffer)[i*2]   *= (float)nb_samples_left/nb_samples_total;
                    ((float*)outputBuffer)[i*2+1] *= (float)nb_samples_left/nb_samples_total;
                    if(nb_samples_left>0)
                        nb_samples_left--;
                }
            }
            
			for(unsigned int i = 0; i < framesPerBuffer*NUM_CHANNELS; i+=2)
			{
                float sinval;
                sinval = sin(dataa->phase);
                if(notesOn)//old sep || (index == dataa->doubleArraySize && sepOn ))
                {
                    ((float*)outputBuffer)[i]   += sinval * (1.0-pan) * vol * 0.5;
                    ((float*)outputBuffer)[i+1] += sinval * pan       * vol * 0.5;
                }
                if(1 || click) {
                    float bassmult = 16*dataa->seperatorDepth+1;
                    //               ((float*)outputBuffer)[i]   +=  vol*2*((float)mymax(0,(framesPerBuffer*NUM_CHANNELS-(i*bassmult)))/framesPerBuffer*NUM_CHANNELS);
                    //               ((float*)outputBuffer)[i+1] +=  vol*2*((float)mymax(0,(framesPerBuffer*NUM_CHANNELS-(i*bassmult)))/framesPerBuffer*NUM_CHANNELS);
                }
				//inc phase if we are under the size, otherwise use noise.
                if(index < dataa->doubleArraySize)
				{
                    dataa->phase+=2.0*3.14592 *freq / SAMPLE_RATE;
                    while(dataa->phase>2.0*3.14592)
                        dataa->phase-=2.0*3.14592;
                }
                else
                {
                    //noise
                    if(dataa->lastNoteIndex<= dataa->doubleArraySize && dataa->durations[dataa->lastNoteIndex] !=0)
                    {
                        dataa->phase = randfloat(2.0*3.14592);
                        pan = 0.5;
                    }
                }
                dataa->sampleCursor++;
                
                //see if we've stepped over a boundry
                if(dataa->sampleCursor > dataa->durations[dataa->lastNoteIndex] * SAMPLE_RATE)
                {
                    dataa->sampleCursor=0;
                    dataa->lastNoteIndex++;
                    index = dataa->lastNoteIndex;
                    ComputeCurrentIndex(index);
                    if(!(dataa->lastNoteIndex<= dataa->doubleArraySize))
                        break;
                    else if (dataa->lastNoteIndex < dataa->doubleArraySize)
                    {
                        freq = (dataa->doubleArray[index] + 100) / 200.0; //hack - values range from -100 to 100
                        freq = freqRange*exp2cursor(freq, (logf(freqRange+freqMin)/logf(2) - logf(freqMin)/logf(2)))+freqMin;
                        pan = ((float)index)/dataa->doubleArraySize;
                    }
                }
			}
		}
        AlgorhythmicAudioIO::Instance()->unLockSortData();
	}
    
    
    // Clip output to [-1.0,+1.0] range
    for(unsigned int i = 0; i < framesPerBuffer*NUM_CHANNELS; i++)
    {
        float f = ((float*)outputBuffer)[i];
        if (f > 1.0f)
            ((float*)outputBuffer)[i] = 1.0f;
        else if (f < -1.0f)
            ((float*)outputBuffer)[i] = -1.0f;
    }
    return 0;
}