예제 #1
0
void BufferedAudioSource::close()
{
	if(!isLoadedInMemory())
	{
		BufferedAudioSourceThread::getInstance()->removeSource(this);        
    }
}
예제 #2
0
void BufferedAudioSource::prime()
{
	if(!isLoadedInMemory())
	{
		// if this is the first time source is added, trigger to read data immediately
		if (BufferedAudioSourceThread::getInstance()->addSource(this)) {
			BufferedAudioSourceThread::getInstance()->readMore();
		}
	}
}
예제 #3
0
void BufferedAudioSource::flush()
{
	if(!isLoadedInMemory())
	{
		BufferedAudioSourceThread::getInstance()->removeSource(this);

		{
			RScopedLock l(&mLock);
			mBuffer.clear();
		}
    }
}
예제 #4
0
void BufferedAudioSource::setPosition(double seconds)
{
	seconds = seconds < 0 ? 0.0f : seconds;
	seconds = seconds > getLength() ? getLength() : seconds;

	RScopedLock l(&mLock);

	Int64 frames = (Int64)(seconds * getSampleRate());
    if(!isLoadedInMemory())
    {
        mBuffer.clear();
        setDecoderPosition(frames);
		BufferedAudioSourceThread::getInstance()->readMore();
    }
}
Int64 ExtAudioFileAudioSource::decodeData(float* buffer, UInt32 numFrames)
{
	RPRINT("decoding data\n");
    UInt32 numChannels = getNumChannels();
    OSStatus err = noErr;
    
    mReadBuffer.resize(numChannels * numFrames);
    
    // Set up the buffers
    setUpBuffers(&mReadBuffer[0], numChannels, numFrames);
    
    // Read the data out of our file, filling our output buffer
    UInt32 framesRead = numFrames;
	if(!isLoadedInMemory())
	{
		RScopedLock l(&mDecodeLock);
		err = ExtAudioFileRead (mAudioFile, &framesRead, mpBufferList);
	}
	else
	{
		err = ExtAudioFileRead (mAudioFile, &framesRead, mpBufferList);
	}
		
    if(err || framesRead == 0)
    {
        mEOF = true;
		RPRINT("done decoding data\n");
        return 0;
    }
    
    // The data is expected to be interlaced
    for(UInt32 j = 0; j < numChannels; ++j)
    {
        float *pTemp = &mReadBuffer[j * numFrames];
        float *pOut = &buffer[j];
        for(UInt32 i = j; i < framesRead; i++)
        {
            *pOut = *pTemp++;
            pOut += numChannels;
        }
    }
    
	RPRINT("done decoding data\n");
    return framesRead;    
}
예제 #6
0
Int64 BufferedAudioSource::readFrames(float* buffer, UInt32 numChannels, UInt32 numFrames, AudioSourceState& state)
{
	RScopedLock l(&mLock);

	Int64 framesRead = numFrames;
	int framesAvailable = mBuffer.size() / getNumChannels() - state.mCurrentFrame;

	// For disk-streaming sources we calculate available frames using the whole buffer
    if(!isLoadedInMemory()) {
        framesAvailable = mBuffer.size() / getNumChannels();
	}

	Int64 loopEndFrame = convertSecondsToSamples(state.mLoopEnd);
	Int64 totalFrames = convertSecondsToSamples(getLength());
	bool needToLoop = state.mLooping && ((state.mCurrentFrame >= loopEndFrame && loopEndFrame > 0) || (framesAvailable == 0 && mEOF));

	if(framesAvailable > 0 && !needToLoop)
	{

		// Make sure we don't read passed the end loop frame
		if(state.mLooping && loopEndFrame > 0 && loopEndFrame > state.mCurrentFrame)
			framesRead = (std::min)(framesRead, loopEndFrame-state.mCurrentFrame);

		if(framesAvailable < framesRead)
			framesRead = framesAvailable;

		int sourceChannels = getNumChannels();
        int frameOffset = state.mCurrentFrame;

        // For disk-streaming sources we always start at the beginning of the buffer
        if(!isLoadedInMemory())
            frameOffset = 0;

		for(UInt32 j = 0; j < numChannels; ++j)
		{
			float *in = NULL;
			if(sourceChannels == 1)
				in = mBuffer.getData(0, frameOffset);
			else
				in = mBuffer.getData(j, frameOffset);

			for(UInt32 i = 0; i < framesRead; ++i)
			{
				*(buffer++) = *in;
				in += sourceChannels;
			}
		}

        state.mCurrentFrame += framesRead;
		
        if(!isLoadedInMemory())
		{
			mBuffer.erase(0, framesRead);
			framesAvailable = mBuffer.size() / getNumChannels();
			UInt32 minimumFrames = getSampleRate() * SECONDS_TO_BUFFER / 2;
			if(framesAvailable <= minimumFrames)
			{
				BufferedAudioSourceThread::getInstance()->readMore();
			}
		}
	}
    else
    {
        framesRead = ERR_BUFFERING;

		if(needToLoop)
		{
			setPosition(state.mLoopStart);
			state.mCurrentFrame = convertSecondsToSamples(state.mLoopStart);

			// Now that we rewinded, read new data if preloaded
			if(isLoadedInMemory())
			{
				return readFrames(buffer, numChannels, numFrames, state);
			}
		}

        if(mEOF)
        {
            return 0; // signal that we are done
        }
		else if(!isLoadedInMemory())
		{
			BufferedAudioSourceThread::getInstance()->readMore();
		}
    }
    
	return framesRead;
}
예제 #7
0
Int64 BufferedAudioSource::readFrames(float* buffer, UInt32 numChannels, UInt32 numFrames, AudioSourceState& state)
{
	mLock.lock();

	Int64 framesRead = numFrames;
	int framesAvailable = mBuffer.size() / getNumChannels() - state.mCurrentFrame;
    
	// For disk-streaming sources we calculate available frames using the whole buffer
    if(!isLoadedInMemory())
        framesAvailable = mBuffer.size() / getNumChannels();
    
	mLock.unlock();

	Int64 loopEndFrame = convertSecondsToSamples(state.mLoopEnd);
	Int64 totalFrames = convertSecondsToSamples(getLength());
	bool needToLoop = state.mLooping && ((state.mCurrentFrame >= loopEndFrame && loopEndFrame > 0) || (framesAvailable == 0 && mEOF));
	
	if(framesAvailable > 0 && !needToLoop)
	{
		RScopedLock l(&mLock);

		if(framesAvailable < numFrames)
			framesRead = framesAvailable;

		int sourceChannels = getNumChannels();
        int frameOffset = state.mCurrentFrame;
        
        // For disk-streaming sources we always start at the beginning of the buffer
        if(!isLoadedInMemory())
            frameOffset = 0;
        
		for(UInt32 j = 0; j < numChannels; ++j)
		{
			float *in = NULL;
			if(sourceChannels == 1)
				in = mBuffer.getData(0, frameOffset);
			else
				in = mBuffer.getData(j, frameOffset);

			for(UInt32 i = 0; i < framesRead; ++i)
			{
				*(buffer++) = *in;
				in += sourceChannels;
			}
		}

        state.mCurrentFrame += framesRead;
		
        if(!isLoadedInMemory())
		{
			mBuffer.erase(0, framesRead);
			framesAvailable = mBuffer.size() / getNumChannels();
			UInt32 minimumFrames = getSampleRate() / 3;  // 1/3 of a second 
			if(framesAvailable <= minimumFrames)
			{
				BufferedAudioSourceThread::getInstance()->readMore();
			}
		}
	}
    else
    {
        framesRead = ERR_BUFFERING;
        
		if(needToLoop)
		{
			setPosition(state.mLoopStart);
			state.mCurrentFrame = convertSecondsToSamples(state.mLoopStart);
		}

		Int64 totalFrames = convertSecondsToSamples(getLength());
        if(state.mCurrentFrame >= totalFrames)
        {
            if(!isLoadedInMemory())
                BufferedAudioSourceThread::getInstance()->removeSource(this);
            
            return 0; // signal that we are done
        }
		else
            if(!isLoadedInMemory())
                BufferedAudioSourceThread::getInstance()->readMore();
    }
    
	return framesRead;
}