size_t rb_write(RingBuffer *rb, const void *data, size_t count) { //assert(rb != NULL); //assert(data != NULL); if (count >= rb_can_write(rb)) return -1; if (rb->rb_head <= rb->rb_tail) { int tail_avail_sz = rb_capacity(rb) - (rb->rb_tail - rb->rb_buff); if (count <= tail_avail_sz) { memcpy(rb->rb_tail, data, count); rb->rb_tail += count; if (rb->rb_tail == rb->rb_buff+rb_capacity(rb)) rb->rb_tail = rb->rb_buff; return count; } else { memcpy(rb->rb_tail, data, tail_avail_sz); rb->rb_tail = rb->rb_buff; return tail_avail_sz + rb_write(rb, (char*)data+tail_avail_sz, count-tail_avail_sz); } } else { memcpy(rb->rb_tail, data, count); rb->rb_tail += count; return count; } }
/****************************************************** * function : serialEvent * Description : arduino serial uart receive interrupt * function * * return : none. * Add by Alex.lin --2014-12-24 ******************************************************/ void serialEvent(void) { uint8_t value = 0; value = (unsigned char)Serial1.read(); if(rb_can_write(&u_ring_buff) > 0) { rb_write(&u_ring_buff, &value, 1); } Serial.println(value, HEX);//不加这句容易出BUG }
//============================================================================= void debug(rb_t *rb, int from_thread) { if(rb==NULL) { fprintf(stderr,"\nrb is NULL\n"); return; } fprintf(stderr,"can read %" PRId64 " @ %" PRId64 " can write %" PRId64 " @ %" PRId64 " %s\n" ,rb_can_read(rb) ,rb->read_index ,rb_can_write(rb) ,rb->write_index ,(from_thread==READER_THREAD ? "reader" : "writer") ); }
// /audio //handler for audio messages int audio_handler(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { if(shutdown_in_progress==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 and channel offset 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,"\n\nchannel offset %d >= available input channels %d! (nothing to receive). shutting down...\n" ,channel_offset ,(argc-data_offset+channel_offset)); fflush(stderr); shutdown_in_progress=1; return 0; } //need to warn when offset + outchannels limited //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; loa = lo_message_get_source(data); strcpy(sender_host,lo_address_get_hostname(loa)); strcpy(sender_port,lo_address_get_port(loa)); remote_sample_rate=argv[3]->i; remote_period_size=lo_blob_datasize((lo_blob)argv[0+data_offset])/bytes_per_sample; fprintf(stderr,"\nsender was (re)started. "); if(remote_period_size!=period_size) { fprintf(stderr,"sender period size: %d samples (%.3f x forward period size)\n\n",remote_period_size,(float)remote_period_size/period_size); } else { fprintf(stderr,"equal sender and receiver period size\n\n"); } }//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; 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; } fflush(stderr); // 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=rb_can_write(rb); if(can_write_count < mc_period_bytes) { buffer_overflow_counter++; ///////////////// fprintf(stderr,"\nBUFFER OVERFLOW! this is bad -----%s\n","\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=rb_write(rb, (void *) data, period_size*bytes_per_sample); } } 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=rb_write(rb_helper, (void *) data, remote_period_size*bytes_per_sample); } //if enough data collected for one larger multichannel period while(rb_can_read(rb_helper) >=mc_period_bytes && rb_can_write(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; rb_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=rb_write(rb,(void *)data,remote_period_size*bytes_per_sample); } } data=orig_data; free(data); } } 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=rb_write(rb, (void *) data, period_size*bytes_per_sample); } } } return 0; }//end audio_handler