Пример #1
0
void *SoundTouch_init(void) 
{
    SoundTouch *soundTouch = new SoundTouch();
    soundTouch->setSetting(SETTING_USE_QUICKSEEK, false);
    soundTouch->setSetting(SETTING_USE_AA_FILTER, true);
    return (void *)soundTouch;
}
Пример #2
0
AVSStereoSoundTouch(PClip _child, float _tempo, float _rate, float _pitch, const AVSValue* args, IScriptEnvironment* env)
: GenericVideoFilter(_child), 
  tempo(_tempo/100.0f), rate(_rate/100.0f), pitch(_pitch/100.0f)
{
//  last_nch = vi.AudioChannels();
  
  dstbuffer = new SFLOAT[BUFFERSIZE * vi.AudioChannels()];

  sample_multiplier  = tempo / pitch;  // Do it the same way the library does it!
  sample_multiplier *= pitch * rate;

  sampler = new SoundTouch();

  sampler->setRate(rate);
  sampler->setTempo(tempo);
  sampler->setPitch(pitch);
  sampler->setChannels(2);
  sampler->setSampleRate(vi.audio_samples_per_second);
  AVSsoundtouch::setSettings(sampler, args, env);

  vi.num_audio_samples = (__int64)((long double)vi.num_audio_samples / sample_multiplier);

  next_sample = 0;  // Next output sample
  inputReadOffset = 0;  // Next input sample
  dst_samples_filled = 0;

}
Пример #3
0
void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env)
{

  if (start != next_sample) {  // Reset on seek
    sampler->clear();
    next_sample = start;
    inputReadOffset = (__int64)(sample_multiplier * (long double)start);  // Reset at new read position (NOT sample exact :( ).
    dst_samples_filled=0;
  }

  bool buffer_full = false;
  int samples_filled = 0;

  do {
    // Empty buffer if something is still left.
    if (dst_samples_filled) {
      int copysamples = min((int)count-samples_filled, dst_samples_filled);
      // Copy finished samples
      if (copysamples) { 
        memcpy((BYTE*)buf+vi.BytesFromAudioSamples(samples_filled), (BYTE*)dstbuffer, (size_t)vi.BytesFromAudioSamples(copysamples));
        samples_filled += copysamples;

        dst_samples_filled -= copysamples;
        // Move non-used samples
        memcpy(dstbuffer, &dstbuffer[copysamples*2], (size_t)vi.BytesFromAudioSamples(dst_samples_filled));
      }
      if (samples_filled >= count)
        buffer_full = true;
    }

    // If buffer empty - refill
    if (dst_samples_filled==0) {
      // Read back samples from filter
      int samples_out = 0;
      int gotsamples = 0;
      do {
        gotsamples = sampler->receiveSamples(&dstbuffer[vi.BytesFromAudioSamples(samples_out)], BUFFERSIZE - samples_out);
        samples_out += gotsamples;
      } while (gotsamples > 0);

      dst_samples_filled = samples_out;

      if (!dst_samples_filled) {  // We didn't get any samples
          // Feed new samples to filter
        child->GetAudio(dstbuffer, inputReadOffset, BUFFERSIZE, env);
        inputReadOffset += BUFFERSIZE;
        sampler->putSamples(dstbuffer, BUFFERSIZE);
      } // End if no samples
    } // end if empty buffer
  } while (!buffer_full);
  next_sample += count;
}
Пример #4
0
void *vc_soundtouch_create(int rate, float pitch)
{
    SoundTouch *st;
    st = new SoundTouch();
    if (st) {
        st->setChannels(1);
        st->setSampleRate(rate);
        st->setPitchSemiTones(pitch);
        st->setSetting(SETTING_USE_QUICKSEEK, 1);
        st->setSetting(SETTING_USE_AA_FILTER, 1);
    }
    return st;
}
Пример #5
0
void vc_voice_change(void *st_, float *fbuf, int16_t *data,
                     int samples, int datalen)
{
    SoundTouch *st = (SoundTouch *)st_;

#if defined(INTEGER_SAMPLES) || defined(SOUNDTOUCH_INTEGER_SAMPLES)

    st->putSamples(data, samples);
    if (st->numSamples() >= samples) {
        st->receiveSamplesEx(data, samples);
    } else {
        memset(data, 0, datalen);
    }

#elif defined(FLOAT_SAMPLES) || defined(SOUNDTOUCH_FLOAT_SAMPLES)

    slin_to_flin(fbuf, data, samples);
    st->putSamples(fbuf, samples);
    if ((int)st->numSamples() >= samples) {
        st->receiveSamples(fbuf, samples);
        flin_to_slin(data, fbuf, samples);
    } else {
        memset(data, 0, datalen);
    }

#else
#  error "unknown soundtouch sample type"
#endif
}
Пример #6
0
void* audioConsumerNoStretch(void* param)
{
    soundTouch.setSampleRate(GameFreq);
    soundTouch.setChannels(2);
    soundTouch.setSetting( SETTING_USE_QUICKSEEK, 1 );
    soundTouch.setSetting( SETTING_USE_AA_FILTER, 1 );
    double speedFactor = static_cast<double>(speed_factor)/100.0;
    soundTouch.setTempo(speedFactor);

    soundTouch.setRate((double)GameFreq/(double)OutputFreq);
    queueData* currQueueData = NULL;
    struct timespec prevTime;

    int lastSpeedFactor = speed_factor;

    //How long to wait for some data
    struct timespec waitTime;
    waitTime.tv_sec = 1;
    waitTime.tv_nsec = 0;

    while(!shutdown)
    {
        struct threadmsg msg;

        clock_gettime(CLOCK_MONOTONIC_RAW, &prevTime);
        int result = thread_queue_get(&audioConsumerQueue, &waitTime, &msg);

        if( result != ETIMEDOUT )
        {
            currQueueData = (queueData*)msg.data;
            int dataLength = currQueueData->lenght;

            if(lastSpeedFactor != speed_factor)
            {
                lastSpeedFactor = speed_factor;
                double speedFactor = static_cast<double>(speed_factor)/100.0;
                soundTouch.setTempo(speedFactor);
            }


            processAudio(currQueueData->data, dataLength);

            free(currQueueData->data);
            free(currQueueData);
        }
    }

    return 0;
}
Пример #7
0
unsigned int SoundTouch_receiveSamples(void *stouch, float *samples, unsigned int maxSamples) 
{
    SoundTouch *soundTouch = (SoundTouch *)stouch;
    return soundTouch->receiveSamples(samples, maxSamples);
}
Пример #8
0
extern "C" DLL_PUBLIC void Java_net_surina_soundtouch_SoundTouch_setTempo(JNIEnv *env, jobject thiz, jlong handle, jfloat tempo)
{
	SoundTouch *ptr = (SoundTouch*)handle;
	ptr->setTempo(tempo);
}
Пример #9
0
void SoundTouch_setTempo(void *stouch, float tempo) 
{
    SoundTouch *soundTouch = (SoundTouch *)stouch;
    soundTouch->setTempo(tempo);
}
Пример #10
0
void SoundTouch_setTempoChange(void *stouch, float percentTempo) 
{
    SoundTouch *soundTouch = (SoundTouch *)stouch;
    soundTouch->setTempoChange(percentTempo);
}
Пример #11
0
void SoundTouch_setChannels(void *stouch, unsigned int channels) 
{
    SoundTouch *soundTouch = (SoundTouch *)stouch;
    soundTouch->setChannels(channels);
}
Пример #12
0
void SoundTouch_setSampleRate(void *stouch, unsigned int sampleRate) 
{
    SoundTouch *soundTouch = (SoundTouch *)stouch;
    soundTouch->setSampleRate(sampleRate); 
}
Пример #13
0
extern "C" DLL_PUBLIC void Java_net_surina_soundtouch_SoundTouch_setSpeed(JNIEnv *env, jobject thiz, jlong handle, jfloat speed)
{
	SoundTouch *ptr = (SoundTouch*)handle;
	ptr->setRate(speed);
}
Пример #14
0
extern "C" DLL_PUBLIC void Java_net_surina_soundtouch_SoundTouch_setPitchSemiTones(JNIEnv *env, jobject thiz, jlong handle, jfloat pitch)
{
	SoundTouch *ptr = (SoundTouch*)handle;
	ptr->setPitchSemiTones(pitch);
}
Пример #15
0
void processAudio(const unsigned char* buffer, unsigned int length)
{
   if (length < primaryBufferBytes)
   {
       unsigned int i;

       for ( i = 0 ; i < length ; i += 4 )
       {
           if(SwapChannels == 0)
           {
               /* Left channel */
              primaryBuffer[ i ] = buffer[ i + 2 ];
              primaryBuffer[ i + 1 ] = buffer[ i + 3 ];

               /* Right channel */
              primaryBuffer[ i + 2 ] = buffer[ i ];
              primaryBuffer[ i + 3 ] = buffer[ i + 1 ];
           }
           else
           {
               /* Left channel */
              primaryBuffer[ i ] = buffer[ i ];
              primaryBuffer[ i + 1 ] = buffer[ i + 1 ];

               /* Right channel */
              primaryBuffer[ i + 2 ] = buffer[ i + 2 ];
              primaryBuffer[ i + 3 ] = buffer[ i + 3 ];
           }
       }
   }
   else
       DebugMessage(M64MSG_WARNING, "processAudio(): Audio primary buffer overflow.");

#ifdef FP_ENABLED
   int numSamples = length/sizeof(short);
   short* primaryBufferShort = (short*)primaryBuffer;
   float primaryBufferFloat[numSamples];

   for(int index = 0; index < numSamples; ++index)
   {
      primaryBufferFloat[index] = static_cast<float>(primaryBufferShort[index])/32767.0;
   }

   soundTouch.putSamples((SAMPLETYPE*)primaryBufferFloat, length/N64_SAMPLE_BYTES);

#else
   soundTouch.putSamples((SAMPLETYPE*)primaryBuffer, length/N64_SAMPLE_BYTES);
#endif

   int outSamples = 0;

   do
   {
      outSamples = soundTouch.receiveSamples((SAMPLETYPE*)secondaryBuffers[secondaryBufferIndex], SecondaryBufferSize);

      if(outSamples != 0 && lock.value > 0)
      {
         SLresult result = (*bufferQueue)->Enqueue(bufferQueue, secondaryBuffers[secondaryBufferIndex],
            outSamples*SLES_SAMPLE_BYTES);

          if(result != SL_RESULT_SUCCESS)
          {
              lock.errors++;
          }
          else
          {
              --lock.value;
              ++lock.count;
          }

         secondaryBufferIndex++;

         if(secondaryBufferIndex > (SecondaryBufferNbr-1))
            secondaryBufferIndex = 0;
      }
   }
   while (outSamples != 0);
}
Пример #16
0
void* audioConsumerStretch(void* param)
{
   /*
   static int sequenceLenMS = 63;
   static int seekWindowMS = 16;
   static int overlapMS = 7;*/

   soundTouch.setSampleRate((uint)GameFreq);
   soundTouch.setChannels(2);
   soundTouch.setSetting( SETTING_USE_QUICKSEEK, 1 );
   soundTouch.setSetting( SETTING_USE_AA_FILTER, 1 );
   //soundTouch.setSetting( SETTING_SEQUENCE_MS, sequenceLenMS );
   //soundTouch.setSetting( SETTING_SEEKWINDOW_MS, seekWindowMS );
   //soundTouch.setSetting( SETTING_OVERLAP_MS, overlapMS );

   soundTouch.setRate((double)GameFreq/(double)OutputFreq);
   double speedFactor = static_cast<double>(speed_factor)/100.0;
   soundTouch.setTempo(speedFactor);
   
   double bufferMultiplier = (double)OutputFreq/DEFAULT_FREQUENCY;

   int maxQueueSize = (int)(TargetSecondaryBuffers + 30.0*bufferMultiplier);
   int minQueueSize = (int)(TargetSecondaryBuffers*bufferMultiplier);
   bool drainQueue = false;

   //Sound queue ran dry, device is running slow
   int ranDry = 0;

   //adjustment used when a device running too slow
   double slowAdjustment = 1.0;
   double currAdjustment = 1.0;

   //how quickly to return to original speed
   const double returnSpeed = 0.10;
   const double minSlowValue = 0.2;
   const double maxSlowValue = 3.0;
   const float maxSpeedUpRate = 0.5;
   const float slowRate = 0.05;
   queueData* currQueueData = NULL;
    struct timespec prevTime;
    struct timespec currTime;

   //How long to wait for some data
   struct timespec waitTime;
   waitTime.tv_sec = 1;
   waitTime.tv_nsec = 0;

   int feedTimeWindowSize = 50;
   int feedTimeIndex = 0;
   bool feedTimesSet = false;
   float feedTimes[feedTimeWindowSize];
   float gameTimes[feedTimeWindowSize];
   float averageGameTime = 0.01666;
   float averageFeedTime = 0.01666;

   while(!shutdown)
   {
      int slesQueueLength = lock.limit - lock.value;

      ranDry = slesQueueLength < minQueueSize;

      struct threadmsg msg;

      clock_gettime(CLOCK_MONOTONIC_RAW, &prevTime);
      int result = thread_queue_get(&audioConsumerQueue, &waitTime, &msg);

      if( result != ETIMEDOUT )
      {
         int threadQueueLength = thread_queue_length(&audioConsumerQueue);

         currQueueData = (queueData*)msg.data;
         int dataLength = currQueueData->lenght;

         float temp =  averageGameTime/averageFeedTime;

          // Only start running algorithm once enough samples are built
          if(lock.count <= lock.limit)
          {
              double speedFactor = static_cast<double>(speed_factor)/100.0;
              soundTouch.setTempo(speedFactor);

              processAudio(currQueueData->data, dataLength);

              free(currQueueData->data);
              free(currQueueData);

              //Useful logging
              //if(slesQueueLength == 0)
              //{
              //DebugMessage(M64MSG_ERROR, "sles_length=%d, min_size=%d, count=%d",
              //             slesQueueLength, minQueueSize, lock.count);
              //}
          }
          else{
              //Game is running too fast speed up audio
              if ((slesQueueLength > maxQueueSize || drainQueue) && !ranDry) {
                  drainQueue = true;
                  currAdjustment = temp +
                                   (float) (slesQueueLength - minQueueSize) / (float) (lock.limit - minQueueSize) *
                                   maxSpeedUpRate;
              }
                  //Device can't keep up with the game or we have too much in the queue after slowing it down
              else if (ranDry) {
                  drainQueue = false;
                  currAdjustment = temp - slowRate;
              }
              else if (!ranDry && slesQueueLength < maxQueueSize) {
                  currAdjustment = temp;
              }

              //Allow the tempo to slow quickly with no minimum value change, but restore original tempo more slowly.
              if (currAdjustment > minSlowValue && currAdjustment < maxSlowValue) {
                  slowAdjustment = currAdjustment;
                  static const int increments = 4;
                  //Adjust tempo in x% increments so it's more steady
                  int temp2 = ((int) (slowAdjustment * 100)) / increments;
                  temp2 *= increments;
                  slowAdjustment = ((double) temp2) / 100;

                  soundTouch.setTempo(slowAdjustment);
              }

              processAudio(currQueueData->data, dataLength);

              free(currQueueData->data);
              free(currQueueData);

              //Useful logging
              //if(slesQueueLength == 0)
              //{
              //DebugMessage(M64MSG_ERROR, "sles_length=%d, thread_length=%d, dry=%d, slow_adj=%f, curr_adj=%f, temp=%f, feed_time=%f, game_time=%f, min_size=%d, count=%d",
              //             slesQueueLength, threadQueueLength, ranDry, slowAdjustment, currAdjustment, temp, averageFeedTime, averageGameTime, minQueueSize, lock.count);
              //}

              //We don't want to calculate the average until we give everything a time to settle.
              //Calculate rates
              clock_gettime(CLOCK_MONOTONIC_RAW, &currTime);

              //Figure out how much to slow down by
              float timeDiff = TimeDiff(&currTime, &prevTime);

              //sometimes this ends up as less than 0, not sure how
              if (timeDiff > 0) {
                  feedTimes[feedTimeIndex] = timeDiff;
              }

              averageFeedTime = GetAverageTime(feedTimes, feedTimesSet ? feedTimeWindowSize : (feedTimeIndex + 1));

              gameTimes[feedTimeIndex] = (float) dataLength / (float) N64_SAMPLE_BYTES / (float) GameFreq;
              averageGameTime = GetAverageTime(gameTimes, feedTimesSet ? feedTimeWindowSize : (feedTimeIndex + 1));

              ++feedTimeIndex;
              if (feedTimeIndex == feedTimeWindowSize) {
                  feedTimeIndex = 0;
                  feedTimesSet = true;
              }
          }
      }
   }

   return 0;
}
Пример #17
0
void SoundTouch_setPitchSemiTones(void *stouch, float semiTones) 
{
    SoundTouch *soundTouch = (SoundTouch *)stouch;
    soundTouch->setPitchSemiTones(semiTones);
}
Пример #18
0
void SoundTouch_putSamples(void *stouch, float *samples, unsigned int numSamples) 
{
    SoundTouch *soundTouch = (SoundTouch *)stouch;
    soundTouch->putSamples(samples, numSamples);
}
static void ChangePcmTone(FILE *inFile, FILE *outFile, float TempoChange, float PitchSemiTones, float RateChange)
{
	SoundTouch soundTouch;

	// Setup the 'SoundTouch' object for processing the sound

	soundTouch.setSampleRate(8000);
	soundTouch.setChannels(1);

	soundTouch.setTempoChange(TempoChange);
	soundTouch.setPitchSemiTones(PitchSemiTones); //’˝œÚ «x÷·¿≠≥§£¨4±»Ωœ¿ÌœÎ
	soundTouch.setRateChange(RateChange);     //’˝œÚ «x÷·¿≠≥§£¨50

	//soundTouch.setTempoChange(20);
	//soundTouch.setPitchSemiTones(6.0f); //’˝œÚ «x÷·¿≠≥§£¨4±»Ωœ¿ÌœÎ
	//soundTouch.setRateChange(0);     //’˝œÚ «x÷·¿≠≥§£¨50

	//soundTouch.setTempoChange(1.0);
	//soundTouch.setPitchSemiTones(20);
	//soundTouch.setRateChange(-2.0);

	soundTouch.setSetting(SETTING_USE_QUICKSEEK, 0);
	soundTouch.setSetting(SETTING_USE_AA_FILTER, 1);
	soundTouch.setSetting(SETTING_SEQUENCE_MS, 40);
	soundTouch.setSetting(SETTING_SEEKWINDOW_MS, 15);
	soundTouch.setSetting(SETTING_OVERLAP_MS, 8);

#if 0
	if (params->speech)
	{
		// use settings for speech processing
		soundTouch.setSetting(SETTING_SEQUENCE_MS, 40);
		soundTouch.setSetting(SETTING_SEEKWINDOW_MS, 15);
		soundTouch.setSetting(SETTING_OVERLAP_MS, 8);
		fprintf(stderr, "Tune processing parameters for speech processing.\n");
	}
#endif
	// Process the sound
	process(&soundTouch, inFile, outFile);	
	fflush(outFile);
}