Esempio n. 1
0
static
void port_event(alsa_seqmidi_t *self, snd_seq_event_t *ev)
{
	const snd_seq_addr_t addr = ev->data.addr;

	if (addr.client == self->client_id)
		return;

	if (ev->type == SND_SEQ_EVENT_PORT_START || ev->type == SND_SEQ_EVENT_PORT_CHANGE) {
		assert (jack_ringbuffer_write_space(self->port_add) >= sizeof(addr));

		debug_log("port_event: add/change %d:%d", addr.client, addr.port);
		jack_ringbuffer_write(self->port_add, (char*)&addr, sizeof(addr));
		sem_post(&self->port_sem);
	} else if (ev->type == SND_SEQ_EVENT_PORT_EXIT) {
		debug_log("port_event: del %d:%d", addr.client, addr.port);
		port_setdead(self->stream[PORT_INPUT].ports, addr);
		port_setdead(self->stream[PORT_OUTPUT].ports, addr);
	}
}
Esempio n. 2
0
/*
 * ==================== Port add/del handling thread ==============================
 */
static
void update_port_type(alsa_seqmidi_t *self, int type, snd_seq_addr_t addr, int caps, const snd_seq_port_info_t *info)
{
	stream_t *str = &self->stream[type];
	int alsa_mask = port_type[type].alsa_mask;
	port_t *port = port_get(str->ports, addr);

	debug_log("update_port_type(%d:%d)", addr.client, addr.port);

	if (port && (caps & alsa_mask)!=alsa_mask) {
		debug_log("setdead: %s", port->name);
		port->is_dead = 1;
	}

	if (!port && (caps & alsa_mask)==alsa_mask) {
		assert (jack_ringbuffer_write_space(str->new_ports) >= sizeof(port));
		port = port_create(self, type, addr, info);
		if (port)
			jack_ringbuffer_write(str->new_ports, (char*)&port, sizeof(port));
	}
}
Esempio n. 3
0
static
void
a2j_port_event (struct a2j * self, snd_seq_event_t * ev)
{
	const snd_seq_addr_t addr = ev->data.addr;

	if (addr.client == self->client_id)
		return;

	if (ev->type == SND_SEQ_EVENT_PORT_START || ev->type == SND_SEQ_EVENT_PORT_CHANGE) {
		if (jack_ringbuffer_write_space(self->port_add) >= sizeof(addr)) {
			a2j_debug("port_event: add/change %d:%d", addr.client, addr.port);
			jack_ringbuffer_write(self->port_add, (char*)&addr, sizeof(addr));
		} else {
			a2j_error("dropping port_event: add/change %d:%d", addr.client, addr.port);
		}
	} else if (ev->type == SND_SEQ_EVENT_PORT_EXIT) {
		a2j_debug("port_event: del %d:%d", addr.client, addr.port);
		a2j_port_setdead(self->stream.port_hash, addr);
	}
}
Esempio n. 4
0
static int process(jack_nframes_t nframes, void* arg)
{
	int cnt;
	static int total;

	/* Do nothing until we're ready to begin. */
	if (!unleash_jack) {
		printf ("nothing to do\n");
		return 0;
	}
	
	for(int i = 0; i < CHANNELS; i++) {
		in[i] = jack_port_get_buffer(inputports[i], nframes);
	}
		
	for (size_t i = 0; i < nframes; i++) {
		for(int j = 0; j < CHANNELS; j++) {
			total++;
			if ((cnt = jack_ringbuffer_write_space(ringbuffer)) >= SAMPLE_SIZE) {
				jack_ringbuffer_write(ringbuffer,
						(void*) (in[j]+i), SAMPLE_SIZE);
				if (total % 5000 == 0) {
					printf ("Available writespace: %i\n", cnt);
				}
			} else {
				printf ("Only %i bytes available after %i samples\n",
						cnt, total);
				halt_tx = 1;
			}
		}
	}

	if (0 == pthread_mutex_trylock(&threadLock))
	{
		pthread_cond_signal(&dataReady);
		pthread_mutex_unlock(&threadLock);
	}

	return 0;
}
Esempio n. 5
0
int audio_feed_process_audio(jack_nframes_t n_frames, void *arg)
    {
    struct audio_feed *self = audio_feed;
    struct threads_info *ti = self->threads_info;
    struct encoder *e;
    struct recorder *r;
    sample_t *input_port_buffer[2];
    int i;
    
    input_port_buffer[0] = jack_port_get_buffer(g.port.output_in_l, n_frames);
    input_port_buffer[1] = jack_port_get_buffer(g.port.output_in_r, n_frames);
    
    /* feed pcm audio data to all encoders that request it */
    for (i = 0; i < ti->n_encoders; i++)
        {
        e = ti->encoder[i];
        switch (e->jack_dataflow_control)
            {
            case JD_OFF:
                break;
            case JD_ON:
                while (jack_ringbuffer_write_space(e->input_rb[1]) < n_frames * sizeof (sample_t))
                    nanosleep(&(struct timespec){0, 10000000}, NULL);
                    
                jack_ringbuffer_write(e->input_rb[0], (char *)input_port_buffer[0], n_frames * sizeof (sample_t));
                jack_ringbuffer_write(e->input_rb[1], (char *)input_port_buffer[1], n_frames * sizeof (sample_t));
                break;
            case JD_FLUSH:
                jack_ringbuffer_reset(e->input_rb[0]);
                jack_ringbuffer_reset(e->input_rb[1]);
                e->jack_dataflow_control = JD_OFF;
                break;
            default:
                fprintf(stderr, "jack_process_callback: unhandled jack_dataflow_control parameter\n");
            }
        }
Esempio n. 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;
	}
Esempio n. 7
0
size_t
jack_ringbuffer_write (jack_ringbuffer_t * rb, const char *src, size_t cnt)
{
  size_t free_cnt;
  size_t cnt2;
  size_t to_write;
  size_t n1, n2;

  if ((free_cnt = jack_ringbuffer_write_space (rb)) == 0) {
    return 0;
  }

  to_write = cnt > free_cnt ? free_cnt : cnt;

  cnt2 = rb->write_ptr + to_write;

  if (cnt2 > rb->size) {
    n1 = rb->size - rb->write_ptr;
    n2 = cnt2 & rb->size_mask;
  } else {
    n1 = to_write;
    n2 = 0;
  }

  memcpy (&(rb->buf[rb->write_ptr]), src, n1);
  rb->write_ptr += n1;
  rb->write_ptr &= rb->size_mask;

  if (n2) {
    memcpy (&(rb->buf[rb->write_ptr]), src + n1, n2);
    rb->write_ptr += n2;
    rb->write_ptr &= rb->size_mask;
  }

  return to_write;
}
Esempio n. 8
0
void gui_message(const char *msg)
{
    if(jack_ringbuffer_write_space(gui_ring) >= 2048)
        jack_ringbuffer_write(gui_ring, msg, 2048);
}
Esempio n. 9
0
// TODO: nonblocking version
int ezjack_write(ezjack_bundle_t *bun, void *buf, int len, ezjack_format_t fmt)
{
	int i, j;

	int fmtsize = _helper_get_fmt_size(fmt); // FIXME: handle erroneous format
	int blockalign = bun->portstack.outcount * fmtsize;
	if(len % blockalign != 0) abort(); // FIXME: do this more gracefully
	int reqlen = len/blockalign;

	while(reqlen > 0)
	{
		int minspace = reqlen * sizeof(float);

		// Get smallest space count
		for(i = 0; i < bun->portstack.outcount; i++)
		{
			int cspace = (int)jack_ringbuffer_write_space(bun->portstack.outrb[i]);

			if(cspace < minspace)
				minspace = cspace;
		}

		minspace /= sizeof(float);

		// Write to ring buffers
		if(minspace > 0)
		{
			// Write to temporaries
			// FIXME: handle all formats
#define HELPER_WRITE_FORMAT(inc, wrap) \
			for(j = 0; j < minspace; j++) \
				for(i = 0; i < bun->portstack.outcount; i++) \
				{ \
					bun->portstack.outbuf[i][j] = wrap; \
					buf += inc; \
				} \

			switch(fmt)
			{
				case EZJackFormatFloat32LE:
				case EZJackFormatFloat32Native:
					HELPER_WRITE_FORMAT(sizeof(float), *(float *)buf);
					break;

				case EZJackFormatU8:
					HELPER_WRITE_FORMAT(1, ((float)*(uint8_t *)buf)/128.0f-1.0f);
					break;

				case EZJackFormatS8:
					HELPER_WRITE_FORMAT(1, ((float)*(int8_t *)buf)/128.0f);
					break;

				case EZJackFormatS16Native:
				case EZJackFormatS16LE:
					HELPER_WRITE_FORMAT(2, ((float)*(int16_t *)buf)/32768.0f);
					break;

				case EZJackFormatU16Native:
				case EZJackFormatU16LE:
					HELPER_WRITE_FORMAT(2, ((float)*(uint16_t *)buf)/32768.0f-1.0f);
					break;

			}

#undef HELPER_WRITE_FORMAT

			// Commit data
			for(i = 0; i < bun->portstack.outcount; i++)
			{
				// FIXME: handle the case where this returns something wrong
				jack_ringbuffer_write(bun->portstack.outrb[i], (char *)(bun->portstack.outbuf[i]), minspace*sizeof(float));
			}

			reqlen -= minspace;
		}

		// Sleep a bit.
		// TODO: use a notify system
		usleep(1000);
	}

	return len;
}
Esempio n. 10
0
void collect_data(SynthEngine *synth, float value, unsigned char type, unsigned char control, unsigned char part, unsigned char kititem, unsigned char engine, unsigned char insert, unsigned char parameter, unsigned char par2)
{
    if (part < NUM_MIDI_PARTS && engine == PART::engine::padSynth)
    {
        if (collect_readData(synth, 0, PART::control::partBusy, part, UNUSED, UNUSED, UNUSED, UNUSED, UNUSED))
        {
            fl_alert("Part %d is busy", int(part));
            return;
        }
    }

    CommandBlock putData;
    size_t commandSize = sizeof(putData);
    putData.data.value = value;
    putData.data.control = control;
    putData.data.part = part;
    putData.data.kit = kititem;
    putData.data.engine = engine;
    putData.data.insert = insert;
    putData.data.parameter = parameter;
    putData.data.par2 = par2;

    unsigned char typetop = type & 0xd0; // pass through redraws *after* command
    unsigned char buttons = type & 7;
    if (part == TOPLEVEL::section::main && (control > 48 || control == 14))
        type = 1; // TODO fix this properly!
    else if (part != TOPLEVEL::section::midiLearn)
    {
        if (buttons == 3 && Fl::event_is_click())
        {
            float newValue;
            putData.data.type = 3 | TOPLEVEL::type::Limits;
            newValue = synth->interchange.readAllData(&putData);
            //cout << "Gui limits new value " << newValue << endl;
            if(Fl::event_state(FL_CTRL) != 0)
            {
                if (putData.data.type & TOPLEVEL::type::Learnable)
                    type = 3; // previous type is now irrelevant
                    // identifying this for button 3 as MIDI learn
                else
                {
                    synth->getGuiMaster()->words->copy_label("Can't learn this control");
                    synth->getGuiMaster()->message->show();
                    synth->getGuiMaster()->message->position(Fl::event_x_root() + 16, Fl::event_y_root());
                    synth->getRuntime().Log("Can't MIDI-learn this control");
                    /* can't use fl_alert here.
                     * For some reason it goes into a loop on spin boxes
                     * and runs menus up to their max value.
                     */
                    type = TOPLEVEL::type::Learnable;
                }
            }
            else
            {
                putData.data.value = newValue;
                type = TOPLEVEL::type::Write | TOPLEVEL::source::UpdateAfterSet;
                // has to be write as it's 'set default'
            }
        }
        else if(buttons > 2)
            type = 1;
            // change scroll wheel to button 1
    }
    type |= typetop;

    putData.data.type = type | TOPLEVEL::source::GUI;

//cout << "collect_data value " << value << "  type " << int(type) << "  control " << int(control) << "  part " << int(part) << "  kit " << int(kititem) << "  engine " << int(engine) << "  insert " << int(insert)  << "  par " << int(parameter) << " par2 " << int(par2) << endl;
    if (jack_ringbuffer_write_space(synth->interchange.fromGUI) >= commandSize)
        jack_ringbuffer_write(synth->interchange.fromGUI, (char*) putData.bytes, commandSize);
    else
        synth->getRuntime().Log("Unable to write to fromGUI buffer.");
}
Esempio n. 11
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;
}
Esempio n. 12
0
int
main (int argc, char *argv[])
{
	const char *client_name;
	const char *server_name = NULL;
	jack_options_t options = JackNullOption;
	jack_status_t status;
  pcap_t* pcap;
  int   offline=0;
  char* iface=NULL;
  char* fname=NULL;
  int   slen=SNAPLEN;
  int   rs=RINGSIZE;
  char  errbuf[PCAP_ERRBUF_SIZE];
  int   promisc=PROMISC;
  double  rate=1.0;

  client_name = strrchr(argv[0], '/');
  if(!client_name)
    client_name=argv[0];
  else
    client_name++;

  int opt;
  while ((opt = getopt(argc, argv, "c:n:s:pi:r:t:b:")) != -1) {
    switch (opt) {
    case 'c':
        client_name=optarg;
        break;
    case 'n':
        server_name=optarg;
        options |= JackServerName;
        break;
    case 's':
        slen=atoi(optarg);
        break;
    case 'p':
        promisc=0;
        break;
    case 'i':
        iface=optarg;
        break;
    case 'r':
        fname=optarg;
        break;
    case 't':
        rate=atof(optarg);
        break;
    case 'b':
        rs=atoi(optarg);
        break;
    case '?':
        usage(argv[0],0);
        break;
    default: /* '?' */
        printf("Invalid option %c\n",opt);
        usage(argv[0],EXIT_FAILURE);
    }
  }

  /* open the pcap source */
  if ((iface && fname) || (!iface && !fname)) {
    printf("Please specify either a interface or a dump file as packet source\n");
    usage(argv[0],EXIT_FAILURE);
  }

  if (iface) {
    pcap = pcap_open_live(iface, slen, promisc, 0, errbuf);
    if (!pcap) {
      printf("Failed to open pcap source %s: %s\n", iface, errbuf);
      exit(EXIT_FAILURE);
    }
  }

  if (fname) {
    pcap = pcap_open_offline(fname, errbuf);
    if (!pcap) {
      printf("Failed to open dump file %s: %s\n", iface, errbuf);
      exit(EXIT_FAILURE);
    }
    offline=1;
  }

  /* set bpf filter */
  if (optind < argc) {
    int   i,s;
    char* bpf_str;
    struct bpf_program bpf_prog;

    for (s=0, i=optind; i<argc; i++) {
      s += strlen(argv[i]) + 1;
    }

    bpf_str = malloc(s);
    if (!bpf_str) {
      printf("Failed to malloc space for bpf filter\n");
      exit(EXIT_FAILURE);
    }

    bpf_str[0]=0;
    for (i=optind; i<argc; i++) {
      strcat(bpf_str,argv[i]);
      strcat(bpf_str," ");
    }

    printf("Setting bpf filter to %s\n", bpf_str);

    if (0>pcap_compile(pcap, &bpf_prog, bpf_str, 1, 0)) {
      printf("Failed to compile bpf filter\n");
      exit(EXIT_FAILURE);
    }

    if (0>pcap_setfilter(pcap, &bpf_prog)) {
      printf("Failed to set bpf filter\n");
      exit(EXIT_FAILURE);
    }

    pcap_freecode(&bpf_prog);
    free(bpf_str);
  }

  /* allocate ringbuffer */
  rb=jack_ringbuffer_create (rs*sizeof(jack_default_audio_sample_t));
  if (!rb) {
    printf("Failed to allocate ringbuffer\n");
    exit(EXIT_FAILURE);
  }

	/* open a client connection to the JACK server */
	client = jack_client_open (client_name, options, &status, server_name);
	if (client == NULL) {
		fprintf (stderr, "jack_client_open() failed, "
			 "status = 0x%2.0x\n", status);
		if (status & JackServerFailed) {
			fprintf (stderr, "Unable to connect to JACK server\n");
		}
		exit (1);
	}
	if (status & JackServerStarted) {
		fprintf (stderr, "JACK server started\n");
	}
	if (status & JackNameNotUnique) {
		client_name = jack_get_client_name(client);
		fprintf (stderr, "unique name `%s' assigned\n", client_name);
	}

	/* tell the JACK server to call `process()' whenever
	   there is work to be done.
	*/

	jack_set_process_callback (client, process, 0);

	/* tell the JACK server to call `jack_shutdown()' if
	   it ever shuts down, either entirely, or if it
	   just decides to stop calling us.
	*/

	jack_on_shutdown (client, jack_shutdown, 0);

	/* display the current sample rate. 
	 */

	printf ("engine sample rate: %" PRIu32 "\n",
		jack_get_sample_rate (client));

	/* create two ports */

	output_port = jack_port_register (client, "output",
					  JACK_DEFAULT_AUDIO_TYPE,
					  JackPortIsOutput, 0);

	/* Tell the JACK server that we are ready to roll.  Our
	 * process() callback will start running now. */

	if (jack_activate (client)) {
		fprintf (stderr, "cannot activate client");
		exit (1);
	}

	/* read packets from pcap source and write it into the ringbuffer */
  char    *buf;
  struct  pcap_pkthdr *h;
  u_int   pcnt=0;
  struct  timeval toff, tnow;
  
  /* mark offset for calculation on first packet */
  toff.tv_sec = -1;

  /* main loop: get packets from pcap source */
	while (0 <= pcap_next_ex(pcap, &h, (const u_char**) &buf)) {
    size_t  s;
    
    if (!buf) break;
    pcnt++;

    /* 
     * if we are reading from a file we sleep in the loop until the timestamp
     * of the packet is reached.
     */
    if (offline) for(;;) {
      struct timeval dt;
      
      gettimeofday(&tnow, NULL);
      
      /* initialize toff on first packet */
      if(toff.tv_sec == -1) {
        tvmov(toff,h->ts);
        tvsub(toff,tnow);
        tvnrm(toff);
      }

      tvmov(dt,h->ts);
      tvsub(dt,tnow);
      tvsub(dt,toff);
      tvnrm(dt);

      if (dt.tv_sec < 0 ) {
        break;
      }
      else if (dt.tv_sec > 0) {
        sleep(dt.tv_sec);
      }
      else {
        usleep(dt.tv_usec);
      }
    }

    /* check available buffer space */
    s = jack_ringbuffer_write_space(rb);
    if (!s)
      continue;

    /* truncate packet if there is not enough space in the buffer */
    if (s > h->caplen)
      s = h->caplen;

    /* write into the ringbuffer and get the next packet */
    jack_ringbuffer_write(rb,buf,s);
	}

	jack_client_close (client);
  
  struct  pcap_stat  ps;
  if(!pcap_stats(pcap, &ps)) {
    printf(
      "%d packets captured\n"
      "%d received by filter\n"
      "%d packets dropped by kernel\n",
      ps.ps_recv, pcnt, ps.ps_drop
    );
  }
  else {
    pcap_perror(pcap,"Failed to optain packet statistics");
  }
	exit (0);
}
size_t
JackRingbuffer::writeSpace()
{
	return jack_ringbuffer_write_space(ringbuffer_);
}
Esempio n. 14
0
/** read from the attached track's ports and stuff the ringbuffers */
nframes_t
Record_DS::process ( nframes_t nframes )
{
    THREAD_ASSERT( RT );

    if ( ! _recording )
        return 0;

     if ( transport->frame < _frame  )
         return 0;

/*    DMESSAGE( "recording actually happening at %lu (start frame %lu)", (unsigned long)transport->frame, (unsigned long)_frame); */

    nframes_t offset = 0;

    if ( _frame > transport->frame &&
         _frame < transport->frame + nframes )
    {
        /* The record start frame falls somewhere within the current
           buffer.  We must discard the unneeded portion and only
           stuff the part requested into the ringbuffer. */

        offset = _frame - transport->frame;

/*         DMESSAGE( "offset = %lu", (unsigned long)offset ); */
    }

    const size_t offset_size = offset * sizeof( sample_t );
    const size_t block_size = ( nframes * sizeof( sample_t ) ) - offset_size;

    for ( int i = channels(); i--;  )
    {
        /* read the entire input buffer */
        void *buf = track()->input[ i ].buffer( nframes );

        /* FIXME: this results in a ringbuffer size that is no longer
         necessarily a multiple of nframes...  how will the other side
         handle that? */

        if ( engine->freewheeling() )
        {
            while ( jack_ringbuffer_write_space( _rb[i] ) < block_size )
                usleep( 10 * 1000 );

            jack_ringbuffer_write( _rb[ i ], ((char*)buf) + offset_size, block_size );
        }
        else
        {
            if ( jack_ringbuffer_write_space( _rb[i] ) < block_size )
            {
                memset( buf, 0, block_size );
                /* FIXME: we need to resync somehow */
                ++_xruns;
            }
            else
            {
                jack_ringbuffer_write( _rb[ i ], ((char*)buf) + offset_size, block_size );
            }
        }
    }

    block_processed();

    /* FIXME: bogus */
    return nframes;
}
Esempio n. 15
0
size_t ringbuffer_write_space(jack_ringbuffer_t *rbuf)
	{
	return jack_ringbuffer_write_space(rbuf);
	}
Esempio n. 16
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 = buffer_alloc( _nframes * channels() * _disk_io_blocks );
    sample_t *cbuf = buffer_alloc( _nframes );

    const nframes_t nframes = _nframes;
    nframes_t blocks_written;

    while ( ! _terminate )
    {

    seek:

        blocks_written = 0;
        read_block( buf, nframes * _disk_io_blocks );

        while ( blocks_written < _disk_io_blocks &&
                wait_for_block() )
        {
//        lock(); // for seeking
            
            if ( _pending_seek )
            {
                /* FIXME: non-RT-safe IO */
                DMESSAGE( "performing seek to frame %lu", (unsigned long)_seek_frame );
                
                _frame = _seek_frame;
                _pending_seek = false;

                flush();
                
                goto seek;
            }

            /* might have received terminate signal while waiting for block */
            if ( _terminate )
                goto done;
        
//        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 = 0; i < channels(); i++ )
            {
                buffer_deinterleave_one_channel( cbuf,
                                                 buf + ( blocks_written * nframes * channels() ),
                                                 i,
                                                 channels(), 
                                                 nframes );

                while ( jack_ringbuffer_write_space( _rb[ i ] ) < block_size )
                    usleep( 100 * 1000 );

                jack_ringbuffer_write( _rb[ i ], ((char*)cbuf), block_size );
            }

            blocks_written++;
        }
    }

done:

    DMESSAGE( "playback thread terminating" );

    free(buf);
    free(cbuf);

//    flush();

    _terminate = false;

    _thread.exit();
}
Esempio n. 17
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);
	}

}
Esempio n. 18
0
//================================================================
// /audio
//handler for audio messages
int osc_audio_handler(const char *path, const char *types, lo_arg **argv, int argc,
	void *data, void *user_data)
{
	if(shutdown_in_progress==1 || not_yet_ready==1)
	{
		return 0;
	}

	//init to 0, increment before use
	msg_received_counter++;

	gettimeofday(&tv, NULL);

	//first blob is at data_offset+1 (one-based)
	int data_offset=4;

	//ignore first n channels/blobs
	data_offset+=channel_offset;

	message_number_prev=message_number;

	//the messages are numbered sequentially. first msg is numberd 1
	message_number=argv[0]->h;

	if(message_number_prev<message_number-1)
	{
		fprintf(stderr,"\ngap in message sequence! possibly lost %" PRId64" message(s) on the way.\n"
			,message_number-message_number_prev-1);
		fflush(stderr);
	}

	//total args count minus metadata args count = number of blobs
	input_port_count=argc-data_offset;

	//only process useful number of channels
	port_count=fmin(input_port_count,output_port_count);

	if(port_count < 1)
	{
		fprintf(stderr,"channel offset %d >= available input channels %d! (nothing to receive). shutting down...\n"
			,channel_offset
			,channel_offset+input_port_count);
		fflush(stderr);
		shutdown_in_progress=1;
		return 0;
	}

	//check sample rate and period size if sender (re)started or values not yet initialized (=no /offer received)
	if(message_number_prev>message_number || message_number==1 || remote_sample_rate==0 || remote_period_size==0 )
	{
		lo_address loa;

		if(use_tcp==1)
		{
			lo_address loa_=lo_message_get_source(data);
			loa=lo_address_new_with_proto(lo_proto,lo_address_get_hostname(loa_),remote_tcp_server_port);
		}
		else
		{
			loa=lo_message_get_source(data);
		}

		strcpy(sender_host,lo_address_get_hostname(loa));
		strcpy(sender_port,lo_address_get_port(loa));

		//option --rebuff
		if(rebuffer_on_restart==1)
		{
			uint64_t can_read_count=jack_ringbuffer_read_space(rb);
			pre_buffer_counter=fmax(0,(float)can_read_count/(float)bytes_per_sample/(float)period_size/(float)port_count);
			//start buffering
			process_enabled=0;
		}
		else
		{
			pre_buffer_counter=0;
		}

		remote_sample_rate=argv[3]->i;

		if(sample_rate!=remote_sample_rate)
		{
			if(close_on_incomp==0)
			{
				//sending deny will tell sender to stop/quit
				lo_message msg=lo_message_new();


				lo_message_add_float(msg,format_version);
				lo_message_add_int32(msg,sample_rate);
// /deny as reply to /audio should be the same as for /deny as reply to /offer
//will need change of /audio (add format, bytes_per_sample)
///////
				lo_message_add_int32(msg,99);

				lo_send_message(loa, "/deny", msg);
				lo_message_free(msg);

				fprintf(stderr,"\ndenying transmission from %s:%s\n(incompatible JACK settings on sender: SR: %d). telling sender to stop.\n",
					lo_address_get_hostname(loa),lo_address_get_port(loa),remote_sample_rate
				);
				fflush(stderr);

				message_number=0;
				message_number_prev=0;
				remote_sample_rate=0;
				remote_period_size=0;
				//pre_buffer_counter=0;
			}
			else
			{
				lo_address loa;

				if(use_tcp==1)
				{
					lo_address loa_=lo_message_get_source(data);
					loa=lo_address_new_with_proto(lo_proto,lo_address_get_hostname(loa_),remote_tcp_server_port);
				}
				else
				{
					loa=lo_message_get_source(data);
				}

				fprintf(stderr,"\ndenying transmission from %s:%s\nincompatible JACK settings on sender: SR: %d.\nshutting down (see option --close)...\n",
					lo_address_get_hostname(loa),lo_address_get_port(loa),remote_sample_rate
				);
				fflush(stderr);

				shutdown_in_progress=1;
				return 0;
			}
		}

		remote_period_size=lo_blob_datasize((lo_blob)argv[0+data_offset])/bytes_per_sample;

		if(shutup==0 && quiet==0)
		{
			fprintf(stderr,"\nsender was (re)started. ");

			lo_address loa=lo_message_get_source(data);
			fprintf(stderr,"receiving from %s:%s\n",lo_address_get_hostname(loa),lo_address_get_port(loa));
		}

		io_simple("/sender_restarted");

		if(shutup==0 && quiet==0)
		{
			if(remote_period_size!=period_size)
			{
				fprintf(stderr,"sender period size: %d samples (%.3f x local)\n\n",remote_period_size,(float)remote_period_size/period_size);
			}
			else
			{
				fprintf(stderr,"equal sender and receiver period size\n\n");
			}

			fflush(stderr);
		}

	}//end if "no-offer init" was needed

	remote_xrun_counter=argv[1]->h;

	lo_timetag tt=argv[2]->t;

	double msg_time=tt.sec+(double)tt.frac/1000000;
	double msg_time_prev=tt_prev.sec+(double)tt_prev.frac/1000000;
//unused for now
//	double time_now=tv.tv_sec+(double)tv.tv_usec/1000000;

	time_interval=msg_time-msg_time_prev;

	time_interval_sum+=time_interval;
	time_interval_avg=(float)time_interval_sum/msg_received_counter;

	tt_prev=tt;

	//reset avg calc, check and reset after use
	if(msg_received_counter>=avg_calc_interval)
	{
		msg_received_counter=0;
		time_interval_sum=0;
	}

	if(pre_buffer_counter>=pre_buffer_size && process_enabled==0)
	{
		//if buffer filled, start to output audio in process()
		process_enabled=1;
	}

	int mc_period_bytes=period_size*bytes_per_sample*port_count;

	//check if a whole mc period can be written to the ringbuffer
	uint64_t can_write_count=jack_ringbuffer_write_space(rb);
	if(can_write_count < mc_period_bytes)
	{
			buffer_overflow_counter++;
			/////////////////
			if(shutup==0 && quiet==0)
			{
				fprintf(stderr,"\rBUFFER OVERFLOW! this is bad -----%s","\033[0J");
			}
			return 0;
	}

	//========================================
	//new: support different period sizes on sender / receiver (still need same SR)
	//this needs more tests and optimization
	if(period_size==remote_period_size)
	{
		int i;
		//don't read more channels than we have outputs
		for(i=0;i < port_count;i++)
		{
			//get blob (=one period of one channel)
			unsigned char *data=lo_blob_dataptr((lo_blob)argv[i+data_offset]);
			//fprintf(stderr,"size %d\n",lo_blob_datasize((lo_blob)argv[i+data_offset]));

			//write to ringbuffer
			//==========================================
			//int cnt=
			jack_ringbuffer_write(rb, (void *) data, 
				period_size*bytes_per_sample);
		}
		pre_buffer_counter++;
	}
	else if(period_size>remote_period_size)
	{
		int i;
		//don't read more channels than we have outputs
		for(i=0;i < port_count;i++)
		{
			//get blob (=one period of one channel)
			unsigned char *data=lo_blob_dataptr((lo_blob)argv[i+data_offset]);
			//fprintf(stderr,"size %d\n",lo_blob_datasize((lo_blob)argv[i+data_offset]));

			//write to temporary ringbuffer until there is enough data
			//==========================================
			//int cnt=
			jack_ringbuffer_write(rb_helper, (void *) data, 
				remote_period_size*bytes_per_sample);
		}

		//if enough data collected for one larger multichannel period

		while(jack_ringbuffer_read_space(rb_helper)	>=mc_period_bytes
		&& jack_ringbuffer_write_space(rb)		>=mc_period_bytes)
		{
			//transfer from helper to main ringbuffer
			unsigned char* data;
			data=malloc(				mc_period_bytes);
			//store orig pointer
			unsigned char* orig_data=data;
			jack_ringbuffer_read(rb_helper,data,	mc_period_bytes);

			for(i=0;i < port_count;i++)
			{
				int k;
				for(k=0;k<(period_size/remote_period_size);k++)
				{
					//reset pointer
					data=orig_data;
					//position in helper buffer for next sample for main buffer
					data+=	k*remote_period_size*bytes_per_sample*port_count
							+ i*remote_period_size*bytes_per_sample;

					//write one channel snipped (remote_period_size) to main buffer
					//int w=
					jack_ringbuffer_write(rb,(void *)data,remote_period_size*bytes_per_sample);
				}
			}
			data=orig_data;
			free(data);

			pre_buffer_counter++;
		}
	}
	else if(period_size<remote_period_size)
	{
		int k;
		for(k=0;k<(remote_period_size/period_size);k++)
		{

			int i;
			//don't read more channels than we have outputs
			for(i=0;i < port_count;i++)
			{
				//get blob (=one period of one channel)
				unsigned char *data=lo_blob_dataptr((lo_blob)argv[i+data_offset]);
				//fprintf(stderr,"size %d\n",lo_blob_datasize((lo_blob)argv[i+data_offset]));

				//write to ringbuffer
				//==========================================
				data+=k*period_size*bytes_per_sample;

				//int cnt=
				jack_ringbuffer_write(rb, (void *) data, 
					period_size*bytes_per_sample);
			}
			pre_buffer_counter++;
		}
	}

	return 0;
}//end osc_audio_handler
Esempio n. 19
0
// JACK specifics.
int qmidinetJackMidiDevice::process ( jack_nframes_t nframes )
{
	jack_nframes_t buffer_size = jack_get_buffer_size(m_pJackClient);

	m_last_frame_time  = jack_last_frame_time(m_pJackClient);

	// Enqueue/dequeue events
	// to/from ring-buffers...
	for (int i = 0; i < m_nports; ++i) {

		if (m_ppJackPortIn && m_ppJackPortIn[i] && m_pJackBufferIn) {
			void *pvBufferIn
				= jack_port_get_buffer(m_ppJackPortIn[i], nframes);
			const int nevents = jack_midi_get_event_count(pvBufferIn);
			const unsigned int nlimit
				= jack_ringbuffer_write_space(m_pJackBufferIn);
			unsigned char  achBuffer[nlimit];
			unsigned char *pchBuffer = &achBuffer[0];
			unsigned int nwrite = 0;
			for (int n = 0; n < nevents; ++n) {
				if (nwrite + sizeof(qmidinetJackMidiEvent) >= nlimit)
					break;
				qmidinetJackMidiEvent *pJackEventIn
					= (struct qmidinetJackMidiEvent *) pchBuffer;
				jack_midi_event_get(&pJackEventIn->event, pvBufferIn, n);
				if (nwrite + sizeof(qmidinetJackMidiEvent)
					+ pJackEventIn->event.size >= nlimit)
					break;
				pJackEventIn->port = i;
				pchBuffer += sizeof(qmidinetJackMidiEvent);
				nwrite += sizeof(qmidinetJackMidiEvent);
				::memcpy(pchBuffer,
					pJackEventIn->event.buffer, pJackEventIn->event.size);
				pchBuffer += pJackEventIn->event.size;
				nwrite += pJackEventIn->event.size;
			}
			if (nwrite > 0) {
				jack_ringbuffer_write(m_pJackBufferIn,
					(const char *) achBuffer, nwrite);
			}
		}
	
		if (m_ppJackPortOut && m_ppJackPortOut[i] && m_pJackBufferOut) {
			void *pvBufferOut
				= jack_port_get_buffer(m_ppJackPortOut[i], nframes);
			jack_midi_clear_buffer(pvBufferOut);
			const unsigned int nlimit
				= jack_midi_max_event_size(pvBufferOut);
			unsigned int nread = 0;
			qmidinetJackMidiEvent ev;
			while (jack_ringbuffer_peek(m_pJackBufferOut,
					(char *) &ev, sizeof(ev)) == sizeof(ev)
					&& nread < nlimit) {
				if (ev.port != i)
					break;
				if (ev.event.time > m_last_frame_time)
					break;
				jack_nframes_t offset = m_last_frame_time - ev.event.time;
				if (offset > buffer_size)
					offset = 0;
				else
					offset = buffer_size - offset;
				jack_ringbuffer_read_advance(m_pJackBufferOut, sizeof(ev));
				jack_midi_data_t *pMidiData
					= jack_midi_event_reserve(pvBufferOut, offset, ev.event.size);
				if (pMidiData)
					jack_ringbuffer_read(m_pJackBufferOut,
						(char *) pMidiData, ev.event.size);
				else
				jack_ringbuffer_read_advance(m_pJackBufferOut, ev.event.size);
				nread += ev.event.size;
			}
		}
	}

	if (m_pJackBufferIn
		&& jack_ringbuffer_read_space(m_pJackBufferIn) > 0)
		m_pRecvThread->sync();

	return 0;
}
Esempio n. 20
0
File: jack.c Progetto: BG2BKK/cmus
static int op_jack_write(const char *buffer, int count)
{
	if (fail) {
		op_jack_exit();
		return -OP_ERROR_INTERNAL;
	}

	if (!drop_done) {
		return 0;
	}

	int frame_size = sf_get_frame_size(sample_format);
	int channels = sf_get_channels(sample_format);
	size_t frames = count / frame_size;

	/* since this is the only place where the ringbuffers get
	 * written, available space will only grow, therefore frames_min
	 * is safe.
	 */
	size_t frames_min = SIZE_MAX;
	for (int c = 0; c < CHANNELS; c++) {
		size_t frames_available = jack_ringbuffer_write_space(ringbuffer[c]) / sizeof(jack_default_audio_sample_t);
		if (frames_available < frames_min) {
			frames_min = frames_available;
		}
	}

	if (frames > frames_min) {
		frames = frames_min;
	}

	jack_default_audio_sample_t buf[CHANNELS][buffer_size];

	/* demux and convert to float */
	for (int pos = 0; pos < count; ) {
		int frame = pos / frame_size;
		for (int c = 0; c < channels; c++) {
			int idx = pos + c * sample_bytes;
			/* for now, only 2 channels and mono are supported */
			if (channel_map[c] == CHANNEL_POSITION_LEFT || channel_map[c] == CHANNEL_POSITION_MONO) {
				buf[0][frame] = read_sample(&buffer[idx]);
			} else if (channel_map[c] == CHANNEL_POSITION_RIGHT || channel_map[c] == CHANNEL_POSITION_MONO) {
				buf[1][frame] = read_sample(&buffer[idx]);
			}
		}
		pos += frame_size;
	}

#ifdef HAVE_SAMPLERATE
	if (resample_ratio > 1.01f || resample_ratio < 0.99) {
		jack_default_audio_sample_t converted[buffer_size];
		SRC_DATA src_data;
		for (int c = 0; c < CHANNELS; c++) {
			src_data.data_in = buf[c];
			src_data.data_out = converted;
			src_data.input_frames = frames;
			src_data.output_frames = frames_min;
			src_data.src_ratio = resample_ratio;
			src_data.end_of_input = 0;

			int err = src_process(src_state[c], &src_data);
			if (err) {
				d_print("libsamplerate err %s\n", src_strerror(err));
			}

			int byte_length = src_data.output_frames_gen * sizeof(jack_default_audio_sample_t);
			jack_ringbuffer_write(ringbuffer[c], (const char*) converted, byte_length);
		}
		return src_data.input_frames_used * frame_size;
	} else {
#endif
		int byte_length = frames * sizeof(jack_default_audio_sample_t);
		for (int c = 0; c < CHANNELS; c++) {
			jack_ringbuffer_write(ringbuffer[c], (const char*) buf[c], byte_length);
		}

		return frames * frame_size;
#ifdef HAVE_SAMPLERATE
	}
#endif
}
Esempio n. 21
0
static size_t ja_write_avail(void *data)
{
   jack_t *jd = (jack_t*)data;
   return jack_ringbuffer_write_space(jd->buffer[0]);
}
Esempio n. 22
0
/*
 * -----------------------------------------------------------------------------
 */
static inline
int can_pass(size_t sz, jack_ringbuffer_t *in, jack_ringbuffer_t *out)
{
    return jack_ringbuffer_read_space(in) >= sz && jack_ringbuffer_write_space(out) >= sz;
}
Esempio n. 23
0
			///Get the number of items that can be written at this time
			size_t getWriteSpace(){
				return jack_ringbuffer_write_space(mRingBufferPtr) / sizeof(Type);
			}
Esempio n. 24
0
void *jack_player_thread(void *unused){
	WfAudioInfo* nfo = &myplayer->info;
	const int nframes = 1024;
	float *tmpbuf = (float*) calloc(nframes * nfo->channels, sizeof(float));
	float *bufptr = tmpbuf;
#ifdef ENABLE_RESAMPLING
	size_t maxbufsiz = nframes;
	int err = 0;
	SRC_STATE* src_state = src_new(SRC_QUALITY, nfo->channels, NULL);
	SRC_DATA src_data;
	int nframes_r = floorf((float) nframes*m_fResampleRatio); ///< # of frames after resampling
#ifdef VARISPEED
	maxbufsiz = (2+nframes_r) * 2;
#else
	maxbufsiz = (1+nframes_r);
#endif
	float *smpbuf = (float*) calloc(maxbufsiz * nfo->channels, sizeof(float));

	src_data.input_frames  = nframes;
	src_data.output_frames = nframes_r;
	src_data.end_of_input  = 0;
	src_data.src_ratio     = m_fResampleRatio;
	src_data.input_frames_used = 0;
	src_data.output_frames_gen = 0;
	src_data.data_in       = tmpbuf;
	src_data.data_out      = smpbuf;
#else
	int nframes_r = nframes; // no resampling
#endif

	int ladspaerr = 0;
#if (defined ENABLE_LADSPA)
	if (m_use_effect && play->enable_effect) {
		int i;
		for(i=0;i<nfo->channels;i++) {
			ladspaerr |= ladspah_init(myplugin[i], m_use_effect, m_effectno, 
					jack_get_sample_rate(j_client) /* m_samplerate */, maxbufsiz);
		}
		if (ladspaerr) {
			dbg(0, "error setting up LADSPA plugin - effect disabled.\n");
		}
	} else {
		ladspaerr = 1;
	}
	play->effect_enabled = ladspaerr ? false : true; // read-only for GUI
#endif

	size_t rbchunk = nframes_r * nfo->channels * sizeof(float);
	play_position = 0;
	int64_t decoder_position = 0;

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

	/** ALL SYSTEMS GO **/
	player_active = 1;
	while(thread_run) {
		int rv = ad_read(myplayer, tmpbuf, nframes * nfo->channels);

		if (rv > 0) decoder_position += rv / nfo->channels;

#ifdef JACK_MIDI
		const float pp[3] = {play->effect_param[0], play->effect_param[1] + midi_note, play->effect_param[2] + midi_octave};
#else
		const float pp[3] = {play->effect_param[0], play->effect_param[1], play->effect_param[2]};
#endif
#if (defined ENABLE_RESAMPLING) && (defined VARISPEED)
		const float varispeed = play->playback_speed;
#if 0
		/* note: libsamplerate slowly approaches a new sample-rate slowly
		 * src_set_ratio() allow for immediate updates at loss of quality */
		static float oldspd = -1;
		if (oldspd != varispeed) {
			if ((err = src_set_ratio(src_state, m_fResampleRatio * varispeed))) dbg(0, "SRC ERROR: %s", src_strerror(err)); // instant change.
			oldspd = varispeed;
		}
#endif
		nframes_r = floorf((float) nframes * m_fResampleRatio * varispeed); ///< # of frames after resampling
		src_data.input_frames  = nframes;
		src_data.output_frames = nframes_r;
		src_data.src_ratio     = m_fResampleRatio * varispeed;
		src_data.end_of_input  = 0;
#endif

		if (rv != nframes * nfo->channels) {
			dbg(1, "end of file.");
			if (rv > 0) {
#ifdef ENABLE_RESAMPLING
# ifdef VARISPEED
				if (1) 
# else
				if(m_fResampleRatio != 1.0)
# endif
				{
					src_data.input_frames = rv / nfo->channels;
#ifdef VARISPEED
					src_data.output_frames = floorf((float)(rv / nfo->channels) * m_fResampleRatio * varispeed);
#else
					src_data.output_frames = floorf((float)(rv / nfo->channels) * m_fResampleRatio);
#endif
					src_data.end_of_input = play->config.loop ? 0 : 1;
					src_process(src_state, &src_data);
					bufptr = smpbuf;
					rv = src_data.output_frames_gen * nfo->channels;
				}
#endif
				if (!ladspaerr) {
					ladspah_set_param(myplugin, nfo->channels, 0 /*cents */, pp[0]); /* -100 .. 100 */
					ladspah_set_param(myplugin, nfo->channels, 1 /*semitones */, pp[1]); /* -12 .. 12 */
					ladspah_set_param(myplugin, nfo->channels, 2 /*octave */, pp[2]);    /*  -3 ..  3 */
					ladspah_process_nch(myplugin, nfo->channels, bufptr, rv / nfo->channels);
				}
				jack_ringbuffer_write(rb, (char *) bufptr, rv *  sizeof(float));
			}
			if (play->config.loop) {
				ad_seek(myplayer, 0);
				decoder_position = 0;
#ifdef ENABLE_RESAMPLING
				//src_reset (src_state); // XXX causes click
# ifdef VARISPEED
				if (1) 
# else
				if(m_fResampleRatio != 1.0)
# endif
				{
					src_data.end_of_input  = 0;
					src_data.input_frames  = nframes;
					src_data.output_frames = nframes_r;
				}
#endif
#if (defined ENABLE_RESAMPLING) && (defined VARISPEED)
				while(thread_run && jack_ringbuffer_write_space(rb) <= maxbufsiz*nfo->channels*sizeof(float))
#else
				while(thread_run && jack_ringbuffer_write_space(rb) <= rbchunk)
#endif
				{
					pthread_cond_wait(&buffer_ready, &player_thread_lock);
				}
				continue;
			}
			else
				break;
		} /* end EOF handling */

#ifdef ENABLE_RESAMPLING
#ifdef VARISPEED
		if(1) // m_fResampleRatio*varispeed != 1.0)
#else
		if(m_fResampleRatio != 1.0)
#endif
		{
			if ((err=src_process(src_state, &src_data))) {
				dbg(0, "SRC PROCESS ERROR: %s", src_strerror(err));
			}
			bufptr = smpbuf;
			rbchunk = src_data.output_frames_gen * nfo->channels * sizeof(float);
		}
#endif
		if (!ladspaerr) {
			ladspah_set_param(myplugin, nfo->channels, 0 /*cent */, pp[0]); /* -100 .. 100 */
			ladspah_set_param(myplugin, nfo->channels, 1 /*semitones */, pp[1]); /* -12 .. 12 */
			ladspah_set_param(myplugin, nfo->channels, 2 /*octave */, pp[2]);    /*  -3 ..  3 */
			ladspah_process_nch(myplugin, nfo->channels, bufptr, rbchunk/ nfo->channels / sizeof(float));
		}
		jack_ringbuffer_write(rb, (char *) bufptr, rbchunk);

#if (defined ENABLE_RESAMPLING) && (defined VARISPEED)
		while(thread_run && jack_ringbuffer_write_space(rb) <= maxbufsiz*nfo->channels*sizeof(float))
#else
		while(thread_run && jack_ringbuffer_write_space(rb) <= rbchunk) 
#endif
		{
#if 1 // flush_ringbuffer on seek
			if (playpause && seek_request != -1) break; 
#endif
			pthread_cond_wait(&buffer_ready, &player_thread_lock);
		}

		/* Handle SEEKs */
		while (seek_request>=0 && seek_request<=1) {
			double csr = seek_request;
			decoder_position = floor(m_frames * seek_request);
			ad_seek(myplayer, decoder_position);
			if (csr == seek_request) {
				seek_request = -1;
#if 1 // flush_ringbuffer !
				size_t rs=jack_ringbuffer_read_space(rb);
				jack_ringbuffer_read_advance(rb,rs);
#endif
				break;
			}
		}
#if (defined ENABLE_RESAMPLING) && (defined VARISPEED)
		update_playposition (decoder_position, varispeed);
#else
		update_playposition (decoder_position, 1.0);
#endif
	}

	/** END OF PLAYBACK **/
#if (defined ENABLE_RESAMPLING) && (defined VARISPEED)
	const float varispeed = play->playback_speed;
#else
	const float varispeed = 1.0;
#endif
	pthread_mutex_unlock(&player_thread_lock);

	if (thread_run) {
		// wait for ringbuffer to empty.
		while (!silent && !playpause) {
			usleep(20);
			update_playposition (decoder_position, varispeed);
		}
		thread_run = 0;
		player_active = 0;
		play->effect_enabled = false;
		int i;
		for(i=0;i<nfo->channels;i++) {
			ladspah_deinit(myplugin[i]);
		}
		JACKclose(); 
	}
	free(tmpbuf);
#ifdef ENABLE_RESAMPLING
	src_delete(src_state);
	free(smpbuf);
#endif
	player_active = 0;
	if(play->status != PLAY_PLAY_PENDING){
		play->next();
	}
	return NULL;
}
Esempio n. 25
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;
}
Esempio n. 26
0
unsigned int JackResampler::WriteSpace()
{
    return (jack_ringbuffer_write_space(fRingBuffer) / sizeof(jack_default_audio_sample_t));
}
Esempio n. 27
0
void* audio_thread(void* arg) {
	RECEIVER *rx=(RECEIVER*)arg;
	struct sockaddr_in audio;
	int audio_length=sizeof(audio);
	int old_state, old_type;
	int bytes_read;
	int on=1;

#ifdef USE_PIPES
	int  pipe_left = *softrock_get_jack_write_pipe_left(rx->client->receiver);
	int  pipe_right = *softrock_get_jack_write_pipe_right(rx->client->receiver);
#else // Use ringbuffers
	jack_ringbuffer_t *rb_left = softrock_get_jack_rb_left(rx->client->receiver);
	jack_ringbuffer_t *rb_right = softrock_get_jack_rb_right(rx->client->receiver);
#endif
	int num_bytes = sizeof(float)*BUFFER_SIZE;
	
	static int second_time = 0;

	BUFFER buffer;
	unsigned long sequence=0L;
	unsigned short offset=0;;


	if (softrock_get_verbose()) fprintf(stderr,"audio_thread port=%d\n",audio_port+(rx->id*2));

	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,&old_state);
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,&old_type);

	rx->audio_socket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
	if(rx->audio_socket<0) {
		perror("create socket failed for server audio socket");
		exit(1);
	}

	setsockopt(rx->audio_socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

	memset(&audio,0,audio_length);
	audio.sin_family=AF_INET;
	audio.sin_addr.s_addr=htonl(INADDR_ANY);
	audio.sin_port=htons(audio_port+(rx->id*2));

	if(bind(rx->audio_socket,(struct sockaddr*)&audio,audio_length)<0) {
		perror("bind socket failed for server audio socket");
		exit(1);
	}

	if (softrock_get_verbose()) fprintf(stderr,"listening for tx %d IQ audio on port %d\n",rx->id,audio_port+(rx->id*2));

	while(1) {
		// get audio from a client
#ifdef SMALL_PACKETS  
		while(1) {
			bytes_read=recvfrom(rx->audio_socket,(char*)&buffer,sizeof(buffer),0,(struct sockaddr*)&audio,(socklen_t *)&audio_length);
			if(bytes_read<0) {
				perror("recvfrom socket failed for tx iq buffer");
				exit(1);
			}

			//fprintf(stderr,"rcvd UDP packet: sequence=%lld offset=%d length=%d\n", buffer.sequence, buffer.offset, buffer.length);

			if(buffer.offset==0) {
				offset=0;
				sequence=buffer.sequence;
				// start of a frame
				memcpy((char *)&rx->output_buffer[buffer.offset/4],(char *)&buffer.data[0],buffer.length);
				offset+=buffer.length;
			} else {
				if((sequence==buffer.sequence) && (offset==buffer.offset)) {
					memcpy((char *)&rx->output_buffer[buffer.offset/4],(char *)&buffer.data[0],buffer.length);
					offset+=buffer.length;
					if(offset==sizeof(rx->output_buffer)) {
						offset=0;
						break;
					}
				} else {
					fprintf(stderr,"missing TX IQ frames expected %ld.%d got %ld.%d\n", (long)sequence,(int)offset,(long)buffer.sequence,(int)buffer.offset);
				}
			}
		}
#else
		bytes_read=recvfrom(rx->audio_socket,rx->output_buffer,sizeof(rx->output_buffer),0,(struct sockaddr*)&audio,(socklen_t *)&audio_length);
		if(bytes_read<0) {
			perror("recvfrom socket failed for audio buffer");
			exit(1);
		}
#endif
		if (softrock_get_jack () == 1) { 
			if (second_time == 32) {// This is for testing only.  It will fail the second connection from QtRadio.
				softrock_set_client_active_rx(rx->client->receiver, ADD_RX);	
			}
			second_time++;
			/*if ( second_time == 4000 ) {
				fprintf(stderr, "reached 4000.\n");
				exit(0);
			}*/	

#ifdef USE_PIPES
			//fprintf(stderr,"client.c pipe_left is: %d \n",pipe_left);
			//fprintf(stderr,"rx->client->receiver is: %d\n",rx->client->receiver);
			error_no = write(pipe_left, &rx->output_buffer[0], num_bytes);
			if (error_no == -1) {
				if ( softrock_get_verbose () == 1) perror("There were problems writing the left pipe for Jack in client.c");
				//fprintf(stderr, "Note: resource temporarilly unavailable indicates write would have blocked.  , blocked %d times\n",blocked_num);
				fprintf(stderr, "blocked %d times\nwritten %d times\n",blocked_num,second_time);
				blocked_num++;
			}
			//else fprintf(stderr,"Wrote %d bytes on left channel.\n",num_bytes);
			error_no = write(pipe_right, &rx->output_buffer[BUFFER_SIZE], num_bytes);
			if (error_no == -1) {
				if ( softrock_get_verbose () == 1) perror("There were problems writing the right pipe for Jack in client.c.");
				fprintf(stderr, "Note: resource temporarilly unavailable indicates write would have blocked.\n");
			}
#else  // Use ringbuffers
			if (( jack_ringbuffer_write_space (rb_left) >= num_bytes ) &&  (jack_ringbuffer_write_space (rb_right) >= num_bytes ))
			{
				jack_ringbuffer_write (rb_left, (const char *) &rx->output_buffer[0], num_bytes);
				jack_ringbuffer_write (rb_right, (const char *) &rx->output_buffer[BUFFER_SIZE], num_bytes);
			}
			else
			{
				fprintf(stderr, "No space left to write in jack ringbuffers.\n");
			}
#endif
		} else {
			process_softrock_output_buffer(rx->output_buffer,&rx->output_buffer[BUFFER_SIZE]);
		}
	}
	softrock_set_client_active_rx (rx->client->receiver, DEC_RX); //How do we ever get here?
}
Esempio n. 28
0
int process(jack_nframes_t nframes, void *arg) {
    struct guitarseq *guitarseq = arg;
    if(!guitarseq) {
        fprintf(stderr, "No guitarseq instance!\n");
        return 1;
    }

    void* port_buf;
    jack_nframes_t now = jack_frame_time (guitarseq->jack_client);

    //Output
    port_buf = jack_port_get_buffer(guitarseq->out_port, nframes);
    jack_midi_clear_buffer(port_buf);
    while (1) {
        jack_nframes_t time;
        //TODO: Do a safer read, in case only part of the message is here
        if (!jack_ringbuffer_read (guitarseq->out_buffer, (char *)&time, sizeof(time))) {
            break;
        }

        // from the future?
        if (time >= now) {
            break;
        }

        // time it right
        jack_nframes_t offset = time - now + nframes - 1;

        // get the size of the event
        size_t size;
        jack_ringbuffer_read(guitarseq->out_buffer, (char *)&size, sizeof(size));

        INFO("out event at %u%+d size %zu\n", now, offset, size);

        if (offset > nframes)
            // from the past, somehow. cram it in at the front
            offset = 0;

        // proceed to giving it to jack
        jack_midi_data_t *buffer = jack_midi_event_reserve (port_buf, offset, size);
        if(buffer) {
            jack_ringbuffer_read(guitarseq->out_buffer, (char *)buffer, size);
        } else {
            // throw it away :( TODO: find more
            jack_ringbuffer_read_advance (guitarseq->out_buffer, size);
            ERROR("threw away MIDI event - no space reserved at time %u offset %d\n",time,offset);
        }
    }

    // 	Input
    port_buf = jack_port_get_buffer(guitarseq->in_port, nframes);
    jack_nframes_t event_count = jack_midi_get_event_count(port_buf);
    for(jack_nframes_t i=0; i<event_count; i++) {
        jack_midi_event_t in_event;
        jack_midi_event_get(&in_event, port_buf, i);

        //adds a note to the ringbuffer
        if (jack_ringbuffer_write_space(guitarseq->in_buffer) >= sizeof(in_event.time)+sizeof(in_event.size)+in_event.size) {
            jack_ringbuffer_write(guitarseq->in_buffer, (char *)&in_event.time, sizeof(in_event.time));
            jack_ringbuffer_write(guitarseq->in_buffer, (char *)&in_event.size, sizeof(in_event.size));
            jack_ringbuffer_write(guitarseq->in_buffer, (char *)in_event.buffer, in_event.size);
        } else {
            ERROR("Couldn't write to ringbuffer at %u, %zu midi data bytes lost\n", in_event.time, in_event.size);
        }
    }

    return 0;
}