예제 #1
0
static int
process (jack_nframes_t nframes, void * arg)
{
	thread_info_t *info = (thread_info_t *) arg ;
	jack_default_audio_sample_t buf [info->channels] ;
	unsigned i, n ;

	if (! info->can_process)
		return 0 ;

	for (n = 0 ; n < info->channels ; n++)
		outs [n] = jack_port_get_buffer (output_port [n], nframes) ;

	for (i = 0 ; i < nframes ; i++)
	{	size_t read_cnt ;

		/* Read one frame of audio. */
		read_cnt = jack_ringbuffer_read (ringbuf, (void*) buf, sample_size*info->channels) ;
		if (read_cnt == 0 && info->read_done)
		{	/* File is done, so stop the main loop. */
			info->play_done = 1 ;
			return 0 ;
			} ;

		/* Update play-position counter. */
		info->pos += read_cnt / (sample_size*info->channels) ;

		/* Output each channel of the frame. */
		for (n = 0 ; n < info->channels ; n++)
			outs [n][i] = buf [n] ;
		} ;

	/* Wake up the disk thread to read more data. */
	if (pthread_mutex_trylock (&disk_thread_lock) == 0)
	{	pthread_cond_signal (&data_ready) ;
		pthread_mutex_unlock (&disk_thread_lock) ;
		} ;

	return 0 ;
} /* process */
예제 #2
0
// This is called by the JACK server in a
// special realtime thread once for each audio cycle.
int jackProcess(jack_nframes_t nframes, void *arg)
{
	int portNum;
	jack_nframes_t frameNum;

	// Only proceed if all ports have been connected
	if (allConnected == 0) return 0;

	// Get pointers to the capture port buffers
	for (portNum=0 ; portNum<NUM_INPUT_PORTS ; portNum++)
	{
		inputBufferArray[portNum] = jack_port_get_buffer(inputPortArray[portNum], nframes);
	}

	// Iterate through input buffers, adding samples to the ring buffer
	for (frameNum=0; frameNum<nframes; frameNum++)
	{
		for (portNum=0; portNum<NUM_INPUT_PORTS; portNum++)
		{
			size_t written = jack_ringbuffer_write(ringBuffer, (void *) &inputBufferArray[portNum][frameNum], sizeof(jack_default_audio_sample_t));
			if (written != sizeof(jack_default_audio_sample_t))
			{
				printf("Ringbuffer overrun\n");
			}
		}
	}

	// Attempt to lock the threadLock mutex, returns zero if lock acquired
	if (pthread_mutex_trylock(&threadLock) == 0)
	{
		// Wake up thread which is waiting for condition (should only be called after lock acquired)
		pthread_cond_signal(&dataReady);

		// Unlock mutex
		pthread_mutex_unlock(&threadLock);
	}

	return 0;
}
예제 #3
0
static int
coreaudio_driver_read (coreaudio_driver_t *driver, jack_nframes_t nframes)
{
    jack_default_audio_sample_t *buf;
    channel_t chn;
    jack_port_t *port;
    JSList *node;

    for (chn = 0, node = driver->capture_ports; node; node = jack_slist_next (node), chn++) {

        port = (jack_port_t *)node->data;

        if (jack_port_connected (port) && (driver->incoreaudio[chn] != NULL)) {
            float *in = driver->incoreaudio[chn];
            buf = jack_port_get_buffer (port, nframes);
            memcpy(buf,in,sizeof(float)*nframes);
        }
    }

    driver->engine->transport_cycle_start (driver->engine,jack_get_microseconds ());
    return 0;
}
예제 #4
0
static int jack_callaudio_process (jack_nframes_t nframes, void *arg)
{

	jack_thread_info_t *info = (jack_thread_info_t *) arg;

	if (!info->ready || !info->running) {
		return 0;
	}
	if( input->getDeviceState() == DspOut::DeviceClosed ) {
		return 0;
	}

	out = (jack_default_audio_sample_t *) jack_port_get_buffer( portout, nframes );
	int numBytes = input->readableBytes();
	if (numBytes > 0) {
		unsigned int samplesleft = input->getBuffer().getSize() / sizeof( short );
		short *inbuf = (short *)input->getBuffer().getData();
		input->readBuffer();
		memcpy( out, inbuf, samplesleft );
	}

	return 1;
}
예제 #5
0
파일: luajack.c 프로젝트: stetre/luajack
void* luajack_get_buffer(luajack_t *port)
/* Wrapper of jack_port_get_buffer() */
	{
#define cud ((pud)->cud)
	pud_t *pud;
	if(!(pud = get_pud(port))) return NULL;
	if(!IsProcessCallback(cud))
		{ luajack_error("function available only in process callback"); return NULL; }
	if(pud->buf)
		{ luajack_error("buffer already retrieved"); return NULL; }
	pud->nframes = cud->nframes;
	pud->buf = jack_port_get_buffer(pud->port, pud->nframes);
	if(!pud->buf)
		{ luajack_error("cannot get port buffer"); return NULL; }
	pud->bufp = 0;
	if(PortIsMidi(pud))
		{
		if(PortIsOutput(pud))
			jack_midi_clear_buffer(pud->buf);
		}	
	return pud->buf;
#undef cud
	}
예제 #6
0
/**
 * \brief JACK Callback function
 * \param nframes number of frames to fill into buffers
 * \param arg unused
 * \return currently always 0
 *
 * Write silence into buffers if paused or an underrun occured
 */
static int outputaudio(jack_nframes_t nframes, void *arg)
{
    struct ao *ao = arg;
    struct priv *p = ao->priv;
    float *bufs[MAX_CHANS];
    int i;
    for (i = 0; i < p->num_ports; i++)
        bufs[i] = jack_port_get_buffer(p->ports[i], nframes);
    if (p->paused || p->underrun || !p->ring)
        silence(bufs, nframes, p->num_ports);
    else if (read_buffer(p->ring, bufs, nframes, p->num_ports) < nframes)
        p->underrun = 1;
    if (p->estimate) {
        float now = mp_time_us() / 1000000.0;
        float diff = p->callback_time + p->callback_interval - now;
        if ((diff > -0.002) && (diff < 0.002))
            p->callback_time += p->callback_interval;
        else
            p->callback_time = now;
        p->callback_interval = (float)nframes / (float)ao->samplerate;
    }
    return 0;
}
예제 #7
0
파일: jackio.c 프로젝트: UIKit0/calfbox
static int copy_midi_data_to_buffer(jack_port_t *port, int buffer_size, struct cbox_midi_buffer *destination)
{
    void *midi = jack_port_get_buffer(port, buffer_size);
    if (!midi)
        return 0;
    uint32_t event_count = jack_midi_get_event_count(midi);

    cbox_midi_buffer_clear(destination);
    for (uint32_t i = 0; i < event_count; i++)
    {
        jack_midi_event_t event;
        
        if (!jack_midi_event_get(&event, midi, i))
        {
            if (!cbox_midi_buffer_write_event(destination, event.time, event.buffer, event.size))
                return -i;
        }
        else
            return -i;
    }
    
    return event_count;
}
예제 #8
0
int process (jack_nframes_t nframes, void *arg)
 {
	//jack_default_audio_sample_t *out = (jack_default_audio_sample_t *) jack_port_get_buffer (output_port, nframes);
	jack_default_audio_sample_t *in = (jack_default_audio_sample_t *) jack_port_get_buffer (input_port, nframes);
	
	int start = (WINDOW_SIZE-1+current_window)*FRAME_SIZE;
	int start2 = (current_window-1)*FRAME_SIZE;
	for ( int i = 0 ; i < nframes ; i++ ) {
		//data_array[i] = (float)out[(pos+i)%DATA_SIZE];
		fftw_in[start+i][0] = (double)in[i];
		if ( current_window > 0 ) {
			fftw_in[start2+i][0] = (double)in[i];
		}
	}
	//pos = (pos + nframes)%DATA_SIZE; 
	
	//printf("Number of frames: %d.\n", (int)nframes);
	
	//memcpy (out, in, sizeof (jack_default_audio_sample_t) * nframes);
	current_window = (current_window + 1)%WINDOW_SIZE; 
	
	return 0;      
 }
예제 #9
0
파일: silentjack.c 프로젝트: l1n/silentjack
/* Callback called by JACK when audio is available.
   Stores value of peak sample */
static
int process_peak(jack_nframes_t nframes, void *arg)
{
	jack_default_audio_sample_t *in;
	unsigned int i;

	/* just incase the port isn't registered yet */
	if (input_port == NULL) {
		return 0;
	}

	/* get the audio samples, and find the peak sample */
	in = (jack_default_audio_sample_t *) jack_port_get_buffer(input_port, nframes);
	for (i = 0; i < nframes; i++) {
		const float s = fabs(in[i]);
		if (s > peak) {
			peak = s;
		}
	}


	return 0;
}
예제 #10
0
파일: jackmidi.cpp 프로젝트: ViktorNova/los
void MidiJackDevice::collectMidiEvents()/*{{{*/
{
    if (!_readEnable)
        return;

    if (!_in_client_jackport) // p3.3.55
        return;

    void* port_buf = jack_port_get_buffer(_in_client_jackport, segmentSize); // p3.3.55

    jack_midi_event_t event;
    jack_nframes_t eventCount = jack_midi_get_event_count(port_buf);
    for (jack_nframes_t i = 0; i < eventCount; ++i)
    {
        jack_midi_event_get(&event, port_buf, i);

#ifdef JACK_MIDI_DEBUG
        printf("MidiJackDevice::collectMidiEvents number:%d time:%d\n", i, event.time);
#endif

        eventReceived(&event);
    }
}/*}}}*/
예제 #11
0
파일: mixer.c 프로젝트: recri/keyer
static int _process(jack_nframes_t nframes, void *arg) {
  _t *data = (_t *)arg;
  float *in0 = jack_port_get_buffer(framework_input(data,0), nframes);
  float *in1 = jack_port_get_buffer(framework_input(data,1), nframes);
  float *in2 = jack_port_get_buffer(framework_input(data,2), nframes);
  float *in3 = jack_port_get_buffer(framework_input(data,3), nframes);
  float *out0 = jack_port_get_buffer(framework_output(data,0), nframes);
  float *out1 = jack_port_get_buffer(framework_output(data,1), nframes);
  AVOID_DENORMALS;
  for (int i = nframes; --i >= 0; ) {
    const _Complex float a = *in0++ + *in1++ * I;
    const _Complex float b = *in2++ + *in3++ * I;
    const _Complex float c = a * b;
    *out0++ = crealf(c);
    *out1++ = cimagf(c);
  }
  return 0;
}
예제 #12
0
static int
process (jack_nframes_t nframes, void *arg)
{
	int chn;
	size_t i;
	jack_thread_info_t *info = (jack_thread_info_t *) arg;

	/* Do nothing until we're ready to begin. */
	if ((!info->can_process) || (!info->can_capture))
		return 0;

	for (chn = 0; chn < nports; chn++)
		in[chn] = jack_port_get_buffer (ports[chn], nframes);

	/* Sndfile requires interleaved data.  It is simpler here to
	 * just queue interleaved samples to a single ringbuffer. */
	for (i = 0; i < nframes; i++) {
		for (chn = 0; chn < nports; chn++) {
			if (jack_ringbuffer_write (rb, (void *) (in[chn]+i),
					      sample_size)
			    < sample_size)
				overruns++;
		}
	}

	/* Tell the disk thread there is work to do.  If it is already
	 * running, the lock will not be available.  We can't wait
	 * here in the process() thread, but we don't need to signal
	 * in that case, because the disk thread will read all the
	 * data queued before waiting again. */
	if (pthread_mutex_trylock (&disk_thread_lock) == 0) {
	    pthread_cond_signal (&data_ready);
	    pthread_mutex_unlock (&disk_thread_lock);
	}

	return 0;
}
예제 #13
0
void midiSendLong(unsigned char *buf, unsigned long len) {
  /*int err = snd_rawmidi_write(handle_out, buf, len);
  if (err != len) {
    fprintf(stderr, "could not write %ld byte to output, return: %d\n", len, err);
    exit(1);
  }*/
  if (jack_midi_output_port == NULL) {
    fprintf(stderr, "midiSendLong failed: output port closed\n");
    exit(1);
  }

  void* output_buf = jack_port_get_buffer (jack_midi_output_port, 1);   
  jack_midi_clear_buffer(output_buf);  

  printhex("send:", buf, len);

  int err = jack_midi_event_write(output_buf, 0, buf, len);
  if (err != 0) { 
    if (err == ENOBUFS) { // if there's not enough space in buffer for event
    }
    fprintf(stderr, "could not write %ld byte to output, return: %d\n", len, err);
    exit(1);
  }
}
예제 #14
0
static int iio_driver_read(iio_driver_t *driver, jack_nframes_t nframes) {
    JSList *node;
    channel_t chn;
    jack_nframes_t i;

    //Debugger<<"iio_driver_read\n";

    if (nframes > 0) {
        ////Debugger<<"iio_driver_read nframes = "<<nframes<<"\n";
//        for (jack_nframes_t i=0; i<nframes; i++){
//            cout<<(float)(*data)(i,0)<<endl;
//        cout<<endl;

        // write to the connected capture ports ...
        node = (JSList *)driver->capture_ports;
        for (chn = 0; node; node = (JSList *)jack_slist_next(node), chn++) {

            //jack_port_t *port = static_cast<jack_port_t *>(node->data);
            jack_port_t *port = (jack_port_t*)(node->data);

            if (!jack_port_connected (port)) /* no-copy optimization */
                continue;

            //jack_default_audio_sample_t *buf = static_cast<jack_default_audio_sample_t *>(jack_port_get_buffer (port, nframes));
            jack_default_audio_sample_t *buf = (jack_default_audio_sample_t *)(jack_port_get_buffer (port, nframes));
            for (i=0; i<nframes; i++) {
                //cout<<"row = "<<i*devChCnt+rowOffset<<" col = "<<col<<endl;
                //buf[i]=(*data)(i*devChCnt+rowOffset, col)*100.;
                buf[i]=(float)i/(float)nframes;
                //cout<<(*data)(i*devChCnt+rowOffset, col)<<'\t'<<buf[i]<<'\n';
            }
        }
        //Debugger<<" spent "<< (driver->engine->get_microseconds()-driver->debug_last_time)<<" us waiting for lock and copying data over\n";
    }
    return 0;
}
예제 #15
0
파일: MidiJack.cpp 프로젝트: BaraMGB/lmms
// we read data from jack
void MidiJack::JackMidiRead(jack_nframes_t nframes)
{
	unsigned int i,b;
	void* port_buf = jack_port_get_buffer(m_input_port, nframes);
	jack_midi_event_t in_event;
	jack_nframes_t event_index = 0;
	jack_nframes_t event_count = jack_midi_get_event_count(port_buf);

	jack_midi_event_get(&in_event, port_buf, 0);
	for(i=0; i<nframes; i++)
	{
		if((in_event.time == i) && (event_index < event_count))
		{
			// lmms is setup to parse bytes coming from a device
			// parse it byte by byte as it expects
			for(b=0;b<in_event.size;b++)
				parseData( *(in_event.buffer + b) );

			event_index++;
			if(event_index < event_count)
				jack_midi_event_get(&in_event, port_buf, event_index);
		}
	}
}
예제 #16
0
int
jack_process(jack_nframes_t nframes, void *arg)
{
	int chn;
	size_t i;
	jack_thread_info_t *info = (jack_thread_info_t *) arg;

	/* Do nothing until we're ready to begin. */
	if ((!info->can_process) || (!info->can_capture))
		return 0;

	for (chn = 0; chn < nports; chn++)
		in[chn] = (jack_default_audio_sample_t*)
			jack_port_get_buffer(ports[chn], nframes);

	//interleave data
	for (i = 0; i < nframes; i++) {
		for (chn = 0; chn < nports; chn++) {
			if (jack_ringbuffer_write(rb, (char *)(in[chn]+i), sample_size)
				 < sample_size) {
				overruns++;
				if (overruns % 10000 == 0) {
					fprintf(stderr, "overruns [%u]\n", overruns);
				}
			}
		}
	}

	//notify detect_note that data is ready for reading
	if (pthread_mutex_trylock(&detect_lock) == 0) {
		pthread_cond_signal(&data_ready);
		pthread_mutex_unlock(&detect_lock);
	}

	return 0;
}
예제 #17
0
/* this is the callback of jack. This should RT-safe.
 */
static int
jack_process_cb (jack_nframes_t nframes, void *arg)
{
  GstJackAudioSink *sink;
  GstRingBuffer *buf;
  gint readseg, len;
  guint8 *readptr;
  gint i, j, flen, channels;
  sample_t *data;

  buf = GST_RING_BUFFER_CAST (arg);
  sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf));

  channels = buf->spec.channels;

  /* get target buffers */
  for (i = 0; i < channels; i++) {
    sink->buffers[i] =
        (sample_t *) jack_port_get_buffer (sink->ports[i], nframes);
  }

  if (gst_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) {
    flen = len / channels;

    /* the number of samples must be exactly the segment size */
    if (nframes * sizeof (sample_t) != flen)
      goto wrong_size;

    GST_DEBUG_OBJECT (sink, "copy %d frames: %p, %d bytes, %d channels",
        nframes, readptr, flen, channels);
    data = (sample_t *) readptr;

    /* the samples in the ringbuffer have the channels interleaved, we need to
     * deinterleave into the jack target buffers */
    for (i = 0; i < nframes; i++) {
      for (j = 0; j < channels; j++) {
        sink->buffers[j][i] = *data++;
      }
    }

    /* clear written samples in the ringbuffer */
    gst_ring_buffer_clear (buf, readseg);

    /* we wrote one segment */
    gst_ring_buffer_advance (buf, 1);
  } else {
    GST_DEBUG_OBJECT (sink, "write %d frames silence", nframes);
    /* We are not allowed to read from the ringbuffer, write silence to all
     * jack output buffers */
    for (i = 0; i < channels; i++) {
      memset (sink->buffers[i], 0, nframes * sizeof (sample_t));
    }
  }
  return 0;

  /* ERRORS */
wrong_size:
  {
    GST_ERROR_OBJECT (sink, "nbytes (%d) != flen (%d)",
        (gint) (nframes * sizeof (sample_t)), flen);
    return 1;
  }
}
예제 #18
0
static int
a2j_process (jack_nframes_t nframes, void * arg)
{
	struct a2j* self = (struct a2j *) arg;
	struct a2j_stream * stream_ptr;
	int i;
	struct a2j_port ** port_ptr;
	struct a2j_port * port;

	if (g_freewheeling) {
		return 0;
	}

	self->cycle_start = jack_last_frame_time (self->jack_client);
	
	stream_ptr = &self->stream;
	a2j_add_ports (stream_ptr);
	
	// process ports
	
	for (i = 0 ; i < PORT_HASH_SIZE ; i++) {

		port_ptr = &stream_ptr->port_hash[i];

		while (*port_ptr != NULL) {

			struct a2j_alsa_midi_event ev;
			jack_nframes_t now;
			jack_nframes_t one_period;
			char *ev_buf;
				
			port = *port_ptr;
			
			if (port->is_dead) {
				if (jack_ringbuffer_write_space (self->port_del) >= sizeof(port_ptr)) {
				
					a2j_debug("jack: removed port %s", port->name);
					*port_ptr = port->next;
					jack_ringbuffer_write (self->port_del, (char*)&port, sizeof(port));
				} else {
					a2j_error ("port deletion lost - no space in event buffer!");
				}

				port_ptr = &port->next;
				continue;
			}

			port->jack_buf = jack_port_get_buffer(port->jack_port, nframes);
				
			/* grab data queued by the ALSA input thread and write it into the JACK
			   port buffer. it will delivered during the JACK period that this
			   function is called from.
			*/
				
			/* first clear the JACK port buffer in preparation for new data 
			 */
				
			// a2j_debug ("PORT: %s process input", jack_port_name (port->jack_port));
				
			jack_midi_clear_buffer (port->jack_buf);
				
			now = jack_frame_time (self->jack_client);
			one_period = jack_get_buffer_size (self->jack_client);
				
			while (jack_ringbuffer_peek (port->inbound_events, (char*)&ev, sizeof(ev) ) == sizeof(ev) ) {
					
				jack_midi_data_t* buf;
				jack_nframes_t offset;
					
				if (ev.time >= self->cycle_start) {
					break;
				}
					
				//jack_ringbuffer_read_advance (port->inbound_events, sizeof (ev));
				ev_buf = (char *) alloca( sizeof(ev) + ev.size );
					
				if (jack_ringbuffer_peek (port->inbound_events, ev_buf, sizeof(ev) + ev.size ) != sizeof(ev) + ev.size)
					break;
					
				offset = self->cycle_start - ev.time;
				if (offset > one_period) {
					/* from a previous cycle, somehow. cram it in at the front */
					offset = 0;
				} else {
					/* offset from start of the current cycle */
					offset = one_period - offset;
				}
					
				a2j_debug ("event at %d offset %d", ev.time, offset);
					
				/* make sure there is space for it */
					
				buf = jack_midi_event_reserve (port->jack_buf, offset, ev.size);
					
				if (buf) {
					/* grab the event */
					memcpy( buf, ev_buf + sizeof(ev), ev.size );
				} else {
					/* throw it away (no space) */
					a2j_error ("threw away MIDI event - not reserved at time %d", ev.time);
				}
				jack_ringbuffer_read_advance (port->inbound_events, sizeof(ev) + ev.size);
					
				a2j_debug("input on %s: sucked %d bytes from inbound at %d", jack_port_name (port->jack_port), ev.size, ev.time);
			}
			
			port_ptr = &port->next;
		}
	}

	return 0;
}
예제 #19
0
파일: jackio.c 프로젝트: UIKit0/calfbox
static int process_cb(jack_nframes_t nframes, void *arg)
{
    struct cbox_jack_io_impl *jii = arg;
    struct cbox_io *io = jii->ioi.pio;
    struct cbox_io_callbacks *cb = io->cb;
    
    io->io_env.buffer_size = nframes;
    for (int i = 0; i < io->io_env.input_count; i++)
        io->input_buffers[i] = jack_port_get_buffer(jii->inputs[i], nframes);
    for (int i = 0; i < io->io_env.output_count; i++)
    {
        io->output_buffers[i] = jack_port_get_buffer(jii->outputs[i], nframes);
        if (!io->output_buffers[i])
            continue;
        for (int j = 0; j < nframes; j ++)
            io->output_buffers[i][j] = 0.f;
    }
    for (GSList *p = io->midi_inputs; p; p = p->next)
    {
        struct cbox_jack_midi_input *input = p->data;
        if (input->hdr.output_set || input->hdr.enable_appsink)
        {
            copy_midi_data_to_buffer(input->port, io->io_env.buffer_size, &input->hdr.buffer);
            if (input->hdr.enable_appsink)
                cbox_midi_appsink_supply(&input->hdr.appsink, &input->hdr.buffer);
        }
        else
            cbox_midi_buffer_clear(&input->hdr.buffer);
    }
    if (cb->on_transport_sync)
    {
        jack_transport_state_t state = jack_transport_query(jii->client, NULL);
        if (state != jii->last_transport_state)
        {
            jack_position_t pos;
            jack_transport_query(jii->client, &pos);
            if (jii->debug_transport)
                g_message("JACK transport: incoming state change, state = %s, last state = %s, pos = %d\n", transport_state_names[state], transport_state_names[(int)jii->last_transport_state], (int)pos.frame);
            if (state == JackTransportStopped)
            {
                if (cb->on_transport_sync(cb->user_data, ts_stopping, pos.frame))
                    jii->last_transport_state = state;
            }
            else
            if (state == JackTransportRolling && jii->last_transport_state == JackTransportStarting)
            {
                if (cb->on_transport_sync(cb->user_data, ts_rolling, pos.frame))
                    jii->last_transport_state = state;
            }
            else
                jii->last_transport_state = state;
        }
    }
    cb->process(cb->user_data, io, nframes);
    for (int i = 0; i < io->io_env.input_count; i++)
        io->input_buffers[i] = NULL;
    for (int i = 0; i < io->io_env.output_count; i++)
        io->output_buffers[i] = NULL;
    for (GSList *p = io->midi_outputs; p; p = g_slist_next(p))
    {
        struct cbox_jack_midi_output *midiout = p->data;

        void *pbuf = jack_port_get_buffer(midiout->port, nframes);
        jack_midi_clear_buffer(pbuf);

        cbox_midi_merger_render(&midiout->hdr.merger);
        if (midiout->hdr.buffer.count)
        {
            uint8_t tmp_data[4];
            for (int i = 0; i < midiout->hdr.buffer.count; i++)
            {
                const struct cbox_midi_event *event = cbox_midi_buffer_get_event(&midiout->hdr.buffer, i);
                const uint8_t *pdata = cbox_midi_event_get_data(event);
                if ((pdata[0] & 0xF0) == 0x90 && !pdata[2] && event->size == 3)
                {
                    tmp_data[0] = pdata[0] & ~0x10;
                    tmp_data[1] = pdata[1];
                    tmp_data[2] = pdata[2];
                    pdata = tmp_data;
                }
                if (jack_midi_event_write(pbuf, event->time, pdata, event->size))
                {
                    g_warning("MIDI buffer overflow on JACK output port '%s'", midiout->hdr.name);
                    break;
                }
            }
        }
    }
    return 0;
}
예제 #20
0
파일: s_audio_jack.c 프로젝트: Angeldude/pd
static int process (jack_nframes_t nframes, void *arg)
{
    int j;
    jack_default_audio_sample_t *out, *in;
        
    if (nframes > JACK_OUT_MAX) jack_out_max = nframes;
    else jack_out_max = JACK_OUT_MAX;
    if (jack_filled >= nframes)
    {
        if (jack_filled != nframes) fprintf(stderr,"Partial read");
        /* hmm, how to find out whether 't_sample' and
           'jack_default_audio_sample_t' are actually the same type? */
        if(sizeof(t_sample)==sizeof(jack_default_audio_sample_t)) 
        {
            for (j = 0; j < sys_outchannels;  j++)
            {
                out = jack_port_get_buffer (output_port[j], nframes);
                memcpy(out, jack_outbuf + (j * BUF_JACK),
                    sizeof(jack_default_audio_sample_t) * nframes);
            }
            for (j = 0; j < sys_inchannels; j++)
            {
                in = jack_port_get_buffer( input_port[j], nframes);
                memcpy(jack_inbuf + (j * BUF_JACK), in,
                    sizeof(jack_default_audio_sample_t) * nframes);
            }
        } 
        else
        {
            unsigned int frame=0;
            t_sample*data;
            for (j = 0; j < sys_outchannels;  j++)
            {
                out = jack_port_get_buffer (output_port[j], nframes);
                data=jack_outbuf + (j * BUF_JACK);
                for(frame=0; frame<nframes; frame++)
                {
                    *out++=*data++;
                }
            }
            for (j = 0; j < sys_inchannels; j++)
            {
                in = jack_port_get_buffer( input_port[j], nframes);
                data=jack_inbuf+(j*BUF_JACK);
                for(frame=0; frame<nframes; frame++)
                {
                  *data++=*in++;
                }
            }
        }
        jack_filled -= nframes;
    }
    else
    { /* PD could not keep up ! */
        if (jack_started) jack_dio_error = 1;
        for (j = 0; j < outport_count;  j++)
        {
            out = jack_port_get_buffer (output_port[j], nframes);
            memset(out, 0, sizeof (float) * nframes); 
        }
        memset(jack_outbuf,0,sizeof(jack_outbuf));
        jack_filled = 0;
    }
    pthread_cond_broadcast(&jack_sem);
    return 0;
}
예제 #21
0
파일: alsa_out.c 프로젝트: recri/keyer
/**
 * The process callback for this JACK application.
 * It is called by JACK at the appropriate times.
 */
int process (jack_nframes_t nframes, void *arg) {

    int rlen;
    int err;
    snd_pcm_sframes_t delay = target_delay;
    int i;

    delay = (num_periods*period_size)-snd_pcm_avail( alsa_handle ) ;

    delay -= jack_frames_since_cycle_start( client );
    // Do it the hard way.
    // this is for compensating xruns etc...

    if( delay > (target_delay+max_diff) ) {
	snd_pcm_rewind( alsa_handle, delay - target_delay );
	output_new_delay = (int) delay;

	delay = target_delay;

	// Set the resample_rate... we need to adjust the offset integral, to do this.
	// first look at the PI controller, this code is just a special case, which should never execute once
	// everything is swung in. 
	offset_integral = - (resample_mean - static_resample_factor) * catch_factor * catch_factor2;
	// Also clear the array. we are beginning a new control cycle.
	for( i=0; i<smooth_size; i++ )
		offset_array[i] = 0.0;
    }
    if( delay < (target_delay-max_diff) ) {

	output_new_delay = (int) delay;

	while ((target_delay-delay) > 0) {
	    snd_pcm_uframes_t to_write = ((target_delay-delay) > 512) ? 512 : (target_delay-delay);
	    snd_pcm_writei( alsa_handle, tmpbuf, to_write );
	    delay += to_write;
	}

	delay = target_delay;

	// Set the resample_rate... we need to adjust the offset integral, to do this.
	offset_integral = - (resample_mean - static_resample_factor) * catch_factor * catch_factor2;
	// Also clear the array. we are beginning a new control cycle.
	for( i=0; i<smooth_size; i++ )
		offset_array[i] = 0.0;
    }
    /* ok... now we should have target_delay +- max_diff on the alsa side.
     *
     * calculate the number of frames, we want to get.
     */

    double offset = delay - target_delay;

    // Save offset.
    offset_array[(offset_differential_index++)% smooth_size ] = offset;

    // Build the mean of the windowed offset array
    // basically fir lowpassing.
    double smooth_offset = 0.0;
    for( i=0; i<smooth_size; i++ )
	    smooth_offset +=
		    offset_array[ (i + offset_differential_index-1) % smooth_size] * window_array[i];
    smooth_offset /= (double) smooth_size;

    // this is the integral of the smoothed_offset
    offset_integral += smooth_offset;

    // Clamp offset.
    // the smooth offset still contains unwanted noise
    // which would go straigth onto the resample coeff.
    // it only used in the P component and the I component is used for the fine tuning anyways.
    if( fabs( smooth_offset ) < pclamp )
	    smooth_offset = 0.0;

    // ok. now this is the PI controller. 
    // u(t) = K * ( e(t) + 1/T \int e(t') dt' )
    // K = 1/catch_factor and T = catch_factor2
    double current_resample_factor = static_resample_factor - smooth_offset / (double) catch_factor - offset_integral / (double) catch_factor / (double)catch_factor2;

    // now quantize this value around resample_mean, so that the noise which is in the integral component doesnt hurt.
    current_resample_factor = floor( (current_resample_factor - resample_mean) * controlquant + 0.5 ) / controlquant + resample_mean;

    // Output "instrumentatio" gonna change that to real instrumentation in a few.
    output_resampling_factor = (float) current_resample_factor;
    output_diff = (float) smooth_offset;
    output_integral = (float) offset_integral;
    output_offset = (float) offset;

    // Clamp a bit.
    if( current_resample_factor < resample_lower_limit ) current_resample_factor = resample_lower_limit;
    if( current_resample_factor > resample_upper_limit ) current_resample_factor = resample_upper_limit;

    // Now Calculate how many samples we need.
    rlen = ceil( ((double)nframes) * current_resample_factor )+2;
    assert( rlen > 2 );

    // Calculate resample_mean so we can init ourselves to saner values.
    resample_mean = 0.9999 * resample_mean + 0.0001 * current_resample_factor;
    /*
     * now this should do it...
     */

    outbuf = alloca( rlen * formats[format].sample_size * num_channels );

    resampbuf = alloca( rlen * sizeof( float ) );
    /*
     * render jack ports to the outbuf...
     */

    int chn = 0;
    JSList *node = playback_ports;
    JSList *src_node = playback_srcs;
    SRC_DATA src;

    while ( node != NULL)
    {
	jack_port_t *port = (jack_port_t *) node->data;
	float *buf = jack_port_get_buffer (port, nframes);

	SRC_STATE *src_state = src_node->data;

	src.data_in = buf;
	src.input_frames = nframes;

	src.data_out = resampbuf;
	src.output_frames = rlen;
	src.end_of_input = 0;

	src.src_ratio = current_resample_factor;

	src_process( src_state, &src );

	formats[format].jack_to_soundcard( outbuf + format[formats].sample_size * chn, resampbuf, src.output_frames_gen, num_channels*format[formats].sample_size, NULL);

	src_node = jack_slist_next (src_node);
	node = jack_slist_next (node);
	chn++;
    }

    // now write the output...
again:
  err = snd_pcm_writei(alsa_handle, outbuf, src.output_frames_gen);
  //err = snd_pcm_writei(alsa_handle, outbuf, src.output_frames_gen);
  if( err < 0 ) {
      printf( "err = %d\n", err );
      if (xrun_recovery(alsa_handle, err) < 0) {
	  printf("Write error: %s\n", snd_strerror(err));
	  exit(EXIT_FAILURE);
      }
      goto again;
  }

    return 0;      
}
 float* AudioOutputDeviceJack::AudioChannelJack::CreateJackPort(uint ChannelNr, AudioOutputDeviceJack* pDevice) throw (AudioOutputException) {
     String port_id = ToString(ChannelNr);
     hJackPort = jack_port_register(pDevice->hJackClient, port_id.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
     if (!hJackPort) throw AudioOutputException("Jack: Cannot register Jack output port.");
     return (float*) jack_port_get_buffer(hJackPort, pDevice->uiMaxSamplesPerCycle);
 }
예제 #23
0
float* JackOutput::getOut_R()
{
	jack_default_audio_sample_t *out = ( jack_default_audio_sample_t * ) jack_port_get_buffer ( output_port_2, jack_server_bufferSize );
	return out;
}
예제 #24
0
TSampleBuffer TJackAudioPort::GetBuffer(jack_nframes_t nframes)
{
    return TSampleBuffer(
            static_cast<jack_default_audio_sample_t*>(jack_port_get_buffer(Port,
                    nframes)), nframes);
}
예제 #25
0
파일: jack.c 프로젝트: rknLA/rove
static int process(jack_nframes_t nframes, void *arg) {
	static int quantize_frames = 0;

#define on_quantize_boundary() (!quantize_frames)

	jack_default_audio_sample_t *out_l;
	jack_default_audio_sample_t *out_r;
	jack_default_audio_sample_t *in_l;
	jack_default_audio_sample_t *in_r;

	jack_nframes_t until_quantize, rate, nframes_left, nframes_offset, i;
	int j, group_count, next_bit;
	uint16_t qfield;

	jack_default_audio_sample_t *buffers[2];

	rove_group_t *g;
	rove_file_t *f;

	group_count = state.group_count;

	rate = jack_get_sample_rate(state.client);

	/* initialize each group's output buffers and zero them */
	for( i = 0; i < group_count; i++ ) {
		g = &state.groups[i];
		
		g->output_buffer_l = out_l = jack_port_get_buffer(g->outport_l, nframes);
		g->output_buffer_r = out_r = jack_port_get_buffer(g->outport_r, nframes);
		
		for( j = 0; j < nframes; j++ )
			out_l[j] = out_r[j] = 0;
	}

	for( nframes_offset = 0; nframes > 0; nframes -= nframes_left ) {
		if( on_quantize_boundary() ) {
			for( j = 0; j < group_count; j++ ) {
				g = &state.groups[j];
				f = g->active_loop;

				process_file(f);
			}

			qfield = state.monome->quantize_field >> 1;

			for( j = 0; qfield; qfield >>= next_bit ) {
				next_bit = ffs(qfield);
				j += next_bit;

				f = (rove_file_t *) state.monome->callbacks[j].data;
				process_file(f);
			}
		}

		until_quantize   = (state.snap_delay - quantize_frames);
		nframes_left     = MIN(until_quantize, nframes);
		quantize_frames += nframes_left;

		if( quantize_frames >= state.snap_delay - 1 )
			quantize_frames = 0;

		for( j = 0; j < group_count; j++ ) {
			g = &state.groups[j];

			if( !(f = g->active_loop) )
				continue;

			if( !rove_file_is_active(f) )
				continue;

			/* will eventually become an array of arbitrary size for better multichannel support */
			buffers[0] = g->output_buffer_l + nframes_offset;
			buffers[1] = g->output_buffer_r + nframes_offset;

			if( f->process_cb )
				f->process_cb(f, buffers, 2, nframes_left, rate);
		}

		nframes_offset += nframes_left;
	}

	out_l = jack_port_get_buffer(outport_l, nframes_offset);
	out_r = jack_port_get_buffer(outport_r, nframes_offset);
	in_l = jack_port_get_buffer(group_mix_inport_l, nframes_offset);
	in_r = jack_port_get_buffer(group_mix_inport_r, nframes_offset);

	memcpy(out_l, in_l, sizeof(jack_default_audio_sample_t) * nframes_offset);
	memcpy(out_r, in_r, sizeof(jack_default_audio_sample_t) * nframes_offset);

	return 0;
}
예제 #26
0
// rt
static int
_process(jack_nframes_t nsamples, void *data)
{
	prog_t *handle = data;
	bin_t *bin = &handle->bin;
	sp_app_t *app = bin->app;

#if defined(JACK_HAS_CYCLE_TIMES)
	clock_gettime(CLOCK_REALTIME, &handle->ntp);
	handle->ntp.tv_sec += JAN_1970; // convert NTP to OSC time
	jack_nframes_t offset = jack_frames_since_cycle_start(handle->client);

	float T;
	jack_get_cycle_times(handle->client, &handle->cycle.cur_frames,
		&handle->cycle.cur_usecs, &handle->cycle.nxt_usecs, &T);
	(void)T;
	
	handle->cycle.ref_frames = handle->cycle.cur_frames + offset;

	// calculate apparent period
	double diff = 1e-6 * (handle->cycle.nxt_usecs - handle->cycle.cur_usecs);

	// calculate apparent samples per period
	handle->cycle.dT = nsamples / diff;
	handle->cycle.dTm1 = 1.0 / handle->cycle.dT;
#endif

	// get transport position
	jack_position_t pos;
	jack_transport_state_t rolling = jack_transport_query(handle->client, &pos) == JackTransportRolling;
	int trans_changed = (rolling != handle->trans.rolling)
		|| (pos.frame != handle->trans.frame)
		|| (pos.beats_per_bar != handle->trans.beats_per_bar)
		|| (pos.beat_type != handle->trans.beat_type)
		|| (pos.ticks_per_beat != handle->trans.ticks_per_beat)
		|| (pos.beats_per_minute != handle->trans.beats_per_minute);

	const size_t sample_buf_size = sizeof(float) * nsamples;
	const sp_app_system_source_t *sources = sp_app_get_system_sources(app);
	const sp_app_system_sink_t *sinks = sp_app_get_system_sinks(app);

	if(sp_app_bypassed(app)) // aka loading state
	{
		//fprintf(stderr, "app is bypassed\n");

		// clear output buffers
		for(const sp_app_system_sink_t *sink=sinks;
			sink->type != SYSTEM_PORT_NONE;
			sink++)
		{
			switch(sink->type)
			{
				case SYSTEM_PORT_NONE:
				case SYSTEM_PORT_CONTROL:
				case SYSTEM_PORT_COM:
					break;

				case SYSTEM_PORT_AUDIO:
				case SYSTEM_PORT_CV:
				{
					void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples);
					memset(out_buf, 0x0, sample_buf_size);
					break;
				}
				case SYSTEM_PORT_MIDI:
				case SYSTEM_PORT_OSC:
				{
					void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples);
					jack_midi_clear_buffer(out_buf);
					break;
				}
			}
		}

		bin_process_pre(bin, nsamples, true);
		bin_process_post(bin);

		return 0;
	}

	//TODO use __builtin_assume_aligned

	// fill input buffers
	for(const sp_app_system_source_t *source=sources;
		source->type != SYSTEM_PORT_NONE;
		source++)
	{
		switch(source->type)
		{
			case SYSTEM_PORT_NONE:
			case SYSTEM_PORT_CONTROL:
				break;

			case SYSTEM_PORT_AUDIO:
			case SYSTEM_PORT_CV:
			{
				const void *in_buf = jack_port_get_buffer(source->sys_port, nsamples);
				memcpy(source->buf, in_buf, sample_buf_size);
				break;
			}
			case SYSTEM_PORT_MIDI:
			{
				void *in_buf = jack_port_get_buffer(source->sys_port, nsamples);
				void *seq_in = source->buf;

				LV2_Atom_Forge *forge = &handle->forge;
				LV2_Atom_Forge_Frame frame;
				lv2_atom_forge_set_buffer(forge, seq_in, SEQ_SIZE);
				LV2_Atom_Forge_Ref ref = lv2_atom_forge_sequence_head(forge, &frame, 0);

				if(ref && trans_changed)
					ref = _trans_event(handle, forge, rolling, &pos);

				int n = jack_midi_get_event_count(in_buf);
				for(int i=0; i<n; i++)
				{
					jack_midi_event_t mev;
					jack_midi_event_get(&mev, in_buf, i);

					//add jack midi event to in_buf
					if(ref)
						ref = lv2_atom_forge_frame_time(forge, mev.time);
					if(ref)
						ref = lv2_atom_forge_atom(forge, mev.size, handle->midi_MidiEvent);
					if(ref)
						ref = lv2_atom_forge_raw(forge, mev.buffer, mev.size);
					if(ref)
						lv2_atom_forge_pad(forge, mev.size);
				}
				if(ref)
					lv2_atom_forge_pop(forge, &frame);
				else
					lv2_atom_sequence_clear(seq_in);

				break;
			}

			case SYSTEM_PORT_OSC:
			{
				void *in_buf = jack_port_get_buffer(source->sys_port, nsamples);
				void *seq_in = source->buf;

				LV2_Atom_Forge *forge = &handle->forge;
				LV2_Atom_Forge_Frame frame;
				lv2_atom_forge_set_buffer(forge, seq_in, SEQ_SIZE);
				LV2_Atom_Forge_Ref ref = lv2_atom_forge_sequence_head(forge, &frame, 0);

				if(ref && trans_changed)
					ref = _trans_event(handle, forge, rolling, &pos);

				int n = jack_midi_get_event_count(in_buf);	
				for(int i=0; i<n; i++)
				{
					jack_midi_event_t mev;
					jack_midi_event_get(&mev, (void *)in_buf, i);

					//add jack osc event to in_buf
					if(osc_check_packet(mev.buffer, mev.size))
					{
						if(ref)
							ref = lv2_atom_forge_frame_time(forge, mev.time);
						handle->ref = ref;
						osc_dispatch_method(mev.buffer, mev.size, methods,
							_bundle_in, _bundle_out, handle);
						ref = handle->ref;
					}
				}
				if(ref)
					lv2_atom_forge_pop(forge, &frame);
				else
					lv2_atom_sequence_clear(seq_in);

				break;
			}

			case SYSTEM_PORT_COM:
			{
				void *seq_in = source->buf;

				LV2_Atom_Forge *forge = &handle->forge;
				LV2_Atom_Forge_Frame frame;
				lv2_atom_forge_set_buffer(forge, seq_in, SEQ_SIZE);
				LV2_Atom_Forge_Ref ref = lv2_atom_forge_sequence_head(forge, &frame, 0);

				const LV2_Atom_Object *obj;
				size_t size;
				while((obj = varchunk_read_request(bin->app_from_com, &size)))
				{
					if(ref)
						ref = lv2_atom_forge_frame_time(forge, 0);
					if(ref)
						ref = lv2_atom_forge_raw(forge, obj, size);
					if(ref)
						lv2_atom_forge_pad(forge, size);

					varchunk_read_advance(bin->app_from_com);
				}
				if(ref)
					lv2_atom_forge_pop(forge, &frame);
				else
					lv2_atom_sequence_clear(seq_in);

				break;
			}
		}
	}

	// update transport state
	handle->trans.rolling = rolling;
	handle->trans.frame = rolling
		? handle->trans.frame + nsamples
		: pos.frame;
	handle->trans.beats_per_bar = pos.beats_per_bar;
	handle->trans.beat_type = pos.beat_type;
	handle->trans.ticks_per_beat = pos.ticks_per_beat;
	handle->trans.beats_per_minute = pos.beats_per_minute;

	bin_process_pre(bin, nsamples, false);

	// fill output buffers
	for(const sp_app_system_sink_t *sink=sinks;
		sink->type != SYSTEM_PORT_NONE;
		sink++)
	{
		switch(sink->type)
		{
			case SYSTEM_PORT_NONE:
			case SYSTEM_PORT_CONTROL:
				break;

			case SYSTEM_PORT_AUDIO:
			case SYSTEM_PORT_CV:
			{
				void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples);
				memcpy(out_buf, sink->buf, sample_buf_size);
				break;
			}
			case SYSTEM_PORT_MIDI:
			{
				void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples);
				const LV2_Atom_Sequence *seq_out = sink->buf;

				// fill midi output buffer
				jack_midi_clear_buffer(out_buf);
				if(seq_out)
				{
					LV2_ATOM_SEQUENCE_FOREACH(seq_out, ev)
					{
						const LV2_Atom *atom = &ev->body;

						if(atom->type != handle->midi_MidiEvent)
							continue; // ignore non-MIDI events

						jack_midi_event_write(out_buf, ev->time.frames,
							LV2_ATOM_BODY_CONST(atom), atom->size);
					}
				}

				break;
			}

			case SYSTEM_PORT_OSC:
			{
				void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples);
				const LV2_Atom_Sequence *seq_out = sink->buf;

				// fill midi output buffer
				jack_midi_clear_buffer(out_buf);
				if(seq_out)
				{
					LV2_ATOM_SEQUENCE_FOREACH(seq_out, ev)
					{
						const LV2_Atom_Object *obj = (const LV2_Atom_Object *)&ev->body;

						handle->osc_ptr = handle->osc_buf;
						handle->osc_end = handle->osc_buf + OSC_SIZE;

						osc_atom_event_unroll(&handle->oforge, obj, _bundle_push_cb,
							_bundle_pop_cb, _message_cb, handle);

						size_t size = handle->osc_ptr
							? handle->osc_ptr - handle->osc_buf
							: 0;

						if(size)
						{
							jack_midi_event_write(out_buf, ev->time.frames,
								handle->osc_buf, size);
						}
					}
				}

				break;
			}

			case SYSTEM_PORT_COM:
			{
				const LV2_Atom_Sequence *seq_out = sink->buf;

				LV2_ATOM_SEQUENCE_FOREACH(seq_out, ev)
				{
					const LV2_Atom *atom = (const LV2_Atom *)&ev->body;

					// try do process events directly
					bin->advance_ui = sp_app_from_ui(bin->app, atom);
					if(!bin->advance_ui) // queue event in ringbuffer instead
					{
						//fprintf(stderr, "plugin ui direct is blocked\n");

						void *ptr;
						size_t size = lv2_atom_total_size(atom);
						if((ptr = varchunk_write_request(bin->app_from_app, size)))
						{
							memcpy(ptr, atom, size);
							varchunk_write_advance(bin->app_from_app, size);
						}
						else
						{
							//fprintf(stderr, "app_from_ui ringbuffer full\n");
							//FIXME
						}
					}
				}
				break;
			}
		}
	}
	
	bin_process_post(bin);

	return 0;
}
예제 #27
0
파일: jackmidi.cpp 프로젝트: ViktorNova/los
bool MidiJackDevice::queueEvent(const MidiPlayEvent& e)
{
    if (!_out_client_jackport) // p3.3.55
        return false;
    void* pb = jack_port_get_buffer(_out_client_jackport, segmentSize); // p3.3.55

    int frameOffset = audio->getFrameOffset();
    unsigned pos = audio->pos().frame();
    int ft = e.time() - frameOffset - pos;

    if (ft < 0)
        ft = 0;
    if (ft >= (int) segmentSize)
    {
        if(debugMsg)
            printf("MidiJackDevice::queueEvent: Event time:%d out of range. offset:%d ft:%d (seg=%d)\n", e.time(), frameOffset, ft, segmentSize);
        if (ft > (int) segmentSize)
            ft = segmentSize - 1;
    }

#ifdef JACK_MIDI_DEBUG
    printf("MidiJackDevice::queueEvent time:%d type:%d ch:%d A:%d B:%d\n", e.time(), e.type(), e.channel(), e.dataA(), e.dataB());
#endif

    switch (e.type())
    {
        case ME_NOTEON:
        case ME_NOTEOFF:
        case ME_POLYAFTER:
        case ME_CONTROLLER:
        case ME_PITCHBEND:
        {
#ifdef JACK_MIDI_DEBUG
            printf("MidiJackDevice::queueEvent note on/off polyafter controller or pitch\n");
#endif

            unsigned char* p = jack_midi_event_reserve(pb, ft, 3);
            if (p == 0)
            {
                #ifdef JACK_MIDI_DEBUG
                fprintf(stderr, "MidiJackDevice::queueEvent NOTE CONTROL PAT or PB: buffer overflow, stopping until next cycle\n");
                #endif
                return false;
            }
            p[0] = e.type() | e.channel();
            p[1] = e.dataA();
            p[2] = e.dataB();
        }
            break;

        case ME_PROGRAM:
        case ME_AFTERTOUCH:
        {
#ifdef JACK_MIDI_DEBUG
            printf("MidiJackDevice::queueEvent program or aftertouch\n");
#endif

            unsigned char* p = jack_midi_event_reserve(pb, ft, 2);
            if (p == 0)
            {
                #ifdef JACK_MIDI_DEBUG
                fprintf(stderr, "MidiJackDevice::queueEvent PROG or AT: buffer overflow, stopping until next cycle\n");
                #endif
                return false;
            }
            p[0] = e.type() | e.channel();
            p[1] = e.dataA();
        }
            break;
        case ME_SYSEX:
        {
#ifdef JACK_MIDI_DEBUG
            printf("MidiJackDevice::queueEvent sysex\n");
#endif

            const unsigned char* data = e.data();
            int len = e.len();
            unsigned char* p = jack_midi_event_reserve(pb, ft, len + 2);
            if (p == 0)
            {
                fprintf(stderr, "MidiJackDevice::queueEvent ME_SYSEX: buffer overflow, sysex too big, event lost\n");
                return true;
            }
            p[0] = 0xf0;
            p[len + 1] = 0xf7;
            memcpy(p + 1, data, len);
        }
            break;
        case ME_SONGPOS:
        case ME_CLOCK:
        case ME_START:
        case ME_CONTINUE:
        case ME_STOP:
            if(debugMsg)
                printf("MidiJackDevice::queueEvent: event type %x not supported\n", e.type());
            return true;
            break;
    }

    return true;
}
예제 #28
0
static int jack_process (jack_nframes_t frames, void * data)
{
	mlt_filter filter = (mlt_filter) data;
 	mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
	int channels = mlt_properties_get_int( properties, "channels" );
	int frame_size = mlt_properties_get_int( properties, "_samples" ) * sizeof(float);
	int sync = mlt_properties_get_int( properties, "_sync" );
	int err = 0;
	int i;
	static int total_size = 0;
  
	jack_ringbuffer_t **output_buffers = mlt_properties_get_data( properties, "output_buffers", NULL );
	if ( output_buffers == NULL )
		return 0;
	jack_ringbuffer_t **input_buffers = mlt_properties_get_data( properties, "input_buffers", NULL );
	jack_port_t **jack_output_ports = mlt_properties_get_data( properties, "jack_output_ports", NULL );
	jack_port_t **jack_input_ports = mlt_properties_get_data( properties, "jack_input_ports", NULL );
	float **jack_output_buffers = mlt_properties_get_data( properties, "jack_output_buffers", NULL );
	float **jack_input_buffers = mlt_properties_get_data( properties, "jack_input_buffers", NULL );
	pthread_mutex_t *output_lock = mlt_properties_get_data( properties, "output_lock", NULL );
	pthread_cond_t *output_ready = mlt_properties_get_data( properties, "output_ready", NULL );
	
	for ( i = 0; i < channels; i++ )
	{
		size_t jack_size = ( frames * sizeof(float) );
		size_t ring_size;
		
		// Send audio through out port
		jack_output_buffers[i] = jack_port_get_buffer( jack_output_ports[i], frames );
		if ( ! jack_output_buffers[i] )
		{
			mlt_log_error( MLT_FILTER_SERVICE(filter), "no buffer for output port %d\n", i );
			err = 1;
			break;
		}
		ring_size = jack_ringbuffer_read_space( output_buffers[i] );
		jack_ringbuffer_read( output_buffers[i], ( char * )jack_output_buffers[i], ring_size < jack_size ? ring_size : jack_size );
		if ( ring_size < jack_size )
			memset( &jack_output_buffers[i][ring_size], 0, jack_size - ring_size );
		
		// Return audio through in port
		jack_input_buffers[i] = jack_port_get_buffer( jack_input_ports[i], frames );
		if ( ! jack_input_buffers[i] )
		{
			mlt_log_error( MLT_FILTER_SERVICE(filter), "no buffer for input port %d\n", i );
			err = 1;
			break;
		}
		
		// Do not start returning audio until we have sent first mlt frame
		if ( sync && i == 0 && frame_size > 0 )
			total_size += ring_size;
		mlt_log_debug( MLT_FILTER_SERVICE(filter), "sync %d frame_size %d ring_size %zu jack_size %zu\n", sync, frame_size, ring_size, jack_size );
		
		if ( ! sync || ( frame_size > 0  && total_size >= frame_size ) )
		{
			ring_size = jack_ringbuffer_write_space( input_buffers[i] );
			jack_ringbuffer_write( input_buffers[i], ( char * )jack_input_buffers[i], ring_size < jack_size ? ring_size : jack_size );
			
			if ( sync )
			{
				// Tell mlt that audio is available
				pthread_mutex_lock( output_lock);
				pthread_cond_signal( output_ready );
				pthread_mutex_unlock( output_lock);

				// Clear sync phase
				mlt_properties_set_int( properties, "_sync", 0 );
			}
		}
	}

	// Often jackd does not send the stopped event through the JackSyncCallback
	jack_client_t *jack_client = mlt_properties_get_data( properties, "jack_client", NULL );
	jack_position_t jack_pos;
	jack_transport_state_t state = jack_transport_query( jack_client, &jack_pos );
	int transport_state = mlt_properties_get_int( properties, "_transport_state" );
	if ( state != transport_state )
	{
		mlt_properties_set_int( properties, "_transport_state", state );
		if ( state == JackTransportStopped )
			jack_sync( state, &jack_pos, filter );
	}

	return err;
}
예제 #29
0
파일: netsource.c 프로젝트: jackaudio/jack2
/**
 * The process callback for this JACK application.
 * It is called by JACK at the appropriate times.
 */
int
process (jack_nframes_t nframes, void *arg)
{
    jack_nframes_t net_period;
    int rx_bufsize, tx_bufsize;

    jack_default_audio_sample_t *buf;
    jack_port_t *port;
    JSList *node;
    int chn;
    int size, i;
    const char *porttype;
    int input_fd;

    jack_position_t local_trans_pos;

    uint32_t *packet_buf_tx, *packet_bufX;
    uint32_t *rx_packet_ptr;
    jack_time_t packet_recv_timestamp;

    if( bitdepth == 1000 || bitdepth == 999)
        net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8) & (~1) ;
    else
        net_period = (float) nframes / (float) factor;

    rx_bufsize =  get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header);
    tx_bufsize =  get_sample_size (bitdepth) * playback_channels * net_period + sizeof (jacknet_packet_header);

    /* Allocate a buffer where both In and Out Buffer will fit */
    packet_buf_tx = alloca (tx_bufsize);

    jacknet_packet_header *pkthdr_tx = (jacknet_packet_header *) packet_buf_tx;

    /*
     * for latency==0 we need to send out the packet before we wait on the reply.
     * but this introduces a cycle of latency, when netsource is connected to itself.
     * so we send out before read only in zero latency mode.
     *
     */

    if( latency == 0 ) {
        /* reset packet_bufX... */
        packet_bufX = packet_buf_tx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t);

        /* ---------- Send ---------- */
        render_jack_ports_to_payload (bitdepth, playback_ports, playback_srcs, nframes,
                                      packet_bufX, net_period, dont_htonl_floats);

        /* fill in packet hdr */
        pkthdr_tx->transport_state = jack_transport_query (client, &local_trans_pos);
        pkthdr_tx->transport_frame = local_trans_pos.frame;
        pkthdr_tx->framecnt = framecnt;
        pkthdr_tx->latency = latency;
        pkthdr_tx->reply_port = reply_port;
        pkthdr_tx->sample_rate = jack_get_sample_rate (client);
        pkthdr_tx->period_size = nframes;

        /* playback for us is capture on the other side */
        pkthdr_tx->capture_channels_audio = playback_channels_audio;
        pkthdr_tx->playback_channels_audio = capture_channels_audio;
        pkthdr_tx->capture_channels_midi = playback_channels_midi;
        pkthdr_tx->playback_channels_midi = capture_channels_midi;
        pkthdr_tx->mtu = mtu;
        if( freewheeling != 0 )
            pkthdr_tx->sync_state = (jack_nframes_t)MASTER_FREEWHEELS;
        else
            pkthdr_tx->sync_state = (jack_nframes_t)deadline_goodness;
        //printf("goodness=%d\n", deadline_goodness );

        packet_header_hton (pkthdr_tx);
        if (cont_miss < 3 * latency + 5) {
            int r;
            for( r = 0; r < redundancy; r++ )
                netjack_sendto (outsockfd, (char *) packet_buf_tx, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu);
        } else if (cont_miss > 50 + 5 * latency) {
            state_connected = 0;
            packet_cache_reset_master_address( packcache );
            //printf ("Frame %d  \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss);
            cont_miss = 0;
        }
    }

    /*
     * ok... now the RECEIVE code.
     *
     */


    if( reply_port )
        input_fd = insockfd;
    else
        input_fd = outsockfd;

    // for latency == 0 we can poll.
    if( (latency == 0) || (freewheeling != 0)  ) {
        jack_time_t deadline = jack_get_time() + 1000000 * jack_get_buffer_size(client) / jack_get_sample_rate(client);
        // Now loop until we get the right packet.
        while(1) {
            jack_nframes_t got_frame;
            if ( ! netjack_poll_deadline( input_fd, deadline ) )
                break;

            packet_cache_drain_socket(packcache, input_fd);

            if (packet_cache_get_next_available_framecnt( packcache, framecnt - latency, &got_frame ))
                if( got_frame == (framecnt - latency) )
                    break;
        }
    } else {
        // normally:
        // only drain socket.
        packet_cache_drain_socket(packcache, input_fd);
    }

    size = packet_cache_retreive_packet_pointer( packcache, framecnt - latency, (char**)&rx_packet_ptr, rx_bufsize, &packet_recv_timestamp );
    /* First alternative : we received what we expected. Render the data
     * to the JACK ports so it can be played. */
    if (size == rx_bufsize) {
        uint32_t *packet_buf_rx = rx_packet_ptr;
        jacknet_packet_header *pkthdr_rx = (jacknet_packet_header *) packet_buf_rx;
        packet_bufX = packet_buf_rx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t);
        // calculate how much time there would have been, if this packet was sent at the deadline.

        int recv_time_offset = (int) (jack_get_time() - packet_recv_timestamp);
        packet_header_ntoh (pkthdr_rx);
        deadline_goodness = recv_time_offset - (int)pkthdr_rx->latency;
        //printf( "deadline goodness = %d ---> off: %d\n", deadline_goodness, recv_time_offset );

        if (cont_miss) {
            //printf("Frame %d  \tRecovered from dropouts\n", framecnt);
            cont_miss = 0;
        }
        render_payload_to_jack_ports (bitdepth, packet_bufX, net_period,
                                      capture_ports, capture_srcs, nframes, dont_htonl_floats);

        state_currentframe = framecnt;
        state_recv_packet_queue_time = recv_time_offset;
        state_connected = 1;
        sync_state = pkthdr_rx->sync_state;
        packet_cache_release_packet( packcache, framecnt - latency );
    }
    /* Second alternative : we've received something that's not
     * as big as expected or we missed a packet. We render silence
     * to the ouput ports */
    else {
        jack_nframes_t latency_estimate;
        if( packet_cache_find_latency( packcache, framecnt, &latency_estimate ) )
            //if( (state_latency == 0) || (latency_estimate < state_latency) )
            state_latency = latency_estimate;

        // Set the counters up.
        state_currentframe = framecnt;
        //state_latency = framecnt - pkthdr->framecnt;
        state_netxruns += 1;

        //printf ("Frame %d  \tPacket missed or incomplete (expected: %d bytes, got: %d bytes)\n", framecnt, rx_bufsize, size);
        //printf ("Frame %d  \tPacket missed or incomplete\n", framecnt);
        cont_miss += 1;
        chn = 0;
        node = capture_ports;
        while (node != NULL) {
            port = (jack_port_t *) node->data;
            buf = jack_port_get_buffer (port, nframes);
            porttype = jack_port_type (port);
            if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size ()) == 0)
                for (i = 0; i < nframes; i++)
                    buf[i] = 0.0;
            else if (strncmp (porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size ()) == 0)
                jack_midi_clear_buffer (buf);
            node = jack_slist_next (node);
            chn++;
        }
    }
    if (latency != 0) {
        /* reset packet_bufX... */
        packet_bufX = packet_buf_tx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t);

        /* ---------- Send ---------- */
        render_jack_ports_to_payload (bitdepth, playback_ports, playback_srcs, nframes,
                                      packet_bufX, net_period, dont_htonl_floats);

        /* fill in packet hdr */
        pkthdr_tx->transport_state = jack_transport_query (client, &local_trans_pos);
        pkthdr_tx->transport_frame = local_trans_pos.frame;
        pkthdr_tx->framecnt = framecnt;
        pkthdr_tx->latency = latency;
        pkthdr_tx->reply_port = reply_port;
        pkthdr_tx->sample_rate = jack_get_sample_rate (client);
        pkthdr_tx->period_size = nframes;

        /* playback for us is capture on the other side */
        pkthdr_tx->capture_channels_audio = playback_channels_audio;
        pkthdr_tx->playback_channels_audio = capture_channels_audio;
        pkthdr_tx->capture_channels_midi = playback_channels_midi;
        pkthdr_tx->playback_channels_midi = capture_channels_midi;
        pkthdr_tx->mtu = mtu;
        if( freewheeling != 0 )
            pkthdr_tx->sync_state = (jack_nframes_t)MASTER_FREEWHEELS;
        else
            pkthdr_tx->sync_state = (jack_nframes_t)deadline_goodness;
        //printf("goodness=%d\n", deadline_goodness );

        packet_header_hton (pkthdr_tx);
        if (cont_miss < 3 * latency + 5) {
            int r;
            for( r = 0; r < redundancy; r++ )
                netjack_sendto (outsockfd, (char *) packet_buf_tx, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu);
        } else if (cont_miss > 50 + 5 * latency) {
            state_connected = 0;
            packet_cache_reset_master_address( packcache );
            //printf ("Frame %d  \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss);
            cont_miss = 0;
        }
    }

    framecnt++;
    return 0;
}
예제 #30
0
int
AudioJACKTarget::process(jack_nframes_t nframes)
{
    if (m_done) return 0;

    if (!m_mutex.tryLock()) {
	return 0;
    }

    if (m_outputs.empty()) {
	m_mutex.unlock();
	return 0;
    }

#ifdef DEBUG_AUDIO_JACK_TARGET    
    std::cout << "AudioJACKTarget::process(" << nframes << "): have a source" << std::endl;
#endif

#ifdef DEBUG_AUDIO_JACK_TARGET    
    if (m_bufferSize != nframes) {
	std::cerr << "WARNING: m_bufferSize != nframes (" << m_bufferSize << " != " << nframes << ")" << std::endl;
    }
#endif

    float **buffers = (float **)alloca(m_outputs.size() * sizeof(float *));

    for (size_t ch = 0; ch < m_outputs.size(); ++ch) {
	buffers[ch] = (float *)jack_port_get_buffer(m_outputs[ch], nframes);
    }

    size_t received = 0;

    if (m_source) {
	received = m_source->getSourceSamples(nframes, buffers);
    }

    for (size_t ch = 0; ch < m_outputs.size(); ++ch) {
        for (size_t i = received; i < nframes; ++i) {
            buffers[ch][i] = 0.0;
        }
    }

    float peakLeft = 0.0, peakRight = 0.0;

    for (size_t ch = 0; ch < m_outputs.size(); ++ch) {

	float peak = 0.0;

	for (size_t i = 0; i < nframes; ++i) {
	    buffers[ch][i] *= m_outputGain;
	    float sample = fabsf(buffers[ch][i]);
	    if (sample > peak) peak = sample;
	}

	if (ch == 0) peakLeft = peak;
	if (ch > 0 || m_outputs.size() == 1) peakRight = peak;
    }
	    
    if (m_source) {
	m_source->setOutputLevels(peakLeft, peakRight);
    }

    m_mutex.unlock();
    return 0;
}