Exemple #1
0
	size_t write(void const *src, size_t len)
	{
		size_t const avail = write_avail();
		if (avail == 0) return 0;

		size_t const limit_len = len > avail ? avail : len;
		size_t const total = wpos + len;
		size_t first, rest;

		if (total > CAPACITY) {
			first = CAPACITY - wpos;
			rest  = total % CAPACITY;
		} else {
			first = limit_len;
			rest  = 0;
		}

		Genode::memcpy(&_data[wpos], src, first);
		wpos = (wpos + first) % CAPACITY;

		if (rest) {
			Genode::memcpy(&_data[wpos], ((char const*)src) + first, rest);
			wpos = (wpos + rest) % CAPACITY;
		}

		return limit_len;
	}
Exemple #2
0
static void dsound_thread(void *data)
{
   DWORD write_ptr;
   dsound_t *ds = (dsound_t*)data;

   SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);

   get_positions(ds, NULL, &write_ptr);
   write_ptr = (write_ptr + ds->buffer_size / 2) % ds->buffer_size;

   while (ds->thread_alive)
   {
      struct audio_lock region;
      DWORD read_ptr, avail, fifo_avail;
      get_positions(ds, &read_ptr, NULL);
      
      avail = write_avail(read_ptr, write_ptr, ds->buffer_size);

      EnterCriticalSection(&ds->crit);
      fifo_avail = fifo_read_avail(ds->buffer);
      LeaveCriticalSection(&ds->crit);

      if (avail < CHUNK_SIZE || ((fifo_avail < CHUNK_SIZE) && (avail < ds->buffer_size / 2)))
      {
         /* No space to write, or we don't have data in our fifo, 
          * but we can wait some time before it underruns ... */


         /* We could opt for using the notification interface,
          * but it is not guaranteed to work, so use high 
          * priority sleeping patterns.
          */
         retro_sleep(1);
         continue;
      }

      if (!grab_region(ds, write_ptr, &region))
      {
         ds->thread_alive = false;
         SetEvent(ds->event);
         break;
      }

      if (fifo_avail < CHUNK_SIZE)
      {
         /* Got space to write, but nothing in FIFO (underrun), 
          * fill block with silence. */

         memset(region.chunk1, 0, region.size1);
         memset(region.chunk2, 0, region.size2);

         release_region(ds, &region);
         write_ptr = (write_ptr + region.size1 + region.size2) % ds->buffer_size;
      }
      else 
      {
         /* All is good. Pull from it and notify FIFO. */

         EnterCriticalSection(&ds->crit);
         if (region.chunk1)
            fifo_read(ds->buffer, region.chunk1, region.size1);
         if (region.chunk2)
            fifo_read(ds->buffer, region.chunk2, region.size2);
         LeaveCriticalSection(&ds->crit);

         release_region(ds, &region);
         write_ptr = (write_ptr + region.size1 + region.size2) % ds->buffer_size;

         SetEvent(ds->event);
      }
   }

   ExitThread(0);
}
Exemple #3
0
size_t FifoBuffer<T, Container>::write(const T* in, size_t num_elems)
{
   size_t write_amount = num_elems > write_avail() ? write_avail() : num_elems;
   m_container.insert(m_container.end(), in, in + write_amount);
   return write_amount;
}