Example #1
0
// wave_write
//
// DESCRIPTION:
//
// Meant to be asynchronous, it supplies the wave sample to the lower
// audio layer and returns. The sample is played later on.  [[[WDW -
// we purposely do not open the audio device as non-blocking because
// managing that would be a pain.  So, we rely a lot upon fifo.cpp and
// event.cpp to not overload us, allowing us to get away with a
// blocking write.  event.cpp:polling_thread in particular appears to
// use get_remaining_time to prevent flooding.]]]
//
// PARAMETERS:
//
// theHandler: the audio device file descriptor
// theMono16BitsWaveBuffer: the audio data
// theSize: the number of bytes (not 16-bit samples)
//
// GLOBALS USED/MODIFIED:
//
// total_samples_sent: modified based upon 16-bit samples sent
//
// RETURNS:
//
// the number of bytes (not 16-bit samples) sent
//
size_t wave_write(void *theHandler,
                  char *theMono16BitsWaveBuffer,
                  size_t theSize)
{
	size_t num;
	if (my_callback_is_output_enabled && (0 == my_callback_is_output_enabled()))
		return 0;

#if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN
	// BIG-ENDIAN, swap the order of bytes in each sound sample
	int c;
	char *out_ptr;
	char *out_end;
	out_ptr = (char *)theMono16BitsWaveBuffer;
	out_end = out_ptr + theSize;
	while (out_ptr < out_end) {
		c = out_ptr[0];
		out_ptr[0] = out_ptr[1];
		out_ptr[1] = c;
		out_ptr += 2;
	}
#endif

	num = write((int)theHandler, theMono16BitsWaveBuffer, theSize);

	// Keep track of the total number of samples sent -- we use this in
	// wave_get_read_position and also use it to help calculate the
	// total_samples_skipped in wave_close.
	//
	total_samples_sent += num / 2;

	return num;
}
Example #2
0
size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize)
{
  ENTER("wave_write");
  size_t bytes_to_write = theSize;
  char* aBuffer=theMono16BitsWaveBuffer;

  assert(stream);

  size_t aTotalFreeMem=0;

  pthread_mutex_lock(&pulse_mutex);

  while (1) 
    {
      if (my_callback_is_output_enabled 
	  && (0==my_callback_is_output_enabled()))
	{
	  SHOW_TIME("wave_write > my_callback_is_output_enabled: no!");
	  theSize=0;
	  goto terminate;
	}

      aTotalFreeMem = pulse_free();
      if (aTotalFreeMem >= bytes_to_write)
	{
	  SHOW("wave_write > aTotalFreeMem(%d) >= bytes_to_write(%d)\n", aTotalFreeMem, bytes_to_write);
	  break;
	}
 
      // TBD: check if really helpful
      if (aTotalFreeMem >= MAXLENGTH*2)
 	{
 	  aTotalFreeMem = MAXLENGTH*2;
 	}
       
      SHOW("wave_write > wait: aTotalFreeMem(%d) < bytes_to_write(%d)\n", aTotalFreeMem, bytes_to_write);

      // 500: threshold for avoiding too many calls to pulse_write
      if (aTotalFreeMem>500)
	{
	  pulse_write(aBuffer, aTotalFreeMem);
	  bytes_to_write -= aTotalFreeMem;
	  aBuffer += aTotalFreeMem;
	}

      usleep(10000);
    }

  pulse_write(aBuffer, bytes_to_write);

 terminate:
  pthread_mutex_unlock(&pulse_mutex);
  SHOW("wave_write: theSize=%d", theSize);
  SHOW_TIME("wave_write > LEAVE");
  return theSize;
}
Example #3
0
size_t wave_write(void* theHandler, 
		  char* theMono16BitsWaveBuffer, 
		  size_t theSize)
{
  size_t num;
  ENTER("wave_write");
  if (my_callback_is_output_enabled && (0==my_callback_is_output_enabled())) {
    SHOW_TIME("wave_write > my_callback_is_output_enabled: no!");
    return 0;
  }

#if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN
  {
    // BIG-ENDIAN, swap the order of bytes in each sound sample
    int c;
    char *out_ptr;
    char *out_end;
    out_ptr = (char *)theMono16BitsWaveBuffer;
    out_end = out_ptr + theSize;
    while(out_ptr < out_end)
    {
      c = out_ptr[0];
      out_ptr[0] = out_ptr[1];
      out_ptr[1] = c;
      out_ptr += 2;
    }
  }
#endif

  num = write((int) theHandler, theMono16BitsWaveBuffer, theSize);

  // Keep track of the total number of samples sent -- we use this in 
  // wave_get_read_position and also use it to help calculate the
  // total_samples_skipped in wave_close.
  //
  total_samples_sent += num / 2;

  if (num < theSize) {
    SHOW("ERROR: wave_write only wrote %d of %d bytes\n", num, theSize);
  } else {
    SHOW("wave_write wrote %d bytes\n", theSize);
  }

  SHOW_TIME("wave_write > LEAVE");
  return num;
}
Example #4
0
size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize)
{
	ENTER("wave_write");
	size_t bytes_written = 0;
	// space in ringbuffer for the sample needed: 1x mono channel but 2x for 1 stereo channel
	size_t bytes_to_write = (out_channels==1) ? theSize : theSize*2;
	my_stream_could_start = 0;
 
	if(pa_stream == NULL)
	{
		SHOW_TIME("wave_write > wave_open_sound\n");
		if (0 != wave_open_sound())
		{
			SHOW_TIME("wave_write > wave_open_sound fails!");
			return 0;
		}
		my_stream_could_start=1;
	}
	else if (!wave_is_busy(NULL))
	{
		my_stream_could_start = 1;
	}
	assert(BUFFER_LENGTH >= bytes_to_write);
 
	if (myWrite >= myBuffer + BUFFER_LENGTH)
	{
		myWrite = myBuffer;
	} // end if (myWrite >= myBuffer + BUFFER_LENGTH)
 
	size_t aTotalFreeMem=0;
	char* aRead = myRead;
	SHOW("wave_write > aRead=%x, myWrite=%x\n", (int)aRead, (int)myWrite);
 
	while (1)
	{
		if (my_callback_is_output_enabled && (0==my_callback_is_output_enabled()))
		{
			SHOW_TIME("wave_write > my_callback_is_output_enabled: no!");
			return 0;
		}
 
		aRead = myRead;
 
		// write pointer is before read pointer?
		if (myWrite >= aRead)
		{
			aTotalFreeMem = aRead + BUFFER_LENGTH - myWrite;
		}
		else // read pointer is before write pointer!
		{
			aTotalFreeMem = aRead - myWrite;
		} // end if (myWrite >= aRead)
 
		if (aTotalFreeMem>1)
		{
			// -1 because myWrite must be different of aRead
			// otherwise buffer would be considered as empty
			aTotalFreeMem -= 1;
		} // end if (aTotalFreeMem>1)
 
		if (aTotalFreeMem >= bytes_to_write)
		{
			break;
		} // end if (aTotalFreeMem >= bytes_to_write)
		
		//SHOW_TIME("wave_write > wait");
		SHOW("wave_write > wait: aTotalFreeMem=%d\n", aTotalFreeMem);
		SHOW("wave_write > aRead=%x, myWrite=%x\n", (int)aRead, (int)myWrite);
		usleep(10000);
	} // end while (1)
 
	aRead = myRead;
 
	// write pointer is ahead the read pointer?
	if (myWrite >= aRead)
	{
		SHOW_TIME("wave_write > myWrite >= aRead");
		// determine remaining free memory to the end of the ringbuffer
		size_t aFreeMem = myBuffer + BUFFER_LENGTH - myWrite;
		// is enough linear space available (regardless 1 or 2 channels)?
		if (aFreeMem >= bytes_to_write)
		{
			// copy direct - no wrap around at end of ringbuffer needed
			myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer, theSize);
		}
		else // not enough linear space available
		{
			// 2 channels (stereo)?
			if (out_channels == 2)
			{
				// copy with wrap around at the end of ringbuffer
				copyBuffer(myWrite, theMono16BitsWaveBuffer, aFreeMem/2);
				myWrite = myBuffer;
				myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer+aFreeMem/2, theSize - aFreeMem/2);
			}
			else // 1 channel (mono)
			{
				// copy with wrap around at the end of ringbuffer
				copyBuffer(myWrite, theMono16BitsWaveBuffer, aFreeMem);
				myWrite = myBuffer;
				myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer+aFreeMem, theSize - aFreeMem);
			} // end if (out_channels == 2)
		} // end if (aFreeMem >= bytes_to_write)
	} // if (myWrite >= aRead)
	else // read pointer is ahead the write pointer
	{
		SHOW_TIME("wave_write > myWrite <= aRead");
		myWrite += copyBuffer(myWrite, theMono16BitsWaveBuffer, theSize);
	} // end if (myWrite >= aRead)
 
	bytes_written = bytes_to_write;
	myWritePosition += theSize/sizeof(uint16_t); // add number of samples
 
	if (my_stream_could_start && (get_used_mem() >= out_channels * sizeof(uint16_t) * FRAMES_PER_BUFFER))
	{
		start_stream();
	} // end if (my_stream_could_start && (get_used_mem() >= out_channels * sizeof(uint16_t) * FRAMES_PER_BUFFER))
 
	SHOW_TIME("wave_write > LEAVE");
 
	return bytes_written;
}