Esempio n. 1
0
/*
 * Wait until the data in the buffer has finished playing.
 */
PaError waitUntilBlioWriteBufferIsEmpty( PaMacBlio *blio, double sampleRate,
                                        size_t framesPerBuffer )
{
    PaError result = paNoError;
    if( blio->outputRingBuffer.buffer ) {
        ring_buffer_size_t framesLeft = PaUtil_GetRingBufferReadAvailable( &blio->outputRingBuffer );

        /* Calculate when we should give up waiting. To be safe wait for two extra periods. */
        PaTime now = PaUtil_GetTime();
        PaTime startTime = now;
        PaTime timeoutTime = startTime + (framesLeft + (2 * framesPerBuffer)) / sampleRate;

        long msecPerBuffer = 1 + (long)( 1000.0 * framesPerBuffer / sampleRate);
        while( framesLeft > 0 && now < timeoutTime ) {
            VDBUG(( "waitUntilBlioWriteBufferIsFlushed: framesLeft = %d, framesPerBuffer = %ld\n",
                  framesLeft, framesPerBuffer ));
            Pa_Sleep( msecPerBuffer );
            framesLeft = PaUtil_GetRingBufferReadAvailable( &blio->outputRingBuffer );
            now = PaUtil_GetTime();
        }

        if( framesLeft > 0 )
        {
            VDBUG(( "waitUntilBlioWriteBufferIsFlushed: TIMED OUT - framesLeft = %d\n", framesLeft ));
            result = paTimedOut;
        }
    }
    return result;
}
Esempio n. 2
0
uint32 AudioStream::Read(short* buffer, size_t count)
{
	size_t cnt;
	size_t toRead = count; // Count is the amount of s16 samples.

	if (!mSource || !mSource->IsValid())
	{
		mIsPlaying = false;
		return 0;
	}
	
	if (PaUtil_GetRingBufferReadAvailable(&mRingBuf) < toRead || !mIsPlaying)
	{
		memset(buffer, 0, toRead);
		toRead = PaUtil_GetRingBufferReadAvailable(&mRingBuf);
	}

	if (mIsPlaying)
	{
		cnt = PaUtil_ReadRingBuffer(&mRingBuf, buffer, toRead);
		mStreamTime += (double)(cnt/Channels) / (double)mSource->GetRate();
		mPlaybackTime = mStreamTime - MixerGetLatency();
	}else
		return 0;

	return cnt ? cnt : mIsPlaying;
}
Esempio n. 3
0
/***************************************************************************
** Get address of region(s) from which we can read data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be written or numBytes, whichever is smaller.
*/
long PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, long numBytes,
                                void **dataPtr1, long *sizePtr1,
                                void **dataPtr2, long *sizePtr2 )
{
    long   index;
    long   available = PaUtil_GetRingBufferReadAvailable( rbuf );
    if( numBytes > available ) numBytes = available;
    /* Check to see if read is not contiguous. */
    index = rbuf->readIndex & rbuf->smallMask;
    if( (index + numBytes) > rbuf->bufferSize )
    {
        /* Write data in two blocks that wrap the buffer. */
        long firstHalf = rbuf->bufferSize - index;
        *dataPtr1 = &rbuf->buffer[index];
        *sizePtr1 = firstHalf;
        *dataPtr2 = &rbuf->buffer[0];
        *sizePtr2 = numBytes - firstHalf;
    }
    else
    {
        *dataPtr1 = &rbuf->buffer[index];
        *sizePtr1 = numBytes;
        *dataPtr2 = NULL;
        *sizePtr2 = 0;
    }
    return numBytes;
}
Esempio n. 4
0
/************************************************************
 * Read data from ring buffer.
 * Will not return until all the data has been read.
 */
long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, int chan, switch_timer_t *timer)
{
	long bytesRead = 0;
	char *p = (char *) data;
	long avail, totalBytes = 0, neededBytes = aStream->bytesPerFrame * numFrames;
	int max = 5000;

	switch_core_timer_next(timer);

	while (totalBytes < neededBytes && --max > 0) {

		avail = PaUtil_GetRingBufferReadAvailable(&aStream->inFIFOs[chan]);
		//printf("AVAILABLE BYTES %ld pass %d\n", avail, 5000 - max);
		if (avail >= neededBytes * 6) {
			PaUtil_FlushRingBuffer(&aStream->inFIFOs[chan]);
			avail = 0;
		} else {

			bytesRead = 0;

			if (totalBytes < neededBytes && avail >= neededBytes) {
				bytesRead = PaUtil_ReadRingBuffer(&aStream->inFIFOs[chan], p, neededBytes);
				totalBytes += bytesRead;
			}

			if (bytesRead) {
				p += bytesRead;
			} else {
				switch_cond_next();
			}
		}
	}

	return totalBytes / aStream->bytesPerFrame;
}
Esempio n. 5
0
signed long GetStreamReadAvailable( PaStream* stream )
{
    PaMacBlio *blio = & ((PaMacCoreStream*)stream) -> blio;
    VVDBUG(("GetStreamReadAvailable()\n"));

    return PaUtil_GetRingBufferReadAvailable( &blio->inputRingBuffer );
}
Esempio n. 6
0
/***************************************************************************
** Get address of region(s) from which we can read data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be written or elementCount, whichever is smaller.
*/
ring_buffer_size_t PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, ring_buffer_size_t elementCount,
        void **dataPtr1, ring_buffer_size_t *sizePtr1,
        void **dataPtr2, ring_buffer_size_t *sizePtr2 )
{
    ring_buffer_size_t   index;
    ring_buffer_size_t   available = PaUtil_GetRingBufferReadAvailable( rbuf );
    if( elementCount > available ) elementCount = available;
    /* Check to see if read is not contiguous. */
    index = rbuf->readIndex & rbuf->smallMask;
    if( (index + elementCount) > rbuf->bufferSize )
    {
        /* Write data in two blocks that wrap the buffer. */
        ring_buffer_size_t firstHalf = rbuf->bufferSize - index;
        *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
        *sizePtr1 = firstHalf;
        *dataPtr2 = &rbuf->buffer[0];
        *sizePtr2 = elementCount - firstHalf;
    }
    else
    {
        *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
        *sizePtr1 = elementCount;
        *dataPtr2 = NULL;
        *sizePtr2 = 0;
    }
    return elementCount;
}
Esempio n. 7
0
void MLPluginController::timerCallback()
{
    const int lessFrequentThingsDivision = 8;
    mClockDivider++;
	fetchChangedProperties();
    
	if(mClockDivider > lessFrequentThingsDivision)
    {
        // do less frequent things (unused)
        mClockDivider = 0;
    }
	
	if(getView())
		viewSignals();
	
#if ML_MAC
	// read from file action queue and do any needed actions
	if(mConvertingPresets)
	{
		FileAction a;
		int filesRead = 0;
		
		if((filesRead = PaUtil_ReadRingBuffer( &mFileActionQueue, &a, 1 )))
		{
			if(a.mFile.exists())
			{
				doFileQueueAction(a);
			}
			int filesInQueue = PaUtil_GetRingBufferReadAvailable(&mFileActionQueue);
			mMaxFileQueueSize = max(filesInQueue, mMaxFileQueueSize);
			if(!filesInQueue) endConvertPresets();
		}
	}
#endif
}
Esempio n. 8
0
float MLPluginController::getConvertProgress()
{
	int remaining = PaUtil_GetRingBufferReadAvailable(&mFileActionQueue);
	float p;
	if(!mConvertingPresets)
	{
		p = 1.f;
	}
	else if(remaining > 0.f)
	{
		if(mMaxFileQueueSize > 0)
		{
			p = (float)(mMaxFileQueueSize - remaining) / (float)(mMaxFileQueueSize);
		}
		else 
		{
			p = 0.f;
		}
	}
	else
	{
		p = 1.f;
	}
	return p;
}
Esempio n. 9
0
/*****************************************************************************
 * RenderCallbackAnalog: This function is called everytime the AudioUnit wants
 * us to provide some more audio data.
 * Don't print anything during normal playback, calling blocking function from
 * this callback is not allowed.
 *****************************************************************************/
OSStatus CoreAudioAUHAL::RenderCallbackAnalog(struct CoreAudioDeviceParameters *deviceParameters,
									  int *ioActionFlags,
									  const AudioTimeStamp *inTimeStamp,
									  unsigned int inBusNumber,
									  unsigned int inNumberFrames,
									  AudioBufferList *ioData )
{
    // initial calc
	int framesToWrite = inNumberFrames;
	int framesAvailable = PaUtil_GetRingBufferReadAvailable(deviceParameters->outputBuffer);
	
	if (framesToWrite > framesAvailable)
	{
		framesToWrite = framesAvailable;
	}
	
	int currentPos = framesToWrite * deviceParameters->stream_format.mBytesPerFrame;
	int underrunLength = (inNumberFrames - framesToWrite) * deviceParameters->stream_format.mBytesPerFrame;

	// write as many frames as possible from buffer
	PaUtil_ReadRingBuffer(deviceParameters->outputBuffer, ioData->mBuffers[0].mData, framesToWrite);
	// write silence to any remainder
	if (underrunLength > 0)
	{
		memset((void *)((uint8_t *)(ioData->mBuffers[0].mData)+currentPos), 0, underrunLength);
	}

    return( noErr );
}
Esempio n. 10
0
_BOOLEAN
CPaCommon::Read(CVector < short >&psData)
{
    if (device_changed)
        ReInit();

    if (stream==NULL)
        return TRUE;

    size_t bytes = psData.Size() * sizeof(short);

    while (PaUtil_GetRingBufferReadAvailable(&ringBuffer)<int(bytes))
    {
        //cout << "Read: want " << bytes << " avail " << PaUtil_GetRingBufferReadAvailable(&ringBuffer) << endl;
        Pa_Sleep(10);
    }

    PaUtil_ReadRingBuffer(&ringBuffer, &psData[0], bytes);
    if (xruns==0)
        return FALSE;
    else
        cout << "overrun" << endl;
    xruns = 0;
    return TRUE;
}
signed long GetStreamReadAvailable( PaStream* stream )
{
    PaMacBlio *blio = & ((PaMacCoreStream*)stream) -> blio;
    VVDBUG(("GetStreamReadAvailable()\n"));

    return PaUtil_GetRingBufferReadAvailable( &blio->inputRingBuffer )
                         / ( blio->outputSampleSizeActual * blio->outChan );
}
Esempio n. 12
0
bool CaudioFifo::pop_input_samples(float *psamples, int size)
{
  int available;
  ring_buffer_size_t elementCount;

  assert(size == m_frame_size);
  available = PaUtil_GetRingBufferReadAvailable(&m_rbufin);
  if (available > 0)
    {
      elementCount = 1;
      PaUtil_ReadRingBuffer(&m_rbufin, psamples, elementCount);
      return true;
    }
  return false;
}
Esempio n. 13
0
static int
playbackCallback(const void *inputBuffer, void *outputBuffer,
                 unsigned long framesPerBuffer,
                 const PaStreamCallbackTimeInfo *,
                 PaStreamCallbackFlags statusFlags, void *userData)
{
    CPaCommon *This = (CPaCommon *) userData;
    (void) inputBuffer;			/* Prevent unused variable warning. */
    long bytes = framesPerBuffer*2*sizeof(short);
    long avail = PaUtil_GetRingBufferReadAvailable(&This->ringBuffer);
    PaUtil_ReadRingBuffer(&This->ringBuffer, outputBuffer, (avail<bytes)?avail:bytes);
    if (statusFlags&paOutputUnderflow)
        This->xruns++;
    return 0;
}
Esempio n. 14
0
uint32 AudioStream::Update()
{
	short tbuf[BUFF_SIZE];
	uint32 eCount = PaUtil_GetRingBufferWriteAvailable(&mRingBuf);
	uint32 ReadTotal;

	if (!mSource) return 0;

	mSource->SetLooping(IsLooping());

	if (ReadTotal = mSource->Read(tbuf, eCount))
	{
		PaUtil_WriteRingBuffer(&mRingBuf, tbuf, ReadTotal);
	}else
	{
		if (!PaUtil_GetRingBufferReadAvailable(&mRingBuf) && !mSource->HasDataLeft())
			mIsPlaying = false;
	}

	return ReadTotal;
}
Esempio n. 15
0
DWORD CoreAudioAUHAL::GetSpace()
{
	DWORD fakeCeiling, bufferDataSize = PaUtil_GetRingBufferReadAvailable(deviceParameters->outputBuffer);
	
	if (m_bIsMusic)
	{
		fakeCeiling = PACKET_SIZE / deviceParameters->stream_format.mChannelsPerFrame;
	}
	else
	{
		fakeCeiling = deviceParameters->stream_format.mSampleRate * CA_BUFFER_FACTOR;
	}
	
	if (bufferDataSize < fakeCeiling)
	{
		return fakeCeiling - bufferDataSize;
	}
	else
	{
		return 0;
	}
}
Esempio n. 16
0
int CaudioFifo::pop_output_samples(float *psamples, int size)
{
  int                available;
  ring_buffer_size_t elementCount;
  int                i;

  assert(size == m_frame_size);
  available = PaUtil_GetRingBufferReadAvailable(&m_rbufout);
  if (available > 0)
    {
      elementCount = 1;
      PaUtil_ReadRingBuffer(&m_rbufout, psamples, elementCount);
    }
  else
    {
      for (i = 0; i < m_frame_size; i++)
	{
	  psamples[i] = 0;
	}
    }
  return available;
}
Esempio n. 17
0
void MLReporter::viewProperties()
{
	while(PaUtil_GetRingBufferReadAvailable(&mChangeQueue) > 0)
	{
		// dequeue name of changed property
		MLSymbol propName;
		PaUtil_ReadRingBuffer( &mChangeQueue, &propName, 1 );

		// do we have viewers for this property?
		MLPropertyViewListMap::iterator look = mPropertyViewsMap.find(propName);
		if (look != mPropertyViewsMap.end())
		{
			// run viewers
			MLPropertyViewList viewers = look->second;
			for(MLPropertyViewList::iterator vit = viewers.begin(); vit != viewers.end(); vit++)
			{
				MLPropertyViewPtr pv = (*vit);
				const MLPropertyView& v = (*pv);
				v.view(mCurrentProperties.getProperty(propName));
			}
		}
	}
}
Esempio n. 18
0
/*****************************************************************************
 * RenderCallbackSPDIF: callback for SPDIF audio output
 *****************************************************************************/
OSStatus CoreAudioAUHAL::RenderCallbackSPDIF(AudioDeviceID inDevice,
                                    const AudioTimeStamp * inNow,
                                    const void * inInputData,
                                    const AudioTimeStamp * inInputTime,
                                    AudioBufferList * outOutputData,
                                    const AudioTimeStamp * inOutputTime,
                                    void * threadGlobals )
{
    CoreAudioDeviceParameters *deviceParameters = (CoreAudioDeviceParameters *)threadGlobals;

#define BUFFER outOutputData->mBuffers[deviceParameters->i_stream_index]
	int framesToWrite = BUFFER.mDataByteSize / (deviceParameters->stream_format.mChannelsPerFrame * deviceParameters->stream_format.mBitsPerChannel/8);
	//fprintf(stderr, "Frames requested: %i (%i bit, %i channels in, %i channels out)\n", 
	//		framesToWrite, 
	//		deviceParameters->stream_format.mBitsPerChannel,
	//		deviceParameters->m_ac3encoder.m_aftenContext.channels,
	//		deviceParameters->stream_format.mChannelsPerFrame);

	if (framesToWrite > PaUtil_GetRingBufferReadAvailable(deviceParameters->outputBuffer))
	{
		// we can't write a frame, send null frame
        memset(BUFFER.mData, 0, BUFFER.mDataByteSize);
    }
	else
	{
		// write a frame
		if (deviceParameters->m_bEncodeAC3)
		{
			PaUtil_ReadRingBuffer(deviceParameters->outputBuffer, deviceParameters->rawSampleBuffer, framesToWrite);
			/*fprintf(stderr, "Got %i frames from encoder\n", */ac3encoderEncodePCM(&deviceParameters->m_ac3encoder, (uint8_t *)&deviceParameters->rawSampleBuffer, (uint8_t *)BUFFER.mData, framesToWrite)/*)*/;

		}
		else PaUtil_ReadRingBuffer(deviceParameters->outputBuffer, BUFFER.mData, framesToWrite);
	}
#undef BUFFER
    return( noErr );
}
Esempio n. 19
0
void SaveThread::run()
{
    int buffer[4096];
    char* tempBuffer = new char[4096 * 4];

    short maxBuffer[512];

    QList<qint16> obuf;

    int pos = 0;

    int peakIndex = 0;

    int format = SF_FORMAT_PCM_24 | SF_FORMAT_RAW;
    QString ending = this->fileName.section('.', -1, -1);
    if (ending == "wav")
    {
        format = SF_FORMAT_PCM_24 | SF_FORMAT_WAV;
    }
    else if (ending == "w64")
    {
        format = SF_FORMAT_PCM_24 | SF_FORMAT_W64;
    }
    else if (ending == "ogg")
    {
        format = SF_FORMAT_OGG | SF_FORMAT_VORBIS;
    }
    else if (ending == "flac")
    {
        format = SF_FORMAT_PCM_24 | SF_FORMAT_FLAC;
    }
    SndfileHandle file(this->fileName.toStdString(), SFM_WRITE, format, 2, 44100);

    QFile peakFile(this->fileName + ".pk");
    peakFile.open(QFile::WriteOnly);

    short towrite[512];

    while (!this->toEnd && this->rb != NULL)
    {
        ring_buffer_size_t len = PaUtil_GetRingBufferReadAvailable(this->rb);
        if (len >= 128)
        {
            PaUtil_ReadRingBuffer(this->rb, tempBuffer, 128);
//            this->rb->get(tempBuffer, 256 * 4);

            qint16 maxLeft1 = 0;
            qint16 maxLeft2 = 0;
            qint16 maxRihgt1 = 0;
            qint16 maxRihgt2 = 0;

            memcpy(&maxBuffer[0], tempBuffer, 128 * 4 * 2);
            for (int i = 1; i < 512; i += 4)
            {
                if (maxBuffer[i] > maxLeft1)
                {
                    maxLeft1 = maxBuffer[i];
                }
                if (maxBuffer[i] < maxLeft2)
                {
                    maxLeft2 = maxBuffer[i];
                }
                if (maxBuffer[i + 2] > maxRihgt1)
                {
                    maxRihgt1 = maxBuffer[i + 2];
                }
                if (maxBuffer[i + 2] < maxRihgt2)
                {
                    maxRihgt2 = maxBuffer[i + 2];
                }
            }
            obuf.append(maxLeft1);
            obuf.append(maxLeft2);
            obuf.append(maxRihgt1);
            obuf.append(maxRihgt2);

            emit signalPeaks(peakIndex, maxLeft1, maxLeft2, maxRihgt1, maxRihgt2);
            ++peakIndex;

            memcpy(&buffer[pos], tempBuffer, 128 * 4 * 2);
            pos += 256;

            if (pos >= 4096)
            {
                file.writef((int*)buffer, 2048);
                pos = 0;
            }

            if (obuf.count() >= 512)
            {
                for (int i = 0; i < 512; ++i)
                {
                    towrite[i] = obuf.at(i);
                }
                peakFile.write((char*)&towrite[0], 1024);
                obuf.clear();
            }
            if (this->shuldSendBuffer && obuf.count() > 0)
            {
                this->shuldSendBuffer = false;
                for (int i = 0; i < obuf.count(); ++i)
                {
                    towrite[i] = obuf.at(i);
                }
                QByteArray ba(obuf.count() * 2, '\0');
                memcpy(ba.data(), &towrite[0], obuf.count() * 2);
                emit signalBuffer(ba);
            }
        }
        else
        {
            msleep(100);
        }
    }

    if (pos > 0)
    {
        file.writef((int*)buffer, pos / 2);
    }

    if (obuf.count() > 0)
    {
        for (int i = 0; i < obuf.count(); ++i)
        {
            towrite[i] = obuf.at(i);
        }
        peakFile.write((char*)&towrite[0], obuf.count() * 2);
        obuf.clear();
    }

    delete [] tempBuffer;

    file.writeSync();

//    sf_close(file.rawHandle());

//    QFile wavfile(this->fileName);
//    wavfile.open(QIODevice::ReadWrite);
//    wavfile.seek(4);
//    int len = wavfile.size() - 8;
//    wavfile.write((char*)&len, 4);
//    wavfile.seek(40);
//    len -= 36;
//    wavfile.write((char*)&len, 4);
//    wavfile.close();

    peakFile.flush();
    peakFile.close();
}
Esempio n. 20
0
void MLPluginController::clearFileActionQueue()
{
	int remaining = PaUtil_GetRingBufferReadAvailable(&mFileActionQueue);
	PaUtil_AdvanceRingBufferReadIndex(&mFileActionQueue, remaining);
}
Esempio n. 21
0
/***************************************************************************
** Return number of elements available for writing. */
ring_buffer_size_t PaUtil_GetRingBufferWriteAvailable( const PaUtilRingBuffer *rbuf )
{
    return ( rbuf->bufferSize - PaUtil_GetRingBufferReadAvailable(rbuf));
}
Esempio n. 22
0
/***************************************************************************
** Return number of elements available for writing. */
ring_buffer_size_t PaUtil_GetRingBufferWriteAvailable( PaUtilRingBuffer *rbuf )
{
    /* Since we are calling PaUtil_GetRingBufferReadAvailable, we don't need an aditional MB */
    return ( rbuf->bufferSize - PaUtil_GetRingBufferReadAvailable(rbuf));
}
Esempio n. 23
0
/*
 * this is the BlioCallback function. It expects to recieve a PaMacBlio Object
 * pointer as userData.
 *
 */
int BlioCallback( const void *input, void *output, unsigned long frameCount,
	const PaStreamCallbackTimeInfo* timeInfo,
        PaStreamCallbackFlags statusFlags,
        void *userData )
{
   PaMacBlio *blio = (PaMacBlio*)userData;
   ring_buffer_size_t framesAvailable;
   ring_buffer_size_t framesToTransfer;
   ring_buffer_size_t framesTransferred;

   /* set flags returned by OS: */
   OSAtomicOr32( statusFlags, &blio->statusFlags ) ;

   /* --- Handle Input Buffer --- */
   if( blio->inChan ) {
      framesAvailable = PaUtil_GetRingBufferWriteAvailable( &blio->inputRingBuffer );

      /* check for underflow */
      if( framesAvailable < frameCount )
      {
          OSAtomicOr32( paInputOverflow, &blio->statusFlags );
          framesToTransfer = framesAvailable;
      }
      else
      {
          framesToTransfer = (ring_buffer_size_t)frameCount;
      }

      /* Copy the data from the audio input to the application ring buffer. */
      /*printf( "reading %d\n", toRead );*/
      framesTransferred = PaUtil_WriteRingBuffer( &blio->inputRingBuffer, input, framesToTransfer );
      assert( framesToTransfer == framesTransferred );
#ifdef PA_MAC__BLIO_MUTEX
      /* Priority inversion. See notes below. */
      blioSetIsInputEmpty( blio, false );
#endif
   }


   /* --- Handle Output Buffer --- */
   if( blio->outChan ) {
      framesAvailable = PaUtil_GetRingBufferReadAvailable( &blio->outputRingBuffer );

      /* check for underflow */
      if( framesAvailable < frameCount )
      {
          /* zero out the end of the output buffer that we do not have data for */
          framesToTransfer = framesAvailable;

          size_t bytesPerFrame = blio->outputSampleSizeActual * blio->outChan;
          size_t offsetInBytes = framesToTransfer * bytesPerFrame;
          size_t countInBytes = (frameCount - framesToTransfer) * bytesPerFrame;
          bzero( ((char *)output) + offsetInBytes, countInBytes );

          OSAtomicOr32( paOutputUnderflow, &blio->statusFlags );
          framesToTransfer = framesAvailable;
      }
      else
      {
          framesToTransfer = (ring_buffer_size_t)frameCount;
      }

      /* copy the data */
      /*printf( "writing %d\n", toWrite );*/
      framesTransferred = PaUtil_ReadRingBuffer( &blio->outputRingBuffer, output, framesToTransfer );
      assert( framesToTransfer == framesTransferred );
#ifdef PA_MAC__BLIO_MUTEX
      /* We have a priority inversion here. However, we will only have to
         wait if this was true and is now false, which means we've got
         some room in the buffer.
         Hopefully problems will be minimized. */
      blioSetIsOutputFull( blio, false );
#endif
   }

   return paContinue;
}
Esempio n. 24
0
// read a ring buffer into the given row of the destination signal.
//
int MLProcRingBuffer::readToSignal(MLSignal& outSig, int samples, int row)
{
	int lastRead = 0;
	int skipped = 0;
	int available = 0;
	MLSample * outBuffer = outSig.getBuffer() + outSig.row(row);
	void * trashBuffer = (void *)mTrashSignal.getBuffer();
	MLSample * trashbufferAsSamples = reinterpret_cast<MLSample*>(trashBuffer);
	static MLSymbol modeSym("mode");
	int mode = (int)getParam(modeSym);
	bool underTrigger = false;
	MLSample triggerVal = 0.f;
		
	samples = min(samples, (int)outSig.getWidth());
	available = (int)PaUtil_GetRingBufferReadAvailable( &mBuf );
    
    // return if we have not accumulated enough signal.
	if (available < samples) return 0;
	
	// depending on trigger mode, trash samples up to the ones we will return.
	switch(mode)
	{
		default:
		case eMLRingBufferNoTrash:
		break;
		
		case eMLRingBufferUpTrig:		
			while (available >= samples+1)	
			{
				// read buffer
				lastRead = (int)PaUtil_ReadRingBuffer( &mBuf, trashBuffer, 1 );
				skipped += lastRead;
				available = (int)PaUtil_GetRingBufferReadAvailable( &mBuf );
				if(trashbufferAsSamples[0] < triggerVal)
				{
					underTrigger = true;
				}
				else
				{
					if (underTrigger == true) break;
					underTrigger = false;
				}
			}
		break;		

		case eMLRingBufferMostRecent:			
			if (available > samples)
			{
				// TODO modify pa ringbuffer instead of reading to trash buffer. 
				lastRead = (int)PaUtil_ReadRingBuffer( &mBuf, trashBuffer, available - samples );  
				// skipped += lastRead;
			}			
		break;
	}
	
    lastRead = (int)PaUtil_ReadRingBuffer( &mBuf, outBuffer, samples );

	// DEBUG
	/*
	const MLSymbol& myName = getName();
	if (!myName.compare("body_position_x_out"))
	{
		available = PaUtil_GetRingBufferReadAvailable( &mBuf );
		if ((skipped == 0) && (lastRead == 0))
		{
			debug() << "-";
		}
		else
		{
	debug() << getName() << " requested " << samples << " read " << lastRead << ", skipped " << skipped << ", avail. " << available << "\n";
		}
	}
	*/

	return lastRead;
}
Esempio n. 25
0
/*
 * this is the BlioCallback function. It expects to recieve a PaMacBlio Object
 * pointer as userData.
 *
 */
int BlioCallback( const void *input, void *output, unsigned long frameCount,
	const PaStreamCallbackTimeInfo* timeInfo,
        PaStreamCallbackFlags statusFlags,
        void *userData )
{
   PaMacBlio *blio = (PaMacBlio*)userData;
   long avail;
   long toRead;
   long toWrite;
   long read;
   long written;

   /* set flags returned by OS: */
   OSAtomicOr32( statusFlags, &blio->statusFlags ) ;

   /* --- Handle Input Buffer --- */
   if( blio->inChan ) {
      avail = PaUtil_GetRingBufferWriteAvailable( &blio->inputRingBuffer );

      /* check for underflow */
      if( avail < frameCount * blio->inputSampleSizeActual * blio->inChan )
      {
         OSAtomicOr32( paInputOverflow, &blio->statusFlags );
      }
      toRead = MIN( avail, frameCount * blio->inputSampleSizeActual * blio->inChan );

      /* copy the data */
      /*printf( "reading %d\n", toRead );*/
      read = PaUtil_WriteRingBuffer( &blio->inputRingBuffer, input, toRead );
      assert( toRead == read );
#ifdef PA_MAC__BLIO_MUTEX
      /* Priority inversion. See notes below. */
      blioSetIsInputEmpty( blio, false );
#endif
   }


   /* --- Handle Output Buffer --- */
   if( blio->outChan ) {
      avail = PaUtil_GetRingBufferReadAvailable( &blio->outputRingBuffer );

      /* check for underflow */
      if( avail < frameCount * blio->outputSampleSizeActual * blio->outChan )
         OSAtomicOr32( paOutputUnderflow, &blio->statusFlags );

      toWrite = MIN( avail, frameCount * blio->outputSampleSizeActual * blio->outChan );

      if( toWrite != frameCount * blio->outputSampleSizeActual * blio->outChan )
         bzero( ((char *)output)+toWrite,
                frameCount * blio->outputSampleSizeActual * blio->outChan - toWrite );
      /* copy the data */
      /*printf( "writing %d\n", toWrite );*/
      written = PaUtil_ReadRingBuffer( &blio->outputRingBuffer, output, toWrite );
      assert( toWrite == written );
#ifdef PA_MAC__BLIO_MUTEX
      /* We have a priority inversion here. However, we will only have to
         wait if this was true and is now false, which means we've got
         some room in the buffer.
         Hopefully problems will be minimized. */
      blioSetIsOutputFull( blio, false );
#endif
   }

   return paContinue;
}
Esempio n. 26
0
PaError ReadStream( PaStream* stream,
                           void *buffer,
                           unsigned long framesRequested )
{
    PaMacBlio *blio = & ((PaMacCoreStream*)stream) -> blio;
    char *cbuf = (char *) buffer;
    PaError ret = paNoError;
    VVDBUG(("ReadStream()\n"));

    while( framesRequested > 0 ) {
       ring_buffer_size_t framesAvailable;
       ring_buffer_size_t framesToTransfer;
       ring_buffer_size_t framesTransferred;
       do {
          framesAvailable = PaUtil_GetRingBufferReadAvailable( &blio->inputRingBuffer );
/*
          printf( "Read Buffer is %%%g full: %ld of %ld.\n",
                  100 * (float)avail / (float) blio->inputRingBuffer.bufferSize,
                  framesAvailable, blio->inputRingBuffer.bufferSize );
*/
          if( framesAvailable == 0 ) {
#ifdef PA_MAC_BLIO_MUTEX
             /**block when empty*/
             ret = UNIX_ERR( pthread_mutex_lock( &blio->inputMutex ) );
             if( ret )
                return ret;
             while( blio->isInputEmpty ) {
                ret = UNIX_ERR( pthread_cond_wait( &blio->inputCond, &blio->inputMutex ) );
                if( ret )
                   return ret;
             }
             ret = UNIX_ERR( pthread_mutex_unlock( &blio->inputMutex ) );
             if( ret )
                return ret;
#else
             Pa_Sleep( PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL );
#endif
          }
       } while( framesAvailable == 0 );
       framesToTransfer = (ring_buffer_size_t) MIN( framesAvailable, framesRequested );
       framesTransferred = PaUtil_ReadRingBuffer( &blio->inputRingBuffer, (void *)cbuf, framesToTransfer );
       cbuf += framesTransferred * blio->inputSampleSizeActual * blio->inChan;
       framesRequested -= framesTransferred;

       if( framesToTransfer == framesAvailable ) {
#ifdef PA_MAC_BLIO_MUTEX
          /* we just emptied the buffer, so we need to mark it as empty. */
          ret = blioSetIsInputEmpty( blio, true );
          if( ret )
             return ret;
          /* of course, in the meantime, the callback may have put some sats
             in, so
             so check for that, too, to avoid a race condition. */
          /* FIXME - this does not seem to fix any race condition. */
          if( PaUtil_GetRingBufferReadAvailable( &blio->inputRingBuffer ) ) {
             blioSetIsInputEmpty( blio, false );
             /* FIXME - why check? ret has not been set? */
             if( ret )
                return ret;
          }
#endif
       }
    }

    /*   Report either paNoError or paInputOverflowed. */
    /*   may also want to report other errors, but this is non-standard. */
    /* FIXME should not clobber ret, use if(blio->statusFlags & paInputOverflow) */
    ret = blio->statusFlags & paInputOverflow;

    /* report underflow only once: */
    if( ret ) {
       OSAtomicAnd32( (uint32_t)(~paInputOverflow), &blio->statusFlags );
       ret = paInputOverflowed;
    }

    return ret;
}
Esempio n. 27
0
/************************************************************
 * Return the number of frames that are available to be read from the
 * stream without having to wait.
 */
long GetAudioStreamReadable(PABLIO_Stream * aStream, int chan)
{
	int bytesFull = PaUtil_GetRingBufferReadAvailable(&aStream->inFIFOs[chan]);
	return bytesFull / aStream->bytesPerFrame;
}
Esempio n. 28
0
PaError ReadStream( PaStream* stream,
                           void *buffer,
                           unsigned long frames )
{
    PaMacBlio *blio = & ((PaMacCoreStream*)stream) -> blio;
    char *cbuf = (char *) buffer;
    PaError ret = paNoError;
    VVDBUG(("ReadStream()\n"));

    while( frames > 0 ) {
       long avail;
       long toRead;
       do {
          avail = PaUtil_GetRingBufferReadAvailable( &blio->inputRingBuffer );
/*
          printf( "Read Buffer is %%%g full: %ld of %ld.\n",
                  100 * (float)avail / (float) blio->inputRingBuffer.bufferSize,
                  avail, blio->inputRingBuffer.bufferSize );
*/
          if( avail == 0 ) {
#ifdef PA_MAC_BLIO_MUTEX
             /**block when empty*/
             ret = UNIX_ERR( pthread_mutex_lock( &blio->inputMutex ) );
             if( ret )
                return ret;
             while( blio->isInputEmpty ) {
                ret = UNIX_ERR( pthread_cond_wait( &blio->inputCond, &blio->inputMutex ) );
                if( ret )
                   return ret;
             }
             ret = UNIX_ERR( pthread_mutex_unlock( &blio->inputMutex ) );
             if( ret )
                return ret;
#else
             Pa_Sleep( PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL );
#endif
          }
       } while( avail == 0 );
       toRead = MIN( avail, frames * blio->inputSampleSizeActual * blio->inChan );
       toRead -= toRead % blio->inputSampleSizeActual * blio->inChan ;
       PaUtil_ReadRingBuffer( &blio->inputRingBuffer, (void *)cbuf, toRead );
       cbuf += toRead;
       frames -= toRead / ( blio->inputSampleSizeActual * blio->inChan );

       if( toRead == avail ) {
#ifdef PA_MAC_BLIO_MUTEX
          /* we just emptied the buffer, so we need to mark it as empty. */
          ret = blioSetIsInputEmpty( blio, true );
          if( ret )
             return ret;
          /* of course, in the meantime, the callback may have put some sats
             in, so
             so check for that, too, to avoid a race condition. */
          if( PaUtil_GetRingBufferReadAvailable( &blio->inputRingBuffer ) ) {
             blioSetIsInputEmpty( blio, false );
             if( ret )
                return ret;
          }
#endif
       }
    }

    /*   Report either paNoError or paInputOverflowed. */
    /*   may also want to report other errors, but this is non-standard. */
    ret = blio->statusFlags & paInputOverflow;

    /* report underflow only once: */
    if( ret ) {
       OSAtomicAnd32( (uint32_t)(~paInputOverflow), &blio->statusFlags );
       ret = paInputOverflowed;
    }

    return ret;
}
Esempio n. 29
0
int MLRingBuffer::getRemaining()
{
    return PaUtil_GetRingBufferReadAvailable(&mBuf);
}