Пример #1
0
/*
 * alGenStreamingBuffers_LOKI
 *
 * Perform full allocation in buffers[0..n-1].  If full allocation
 * is not possible, the appropriate error is set and the function
 * returns.  Each buffer id in a sucessful call can be used with
 * BufferAppendData.
 *
 * If n is 0, legal nop.  If n < 0, set INVALID_VALUE and nop.
 *
 */
void alGenStreamingBuffers_LOKI( ALsizei n, ALuint *buffer) {
	AL_buffer *buf;
	int i;

	if(n == 0) {
		/* silently return */
		return;
	}

	if(n < 0) {
		_alDebug(ALD_BUFFER, __FILE__, __LINE__,
		      "alGenStreamingBuffers_LOKI: invalid n %d\n", n);

		_alcDCLockContext();
		_alDCSetError( AL_INVALID_VALUE );
		_alcDCUnlockContext();

		return;
	}

	/* generate normal buffers */
	alGenBuffers( n, buffer );

	_alLockBuffer();

	for( i = 0; i < n; i++ ) {
		buf = _alGetBuffer( buffer[i] );
		if( buf == NULL ) {
			/* allocation must have failed */
			_alUnlockBuffer();

			return;
		}

		/* make sure to set the streaming flag */
		buf->flags |= ALB_STREAMING;
	}

	_alUnlockBuffer();

	return;
}
Пример #2
0
/**
 * Specify data to be filled into a looping buffer.
 * This takes the current position at the time of the
 *  call, and returns the number of samples written.
 *
 *  FIXME: this version is not as stingy about memory as
 *         it could be.
 *
 *  FIXME: move convert to the bottom of the testing, so
 *   	   that only as much data as is being used will be
 *   	   converted.
 *
 *  FIXME: mostly untested
 *
 *  FIXME: this is the most horrible function ever.  I can only
 *  	   claim responsibility for 50% of the hideous horror that
 *  	   is this function.  Before you smite me to eternal damnation
 *  	   for the monstrosity that follows, please keep in mind that
 *  	   the remaining half of the horror belongs squarely on those
 *  	   who defined the semantics and side effects of this disgusting
 *  	   monster.
 *
 */
ALsizei alBufferAppendData_LOKI( ALuint   buffer,
                            ALenum   format,
                            void*    data,
		            ALsizei  osamps,
                            ALsizei  freq ) {
	AL_buffer *buf;
	ALuint osize;  /* old size */
	ALuint csize;  /* converted size */
	ALuint nsamps; /* number of samples that csize represents */
	ALuint csamps; /* number of samples to convert */
	ALuint psize;  /* predicted size of passed data after conversion */
	ALuint orig_csamps; /* original number of samples to convert, pre truncation */
	unsigned int remainingspace = 0;
	unsigned int copyoffset = 0;
	unsigned int copysize   = 0;
	ALenum tformat = 0; /* buffer's target format */
	ALuint tfreq = 0;   /* buffer's target frequency */
	void *temp = NULL;
	ALuint i;

	_alLockBuffer();

	buf = _alGetBuffer(buffer);
	if(buf == NULL) {
		/* invalid buffers go */
		_alUnlockBuffer();

		_alDebug(ALD_BUFFER, __FILE__, __LINE__,
			"buffer id %d is invalid",
			buffer);

		_alDCSetError(AL_INVALID_NAME);

		return 0;
	}

	/*
	 * Non streaming buffers go bye bye
	 */
	if(!(buf->flags & ALB_STREAMING)) {
		_alUnlockBuffer();

		_alDebug(ALD_STREAMING, __FILE__, __LINE__,
			"buffer id %d not created with alGenStreamingBuffer",
			buffer);

		_alDCSetError(AL_INVALID_OPERATION);

		return 0;
	}

	/* initialize stuff */

	osize = buf->size;

	/*
	 * Set csamps to the size of osamps in bytes.
	 *
	 * make sure that csamps contains an even multiple of
	 * the number of channels
	 */
	csamps  = osamps;
	csamps -= (csamps % _alGetChannelsFromFormat(format));
	csamps *= (_alGetBitsFromFormat(format) / 8);

	orig_csamps = csamps;

	/* Set psize to the value that csamps would be in converted format */
	psize = _al_PCMRatioify(freq, buf->frequency, format, buf->format, csamps);

	/* set nsamps */
	nsamps = osamps;

	if(buf->streampos > buf->size) {
		/* underflow! */
		_alDebug(ALD_STREAMING,
			__FILE__, __LINE__, "underflow! sp|size %d|%d",
			buf->streampos, buf->size);

		buf->streampos = buf->appendpos = 0;
		remainingspace = buf->size;
	} else if(buf->appendpos > buf->streampos) {
		remainingspace = buf->size - buf->appendpos;
	} else if(buf->size != 0) {
		remainingspace = buf->streampos - buf->appendpos;
	} else {
		remainingspace = 0;
	}

	if((remainingspace >= MINSTREAMCHUNKSIZE) ||
	   (psize <= remainingspace)) {
		/* only take enough space to fill buffer. */
		_alDebug(ALD_STREAMING, __FILE__, __LINE__,
		"fill data to end: rs|sp|ap. %d|%d|%d",
			remainingspace, buf->streampos, buf->appendpos);

		if(remainingspace < psize) {
			copysize = remainingspace;
		} else {
			copysize = psize;
		}

		/* scale samples */
		nsamps *= copysize;
		nsamps /= psize;

		/* remember to set copyoffset for offset_memcpy below */
		copyoffset = buf->appendpos;

		buf->appendpos += copysize;
	} else if((osize > EXPANDSTREAMBUFSIZE)         &&
		  (buf->streampos > MINSTREAMCHUNKSIZE) &&
	          (buf->appendpos > buf->streampos)) {
		/*
		 *  Okay:
		 *
		 *  Since streampos is after append pos, and
		 *  streampos is less than the min stream chunk
		 *  size, we can safely wrap around and put the
		 *  data at the beginning (the WRAP flag gets
		 *  removed elsewhere.
		 *
		 *  The only thing is, if the buffer is still
		 *  fairly small, it would be nice to expand it
		 *  so that it can accomodate more data (within
		 *  reason).  So we check to see if the size
		 *  greater than a certain threshold (expandbuffersize),
		 *  below which we defer to allow BufferAppendData to
		 *  expand the buffer.
		 */
		_alDebug(ALD_STREAMING, __FILE__, __LINE__,
			"reset offset 0 osize|psize|sp|ap|rs %d|%d|%d|%d|%d",
			osize, psize, buf->streampos, buf->appendpos,
			remainingspace);

		if(buf->streampos < psize) {
			copysize = buf->streampos;
		} else {
			copysize = psize;
		}

		/* scale samples */
		nsamps *= copysize;
		nsamps /= psize;

		copyoffset = 0;

		buf->appendpos = copysize;

		/* we can wrap. */
		buf->flags |= ALB_STREAMING_WRAP;
	} else if(buf->streampos < buf->appendpos) {
		unsigned int newsize;

		_alDebug(ALD_STREAMING, __FILE__, __LINE__,
			"eb time: size|rs|ap|sp      %d|%d|%d|%d",
			osize, remainingspace, buf->appendpos, buf->streampos);

		/* we must expand the size of our buffer */
		newsize = buf->appendpos + psize;

		assert(newsize >= osize);

		for(i = 0; i < buf->num_buffers; i++) {
			temp = realloc(buf->orig_buffers[i], newsize);
			if(temp == NULL) {
				_alUnlockBuffer();

				return 0;
			}

			buf->orig_buffers[i] = temp;
		}

		/* set copy params for offset_memcpy below */
		copyoffset = buf->appendpos;
		copysize   = psize;

		/* reset size */
		buf->size = newsize;

		/*
		 * set append
		 */
		buf->appendpos += psize;
	}  else if(buf->size > 0) {
		/* not ready to accept data */
		_alDebug(ALD_STREAMING, __FILE__, __LINE__,
			"osize|sp|ap|rs %d|%d|%d|%d",
			osize,
			buf->streampos,
			buf->appendpos,
			remainingspace);

		_alUnlockBuffer();
		return 0;
	}

	/*
	 * unlock buffer for time intensive stuff, but
	 * get buffer params first
	 */
	tformat = buf->format;
	tfreq   = buf->frequency;

	_alUnlockBuffer();

	/*
	 *  Recompute csamps to reflect a decrease of the amount of
	 *  data that we will use.
	 */
	csamps  = nsamps;
	csamps -= (csamps % _alGetChannelsFromFormat(format));
	csamps *= (_alGetBitsFromFormat(format) / 8);

	/*
	 * We should decide how much data to use such that csize is
	 * a reasonable number.
	 *
	 * bufferAppendScratch = converted data scratch space
	 * csize = converted data's size
	 *
	 * nsamps = number of samples that csize represents
	 */
	if(scratch.size < csamps * (_alGetBitsFromFormat(format)/8)) {
		temp = realloc(scratch.data, csamps * (_alGetBitsFromFormat(format)/8));
		if(temp == NULL) {
			/* oops */
			return 0;
		}

		scratch.data = temp;
		scratch.size = csamps * (_alGetBitsFromFormat(format)/8);
	}

	memcpy(scratch.data, data, csamps * (_alGetBitsFromFormat(format)>>3));

	temp = _alBufferCanonizeData(format,
				     scratch.data,
				     csamps,
				     freq,
				     tformat,
				     tfreq,
				     &csize,
				     AL_TRUE);
	if(temp == NULL) {
		/* conversion problem */
		_alDCSetError(AL_OUT_OF_MEMORY);

		_alDebug(ALD_CONVERT, __FILE__, __LINE__,
			"streaming buffer id %d: could not convert",
			buffer);

		return 0;
	}

	/* lock buffer again, as we are about to make changes */
	_alLockBuffer();

	if(buf->size == 0) {
		/* first time: copy data */
		_alDebug(ALD_STREAMING, __FILE__, __LINE__,
			"first time!");

		/* first time */
		buf->size = csize / _alGetChannelsFromFormat(buf->format);

		for(i = 0; i < buf->num_buffers; i++) {
			temp = realloc(buf->orig_buffers[i], csize / _alGetChannelsFromFormat(buf->format));
			if(temp == NULL) {
				_alUnlockBuffer();

				return 0;
			}

			buf->orig_buffers[i] = temp;
		}

		_alMonoify((ALshort **) buf->orig_buffers,
			   scratch.data,
			   csize / _alGetChannelsFromFormat(buf->format),
			   buf->num_buffers, _alGetChannelsFromFormat(buf->format));

		buf->appendpos    = csize;

		_alUnlockBuffer();

		return osamps;
	}

	_alMonoifyOffset((ALshort **) buf->orig_buffers,
			 copyoffset,
			 scratch.data,
			 csize / _alGetChannelsFromFormat(buf->format),
			 buf->num_buffers, _alGetChannelsFromFormat(buf->format));

/*
	offset_memcpy(buf->_orig_buffer, copyoffset, bufferAppendScratch, copysize);
 */

	_alUnlockBuffer();

	return nsamps;
}
Пример #3
0
/**
 *
 * alBufferWriteData_LOKI( ALuint  bid,
 *               ALenum  format,
 *               ALvoid  *data,
 *               ALsizei size,
 *               ALsizei freq
 *               ALenum  internalFormat )
 *
 * associates data with bid, with format hint
 *
 * If format is invalid, set AL_INVALID_ENUM.  If bid is not a valid buffer
 * name, set AL_INVALID_NAME.  If not enough memory is available to make a
 * copy of this data, set AL_OUT_OF_MEMORY.
 */
void alBufferWriteData_LOKI( ALuint  bid,
		   ALenum  format,
                   void   *data,
		   ALsizei size,
		   ALsizei freq,
		   ALenum internalFormat ) {
	AL_buffer *buf;
	unsigned int retsize;
	void *cdata;
	ALuint i;

	_alLockBuffer();

	buf = _alGetBuffer(bid);
	if(buf == NULL) {
		_alDebug(ALD_BUFFER, __FILE__, __LINE__,
		      "alBufferData: buffer id %d not valid",
		      bid);

		_alDCSetError(AL_INVALID_NAME);

		_alUnlockBuffer();
		return;
	}

	cdata = _alBufferCanonizeData(format,
				      data,
				      size,
				      freq,
				      internalFormat,
				      buf->frequency,
				      &retsize,
				      AL_FALSE);

	if(cdata == NULL) {
		/*  _alBufferCanonize Data should set error */
		_alUnlockBuffer();
		return;
	}

	if(buf->flags & ALB_STREAMING) {
		/* Streaming buffers cannot use alBufferData */
		_alDCSetError(AL_INVALID_OPERATION);

		free(cdata);

		_alUnlockBuffer();

		return;
	}

	buf->format = internalFormat;

	if(buf->size < retsize)
	{
		void *temp_copies[_ALC_MAX_CHANNELS] = { NULL };
		ALboolean success = AL_TRUE;

		/* don't use realloc */
		_alBufferFreeOrigBuffers(buf);

		for(i = 0; i < _alGetChannelsFromFormat(buf->format); i++)
		{
			temp_copies[i] = malloc(retsize);
			success = (temp_copies[i] != NULL) ? AL_TRUE : AL_FALSE;
		}

		if(!success)
		{
			free(cdata);

			for(i = 0; i < _alGetChannelsFromFormat(buf->format); i++)
			{
				free(temp_copies[i]);
			}

			/* JIV FIXME: lock context */
			_alcDCLockContext();
			_alDCSetError(AL_OUT_OF_MEMORY);
			_alcDCUnlockContext();

			_alUnlockBuffer();

			return;
		}

		switch(_alGetChannelsFromFormat(buf->format))
		{
			case 1:
			  for(i = 0; i < elementsof(buf->orig_buffers); i++)
			  {
				  buf->orig_buffers[i] = temp_copies[0];
			  }

			  break;
			case 2:
			  for(i = 0; i < elementsof(buf->orig_buffers); i += 2)
			  {
				  buf->orig_buffers[i]   = temp_copies[0];
				  buf->orig_buffers[i+1] = temp_copies[1];
			  }

			  break;
			case 4:
			  assert(elementsof(buf->orig_buffers) >= 4);
			  for(i = 0; i < elementsof(buf->orig_buffers); i += 4)
			  {
				  buf->orig_buffers[i]   = temp_copies[0];
				  buf->orig_buffers[i+1] = temp_copies[1];
				  buf->orig_buffers[i+2] = temp_copies[2];
				  buf->orig_buffers[i+3] = temp_copies[3];
			  }
			  break;
			case 6:
			  assert(elementsof(buf->orig_buffers) >= 6);
			  for(i = 0; i < elementsof(buf->orig_buffers); i += 6)
			  {
				  buf->orig_buffers[i]   = temp_copies[0];
				  buf->orig_buffers[i+1] = temp_copies[1];
				  buf->orig_buffers[i+2] = temp_copies[2];
				  buf->orig_buffers[i+3] = temp_copies[3];
				  buf->orig_buffers[i+4] = temp_copies[4];
				  buf->orig_buffers[i+5] = temp_copies[5];
			  }

			  break;
			default:
			  /* well this is weird */
			  assert(0);
			  break;
		}
	}


	_alMonoify((ALshort **) buf->orig_buffers,
		   cdata,
		   retsize / _alGetChannelsFromFormat(buf->format),
		   buf->num_buffers, _alGetChannelsFromFormat(buf->format));

	free(cdata);

	buf->size = retsize / _alGetChannelsFromFormat(buf->format);

	_alUnlockBuffer();

	return;
}
Пример #4
0
void alBufferi_LOKI(ALuint buffer, ALenum param, ALint value) {
	AL_buffer *buf = NULL;

	_alLockBuffer();
	buf = _alGetBuffer(buffer);

	if(buf == NULL) {
		_alUnlockBuffer();

		_alDebug(ALD_BUFFER, __FILE__, __LINE__,
			"buffer id %d is a bad index", buffer);

		_alDCSetError(AL_INVALID_NAME);
		return;
	}

	switch(param) {
		case AL_FREQUENCY:
		  buf->frequency = value;
		  break;
		case AL_BITS:
		  switch(value) {
		      case 8:
			switch(_alGetChannelsFromFormat(buf->format)) {
			    case 1:
			      buf->format = AL_FORMAT_MONO8;
			      break;
			    case 2:
			      buf->format = AL_FORMAT_STEREO8;
			      break;
			    default:
			      break;
			}
			break;
		      case 16:
			switch(_alGetChannelsFromFormat(buf->format)) {
			    case 1:
			      buf->format = AL_FORMAT_MONO16;
			      break;
			    case 2:
			      buf->format = AL_FORMAT_STEREO16;
			      break;
			    default:
			      break;
			}
			break;
		  }
		  break;
		case AL_CHANNELS:
		  switch(value) {
		      case 1:
			switch(_alGetBitsFromFormat(buf->format)) {
			    case 8:
			      buf->format = AL_FORMAT_MONO8;
			      break;
			    case 16:
			      buf->format = AL_FORMAT_MONO16;
			      break;
			    default: break;
			}
			break;
		      case 2:
			switch(_alGetBitsFromFormat(buf->format)) {
			    case 8:
			      buf->format = AL_FORMAT_STEREO8;
			      break;
			    case 16:
			      buf->format = AL_FORMAT_STEREO16;
			      break;
			}
			break;
		  }
		  break;
		case AL_SIZE:
		  buf->size = value;
		  break;
		default:
		  _alDebug(ALD_BUFFER, __FILE__, __LINE__,
			"alBufferi bad param 0x%x", param);

		  _alDCSetError(AL_INVALID_ENUM);
		  break;
	}

	_alUnlockBuffer();

	return;
}
Пример #5
0
/*
 * alSourceQueueBuffers( ALuint sid, ALsizei numBuffers, ALuint *bids )
 *
 * Queue bids[0..numBuffers-1] to the source named sid, setting
 * AL_INVALID_VALUE if numBuffers < 0, or AL_INVALID_NAME if either sid or and
 * bid in bids[0..numBuffers-1] is not a valid buffer.
 */
void alSourceQueueBuffers( ALuint sid, ALsizei numBuffers, ALuint *bids ) {
	AL_source *src;
	ALsizei i;

	if( numBuffers == 0) {
		/* with n == 0, we NOP */
		return;
	}

	if( numBuffers < 0) {
		_alDebug(ALD_SOURCE, __FILE__, __LINE__,
		      "alSourceQueueBuffers: illegal n value %d\n", numBuffers );

		_alcDCLockContext();
		_alDCSetError( AL_INVALID_VALUE );
		_alcDCUnlockContext();

		return;
	}

	SOURCELOCK();

	src = _alDCGetSource( sid );
	if( src == NULL ) {
		_alDCSetError( AL_INVALID_NAME );

		_alDebug(ALD_SOURCE, __FILE__, __LINE__,
		      "alSourceQueueBuffers: invalid sid %d\n", sid );

		SOURCEUNLOCK();

		return;
	}

	_alLockBuffer();

	/* make sure that bids are valid */
	for( i = 0; i < numBuffers; i++ ) {
		if( _alIsBuffer( bids[i] ) == AL_FALSE ) {
			/*
			 * we have an invalid bid.  bid 0 is okay but the
			 * rest are not.
			 */
			if( bids[i] != 0 ) {
				_alUnlockBuffer();

				_alDCSetError( AL_INVALID_NAME );

				SOURCEUNLOCK();

				return;
			}
		}
	}

	/* now, append the bids */
	for( i = 0; i < numBuffers; i++ ) {
		if( bids[i] != 0 ) {
			/*
			 * only append non-0 bids, because we don't
			 * need them anyway.
			 */
		  	_alSourceQueueAppend( src, bids[i] );
		}
	}

	/* we're done */

	_alUnlockBuffer();
	SOURCEUNLOCK();

	return;
}