Beispiel #1
0
bool WaveTrack::Get(samplePtr buffer, sampleFormat format,
                    longSampleCount start, sampleCount len)
{
   longSampleCount startTime = (longSampleCount)floor(mOffset*mRate + 0.5);
   longSampleCount endTime = startTime + mSequence->GetNumSamples();

   if (start+len < startTime || start>=endTime) {
      ClearSamples(buffer, format, 0, len);
      return true;
   }

   sampleCount s0 = (sampleCount)(start - startTime);
   sampleCount soffset = 0;
   sampleCount getlen = len;

   if (s0 < 0) {
      soffset = -s0;
      getlen -= soffset;
      s0 = 0;
   }

   if (s0+getlen > mSequence->GetNumSamples())
      getlen = mSequence->GetNumSamples() - s0;

   if (!mSequence->Get(buffer + soffset*SAMPLE_SIZE(format), format,
                       s0, getlen)) {
      ClearSamples(buffer, format, 0, len);
      return false;
   }

   ClearSamples(buffer, format, 0, soffset);
   ClearSamples(buffer, format, soffset+getlen, len-(soffset+getlen));

   return true;
}
Beispiel #2
0
void Mixer::GetSamples(WaveTrack *src, int s0, int slen)
{
   // Retrieves samples from a track, even outside of the range which
   // contains samples.  (Fills in extra space with zeros.)
   // Puts samples in mTemp
   
   if (slen > mTempBufferSize) {
      mTempBufferSize = slen;
      DeleteSamples(mTemp);
      mTemp = NewSamples(mTempBufferSize, mFormat);
   }
   
   int soffset = 0;
   int getlen = slen;
   if (s0 < 0) {
      soffset = -s0;
      getlen -= soffset;
      s0 = 0;
   }
   if (s0+getlen > src->GetNumSamples()) {
      getlen = src->GetNumSamples() - s0;
   }
   
   src->Get(mTemp + soffset*SAMPLE_SIZE(mFormat), mFormat,
            (sampleCount)s0, (sampleCount)getlen);

   ClearSamples(mTemp, mFormat, 0, soffset);
   ClearSamples(mTemp, mFormat, soffset+getlen, slen-(soffset+getlen));
}
Beispiel #3
0
size_t SilentBlockFile::ReadData(samplePtr data, sampleFormat format,
                              size_t WXUNUSED(start), size_t len, bool) const
{
   ClearSamples(data, format, 0, len);

   return len;
}
Beispiel #4
0
int SilentBlockFile::ReadData(samplePtr data, sampleFormat format,
                              sampleCount start, sampleCount len)
{
   ClearSamples(data, format, 0, len);

   return len;
}
Beispiel #5
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");
}
Beispiel #6
0
bool WaveTrack::Get(samplePtr buffer, sampleFormat format,
                    longSampleCount start, sampleCount len)
{
   // Simple optimization: When this buffer is completely contained within one clip,
   // don't clear anything (because we never won't have to). Otherwise, just clear
   // everything to be on the safe side.
   WaveClipList::Node* it;
   
   bool doClear = true;
   for (it=GetClipIterator(); it; it=it->GetNext())
   {
      WaveClip *clip = it->GetData();
      if (start >= clip->GetStartSample() && start+len <= clip->GetEndSample())
      {
         doClear = false;
         break;
      }
   }
   if (doClear)
      ClearSamples(buffer, format, 0, len);

   for (it=GetClipIterator(); it; it=it->GetNext())
   {
      WaveClip *clip = it->GetData();

      longSampleCount clipStart = clip->GetStartSample();
      longSampleCount clipEnd = clip->GetEndSample();

      if (clipEnd > start && clipStart < start+len)
      {
         // Clip sample region and Get/Put sample region overlap
         sampleCount samplesToCopy = start+len - clipStart;
         if (samplesToCopy > clip->GetNumSamples())
            samplesToCopy = clip->GetNumSamples();
         longSampleCount inclipDelta = 0;
         longSampleCount startDelta = clipStart - start;
         if (startDelta < 0)
         {
            inclipDelta = -startDelta; // make positive value
            samplesToCopy -= inclipDelta;
            startDelta = 0;
         }

         if (!clip->GetSamples((samplePtr)(((char*)buffer)+startDelta*SAMPLE_SIZE(format)),
                               format, inclipDelta, samplesToCopy))
         {
            wxASSERT(false); // should always work
            return false;
         }
      }
   }

   return true;
}
Beispiel #7
0
/// Returns the 64K summary data block
/// Fill with zeroes and return false if data are unavailable for any reason.
bool ODDecodeBlockFile::Read64K(float *buffer, size_t start, size_t len)
{
   if(IsSummaryAvailable())
   {
      return SimpleBlockFile::Read64K(buffer,start,len);
   }
   else
   {
      ClearSamples((samplePtr)buffer, floatSample, 0, len);
      return false;
   }
}
/// Returns the 64K summary data block.
/// Fill with zeroes and return false if data are unavailable for any reason.
bool ODPCMAliasBlockFile::Read64K(float *buffer, size_t start, size_t len)
{
   if(IsSummaryAvailable())
   {
      return PCMAliasBlockFile::Read64K(buffer,start,len);
   }
   else
   {
      //return nothing - it hasn't been calculated yet
      ClearSamples((samplePtr)buffer, floatSample, 0, len);
      return false;
   }
}
/// Returns the 256 byte summary data block.
/// Fill with zeroes and return false if data are unavailable for any reason.
bool ODPCMAliasBlockFile::Read256(float *buffer, size_t start, size_t len)
{
   if(IsSummaryAvailable())
   {
      return PCMAliasBlockFile::Read256(buffer,start,len);
   }
   else
   {
      //return nothing.
      ClearSamples((samplePtr)buffer, floatSample, 0, len);
      return false;
   }
}
Beispiel #10
0
bool Sequence::InsertSilence(sampleCount s0, sampleCount len)
{
   // Create a new track containing as much silence as we
   // need to insert, and then call Paste to do the insertion
   Sequence *sTrack = new Sequence(mDirManager, mSampleFormat);

   sampleCount idealSamples = GetIdealBlockSize();

   // Allocate a zeroed buffer
   samplePtr buffer = NewSamples(idealSamples, mSampleFormat);
   ClearSamples(buffer, mSampleFormat, 0, idealSamples);

   sampleCount pos = 0;
   BlockFile *firstBlockFile = NULL;

   while (len) {
      sampleCount l = (len > idealSamples ? idealSamples : len);

      SeqBlock *w = new SeqBlock();
      w->start = pos;
      w->len = l;
      w->min = float(0.0);
      w->max = float(0.0);
      w->rms = float(0.0);
      if (pos == 0 || len == l) {
         w->f = mDirManager->NewBlockFile(mSummary->totalSummaryBytes);
         firstBlockFile = w->f;
         FirstWrite(buffer, w, l);
      } else {
         w->f = mDirManager->CopyBlockFile(firstBlockFile);
         if (!w->f) {
            // TODO set error message
            return false;
         }
      }

      sTrack->mBlock->Add(w);

      pos += l;
      len -= l;
   }

   sTrack->mNumSamples = pos;

   Paste(s0, sTrack);

   delete sTrack;
   DeleteSamples(buffer);

   return ConsistencyCheck("InsertSilence");
}
/// 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 ODDecodeBlockFile::ReadData(samplePtr data, sampleFormat format,
                                sampleCount start, sampleCount len)
{
   int ret;
   LockRead();
   if(IsSummaryAvailable())
      ret= SimpleBlockFile::ReadData(data,format,start,len);
   else
   {
      //we should do an ODRequest to start processing the data here, and wait till it finishes. and just do a SimpleBlockFIle
      //ReadData.
      ClearSamples(data, format, 0, len);
      ret= len;
   }
   UnlockRead();
   return ret;
}
Beispiel #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
size_t ODDecodeBlockFile::ReadData(samplePtr data, sampleFormat format,
                                size_t start, size_t len, bool mayThrow) const
{
   auto locker = LockForRead();
   if(IsSummaryAvailable())
      return SimpleBlockFile::ReadData(data, format, start, len, mayThrow);
   else
   {
      if (mayThrow)
         throw NotYetAvailableException{ mAudioFileName };

      //we should do an ODRequest to start processing the data here, and wait till it finishes. and just do a SimpleBlockFile
      //ReadData.
      ClearSamples(data, format, 0, len);
      return 0;
   }
}
Beispiel #13
0
size_t RingBuffer::Clear(sampleFormat format, size_t samplesToClear)
{
   samplesToClear = std::min( samplesToClear, AvailForPut() );
   size_t cleared = 0;
   auto pos = mEnd;

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

      ClearSamples(mBuffer.ptr(), format, pos, block);

      pos = (pos + block) % mBufferSize;
      samplesToClear -= block;
      cleared += block;
   }

   mEnd = pos;

   return cleared;
}
Beispiel #14
0
bool Sequence::Read(samplePtr buffer, sampleFormat format,
                    SeqBlock * b, sampleCount start, sampleCount len) const
{
   wxASSERT(b);
   wxASSERT(start >= 0);
   wxASSERT(start + len <= b->f->GetLength());

   BlockFile *f = b->f;

   int result = f->ReadData(buffer, format, start, len);

   if (result != len) 
   {
      wxLogError(wxT("Expected to read %d samples, got %d samples.\n"), len, result);
      if (result < 0)
         result = 0;
      ClearSamples(buffer, format, result, len-result);
   }

   return true;
}
Beispiel #15
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"));
}
Beispiel #16
0
int audacityAudioCallback(
		void *inputBuffer, void *outputBuffer,
		unsigned long framesPerBuffer,
		PaTimestamp outTime, void *userData )
{
   int numOutChannels = gAudioIO->mNumOutChannels;
   int numInChannels = gAudioIO->mNumInChannels;
   int minIndex = 0, minID = 0;
   unsigned int i;
   
   //
   // Copy from our pool of output buffers to PortAudio's output buffer
   //
   
   if (outputBuffer && numOutChannels > 0) {
   
      for(i=0; i<gAudioIO->mNumOutBuffers; i++) {
         if (gAudioIO->mOutBuffer[i].ID>0 &&
             (minID==0 || gAudioIO->mOutBuffer[i].ID < minID)) {
            minID = gAudioIO->mOutBuffer[i].ID;
            minIndex = i;
         }
      }
      if (minID > 0) {
         AudioIOBuffer *b = &gAudioIO->mOutBuffer[minIndex];
         sampleCount len  = b->len;
      
         memcpy(outputBuffer, b->data,
                len * numOutChannels * SAMPLE_SIZE(gAudioIO->GetFormat()));

         // Fill rest of buffer with silence
         if (len < (sampleCount) framesPerBuffer)
            ClearSamples((samplePtr)outputBuffer, gAudioIO->GetFormat(),
                         len*numOutChannels,
                         (framesPerBuffer-len)*numOutChannels);
         
         b->ID = 0;
      }
      else {
         // we had a buffer underrun!
         
         // play silence
         ClearSamples((samplePtr)outputBuffer, gAudioIO->GetFormat(),
                      0, framesPerBuffer * numOutChannels);
         
         // increase number of output buffers to prevent another underrun!
         if (gAudioIO->mNumOutBuffers < gAudioIO->mMaxBuffers)
            gAudioIO->mNumOutBuffers++;
      }
   }
   
   //
   // Copy from PortAudio's input buffer to one of our input buffers.
   //
   
   if (inputBuffer && numInChannels > 0) {
      bool found = false;
      for(i=0; i<gAudioIO->mNumInBuffers; i++) {
         if (gAudioIO->mInBuffer[i].ID == 0) {
            int len = framesPerBuffer;
            int sampleSize = SAMPLE_SIZE(gAudioIO->GetFormat());
            
            AudioIOBuffer *b = &gAudioIO->mInBuffer[i];
            memcpy(b->data, inputBuffer,
                   len * numInChannels * sampleSize);
            b->len = len;
            b->ID = gAudioIO->mInID;
            gAudioIO->mInID++;
            found = true;
            
            int checksum = 0;
            for(int k=0; k<len*numInChannels*sampleSize; k++)
               checksum += ((char *)inputBuffer)[k];
            if (checksum == gAudioIO->mLastChecksum) {
               gAudioIO->mRepeats++;
               gAudioIO->mRepeatPoint = gAudioIO->mT;
            }
            gAudioIO->mLastChecksum = checksum;
            
            break;
         }
      }
      
      if (!found) {
         // we had a buffer underrun!
         
         gAudioIO->mInUnderruns++;
      }
   }
   
   return 0;
}