Ejemplo n.º 1
0
// Prepare a sample buffer for autocorrelation
bool Autotune::PrepareSample(SmpLength maxShift)
//----------------------------------------------
{

	// Determine which parts of the sample should be examined.
	SmpLength sampleOffset = 0, sampleLoopStart = 0, sampleLoopEnd = sample.nLength;
	if(selectionEnd >= sampleLoopStart + MIN_SAMPLE_LENGTH)
	{
		// A selection has been specified: Examine selection
		sampleOffset = selectionStart;
		sampleLoopStart = 0;
		sampleLoopEnd = selectionEnd - selectionStart;
	} else if(sample.uFlags[CHN_SUSTAINLOOP] && sample.nSustainEnd >= sample.nSustainStart + MIN_SAMPLE_LENGTH)
	{
		// A sustain loop is set: Examine sample up to sustain loop and, if necessary, execute the loop several times
		sampleOffset = 0;
		sampleLoopStart = sample.nSustainStart;
		sampleLoopEnd = sample.nSustainEnd;
	} else if(sample.uFlags[CHN_LOOP] && sample.nLoopEnd >= sample.nLoopStart + MIN_SAMPLE_LENGTH)
	{
		// A normal loop is set: Examine sample up to loop and, if necessary, execute the loop several times
		sampleOffset = 0;
		sampleLoopStart = sample.nLoopStart;
		sampleLoopEnd = sample.nLoopEnd;
	}

	// We should analyse at least a one second (= GetSampleRate() samples) long sample.
	sampleLength = std::max<SmpLength>(sampleLoopEnd, sample.GetSampleRate(modType)) + maxShift;
	sampleLength = (sampleLength + 7) & ~7;

	if(sampleData != nullptr)
	{
		delete[] sampleData;
	}
	sampleData = new int16[sampleLength];
	if(sampleData == nullptr)
	{
		return false;
	}

	// Copy sample over.
	switch(sample.GetElementarySampleSize())
	{
	case 1:
		CopySamples(static_cast<int8 *>(sample.pSample) + sampleOffset * sample.GetNumChannels(), sampleLoopStart, sampleLoopEnd);
		return true;

	case 2:
		CopySamples(static_cast<int16 *>(sample.pSample) + sampleOffset * sample.GetNumChannels(), sampleLoopStart, sampleLoopEnd);
		return true;
	}

	return false;

}
Ejemplo n.º 2
0
/// Retrieves a portion of the 64K summary buffer from this BlockFile.  This
/// data provides information about the minimum value, the maximum
/// value, and the maximum RMS value for every group of 64K samples in the
/// file.
///
/// @param *buffer The area where the summary information will be
///                written.  It must be at least len*3 long.
/// @param start   The offset in 64K-sample increments
/// @param len     The number of 64K-sample summary frames to read
bool BlockFile::Read64K(float *buffer,
                        sampleCount start, sampleCount len)
{
   wxASSERT(start >= 0);

   char *summary = new char[mSummaryInfo.totalSummaryBytes];
   this->ReadSummary(summary);

   if (start+len > mSummaryInfo.frames64K)
      len = mSummaryInfo.frames64K - start;

   CopySamples(summary + mSummaryInfo.offset64K + 
               (start * mSummaryInfo.bytesPerFrame),
               mSummaryInfo.format,
               (samplePtr)buffer, floatSample, len*mSummaryInfo.fields);

   if (mSummaryInfo.fields == 2) {
      // No RMS info; make guess
      int i;
      for(i=len-1; i>=0; i--) {
         buffer[3*i+2] = (fabs(buffer[2*i]) + fabs(buffer[2*i+1]))/4.0;
         buffer[3*i+1] = buffer[2*i+1];
         buffer[3*i] = buffer[2*i];
      }
   }

   delete[] summary;

   return true;
}
Ejemplo n.º 3
0
/// A thread-safe version of CalcSummary.  BlockFile::CalcSummary
/// uses a static summary array across the class, which we can't use.
/// Get a buffer containing a summary block describing this sample
/// data.  This must be called by derived classes when they
/// are constructed, to allow them to construct their summary data,
/// after which they should write that data to their disk file.
///
/// This method also has the side effect of setting the mMin, mMax,
/// and mRMS members of this class.
///
/// Unlike BlockFile's implementation You SHOULD DELETE the returned buffer.
/// this is protected so it shouldn't be hard to deal with - just override
/// all BlockFile methods that use this method.
///
/// @param buffer A buffer containing the sample data to be analyzed
/// @param len    The length of the sample data
/// @param format The format of the sample data.
void *ODPCMAliasBlockFile::CalcSummary(samplePtr buffer, size_t len,
                             sampleFormat format, ArrayOf<char> &cleanup)
{
   cleanup.reinit(mSummaryInfo.totalSummaryBytes);
   char* localFullSummary = cleanup.get();

   memcpy(localFullSummary, aheaderTag, aheaderTagLen);

   float *summary64K = (float *)(localFullSummary + mSummaryInfo.offset64K);
   float *summary256 = (float *)(localFullSummary + mSummaryInfo.offset256);

   float *fbuffer;

   //mchinen: think we can hack this - don't allocate and copy if we don't need to.,
   if(format==floatSample)
   {
      fbuffer = (float*)buffer;
   }
   else
   {
      fbuffer = new float[len];
      CopySamples(buffer, format,
               (samplePtr)fbuffer, floatSample, len);
   }

   BlockFile::CalcSummaryFromBuffer(fbuffer, len, summary256, summary64K);

   //if we've used the float sample..
   if(format!=floatSample)
   {
      delete[] fbuffer;
   }
   return localFullSummary;
}
Ejemplo n.º 4
0
int RingBuffer::Get(samplePtr buffer, sampleFormat format,
                    int samplesToCopy)
{
   samplePtr dest;
   int block;
   int copied;
   int len = Len();

   if (samplesToCopy > len)
      samplesToCopy = len;

   dest = buffer;
   copied = 0;

   while(samplesToCopy) {
      block = samplesToCopy;
      if (block > mBufferSize - mStart)
         block = mBufferSize - mStart;

      CopySamples(mBuffer.ptr() + mStart * SAMPLE_SIZE(mFormat), mFormat,
                  dest, format,
                  block);

      dest += block * SAMPLE_SIZE(format);
      mStart = (mStart + block) % mBufferSize;
      samplesToCopy -= block;
      copied += block;
   }

   return copied;
}
Ejemplo n.º 5
0
int RingBuffer::Put(samplePtr buffer, sampleFormat format,
                    int samplesToCopy)
{
   samplePtr src;
   int block;
   int copied;
   int pos;
   int len = Len();

   if (samplesToCopy > (mBufferSize-4) - len)
      samplesToCopy = (mBufferSize-4) - len;

   src = buffer;
   copied = 0;
   pos = mEnd;

   while(samplesToCopy) {
      block = samplesToCopy;
      if (block > mBufferSize - pos)
         block = mBufferSize - pos;

      CopySamples(src, format,
                  mBuffer.ptr() + pos * SAMPLE_SIZE(mFormat), mFormat,
                  block);

      src += block * SAMPLE_SIZE(format);
      pos = (pos + block) % mBufferSize;
      samplesToCopy -= block;
      copied += block;
   }

   mEnd = pos;

   return copied;
}
Ejemplo n.º 6
0
size_t RingBuffer::Put(samplePtr buffer, sampleFormat format,
                    size_t samplesToCopy)
{
   samplesToCopy = std::min( samplesToCopy, AvailForPut() );
   auto src = buffer;
   size_t copied = 0;
   auto pos = mEnd;

   while(samplesToCopy) {
      auto block = std::min( samplesToCopy, mBufferSize - pos );

      CopySamples(src, format,
                  mBuffer.ptr() + pos * SAMPLE_SIZE(mFormat), mFormat,
                  block);

      src += block * SAMPLE_SIZE(format);
      pos = (pos + block) % mBufferSize;
      samplesToCopy -= block;
      copied += block;
   }

   mEnd = pos;

   return copied;
}
Ejemplo n.º 7
0
/// A thread-safe version of CalcSummary.  BlockFile::CalcSummary
/// uses a static summary array across the class, which we can't use.
/// Get a buffer containing a summary block describing this sample
/// data.  This must be called by derived classes when they
/// are constructed, to allow them to construct their summary data,
/// after which they should write that data to their disk file.
///
/// This method also has the side effect of setting the mMin, mMax,
/// and mRMS members of this class.
///
/// Unlike BlockFile's implementation You SHOULD DELETE the returned buffer.
/// this is protected so it shouldn't be hard to deal with - just override
/// all BlockFile methods that use this method.
///
/// @param buffer A buffer containing the sample data to be analyzed
/// @param len    The length of the sample data
/// @param format The format of the sample data.
void *ODDecodeBlockFile::CalcSummary(samplePtr buffer, size_t len,
                             sampleFormat format, ArrayOf<char> &cleanup)
{
   cleanup.reinit(mSummaryInfo.totalSummaryBytes);
   char* localFullSummary = cleanup.get();

   memcpy(localFullSummary, bheaderTag, bheaderTagLen);

   float *summary64K = (float *)(localFullSummary + mSummaryInfo.offset64K);
   float *summary256 = (float *)(localFullSummary + mSummaryInfo.offset256);

   Floats floats;
   float *fbuffer;

   //mchinen: think we can hack this - don't allocate and copy if we don't need to.,
   if(format==floatSample)
   {
      fbuffer = (float*)buffer;
   }
   else
   {
      floats.reinit(len);
      fbuffer = floats.get();
      CopySamples(buffer, format,
               (samplePtr)fbuffer, floatSample, len);
   }

   BlockFile::CalcSummaryFromBuffer(fbuffer, len, summary256, summary64K);

   return localFullSummary;
}
Ejemplo n.º 8
0
// Pass NULL to set silence
bool Sequence::Set(samplePtr buffer, sampleFormat format,
                   sampleCount start, sampleCount len)
{
   if (start < 0 || start > mNumSamples ||
       start+len > mNumSamples)
      return false;

   samplePtr temp = NULL;
   if (format != mSampleFormat) {
      temp = NewSamples(mMaxSamples, mSampleFormat);
      wxASSERT(temp);
   }

   samplePtr silence = NULL;
   if (!buffer) {
      silence = NewSamples(mMaxSamples, format);
      wxASSERT(silence);
      ClearSamples(silence, format, 0, mMaxSamples);
   }

   int b = FindBlock(start);

   while (len) {
      int blen = mBlock->Item(b)->start + mBlock->Item(b)->len - start;
      if (blen > len)
         blen = len;

      if (buffer) {
         if (format == mSampleFormat)
            CopyWrite(buffer, mBlock->Item(b), start - mBlock->Item(b)->start,
                      blen);
         else {
            CopySamples(buffer, format, temp, mSampleFormat, blen);
            CopyWrite(temp, mBlock->Item(b), start - mBlock->Item(b)->start,
                      blen);
         }
         buffer += (blen * SAMPLE_SIZE(format));
      } else
         CopyWrite(silence, mBlock->Item(b), start - mBlock->Item(b)->start,
                   blen);

      len -= blen;
      start += blen;
      b++;
   }

   if (!buffer)
      DeleteSamples(silence);

   if (format != mSampleFormat)
      DeleteSamples(temp);

   return ConsistencyCheck("Set");
}
Ejemplo n.º 9
0
int EffectNyquist::GetCallback(float *buffer, int ch,
                               long start, long len, long totlen)
{
   if (mCurBuffer[ch]) {
      if ((mCurStart[ch] + start) < mCurBufferStart[ch] ||
          (mCurStart[ch] + start)+len >
          mCurBufferStart[ch]+mCurBufferLen[ch]) {
         delete[] mCurBuffer[ch];
         mCurBuffer[ch] = NULL;
      }
   }

   if (!mCurBuffer[ch]) {
      mCurBufferStart[ch] = (mCurStart[ch] + start);
      mCurBufferLen[ch] = mCurTrack[ch]->GetBestBlockSize(mCurBufferStart[ch]);

      if (mCurBufferLen[ch] < len) {
         mCurBufferLen[ch] = mCurTrack[ch]->GetIdealBlockSize();
      }

      if (mCurBufferStart[ch] + mCurBufferLen[ch] > mCurStart[ch] + mCurLen) {
         mCurBufferLen[ch] = mCurStart[ch] + mCurLen - mCurBufferStart[ch];
      }

      mCurBuffer[ch] = NewSamples(mCurBufferLen[ch], floatSample);
      if (!mCurTrack[ch]->Get(mCurBuffer[ch], floatSample,
                              mCurBufferStart[ch], mCurBufferLen[ch])) {

         wxPrintf(wxT("GET error\n"));

         return -1;
      }
   }

   long offset = (mCurStart[ch] + start) - mCurBufferStart[ch];
   CopySamples(mCurBuffer[ch] + offset*SAMPLE_SIZE(floatSample), floatSample,
               (samplePtr)buffer, floatSample,
               len);

   if (ch == 0) {
      double progress = mScale*(((float)start+len)/mCurLen);

      if (progress > mProgressIn) {
         mProgressIn = progress;
      }

      if (TotalProgress(mProgressIn+mProgressOut+mProgressTot)) {
         return -1;
      }
   }

   return 0;
}
Ejemplo n.º 10
0
bool WaveClip::Append(samplePtr buffer, sampleFormat format,
                      sampleCount len, unsigned int stride /* = 1 */,
                      XMLWriter* blockFileLog /*=NULL*/)
{
   //wxLogDebug(wxT("Append: len=%i"), len);
   
   sampleCount maxBlockSize = mSequence->GetMaxBlockSize();
   sampleCount blockSize = mSequence->GetIdealAppendLen();
   sampleFormat seqFormat = mSequence->GetSampleFormat();

   if (!mAppendBuffer)
      mAppendBuffer = NewSamples(maxBlockSize, seqFormat);

   for(;;) {
      if (mAppendBufferLen >= blockSize) {
         bool success =
            mSequence->Append(mAppendBuffer, seqFormat, blockSize,
                              blockFileLog);
         if (!success)
            return false;
         memmove(mAppendBuffer,
                 mAppendBuffer + blockSize * SAMPLE_SIZE(seqFormat),
                 (mAppendBufferLen - blockSize) * SAMPLE_SIZE(seqFormat));
         mAppendBufferLen -= blockSize;
         blockSize = mSequence->GetIdealAppendLen();
      }

      if (len == 0)
         break;

      int toCopy = maxBlockSize - mAppendBufferLen;
      if (toCopy > len)
         toCopy = len;

      CopySamples(buffer, format,
                  mAppendBuffer + mAppendBufferLen * SAMPLE_SIZE(seqFormat),
                  seqFormat,
                  toCopy,
                  true, // high quality
                  stride);

      mAppendBufferLen += toCopy;
      buffer += toCopy * SAMPLE_SIZE(format) * stride;
      len -= toCopy;
   }

   UpdateEnvelopeTrackLen();
   MarkChanged();

   return true;
}
Ejemplo n.º 11
0
bool WaveTrack::Append(samplePtr buffer, sampleFormat format,
                       sampleCount len, unsigned int stride /* = 1 */)
{
   //wxCriticalSectionLocker locker(mAppendCriticalSection);

   sampleCount maxBlockSize = mSequence->GetMaxBlockSize();
   sampleCount blockSize = mSequence->GetIdealAppendLen();
   sampleFormat seqFormat = mSequence->GetSampleFormat();

   if (!mAppendBuffer)
      mAppendBuffer = NewSamples(maxBlockSize, seqFormat);

   for(;;) {
      if (mAppendBufferLen >= blockSize) {
         bool success =
            mSequence->Append(mAppendBuffer, seqFormat, blockSize);
         if (!success)
            return false;
         memmove(mAppendBuffer,
                 mAppendBuffer + blockSize * SAMPLE_SIZE(seqFormat),
                 (mAppendBufferLen - blockSize) * SAMPLE_SIZE(seqFormat));
         mAppendBufferLen -= blockSize;
         blockSize = mSequence->GetIdealAppendLen();
      }

      if (len == 0)
         break;

      int toCopy = maxBlockSize - mAppendBufferLen;
      if (toCopy > len)
         toCopy = len;

      CopySamples(buffer, format,
                  mAppendBuffer + mAppendBufferLen * SAMPLE_SIZE(seqFormat),
                  seqFormat,
                  toCopy,
                  true, /* high quality */
                  stride);

      mAppendBufferLen += toCopy;
      buffer += toCopy * SAMPLE_SIZE(format) * stride;
      len -= toCopy;
   }

   mEnvelope->SetTrackLen(mSequence->GetNumSamples() / mRate);
   MarkChanged();

   return true;
}
Ejemplo n.º 12
0
/// Reads the specified data from the aliased file, using libsndfile,
/// and converts it to the given sample format.
///
/// @param data   The buffer to read the sample data into.
/// @param format The format to convert the data into
/// @param start  The offset within the block to begin reading
/// @param len    The number of samples to read
int PCMAliasBlockFile::ReadData(samplePtr data, sampleFormat format,
                                sampleCount start, sampleCount len)
{
   SF_INFO info;

   memset(&info, 0, sizeof(info));

   SNDFILE *sf = sf_open(mAliasedFullPath, SFM_READ, &info);
   if (!sf)
      return 0;

   sf_seek(sf, mAliasStart + start, SEEK_SET);
   samplePtr buffer = NewSamples(len * info.channels, floatSample);

   int framesRead = 0;

   if (format == int16Sample &&
       !sf_subtype_more_than_16_bits(info.format)) {
      // Special case: if the file is in 16-bit (or less) format,
      // and the calling method wants 16-bit data, go ahead and
      // read 16-bit data directly.  This is a pretty common
      // case, as most audio files are 16-bit.
      framesRead = sf_readf_short(sf, (short *)buffer, len);
      for (int i = 0; i < framesRead; i++)
         ((short *)data)[i] =
            ((short *)buffer)[(info.channels * i) + mAliasChannel];
   }
   else {
      // Otherwise, let libsndfile handle the conversion and
      // scaling, and pass us normalized data as floats.  We can
      // then convert to whatever format we want.
      framesRead = sf_readf_float(sf, (float *)buffer, len);
      float *bufferPtr = &((float *)buffer)[mAliasChannel];
      CopySamples((samplePtr)bufferPtr, floatSample,
                  (samplePtr)data, format,
                  framesRead, true, info.channels);
   }

   DeleteSamples(buffer);

   sf_close(sf);

   return framesRead;
}
Ejemplo n.º 13
0
sampleCount Mixer::MixSameRate(int *channelFlags, WaveTrack *track,
                               longSampleCount *pos)
{
   int slen = mMaxOut;
   int c;
   double t = *pos / track->GetRate();

   if (t + slen/track->GetRate() > mT1)
      slen = (int)((mT1 - t) * track->GetRate() + 0.5);
   
   if (slen <= 0)
      return 0;

   if (slen > mMaxOut)
      slen = mMaxOut;

   track->Get((samplePtr)mFloatBuffer, floatSample, *pos, slen);
   track->GetEnvelopeValues(mEnvValues, slen, t, 1.0 / mRate);
   for(int i=0; i<slen; i++)
      mFloatBuffer[i] *= mEnvValues[i]; // Track gain control will go here?
   
   if (mFormat == track->GetSampleFormat())
   {
      CopySamplesNoDither((samplePtr)mFloatBuffer, floatSample,
                          mTemp, mFormat, slen);
   } else {
      CopySamples((samplePtr)mFloatBuffer, floatSample,
                          mTemp, mFormat, slen);
   }
   

   for(c=0; c<mNumChannels; c++)
      if (mApplyTrackGains)
         mGains[c] = track->GetChannelGain(c);
      else
         mGains[c] = 1.0;

   MixBuffers(mNumChannels, channelFlags, mGains, mFormat,
              mTemp, mBuffer, slen, mInterleaved);

   *pos += slen;

   return slen;
}
Ejemplo n.º 14
0
bool Sequence::ConvertToSampleFormat(sampleFormat format)
{
   if (format == mSampleFormat)
      return true;

   if (mBlock->Count() == 0) {
      mSampleFormat = format;
      return true;
   }

   sampleFormat oldFormat = mSampleFormat;
   mSampleFormat = format;

   for (unsigned int i = 0; i < mBlock->Count(); i++) {
      BlockFile *oldBlock = mBlock->Item(i)->f;
      sampleCount len = mBlock->Item(i)->len;

      if (!oldBlock->IsAlias()) {
         BlockFile *newBlock =
            mDirManager->NewBlockFile(mSummary->totalSummaryBytes);

         samplePtr buffer1 = NewSamples(len, oldFormat);
         samplePtr buffer2 = NewSamples(len, mSampleFormat);

         oldBlock->ReadData(buffer1, oldFormat, 0, len);
         CopySamples(buffer1, oldFormat,
                     buffer2, mSampleFormat, len);
         newBlock->WriteData(buffer2, mSampleFormat, len);

         mBlock->Item(i)->f = newBlock;
         mDirManager->Deref(oldBlock);

         UpdateSummaries(buffer2, mBlock->Item(i), len);

         DeleteSamples(buffer2);
         DeleteSamples(buffer1);
      }
   }

   return true;
}
Ejemplo n.º 15
0
size_t RingBuffer::Get(samplePtr buffer, sampleFormat format,
                       size_t samplesToCopy)
{
   samplesToCopy = std::min( samplesToCopy, Len() );
   auto dest = buffer;
   size_t copied = 0;

   while(samplesToCopy) {
      auto block = std::min( samplesToCopy, mBufferSize - mStart );

      CopySamples(mBuffer.ptr() + mStart * SAMPLE_SIZE(mFormat), mFormat,
                  dest, format,
                  block);

      dest += block * SAMPLE_SIZE(format);
      mStart = (mStart + block) % mBufferSize;
      samplesToCopy -= block;
      copied += block;
   }

   return copied;
}
Ejemplo n.º 16
0
bool Sequence::ConvertToSampleFormat(sampleFormat format)
{
   if (format == mSampleFormat)
      return true;

   if (mBlock->Count() == 0) {
      mSampleFormat = format;
      return true;
   }

   sampleFormat oldFormat = mSampleFormat;
   mSampleFormat = format;

   for (unsigned int i = 0; i < mBlock->Count(); i++) {
      SeqBlock *b = mBlock->Item(i);
      BlockFile *oldBlock = b->f;
      sampleCount len = b->f->GetLength();

      if (!oldBlock->IsAlias()) {
         BlockFile *newBlock;

         samplePtr buffer1 = NewSamples(len, oldFormat);
         samplePtr buffer2 = NewSamples(len, mSampleFormat);

         oldBlock->ReadData(buffer1, oldFormat, 0, len);
         CopySamples(buffer1, oldFormat,
                     buffer2, mSampleFormat, len);
         newBlock = mDirManager->NewSimpleBlockFile(buffer2, len, mSampleFormat);

         mBlock->Item(i)->f = newBlock;
         mDirManager->Deref(oldBlock);

         DeleteSamples(buffer2);
         DeleteSamples(buffer1);
      }
   }

   return true;
}
Ejemplo n.º 17
0
bool Sequence::Append(samplePtr buffer, sampleFormat format,
                      sampleCount len, XMLWriter* blockFileLog /*=NULL*/)
{
   // Quick check to make sure that it doesn't overflow
   if (((double)mNumSamples) + ((double)len) > wxLL(9223372036854775807))
      return false;

   samplePtr temp = NULL;
   if (format != mSampleFormat) {
      temp = NewSamples(mMaxSamples, mSampleFormat);
      wxASSERT(temp);
   }

   // If the last block is not full, we need to add samples to it
   int numBlocks = mBlock->Count();
   if (numBlocks > 0 && mBlock->Item(numBlocks - 1)->f->GetLength() < mMinSamples) {
      SeqBlock *lastBlock = mBlock->Item(numBlocks - 1);
      sampleCount addLen;
      if (lastBlock->f->GetLength() + len < mMaxSamples)
         addLen = len;
      else
         addLen = GetIdealBlockSize() - lastBlock->f->GetLength();

      SeqBlock *newLastBlock = new SeqBlock();

      samplePtr buffer2 = NewSamples((lastBlock->f->GetLength() + addLen), mSampleFormat);
      Read(buffer2, mSampleFormat, lastBlock, 0, lastBlock->f->GetLength());

      CopySamples(buffer,
                  format,
                  buffer2 + lastBlock->f->GetLength() * SAMPLE_SIZE(mSampleFormat),
                  mSampleFormat,
                  addLen);

      newLastBlock->start = lastBlock->start;
      int newLastBlockLen = lastBlock->f->GetLength() + addLen;

      newLastBlock->f =
         mDirManager->NewSimpleBlockFile(buffer2, newLastBlockLen, mSampleFormat,
                                         blockFileLog != NULL);
      if (blockFileLog)
         ((SimpleBlockFile*)newLastBlock->f)->SaveXML(*blockFileLog);
         
      DeleteSamples(buffer2);

      mDirManager->Deref(lastBlock->f);
      delete lastBlock;
      mBlock->Item(numBlocks - 1) = newLastBlock;

      len -= addLen;
      mNumSamples += addLen;
      buffer += addLen * SAMPLE_SIZE(format);
   }
   // Append the rest as new blocks
   while (len) {
      sampleCount idealSamples = GetIdealBlockSize();
      sampleCount l = (len > idealSamples ? idealSamples : len);
      SeqBlock *w = new SeqBlock();
      w->start = mNumSamples;

      if (format == mSampleFormat) {
         w->f = mDirManager->NewSimpleBlockFile(buffer, l, mSampleFormat,
                                                blockFileLog != NULL);
      }
      else {
         CopySamples(buffer, format, temp, mSampleFormat, l);
         w->f = mDirManager->NewSimpleBlockFile(temp, l, mSampleFormat,
                                                blockFileLog != NULL);
      }

      if (blockFileLog)
         ((SimpleBlockFile*)w->f)->SaveXML(*blockFileLog);

      mBlock->Add(w);

      buffer += l * SAMPLE_SIZE(format);
      mNumSamples += l;
      len -= l;
   }

   if (format != mSampleFormat)
      DeleteSamples(temp);

// JKC: During generate we use Append again and again.
// If generating a long sequence this test would give O(n^2) 
// performance - not good!
#ifdef VERY_SLOW_CHECKING
   ConsistencyCheck(wxT("Append"));
#endif

   return true;
}
Ejemplo n.º 18
0
// Pass NULL to set silence
bool Sequence::Set(samplePtr buffer, sampleFormat format,
                   sampleCount start, sampleCount len)
{
   if (start < 0 || start > mNumSamples ||
       start+len > mNumSamples)
      return false;

   samplePtr temp = NULL;
   if (format != mSampleFormat) {
      temp = NewSamples(mMaxSamples, mSampleFormat);
      wxASSERT(temp);
   }

   samplePtr silence = NULL;
   if (!buffer) {
      silence = NewSamples(mMaxSamples, format);
      wxASSERT(silence);
      ClearSamples(silence, format, 0, mMaxSamples);
   }

   int b = FindBlock(start);

   while (len) {
      int blen = mBlock->Item(b)->start + mBlock->Item(b)->f->GetLength() - start;
      if (blen > len)
         blen = len;

      if (buffer) {
         if (format == mSampleFormat)
            CopyWrite(buffer, mBlock->Item(b), start - mBlock->Item(b)->start,
                      blen);
         else {
            CopySamples(buffer, format, temp, mSampleFormat, blen);
            CopyWrite(temp, mBlock->Item(b), start - mBlock->Item(b)->start,
                      blen);
         }
         buffer += (blen * SAMPLE_SIZE(format));
      }
      else {
         // If it's a full block of silence
         if (start == mBlock->Item(b)->start &&
             blen == mBlock->Item(b)->f->GetLength()) {

            mDirManager->Deref(mBlock->Item(b)->f);
            mBlock->Item(b)->f = new SilentBlockFile(blen);
         }
         else {
            // Otherwise write silence just to the portion of the block
            CopyWrite(silence, mBlock->Item(b),
                      start - mBlock->Item(b)->start, blen);
         }
      }

      len -= blen;
      start += blen;
      b++;
   }

   if (!buffer)
      DeleteSamples(silence);

   if (format != mSampleFormat)
      DeleteSamples(temp);

   return ConsistencyCheck(wxT("Set"));
}
Ejemplo n.º 19
0
/// A thread-safe version of CalcSummary.  BlockFile::CalcSummary
/// uses a static summary array across the class, which we can't use.
/// Get a buffer containing a summary block describing this sample
/// data.  This must be called by derived classes when they
/// are constructed, to allow them to construct their summary data,
/// after which they should write that data to their disk file.
///
/// This method also has the side effect of setting the mMin, mMax,
/// and mRMS members of this class.
///
/// Unlike BlockFile's implementation You SHOULD delete the returned buffer.
/// this is protected so it shouldn't be hard to deal with - just override
/// all BlockFile methods that use this method.
///
/// @param buffer A buffer containing the sample data to be analyzed
/// @param len    The length of the sample data
/// @param format The format of the sample data.
void *ODPCMAliasBlockFile::CalcSummary(samplePtr buffer, sampleCount len,
                             sampleFormat format)
{
   char* localFullSummary = new char[mSummaryInfo.totalSummaryBytes];

   memcpy(localFullSummary, aheaderTag, aheaderTagLen);

   float *summary64K = (float *)(localFullSummary + mSummaryInfo.offset64K);
   float *summary256 = (float *)(localFullSummary + mSummaryInfo.offset256);

   float *fbuffer;
   
   //mchinen: think we can hack this - don't allocate and copy if we don't need to.,
   if(format==floatSample)
   {
      fbuffer = (float*)buffer;
   }
   else
   {
      fbuffer = new float[len];
      CopySamples(buffer, format,
               (samplePtr)fbuffer, floatSample, len);
   }
   sampleCount sumLen;
   sampleCount i, j, jcount;

   float min, max;
   float sumsq;

   // Recalc 256 summaries
   sumLen = (len + 255) / 256;

   
   for (i = 0; i < sumLen; i++) {
      min = fbuffer[i * 256];
      max = fbuffer[i * 256];
      sumsq = ((float)min) * ((float)min);
      jcount = 256;
      if (i * 256 + jcount > len)
         jcount = len - i * 256;
      for (j = 1; j < jcount; j++) {
         float f1 = fbuffer[i * 256 + j];
         sumsq += ((float)f1) * ((float)f1);
         if (f1 < min)
            min = f1;
         else if (f1 > max)
            max = f1;
      }

      float rms = (float)sqrt(sumsq / jcount);

      summary256[i * 3] = min;
      summary256[i * 3 + 1] = max;
      summary256[i * 3 + 2] = rms;
   }
   
   for (i = sumLen; i < mSummaryInfo.frames256; i++) {
      summary256[i * 3] = 0.0f;
      summary256[i * 3 + 1] = 0.0f;
      summary256[i * 3 + 2] = 0.0f;
   }

   // Recalc 64K summaries
   sumLen = (len + 65535) / 65536;

   for (i = 0; i < sumLen; i++) {
      min = summary256[3 * i * 256];
      max = summary256[3 * i * 256 + 1];
      sumsq = (float)summary256[3 * i * 256 + 2];
      sumsq *= sumsq;

      for (j = 1; j < 256; j++) {
         if (summary256[3 * (i * 256 + j)] < min)
            min = summary256[3 * (i * 256 + j)];
         if (summary256[3 * (i * 256 + j) + 1] > max)
            max = summary256[3 * (i * 256 + j) + 1];
         float r1 = summary256[3 * (i * 256 + j) + 2];
         sumsq += r1*r1;
      }

      float rms = (float)sqrt(sumsq / 256);

      summary64K[i * 3] = min;
      summary64K[i * 3 + 1] = max;
      summary64K[i * 3 + 2] = rms;
   }
   for (i = sumLen; i < mSummaryInfo.frames64K; i++) {
      summary64K[i * 3] = 0.0f;
      summary64K[i * 3 + 1] = 0.0f;
      summary64K[i * 3 + 2] = 0.0f;
   }

   // Recalc block-level summary
   min = summary64K[0];
   max = summary64K[1];
   sumsq = (float)summary64K[2];
   sumsq *= sumsq;

   for (i = 1; i < sumLen; i++) {
      if (summary64K[3*i] < min)
         min = summary64K[3*i];
      if (summary64K[3*i+1] > max)
         max = summary64K[3*i+1];
      float r1 = (float)summary64K[3*i+2];
      sumsq += (r1*r1);
   }

   mMin = min;
   mMax = max;
   mRMS = sqrt(sumsq / sumLen);
   

   //if we've used the float sample..
   if(format!=floatSample)
   {
      delete[] fbuffer;
   }
   return localFullSummary;
}
Ejemplo n.º 20
0
int BlockFile::ReadData(void *data, sampleFormat format,
                        sampleCount start, sampleCount len)
{
   int i;

   if (mType == BLOCK_TYPE_ALIAS) {
      SF_INFO info;
      SNDFILE *sf = sf_open(mAliasFullPath, SFM_READ, &info);

      if (!sf)
         return 0;

      sf_seek(sf, mStart + start, SEEK_SET);
      samplePtr buffer = NewSamples(len * info.channels, floatSample);

      int framesRead = 0;
      switch(format) {
      case int16Sample:
         framesRead = sf_readf_short(sf, (short *)buffer, len);
         for (i = 0; i < framesRead; i++)
            ((short *)data)[i] =
               ((short *)buffer)[(info.channels * i) + mChannel];
         break;

      case floatSample:
         framesRead = sf_readf_float(sf, (float *)buffer, len);
         for (i = 0; i < framesRead; i++)
            ((float *)data)[i] =
               ((float *)buffer)[(info.channels * i) + mChannel];
         break;
      
      default:
         framesRead = sf_readf_float(sf, (float *)buffer, len);
         for (i = 0; i < framesRead; i++)
            ((float *)buffer)[i] =
               ((float *)buffer)[(info.channels * i) + mChannel];
         CopySamples((samplePtr)buffer, floatSample,
                     (samplePtr)data, format, framesRead);
      }

      DeleteSamples(buffer);

      sf_close(sf);

      return framesRead;

   }
   else {
      wxFFile file;
      int read;

      if (!file.Open((const wxChar *) mFullPath, "rb"))
         return 0;

      file.Seek(mSummaryLen +
                start * SAMPLE_SIZE(mSampleFormat), wxFromStart);

      if (format == mSampleFormat) {
         int bytes = len * SAMPLE_SIZE(mSampleFormat);
         read = (int)file.Read(data, (size_t)bytes);
         read /= SAMPLE_SIZE(mSampleFormat);
      }
      else {
         samplePtr buffer = NewSamples(len, mSampleFormat);
         int srcBytes = len * SAMPLE_SIZE(mSampleFormat);
         read = (int)file.Read(buffer, (size_t)srcBytes);
         read /= SAMPLE_SIZE(mSampleFormat);
         CopySamples(buffer, mSampleFormat,
                     (samplePtr)data, format, read);
         DeleteSamples(buffer);
      }

      file.Close();
      return read;
   }
}
Ejemplo n.º 21
0
/// Get a buffer containing a summary block describing this sample
/// data.  This must be called by derived classes when they
/// are constructed, to allow them to construct their summary data,
/// after which they should write that data to their disk file.
///
/// This method also has the side effect of setting the mMin, mMax,
/// and mRMS members of this class.
///
/// You must not delete the returned buffer; it is static to this
/// method.
///
/// @param buffer A buffer containing the sample data to be analyzed
/// @param len    The length of the sample data
/// @param format The format of the sample data.
void *BlockFile::CalcSummary(samplePtr buffer, sampleCount len,
                             sampleFormat format)
{
   if(fullSummary)delete[] fullSummary;
   fullSummary = new char[mSummaryInfo.totalSummaryBytes];

   memcpy(fullSummary, headerTag, headerTagLen);

   float *summary64K = (float *)(fullSummary + mSummaryInfo.offset64K);
   float *summary256 = (float *)(fullSummary + mSummaryInfo.offset256);

   float *fbuffer = new float[len];
   CopySamples(buffer, format,
               (samplePtr)fbuffer, floatSample, len);

   sampleCount sumLen;
   sampleCount i, j, jcount;

   float min, max;
   float sumsq;

   // Recalc 256 summaries
   sumLen = (len + 255) / 256;

   for (i = 0; i < sumLen; i++) {
      min = fbuffer[i * 256];
      max = fbuffer[i * 256];
      sumsq = ((float)min) * ((float)min);
      jcount = 256;
      if (i * 256 + jcount > len)
         jcount = len - i * 256;
      for (j = 1; j < jcount; j++) {
         float f1 = fbuffer[i * 256 + j];
         sumsq += ((float)f1) * ((float)f1);
         if (f1 < min)
            min = f1;
         else if (f1 > max)
            max = f1;
      }

      float rms = (float)sqrt(sumsq / jcount);

      summary256[i * 3] = min;
      summary256[i * 3 + 1] = max;
      summary256[i * 3 + 2] = rms;
   }
   for (i = sumLen; i < mSummaryInfo.frames256; i++) {
      summary256[i * 3] = 0.0f;
      summary256[i * 3 + 1] = 0.0f;
      summary256[i * 3 + 2] = 0.0f;
   }

   // Recalc 64K summaries
   sumLen = (len + 65535) / 65536;

   for (i = 0; i < sumLen; i++) {
      min = summary256[3 * i * 256];
      max = summary256[3 * i * 256 + 1];
      sumsq = (float)summary256[3 * i * 256 + 2];
      sumsq *= sumsq;

      for (j = 1; j < 256; j++) {
         if (summary256[3 * (i * 256 + j)] < min)
            min = summary256[3 * (i * 256 + j)];
         if (summary256[3 * (i * 256 + j) + 1] > max)
            max = summary256[3 * (i * 256 + j) + 1];
         float r1 = summary256[3 * (i * 256 + j) + 2];
         sumsq += r1*r1;
      }

      float rms = (float)sqrt(sumsq / 256);

      summary64K[i * 3] = min;
      summary64K[i * 3 + 1] = max;
      summary64K[i * 3 + 2] = rms;
   }
   for (i = sumLen; i < mSummaryInfo.frames64K; i++) {
      summary64K[i * 3] = 0.0f;
      summary64K[i * 3 + 1] = 0.0f;
      summary64K[i * 3 + 2] = 0.0f;
   }

   // Recalc block-level summary
   min = summary64K[0];
   max = summary64K[1];
   sumsq = (float)summary64K[2];
   sumsq *= sumsq;

   for (i = 1; i < sumLen; i++) {
      if (summary64K[3*i] < min)
         min = summary64K[3*i];
      else if (summary64K[3*i+1] > max)
         max = summary64K[3*i+1];
      float r1 = (float)summary64K[3*i+2];
      sumsq += (r1*r1);
   }

   mMin = min;
   mMax = max;
   mRMS = sqrt(sumsq / sumLen);

   delete[] fbuffer;

   return fullSummary;
}
Ejemplo n.º 22
0
bool WaveClip::GetWaveDisplay(float *min, float *max, float *rms,int* bl,
                               sampleCount *where,
                               int numPixels, double t0,
                               double pixelsPerSecond, bool &isLoadingOD)
{
   mWaveCacheMutex.Lock();
   
   
   if (mWaveCache &&
       mWaveCache->dirty == mDirty &&
       mWaveCache->start == t0 &&
       mWaveCache->len >= numPixels &&
       mWaveCache->pps == pixelsPerSecond) {
       
      //check for invalid regions, and make the bottom if an else if.
      //invalid regions are kept in a sorted array. 
      for(int i=0;i<mWaveCache->GetNumInvalidRegions();i++)
      {  
         int invStart;
         invStart = mWaveCache->GetInvalidRegionStart(i);
         int invEnd;
         invEnd = mWaveCache->GetInvalidRegionEnd(i);
         
         int regionODPixels;
         regionODPixels =0;
         int regionODPixelsAfter;
         regionODPixelsAfter =0;
         //before check number of ODPixels 
         for(int j=invStart;j<invEnd;j++)
         {
            if(mWaveCache->bl[j]<0)
               regionODPixels++;
         }
         mSequence->GetWaveDisplay(&mWaveCache->min[invStart],
                                        &mWaveCache->max[invStart],
                                        &mWaveCache->rms[invStart],
                                        &mWaveCache->bl[invStart],
                                        invEnd-invStart,
                                        &mWaveCache->where[invStart],
                                        mRate / pixelsPerSecond);
         //after check number of ODPixels 
         for(int j=invStart;j<invEnd;j++)
         {
            if(mWaveCache->bl[j]<0)
               regionODPixelsAfter++;
         }
         //decrement the number of od pixels.
         mWaveCache->numODPixels -= (regionODPixels - regionODPixelsAfter);
      }
      mWaveCache->ClearInvalidRegions();
       

      memcpy(min, mWaveCache->min, numPixels*sizeof(float));
      memcpy(max, mWaveCache->max, numPixels*sizeof(float));
      memcpy(rms, mWaveCache->rms, numPixels*sizeof(float));
      memcpy(bl, mWaveCache->bl, numPixels*sizeof(int));
      memcpy(where, mWaveCache->where, (numPixels+1)*sizeof(sampleCount));
      isLoadingOD = mWaveCache->numODPixels>0;
      mWaveCacheMutex.Unlock();
      return true;
   }

   WaveCache *oldCache = mWaveCache;

   mWaveCache = new WaveCache(numPixels);
   mWaveCache->pps = pixelsPerSecond;
   mWaveCache->rate = mRate;
   mWaveCache->start = t0;
   double tstep = 1.0 / pixelsPerSecond;

   sampleCount x;

   for (x = 0; x < mWaveCache->len + 1; x++) {
      mWaveCache->where[x] =
         (sampleCount) floor(t0 * mRate +
                             ((double) x) * mRate * tstep + 0.5);
   }

   //mchinen: I think s0 - s1 represents the range of samples that we will need to look up.  likewise p0-p1 the number of pixels.
   sampleCount s0 = mWaveCache->where[0];
   sampleCount s1 = mWaveCache->where[mWaveCache->len];
   int p0 = 0;
   int p1 = mWaveCache->len;

   // Optimization: if the old cache is good and overlaps
   // with the current one, re-use as much of the cache as
   // possible
   if (oldCache->dirty == mDirty &&
       oldCache->pps == pixelsPerSecond &&
       oldCache->where[0] < mWaveCache->where[mWaveCache->len] &&
       oldCache->where[oldCache->len] > mWaveCache->where[0]) {

      //now we are assuming the entire range is covered by the old cache and reducing s1/s0 as we find out otherwise.
      s0 = mWaveCache->where[mWaveCache->len];  //mchinen:s0 is the min sample covered up to by the wave cache.  will shrink if old doen't overlap
      s1 = mWaveCache->where[0];  //mchinen - same, but the maximum sample covered.  
      p0 = mWaveCache->len;
      p1 = 0;

      //check for invalid regions, and make the bottom if an else if.
      //invalid regions are keep in a sorted array. 
      //TODO:integrate into below for loop so that we only load inval regions if 
      //necessary.  (usually is the case, so no rush.)   
      //also, we should be updating the NEW cache, but here we are patching the old one up.
      for(int i=0;i<oldCache->GetNumInvalidRegions();i++)
      {  
         int invStart;
         invStart = oldCache->GetInvalidRegionStart(i);
         int invEnd;
         invEnd = oldCache->GetInvalidRegionEnd(i);
         mSequence->GetWaveDisplay(&oldCache->min[invStart],
                                        &oldCache->max[invStart],
                                        &oldCache->rms[invStart],
                                        &oldCache->bl[invStart],
                                        invEnd-invStart,
                                        &oldCache->where[invStart],
                                        mRate / pixelsPerSecond);
      }
      oldCache->ClearInvalidRegions();
      
      for (x = 0; x < mWaveCache->len; x++)
      {
          
         
         
         //below is regular cache access.  
         if (mWaveCache->where[x] >= oldCache->where[0] &&
             mWaveCache->where[x] <= oldCache->where[oldCache->len - 1]) {
             
             //if we hit an invalid region, load it up.

            int ox =
                int ((double (oldCache->len) *
                      (mWaveCache->where[x] -
                       oldCache->where[0])) /(oldCache->where[oldCache->len] -
                                             oldCache->where[0]) + 0.5);

            mWaveCache->min[x] = oldCache->min[ox];
            mWaveCache->max[x] = oldCache->max[ox];
            mWaveCache->rms[x] = oldCache->rms[ox];
            mWaveCache->bl[x] = oldCache->bl[ox];
         } else {
            if (mWaveCache->where[x] < s0) {
               s0 = mWaveCache->where[x];
               p0 = x;
            }
            if (mWaveCache->where[x + 1] > s1) {
               s1 = mWaveCache->where[x + 1];
               p1 = x + 1;
            }
         }
      }
   }

   if (p1 > p0) {

      /* handle values in the append buffer */

      int numSamples = mSequence->GetNumSamples();
      int a;

      for(a=p0; a<p1; a++)
         if (mWaveCache->where[a+1] > numSamples)
            break;

      //compute the values that are outside the overlap from scratch.  
      if (a < p1) {
         int i;

         sampleFormat seqFormat = mSequence->GetSampleFormat();
		 bool didUpdate = false;
         for(i=a; i<p1; i++) {
            sampleCount left;
			left = mWaveCache->where[i] - numSamples;
            sampleCount right;
			right = mWaveCache->where[i+1] - numSamples;

            //wxCriticalSectionLocker locker(mAppendCriticalSection);

            if (left < 0)
               left = 0;
            if (right > mAppendBufferLen)
               right = mAppendBufferLen;

            if (right > left) {
               float *b;
               sampleCount len = right-left;
               sampleCount j;

               if (seqFormat == floatSample)
                  b = &((float *)mAppendBuffer)[left];
               else {
                  b = new float[len];
                  CopySamples(mAppendBuffer + left*SAMPLE_SIZE(seqFormat),
                              seqFormat,
                              (samplePtr)b, floatSample, len);
               }

               float max = b[0];
               float min = b[0];
               float sumsq = b[0] * b[0];

               for(j=1; j<len; j++) {
                  if (b[j] > max)
                     max = b[j];
                  if (b[j] < min)
                     min = b[j];
                  sumsq += b[j]*b[j];
               }

               mWaveCache->min[i] = min;
               mWaveCache->max[i] = max;
               mWaveCache->rms[i] = (float)sqrt(sumsq / len);
               mWaveCache->bl[i] = 1; //for now just fake it.  

               if (seqFormat != floatSample)
                  delete[] b;
				
			  didUpdate=true;
            }
         }         

         // So that the sequence doesn't try to write any
         // of these values
         //mchinen: but only do this if we've updated pixels in the cache.
         if(didUpdate)
			p1 = a;
      }

      if (p1 > p0) {
         if (!mSequence->GetWaveDisplay(&mWaveCache->min[p0],
                                        &mWaveCache->max[p0],
                                        &mWaveCache->rms[p0],
                                        &mWaveCache->bl[p0],
                                        p1-p0,
                                        &mWaveCache->where[p0],
                                        mRate / pixelsPerSecond))
         {
            isLoadingOD=false;
            mWaveCacheMutex.Unlock();
            return false;
         }
      }
   }

   mWaveCache->dirty = mDirty;
   delete oldCache;

   memcpy(min, mWaveCache->min, numPixels*sizeof(float));
   memcpy(max, mWaveCache->max, numPixels*sizeof(float));
   memcpy(rms, mWaveCache->rms, numPixels*sizeof(float));
   memcpy(bl, mWaveCache->bl, numPixels*sizeof(int));
   memcpy(where, mWaveCache->where, (numPixels+1)*sizeof(sampleCount));
   
   //find the number of OD pixels - the only way to do this is by recounting since we've lost some old cache.
   mWaveCache->numODPixels = 0;
   for(int j=0;j<mWaveCache->len;j++)
      if(mWaveCache->bl[j]<0)
         mWaveCache->numODPixels++;

   isLoadingOD = mWaveCache->numODPixels>0;
   mWaveCacheMutex.Unlock();
   return true;
}
Ejemplo n.º 23
0
sampleCount Mixer::Process(int maxToProcess)
{
   if (mT >= mT1)
      return 0;
   
   int i, j;
   sampleCount out;
   sampleCount maxOut = 0;
   int *channelFlags = new int[mNumChannels];

   mMaxOut = maxToProcess;

   Clear();
   for(i=0; i<mNumInputTracks; i++) {
      WaveTrack *track = mInputTrack[i];
      for(j=0; j<mNumChannels; j++)
         channelFlags[j] = 0;

      if( mMixerSpec ) {
         //ignore left and right when downmixing is not required
         for( j = 0; j < mNumChannels; j++ )
            channelFlags[ j ] = mMixerSpec->mMap[ i ][ j ] ? 1 : 0;
      }
      else {
         switch(track->GetChannel()) {
         case Track::MonoChannel:
         default:
            for(j=0; j<mNumChannels; j++)
               channelFlags[j] = 1;
            break;
         case Track::LeftChannel:
            channelFlags[0] = 1;
            break;
         case Track::RightChannel:
            if (mNumChannels >= 2)
               channelFlags[1] = 1;
            else
               channelFlags[0] = 1;
            break;
         }
      }

      if (mTimeTrack ||
          track->GetRate() != mRate)
         out = MixVariableRates(channelFlags, track,
                                &mSamplePos[i], mSampleQueue[i],
                                &mQueueStart[i], &mQueueLen[i], mSRC[i]);
      else
         out = MixSameRate(channelFlags, track, &mSamplePos[i]);

      if (out > maxOut)
         maxOut = out;
   }
   out = mInterleaved ? maxOut * mNumChannels : maxOut;
   for(int c=0; c<mNumBuffers; c++)
      CopySamples(mTemp[c], floatSample, mBuffer[c], mFormat, out);

   mT += (maxOut / mRate);

   delete [] channelFlags; 

   return maxOut;
}
Ejemplo n.º 24
0
/// Read the data portion of the block file using libsndfile.  Convert it
/// to the given format if it is not already.
///
/// @param data   The buffer where the data will be stored
/// @param format The format the data will be stored in
/// @param start  The offset in this block file
/// @param len    The number of samples to read
int SimpleBlockFile::ReadData(samplePtr data, sampleFormat format,
                        sampleCount start, sampleCount len)
{
   if (mCache.active)
   {
      //wxLogDebug("SimpleBlockFile::ReadData(): Data are already in cache.");

      if (len > mLen - start)
         len = mLen - start;
      CopySamples(
         (samplePtr)(((char*)mCache.sampleData) +
            start * SAMPLE_SIZE(mCache.format)),
         mCache.format, data, format, len);
      return len;
   } else
   {
      //wxLogDebug("SimpleBlockFile::ReadData(): Reading data from disk.");

      SF_INFO info;
      wxFile f;   // will be closed when it goes out of scope
      SNDFILE *sf = NULL;
      {
         Maybe<wxLogNull> silence{};
         if (mSilentLog)
            silence.create();

         memset(&info, 0, sizeof(info));

         if (f.Open(mFileName.GetFullPath())) {
            // Even though there is an sf_open() that takes a filename, use the one that
            // takes a file descriptor since wxWidgets can open a file with a Unicode name and
            // libsndfile can't (under Windows).
            sf = sf_open_fd(f.fd(), SFM_READ, &info, FALSE);
         }

         if (!sf) {

            memset(data, 0, SAMPLE_SIZE(format)*len);

            mSilentLog = TRUE;

            return len;
         }
      }
      mSilentLog=FALSE;

      sf_seek(sf, start, SEEK_SET);
      SampleBuffer buffer(len, floatSample);

      int framesRead = 0;

      // If both the src and dest formats are integer formats,
      // read integers from the file (otherwise we would be
      // converting to float and back, which is unneccesary)
      if (format == int16Sample &&
          sf_subtype_is_integer(info.format)) {
         framesRead = sf_readf_short(sf, (short *)data, len);
      }
      else
      if (format == int24Sample &&
          sf_subtype_is_integer(info.format))
      {
         framesRead = sf_readf_int(sf, (int *)data, len);

         // libsndfile gave us the 3 byte sample in the 3 most
         // significant bytes -- we want it in the 3 least
         // significant bytes.
         int *intPtr = (int *)data;
         for( int i = 0; i < framesRead; i++ )
            intPtr[i] = intPtr[i] >> 8;
      }
      else {
Ejemplo n.º 25
0
bool Sequence::UpdateSummaries(samplePtr buffer,
                               SeqBlock * b, sampleCount len)
{
   char *fullSummary = (char *)malloc(mSummary->totalSummaryBytes);

   memcpy(fullSummary, headerTag, headerTagLen);

   float *summary64K = (float *)(fullSummary + mSummary->offset64K);
   float *summary256 = (float *)(fullSummary + mSummary->offset256);

   float *fbuffer = new float[len];
   CopySamples(buffer, mSampleFormat,
               (samplePtr)fbuffer, floatSample, len);

   sampleCount sumLen;
   sampleCount i, j, jcount;

   float min, max;
   float sumsq;

   // Recalc 256 summaries
   sumLen = (len + 255) / 256;

   for (i = 0; i < sumLen; i++) {
      min = fbuffer[i * 256];
      max = fbuffer[i * 256];
      sumsq = ((float)min) * ((float)min);
      jcount = 256;
      if (i * 256 + jcount > len)
         jcount = len - i * 256;
      for (j = 1; j < jcount; j++) {
         float f1 = fbuffer[i * 256 + j];
         sumsq += ((float)f1) * ((float)f1);
         if (f1 < min)
            min = f1;
         else if (f1 > max)
            max = f1;
      }

      float rms = (float)sqrt(sumsq / jcount);

      summary256[i * 3] = min;
      summary256[i * 3 + 1] = max;
      summary256[i * 3 + 2] = rms;
   }
   for (i = sumLen; i < mSummary->frames256; i++) {
      summary256[i * 3] = 0.0f;
      summary256[i * 3 + 1] = 0.0f;
      summary256[i * 3 + 2] = 0.0f;
   }

   // Recalc 64K summaries
   sumLen = (len + 65535) / 65536;

   for (i = 0; i < sumLen; i++) {
      min = summary256[3 * i * 256];
      max = summary256[3 * i * 256 + 1];
      sumsq = (float)summary256[3 * i * 256 + 2];
      sumsq *= sumsq;

      for (j = 1; j < 256; j++) {
         if (summary256[3 * (i * 256 + j)] < min)
            min = summary256[3 * (i * 256 + j)];
         if (summary256[3 * (i * 256 + j) + 1] > max)
            max = summary256[3 * (i * 256 + j) + 1];
         float r1 = summary256[3 * (i * 256 + j) + 2];
         sumsq += r1*r1;
      }

      float rms = (float)sqrt(sumsq / 256);

      summary64K[i * 3] = min;
      summary64K[i * 3 + 1] = max;
      summary64K[i * 3 + 2] = rms;
   }
   for (i = sumLen; i < mSummary->frames64K; i++) {
      summary64K[i * 3] = 0.0f;
      summary64K[i * 3 + 1] = 0.0f;
      summary64K[i * 3 + 2] = 0.0f;
   }

   // Recalc block-level summary
   min = summary64K[0];
   max = summary64K[1];
   sumsq = (float)summary64K[2];
   sumsq *= sumsq;
   
   for (i = 1; i < sumLen; i++) {
      if (summary64K[3*i] < min)
         min = summary64K[3*i];
      else if (summary64K[3*i+1] > max)
         max = summary64K[3*i+1];
      float r1 = (float)summary64K[3*i+2];
      sumsq += (r1*r1);
   }
   b->min = min;
   b->max = max;
   b->rms = sqrt(sumsq / sumLen);

   b->f->WriteSummary(fullSummary);

   delete[] fbuffer;
   free(fullSummary);

   return true;
}
Ejemplo n.º 26
0
void ComputeLegacySummaryInfo(wxFileName fileName,
                              int summaryLen,
                              sampleFormat format,
                              SummaryInfo *info,
                              bool noRMS,bool Silent,
                              float *min, float *max, float *rms)
{
   int fields = 3; /* min, max, rms */

   if (noRMS)
      fields = 2;

   info->fields = fields;
   info->format = format;
   info->bytesPerFrame =
      SAMPLE_SIZE(info->format) * fields;
   info->totalSummaryBytes = summaryLen;
   info->offset64K = 20; /* legacy header tag len */
   info->frames64K = (summaryLen-20) /
      (info->bytesPerFrame * 256);
   info->offset256 = info->offset64K +
      (info->frames64K * info->bytesPerFrame);
   info->frames256 =
      (summaryLen - 20 -
       (info->frames64K * info->bytesPerFrame)) /
      info->bytesPerFrame;

   //
   // Compute the min, max, and RMS of the block from the
   // 64K summary data
   //

   float *summary = new float[info->frames64K * fields];
   SampleBuffer data(info->frames64K * fields,
      info->format);

   int read;
   {
      Maybe<wxLogNull> silence{};
      wxFFile summaryFile(fileName.GetFullPath(), wxT("rb"));
      if (Silent)
         silence.create();

      if (!summaryFile.IsOpened()) {
         wxLogWarning(wxT("Unable to access summary file %s; substituting silence for remainder of session"),
            fileName.GetFullPath().c_str());

         read = info->frames64K * info->bytesPerFrame;
         memset(data.ptr(), 0, read);
      }
      else{
         summaryFile.Seek(info->offset64K);
         read = summaryFile.Read(data.ptr(),
            info->frames64K *
            info->bytesPerFrame);
      }
   }

   int count = read / info->bytesPerFrame;

   CopySamples(data.ptr(), info->format,
               (samplePtr)summary, floatSample, count);

   (*min) = FLT_MAX;
   (*max) = FLT_MIN;
   float sumsq = 0;

   for(int i=0; i<count; i++) {
      if (summary[fields*i] < (*min))
         (*min) = summary[fields*i];
      if (summary[fields*i+1] > (*max))
         (*max) = summary[fields*i+1];
      if (fields >= 3)
         sumsq += summary[fields*i+2]*summary[fields*i+2];
   }
   if (fields >= 3)
      (*rms) = sqrt(sumsq / count);
   else
      (*rms) = 0;

   delete[] summary;
}
Ejemplo n.º 27
0
void ComputeLegacySummaryInfo(wxFileName fileName,
                              int summaryLen,
                              sampleFormat format,
                              SummaryInfo *info,
                              bool noRMS,
                              float *min, float *max, float *rms)
{
   int fields = 3; /* min, max, rms */

   if (noRMS)
      fields = 2;

   info->fields = fields;
   info->format = format;
   info->bytesPerFrame =
      SAMPLE_SIZE(info->format) * fields;
   info->totalSummaryBytes = summaryLen;
   info->offset64K = 20; /* legacy header tag len */
   info->frames64K = (summaryLen-20) /
      (info->bytesPerFrame * 256);
   info->offset256 = info->offset64K +
      (info->frames64K * info->bytesPerFrame);
   info->frames256 =
      (summaryLen - 20 -
       (info->frames64K * info->bytesPerFrame)) /
      info->bytesPerFrame;

   //
   // Compute the min, max, and RMS of the block from the
   // 64K summary data
   //

   float *summary = new float[info->frames64K * fields];
   samplePtr data = NewSamples(info->frames64K * fields,
                               info->format);

   wxFFile summaryFile;
   if( !summaryFile.Open(fileName.GetFullPath(), "rb") ) {
      delete[] data;
      return;
   }
   summaryFile.Seek(info->offset64K);
   int read = summaryFile.Read(data,
                               info->frames64K *
                               info->bytesPerFrame);

   int count = read / info->bytesPerFrame;

   CopySamples(data, info->format,
               (samplePtr)summary, floatSample, count);

   (*min) = FLT_MAX;
   (*max) = FLT_MIN;
   float sumsq = 0;

   for(int i=0; i<count; i++) {
      if (summary[fields*i] < (*min))
         (*min) = summary[fields*i];
      if (summary[fields*i+1] > (*max))
         (*max) = summary[fields*i+1];
      if (fields >= 3)
         sumsq += summary[fields*i+2]*summary[fields*i+2];
   }
   if (fields >= 3)
      (*rms) = sqrt(sumsq / count);
   else
      (*rms) = 0;

   DeleteSamples(data);
   delete[] summary;   
}
Ejemplo n.º 28
0
/// Reads the specified data from the aliased file, using libsndfile,
/// and converts it to the given sample format.
///
/// @param data   The buffer to read the sample data into.
/// @param format The format to convert the data into
/// @param start  The offset within the block to begin reading
/// @param len    The number of samples to read
int PCMAliasBlockFile::ReadData(samplePtr data, sampleFormat format,
                                sampleCount start, sampleCount len)
{
   SF_INFO info;

   if(!mAliasedFileName.IsOk()){ // intentionally silenced
      memset(data,0,SAMPLE_SIZE(format)*len);
      return len;
   }

   wxFile f;   // will be closed when it goes out of scope
   SNDFILE *sf = NULL;
   {
      Maybe<wxLogNull> silence{};
      if (mSilentAliasLog)
         silence.create();

      memset(&info, 0, sizeof(info));

      if (f.Exists(mAliasedFileName.GetFullPath())) { // Don't use Open if file does not exits
         if (f.Open(mAliasedFileName.GetFullPath())) {
            // Even though there is an sf_open() that takes a filename, use the one that
            // takes a file descriptor since wxWidgets can open a file with a Unicode name and
            // libsndfile can't (under Windows).
            ODManager::LockLibSndFileMutex();
            sf = sf_open_fd(f.fd(), SFM_READ, &info, FALSE);
            ODManager::UnlockLibSndFileMutex();
         }
      }

      if (!sf){
         memset(data, 0, SAMPLE_SIZE(format)*len);
         silence.reset();
         mSilentAliasLog = TRUE;

         // Set a marker to display an error message for the silence
         if (!wxGetApp().ShouldShowMissingAliasedFileWarning())
            wxGetApp().MarkAliasedFilesMissingWarning(this);
         return len;
      }
   }
   mSilentAliasLog=FALSE;

   ODManager::LockLibSndFileMutex();
   sf_seek(sf, mAliasStart + start, SEEK_SET);
   ODManager::UnlockLibSndFileMutex();
   SampleBuffer buffer(len * info.channels, floatSample);

   int framesRead = 0;

   if (format == int16Sample &&
       !sf_subtype_more_than_16_bits(info.format)) {
      // Special case: if the file is in 16-bit (or less) format,
      // and the calling method wants 16-bit data, go ahead and
      // read 16-bit data directly.  This is a pretty common
      // case, as most audio files are 16-bit.
      ODManager::LockLibSndFileMutex();
      framesRead = sf_readf_short(sf, (short *)buffer.ptr(), len);
      ODManager::UnlockLibSndFileMutex();
      for (int i = 0; i < framesRead; i++)
         ((short *)data)[i] =
            ((short *)buffer.ptr())[(info.channels * i) + mAliasChannel];
   }
   else {
      // Otherwise, let libsndfile handle the conversion and
      // scaling, and pass us normalized data as floats.  We can
      // then convert to whatever format we want.
      ODManager::LockLibSndFileMutex();
      framesRead = sf_readf_float(sf, (float *)buffer.ptr(), len);
      ODManager::UnlockLibSndFileMutex();
      float *bufferPtr = &((float *)buffer.ptr())[mAliasChannel];
      CopySamples((samplePtr)bufferPtr, floatSample,
                  (samplePtr)data, format,
                  framesRead, true, info.channels);
   }

   ODManager::LockLibSndFileMutex();
   sf_close(sf);
   ODManager::UnlockLibSndFileMutex();
   return framesRead;
}
Ejemplo n.º 29
0
/// Reads the specified data from the aliased file, using libsndfile,
/// and converts it to the given sample format.
/// Copied from PCMAliasBlockFIle but wxLog calls taken out for thread safety
///
/// @param data   The buffer to read the sample data into.
/// @param format The format to convert the data into
/// @param start  The offset within the block to begin reading
/// @param len    The number of samples to read
int ODPCMAliasBlockFile::ReadData(samplePtr data, sampleFormat format,
                                sampleCount start, sampleCount len)
{

   mReadDataMutex.Lock();

   SF_INFO info;

   if(!mAliasedFileName.IsOk()){ // intentionally silenced 
      memset(data,0,SAMPLE_SIZE(format)*len);
      mReadDataMutex.Unlock();

         return len;
   }

   memset(&info, 0, sizeof(info));

   wxString aliasPath = mAliasedFileName.GetFullPath();
   //there are thread-unsafe crashes here - not sure why.  sf_open may be called on the same file
   //from different threads, but this seems okay, unless it is implemented strangely..  
   static ODLock sfMutex;

   wxFile f;   // will be closed when it goes out of scope
   SNDFILE *sf = NULL;

   if (f.Open(aliasPath)) {
      // Even though there is an sf_open() that takes a filename, use the one that
      // takes a file descriptor since wxWidgets can open a file with a Unicode name and
      // libsndfile can't (under Windows).
      ODManager::LockLibSndFileMutex();
      sf = sf_open_fd(f.fd(), SFM_READ, &info, FALSE);
      ODManager::UnlockLibSndFileMutex();
   }
   
   if (!sf){
      
      memset(data,0,SAMPLE_SIZE(format)*len);

      mSilentAliasLog=TRUE;

      mReadDataMutex.Unlock();
      return len;
   }

   mSilentAliasLog=FALSE;

   ODManager::LockLibSndFileMutex();
   sf_seek(sf, mAliasStart + start, SEEK_SET);
   ODManager::UnlockLibSndFileMutex();

   samplePtr buffer = NewSamples(len * info.channels, floatSample);

   int framesRead = 0;

   if (format == int16Sample &&
       !sf_subtype_more_than_16_bits(info.format)) {
      // Special case: if the file is in 16-bit (or less) format,
      // and the calling method wants 16-bit data, go ahead and
      // read 16-bit data directly.  This is a pretty common
      // case, as most audio files are 16-bit.
      ODManager::LockLibSndFileMutex();
      framesRead = sf_readf_short(sf, (short *)buffer, len);
      ODManager::UnlockLibSndFileMutex();

      for (int i = 0; i < framesRead; i++)
         ((short *)data)[i] =
            ((short *)buffer)[(info.channels * i) + mAliasChannel];
   }
   else {
      // Otherwise, let libsndfile handle the conversion and
      // scaling, and pass us normalized data as floats.  We can
      // then convert to whatever format we want.
      ODManager::LockLibSndFileMutex();
      framesRead = sf_readf_float(sf, (float *)buffer, len);
      ODManager::UnlockLibSndFileMutex();
      float *bufferPtr = &((float *)buffer)[mAliasChannel];
      CopySamples((samplePtr)bufferPtr, floatSample,
                  (samplePtr)data, format,
                  framesRead, true, info.channels);
   }

   DeleteSamples(buffer);

   ODManager::LockLibSndFileMutex();
   sf_close(sf);
   ODManager::UnlockLibSndFileMutex();
   
   mReadDataMutex.Unlock();
   return framesRead;
}
Ejemplo n.º 30
0
bool Sequence::Append(samplePtr buffer, sampleFormat format,
                      sampleCount len)
{
   samplePtr temp = NULL;
   if (format != mSampleFormat) {
      temp = NewSamples(mMaxSamples, mSampleFormat);
      wxASSERT(temp);
   }

   // If the last block is not full, we need to add samples to it
   int numBlocks = mBlock->Count();
   if (numBlocks > 0 && mBlock->Item(numBlocks - 1)->len < mMinSamples) {
      SeqBlock *lastBlock = mBlock->Item(numBlocks - 1);
      sampleCount addLen;
      if (lastBlock->len + len < mMaxSamples)
         addLen = len;
      else
         addLen = GetIdealBlockSize() - lastBlock->len;

      SeqBlock *newLastBlock = NewInitedSeqBlock();

      samplePtr buffer2 = NewSamples((lastBlock->len + addLen), mSampleFormat);
      Read(buffer2, mSampleFormat, lastBlock, 0, lastBlock->len);

      if (format == mSampleFormat)
         memcpy(buffer2 + lastBlock->len * SAMPLE_SIZE(format),
                buffer,
                addLen * SAMPLE_SIZE(format));
      else {
         CopySamples(buffer, format, temp, mSampleFormat, addLen);
         memcpy(buffer2 + lastBlock->len * SAMPLE_SIZE(format),
                temp,
                addLen * SAMPLE_SIZE(format));
      }

      newLastBlock->start = lastBlock->start;
      newLastBlock->len = lastBlock->len + addLen;

      FirstWrite(buffer2, newLastBlock, lastBlock->len + addLen);

      DeleteSamples(buffer2);

      mDirManager->Deref(lastBlock->f);
      delete lastBlock;
      mBlock->Item(numBlocks - 1) = newLastBlock;

      len -= addLen;
      mNumSamples += addLen;
      buffer += addLen * SAMPLE_SIZE(format);
   }
   // Append the rest as new blocks
   while (len) {
      sampleCount idealSamples = GetIdealBlockSize();
      sampleCount l = (len > idealSamples ? idealSamples : len);
      SeqBlock *w = new SeqBlock();
      w->f = mDirManager->NewBlockFile(mSummary->totalSummaryBytes);
      w->start = mNumSamples;
      w->len = l;

      if (format == mSampleFormat)
         FirstWrite(buffer, w, l);
      else {
         CopySamples(buffer, format, temp, mSampleFormat, l);
         FirstWrite(temp, w, l);
      }

      mBlock->Add(w);

      buffer += l * SAMPLE_SIZE(format);
      mNumSamples += l;
      len -= l;
   }

   if (format != mSampleFormat)
      DeleteSamples(temp);

   ConsistencyCheck("Append");

   return true;
}