示例#1
0
			/**
			  @brief Write an array of values into the ring buffer.

			  \param src an array of values to write
			  \param cnt the number of items from the array to write into our buffer
			  */
			void write(Type *src, unsigned int cnt){
				jack_ringbuffer_data_t writeVec[2];
				unsigned int write_size = sizeof(Type) * cnt;
				if(cnt > getWriteSpace()){
					//throw error!!!!
					return;
				}

				//get the write vector
				jack_ringbuffer_get_write_vector(mRingBufferPtr, writeVec);
				//if there is enough room in the first vector then just write there
				if(writeVec[0].len >= write_size){
					memcpy(writeVec[0].buf,src,write_size);
				} else {
					//if there is no room in the first vector then write into the second
					if(writeVec[0].len == 0){
						memcpy(writeVec[1].buf,src,write_size);
					} else {
						//this is more tricky, we have to split the data up
						char * byterep = (char *)src;
						//copy the first chunck
						memcpy(writeVec[0].buf, byterep, writeVec[0].len);
						//copy the second chunck
						memcpy(writeVec[1].buf, byterep + writeVec[0].len, write_size - writeVec[0].len);
					}
				}
				jack_ringbuffer_write_advance(mRingBufferPtr, write_size);
			}
示例#2
0
int ringbuffer_luawrite(jack_ringbuffer_t *rbuf, lua_State *L, int arg)
/* bool, errmsg = write(..., tag, data)
 * expects 
 * tag (integer) at index 'arg' of the stack, and 
 * data (string) at index 'arg+1' (optional)
 *
 * if there is not enough space available, it returns 'false, "no space"';
 * data may be an empty string ("") or nil, in which case it defaults
 * to the empty string (i.e., the message has only the header).
 */
	{
	jack_ringbuffer_data_t vec[2];
	hdr_t hdr;
	int isnum;
	size_t space, cnt;
	size_t len;
	const char *data;
	hdr.tag = (uint32_t)lua_tointegerx(L, arg, &isnum);
	if(!isnum)
		luaL_error(L, "invalid tag");

	data = luaL_optlstring(L, arg + 1, NULL, &len);
	if(!data)
		hdr.len = 0;
	else
		hdr.len = len; /*@@*/

	space = jack_ringbuffer_write_space(rbuf);
	if((sizeof(hdr) + hdr.len) > space)
		{ lua_pushboolean(L, 0); return 1; }

	/* write header first (this automatically advances) */
	cnt = jack_ringbuffer_write(rbuf, (const char *)&hdr, sizeof(hdr));
	if(cnt != sizeof(hdr))
		return luaL_error(L, UNEXPECTED_ERROR);

	if(hdr.len)
		{
		/* write data */
		jack_ringbuffer_get_write_vector(rbuf, vec);
		if((vec[0].len+vec[1].len) < hdr.len)
			return luaL_error(L, UNEXPECTED_ERROR);
		if(vec[0].len >= hdr.len)
			memcpy(vec[0].buf, data, hdr.len);
		else
			{
			memcpy(vec[0].buf, data, vec[0].len);
			memcpy(vec[1].buf, data + vec[0].len, hdr.len - vec[0].len);
			}
		jack_ringbuffer_write_advance(rbuf, hdr.len);
		}
	lua_pushboolean(L, 1);
	return 1;
	}
示例#3
0
static void *
disk_thread (void *arg)
{	thread_info_t *info = (thread_info_t *) arg ;
	sf_count_t buf_avail, read_frames ;
	jack_ringbuffer_data_t vec [2] ;
	size_t bytes_per_frame = sample_size*info->channels ;

	pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL) ;
	pthread_mutex_lock (&disk_thread_lock) ;

	while (1)
	{	jack_ringbuffer_get_write_vector (ringbuf, vec) ;

		read_frames = 0 ;

		if (vec [0].len)
		{	/* Fill the first part of the ringbuffer. */
			buf_avail = vec [0].len / bytes_per_frame ;
			read_frames = sf_readf_float (info->sndfile, (float *) vec [0].buf, buf_avail) ;
			if (vec [1].len)
			{	/* Fill the second part of the ringbuffer? */
				buf_avail = vec [1].len / bytes_per_frame ;
				read_frames += sf_readf_float (info->sndfile, (float *) vec [1].buf, buf_avail) ;
				} ;
			} ;

		if (read_frames == 0)
			break ; /* end of file? */

		jack_ringbuffer_write_advance (ringbuf, read_frames * bytes_per_frame) ;

		/* Tell process that we've filled the ringbuffer. */
		info->can_process = 1 ;

		/* Wait for the process thread to wake us up. */
		pthread_cond_wait (&data_ready, &disk_thread_lock) ;
		} ;

	/* Tell that we're done reading the file. */
	info->read_done = 1 ;
	pthread_mutex_unlock (&disk_thread_lock) ;

	return 0 ;
} /* disk_thread */
示例#4
0
/*
 * Low level input.
 */
static
int do_midi_input(process_midi_t *proc)
{
    input_port_t *port = (input_port_t*) proc->port;
    if (!midi_is_ready(proc))
        return 0;

    if (port->base.is_ready) {
        jack_ringbuffer_data_t vec[2];
        int res;

        jack_ringbuffer_get_write_vector(port->base.data_ring, vec);
        if (jack_ringbuffer_write_space(port->base.event_ring) < sizeof(event_head_t) || vec[0].len < 1) {
            port->overruns++;
            if (port->base.npfds)
                debug_log("midi_in: internal overflow on %s", port->base.name);
            // remove from poll to prevent busy-looping
            port->base.npfds = 0;
            return 1;
        }
        res = snd_rawmidi_read(port->base.rawmidi, vec[0].buf, vec[0].len);
        if (res < 0 && res != -EWOULDBLOCK) {
            error_log("midi_in: reading from port %s failed: %s", port->base.name, snd_strerror(res));
            return 0;
        } else if (res > 0) {
            event_head_t event;
            event.time = proc->cur_time;
            event.size = res;
            event.overruns = port->overruns;
            port->overruns = 0;
            debug_log("midi_in: read %d bytes at %d", (int)event.size, (int)event.time);
            jack_ringbuffer_write_advance(port->base.data_ring, event.size);
            jack_ringbuffer_write(port->base.event_ring, (char*)&event, sizeof(event));
        }
        port->base.is_ready = 0;
    }

    if (!midi_update_pfds(proc))
        return 0;

    return 1;
}
示例#5
0
static void 
queue_midi (JackVST *jvst, int val1, int val2, int val3)
{
	struct VstMidiEvent *pevent;
	jack_ringbuffer_data_t vec[2];

	jack_ringbuffer_get_write_vector (jvst->event_queue, vec);

	if (vec[0].len < sizeof (struct VstMidiEvent)) {
		fst_error ("event queue has no write space");
		return;
	}
		
	pevent = (struct VstMidiEvent *) vec[0].buf;

	//  printf("note: %d\n",note);
	
	pevent->type = kVstMidiType;
	pevent->byteSize = 24;
	pevent->deltaFrames = 0;
	pevent->flags = 0;
	pevent->detune = 0;
	pevent->noteLength = 0;
	pevent->noteOffset = 0;
	pevent->reserved1 = 0;
	pevent->reserved2 = 0;
	pevent->noteOffVelocity = 0;
	pevent->midiData[0] = val1;
	pevent->midiData[1] = val2;
	pevent->midiData[2] = val3;
	pevent->midiData[3] = 0;
	
	//printf("Sending: %x %x %x\n",val1,val2,val3);

	jack_ringbuffer_write_advance (jvst->event_queue, sizeof (struct VstMidiEvent));
}
示例#6
0
int ringbuffer_cwrite(jack_ringbuffer_t *rbuf, uint32_t tag, const void *data, size_t len)
/* C version: returns 1 on success and 0 on error */
	{
	jack_ringbuffer_data_t vec[2];
	hdr_t hdr;
	size_t space, cnt;
	hdr.tag = tag;

	hdr.len = data!=NULL ? len : 0;

	space = jack_ringbuffer_write_space(rbuf);
	if((sizeof(hdr) + hdr.len) > space)
		return 0;

	/* write header first (this automatically advances) */
	cnt = jack_ringbuffer_write(rbuf, (const char *)&hdr, sizeof(hdr));
	if(cnt != sizeof(hdr))
		return luajack_error(UNEXPECTED_ERROR);

	if(hdr.len)
		{
		/* write data */
		jack_ringbuffer_get_write_vector(rbuf, vec);
		if((vec[0].len+vec[1].len) < hdr.len)
			return luajack_error(UNEXPECTED_ERROR);
		if(vec[0].len >= hdr.len)
			memcpy(vec[0].buf, data, hdr.len);
		else
			{
			memcpy(vec[0].buf, data, vec[0].len);
			memcpy(vec[1].buf, (char*)data + vec[0].len, hdr.len - vec[0].len);
			}
		jack_ringbuffer_write_advance(rbuf, hdr.len);
		}
	return 1;
	}
示例#7
0
static void
a2j_input_event (struct a2j * self, snd_seq_event_t * alsa_event)
{
	jack_midi_data_t data[MAX_EVENT_SIZE];
	struct a2j_stream *str = &self->stream;
	long size;
	struct a2j_port *port;
	jack_nframes_t now;

	now = jack_frame_time (self->jack_client);
  
	if ((port = a2j_port_get(str->port_hash, alsa_event->source)) == NULL) {
		return;
	}

	/*
	 * RPNs, NRPNs, Bank Change, etc. need special handling
	 * but seems, ALSA does it for us already.
	 */
	snd_midi_event_reset_decode(str->codec);
	if ((size = snd_midi_event_decode(str->codec, data, sizeof(data), alsa_event))<0) {
		return;
	}

	// fixup NoteOn with vel 0
	if ((data[0] & 0xF0) == 0x90 && data[2] == 0x00) {
		data[0] = 0x80 + (data[0] & 0x0F);
		data[2] = 0x40;
	}

	a2j_debug("input: %d bytes at event_frame=%u", (int)size, now);

	if (jack_ringbuffer_write_space(port->inbound_events) >= (sizeof(struct a2j_alsa_midi_event) + size)) {
		struct a2j_alsa_midi_event ev;
		char *ev_charp = (char*) &ev;
		size_t limit;
		size_t to_write = sizeof(ev);

		jack_ringbuffer_data_t vec[2];
		jack_ringbuffer_get_write_vector( port->inbound_events, vec );
		ev.time = now;
		ev.size = size;

    
		limit = (to_write > vec[0].len ? vec[0].len : to_write);
		if( limit ) {
			memcpy( vec[0].buf, ev_charp, limit );
			to_write -= limit;
			ev_charp += limit;
			vec[0].buf += limit;
			vec[0].len -= limit;
		}
		if( to_write ) {
			memcpy( vec[1].buf, ev_charp, to_write );
			vec[1].buf += to_write;
			vec[1].len -= to_write;
		}

		to_write = size;
		ev_charp = (char *)data;
		limit = (to_write > vec[0].len ? vec[0].len : to_write);
		if( limit )
			memcpy( vec[0].buf, ev_charp, limit );
		to_write -= limit;
		ev_charp += limit;
		if( to_write )
			memcpy( vec[1].buf, ev_charp, to_write );

		jack_ringbuffer_write_advance( port->inbound_events, sizeof(ev) + size );
	} else {
		a2j_error ("MIDI data lost (incoming event buffer full): %ld bytes lost", size);
	}

}
示例#8
0
void
Playback_DS::disk_thread ( void )
{
    _thread.name( "Playback" );

    DMESSAGE( "playback thread running" );

    /* buffer to hold the interleaved data returned by the track reader */
    sample_t *buf = new sample_t[ _nframes * channels() * _disk_io_blocks ];
#ifndef AVOID_UNNECESSARY_COPYING
    sample_t *cbuf = new sample_t[ _nframes * _disk_io_blocks ];
#endif

    int blocks_ready = 0;

    const nframes_t nframes = _nframes * _disk_io_blocks;

    while ( wait_for_block() )
    {

//        lock(); // for seeking

        if ( seek_pending() )
        {
            /* FIXME: non-RT-safe IO */
            DMESSAGE( "performing seek to frame %lu", (unsigned long)_pending_seek );

            _frame = _pending_seek;
            _pending_seek = -1;
            blocks_ready = 0;
        }

        if ( ++blocks_ready < _disk_io_blocks )
        {
            /* wait for more space */
            continue;
        }

        /* reset */
        blocks_ready = 0;

        read_block( buf, nframes );

//        unlock(); // for seeking

        /* deinterleave the buffer and stuff it into the per-channel ringbuffers */

        const size_t block_size = nframes * sizeof( sample_t );

        for ( int i = channels(); i--; )
        {

#ifdef AVOID_UNNECESSARY_COPYING
            /* deinterleave direcectly into the ringbuffer to avoid
             * unnecessary copying */

            jack_ringbuffer_data_t rbd[2];

            memset( rbd, 0, sizeof( rbd ) );

            jack_ringbuffer_get_write_vector( _rb[ i ], rbd );

            if ( rbd[ 0 ].len >= block_size )
            {
                /* it'll all fit in one go */
                buffer_deinterleave_one_channel( (sample_t*)rbd[ 0 ].buf, buf, i, channels(), nframes );
            }
            else if ( rbd[ 0 ].len + rbd[ 1 ].len >= block_size )
            {
                /* there's enough space in the ringbuffer, but it's not contiguous */

                assert( ! ( rbd[ 0 ].len % sizeof( sample_t )  ) );
//                assert( ! ( rbd[ 1 ].len % sizeof( sample_t )  ) );

                const nframes_t f = rbd[ 0 ].len / sizeof( sample_t );

                /* do the first half */
                buffer_deinterleave_one_channel( (sample_t*)rbd[ 0 ].buf, buf, i, channels(), f );

                assert( rbd[ 1 ].len >= ( nframes - f ) * sizeof( sample_t ) );

                /* do the second half */
                buffer_deinterleave_one_channel( (sample_t*)rbd[ 1 ].buf, buf + f, i, channels(), nframes - f );
            }
            else
                ++_xruns;

            jack_ringbuffer_write_advance( _rb[ i ], block_size );
#else
            buffer_deinterleave_one_channel( cbuf, buf, i, channels(), nframes );

            if ( jack_ringbuffer_write( _rb[ i ], (char*)cbuf, block_size ) < block_size )
                ++_xruns;
#endif
        }

    }

    DMESSAGE( "playback thread terminating" );

    delete[] buf;
#ifndef AVOID_UNNECESSARY_COPYING
    delete[] cbuf;
#endif

    _terminate = false;
}