Exemplo n.º 1
0
static void OPL_AdvanceTime(unsigned int nsamples)
{
	opl_callback_t callback;
	void *callback_data;


	// Advance time.

	current_time += nsamples;

	if (opl_paused)
	{
		pause_offset += nsamples;
	}

	// Are there callbacks to invoke now?  Keep invoking them
	// until there are none more left.

	while (!OPL_Queue_IsEmpty(callback_queue)
		&& current_time >= OPL_Queue_Peek(callback_queue) + pause_offset)
	{
		// Pop the callback from the queue to invoke it.

		if (!OPL_Queue_Pop(callback_queue, &callback, &callback_data))
		{
			break;
		}


		callback(callback_data);

	}

}
Exemplo n.º 2
0
static int CallbackWaiting(uint64_t *next_time)
{
    // If paused, just wait in 50ms increments until unpaused.
    // Update pause_offset so after we unpause, the callback 
    // times will be right.

    if (opl_timer_paused)
    {
        *next_time = current_time + 50 * OPL_MS;
        pause_offset += 50 * OPL_MS;
        return 0;
    }

    // If there are no queued callbacks, sleep for 50ms at a time
    // until a callback is added.

    if (OPL_Queue_IsEmpty(callback_queue))
    {
        *next_time = current_time + 50 * OPL_MS;
        return 0;
    }

    // Read the time of the first callback in the queue.
    // If the time for the callback has not yet arrived,
    // we must sleep until the callback time.

    *next_time = OPL_Queue_Peek(callback_queue) + pause_offset;

    return *next_time <= current_time;
}
Exemplo n.º 3
0
static void OPL_Mix_Callback(void *udata,
                             Uint8 *byte_buffer,
                             int buffer_bytes)
{
    int16_t *buffer;
    unsigned int buffer_len;
    unsigned int filled = 0;

    // Buffer length in samples (quadrupled, because of 16-bit and stereo)

    buffer = (int16_t *) byte_buffer;
    buffer_len = buffer_bytes / 4;

    // Repeatedly call the OPL emulator update function until the buffer is
    // full.

    while (filled < buffer_len)
    {
        uint64_t next_callback_time;
        uint64_t nsamples;

        SDL_LockMutex(callback_queue_mutex);

        // Work out the time until the next callback waiting in
        // the callback queue must be invoked.  We can then fill the
        // buffer with this many samples.

        if (opl_sdl_paused || OPL_Queue_IsEmpty(callback_queue))
        {
            nsamples = buffer_len - filled;
        }
        else
        {
            next_callback_time = OPL_Queue_Peek(callback_queue) + pause_offset;

            nsamples = (next_callback_time - current_time) * mixing_freq;
            nsamples = (nsamples + OPL_SECOND - 1) / OPL_SECOND;

            if (nsamples > buffer_len - filled)
            {
                nsamples = buffer_len - filled;
            }
        }

        SDL_UnlockMutex(callback_queue_mutex);

        // Add emulator output to buffer.

        FillBuffer(buffer + filled * 2, nsamples);
        filled += nsamples;

        // Invoke callbacks for this point in time.

        AdvanceTime(nsamples);
    }
}
Exemplo n.º 4
0
void OPL_Render_Samples(void *dest, unsigned buffer_len)
{
	unsigned int filled = 0;


	short *buffer = (short *)dest;


	// Repeatedly call the OPL emulator update function until the buffer is
	// full.

	while (filled < buffer_len)
	{
		unsigned int next_callback_time;
		unsigned int nsamples;


		// Work out the time until the next callback waiting in
		// the callback queue must be invoked.  We can then fill the
		// buffer with this many samples.

		if (opl_paused || OPL_Queue_IsEmpty(callback_queue))
		{
			nsamples = buffer_len - filled;
		}
		else
		{
			next_callback_time = OPL_Queue_Peek(callback_queue) + pause_offset;

			nsamples = next_callback_time - current_time;

			if (nsamples > buffer_len - filled)
			{
				nsamples = buffer_len - filled;
			}
		}


		// Add emulator output to buffer.
#ifdef STEREO
		FillBuffer(buffer + filled * 2, nsamples);
#else
		FillBuffer(buffer + filled, nsamples);
#endif
		filled += nsamples;

		// Invoke callbacks for this point in time.

		OPL_AdvanceTime(nsamples);
	}
}
Exemplo n.º 5
0
int main()
{
    opl_callback_queue_t *queue;
    int iteration;

    queue = OPL_Queue_Create();

    for (iteration=0; iteration<5000; ++iteration)
    {
        opl_callback_t callback;
        void *data;
        unsigned int time;
        unsigned int newtime;
        int i;

        for (i=0; i<MAX_OPL_QUEUE; ++i)
        {
            time = rand() % 0x10000;
            OPL_Queue_Push(queue, NULL, NULL, time);
        }

        time = 0;

        for (i=0; i<MAX_OPL_QUEUE; ++i)
        {
            assert(!OPL_Queue_IsEmpty(queue));
            newtime = OPL_Queue_Peek(queue);
            assert(OPL_Queue_Pop(queue, &callback, &data));

            assert(newtime >= time);
            time = newtime;
        }

        assert(OPL_Queue_IsEmpty(queue));
        assert(!OPL_Queue_Pop(queue, &callback, &data));
    }
}
Exemplo n.º 6
0
static void AdvanceTime(unsigned int nsamples)
{
    opl_callback_t callback;
    void *callback_data;
    uint64_t us;

    SDL_LockMutex(callback_queue_mutex);

    // Advance time.

    us = ((uint64_t) nsamples * OPL_SECOND) / mixing_freq;
    current_time += us;

    if (opl_sdl_paused)
    {
        pause_offset += us;
    }

    // Are there callbacks to invoke now?  Keep invoking them
    // until there are no more left.

    while (!OPL_Queue_IsEmpty(callback_queue)
        && current_time >= OPL_Queue_Peek(callback_queue) + pause_offset)
    {
        // Pop the callback from the queue to invoke it.

        if (!OPL_Queue_Pop(callback_queue, &callback, &callback_data))
        {
            break;
        }

        // The mutex stuff here is a bit complicated.  We must
        // hold callback_mutex when we invoke the callback (so that
        // the control thread can use OPL_Lock() to prevent callbacks
        // from being invoked), but we must not be holding
        // callback_queue_mutex, as the callback must be able to
        // call OPL_SetCallback to schedule new callbacks.

        SDL_UnlockMutex(callback_queue_mutex);

        SDL_LockMutex(callback_mutex);
        callback(callback_data);
        SDL_UnlockMutex(callback_mutex);

        SDL_LockMutex(callback_queue_mutex);
    }

    SDL_UnlockMutex(callback_queue_mutex);
}