static void sco_close_output_stream(struct audio_hw_device *dev, struct audio_stream_out *stream_out) { struct sco_dev *sco_dev = (struct sco_dev *) dev; struct sco_stream_out *out = (struct sco_stream_out *) stream_out; DBG("dev %p stream %p fd %d", dev, stream_out, sco_dev->out->fd); if (sco_dev->out && sco_dev->out->fd) { close(sco_dev->out->fd); sco_dev->out->fd = -1; } if (out->resampler) release_resampler(out->resampler); free(out->downmix_buf); free(out); sco_dev->out = NULL; }
//This is the rx samples forwarding thread (private) void *usrp_rx_forwarder_thread (void *param) { RECEIVER *pRec = (RECEIVER *)param; int old_state, old_type; //debug //std::cerr << inspect_receiver(pRec) << std::endl; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,&old_state); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,&old_type); RECEIVER_CYCLE = true; pRec->samples = 0; std::vector<std::complex<float> > *buff; QUEUE_BUFFER_ENTRY *item; //NEW RES LIB int resampler_id = resampler_setup_new(MAX_USRP_RX_BUFFER, DECIM_RX, INTERP_RX); if (resampler_id < 0) { //FAILURE! std::cerr << "RX Resampler object definition failed. Exiting..." << std::endl; exit (1); } std::cerr << boost::format("RX thread Using resampler %d.") % resampler_id << std::endl; std::cerr << "Starting the RX Data forwarding thread cycle" << std::endl; while(1) { pthread_mutex_lock(&RECEIVER_CYCLE_lock); bool do_cycle = RECEIVER_CYCLE; pthread_mutex_unlock(&RECEIVER_CYCLE_lock); if (! do_cycle) break; //Extract from queue //If there is Vector buffer in the queue pthread_mutex_lock(&rx_queue_lock); item = TAILQ_FIRST(&rx_samples_iq_stream); if (item != NULL) { //Take next Vector buffer from the queue buff = (std::vector<std::complex<float> > *)item->data; TAILQ_REMOVE(&rx_samples_iq_stream, item, entries); rx_queue_length--; pthread_mutex_unlock(&rx_queue_lock); } else { pthread_mutex_unlock(&rx_queue_lock); usleep(QUEUE_WAIT_TIME); continue; } //RX path is disabled: skip the rest if (drop_rx_samples) { //Vector cleanup delete buff; free(item); continue; } size_t num_rx_samps = buff->size(); //Rational resampling is applied at this point //Interleaving real/imag in the resampler buffer if (real_position == 1) { unsigned int i; #pragma omp parallel for schedule(static) private(i) for (i=0; i<num_rx_samps; ++i) resampler_load_data(resampler_id, i, (*buff)[i].imag(), (*buff)[i].real()); } else { unsigned int i; #pragma omp parallel for schedule(static) private(i) for (i=0; i<num_rx_samps; ++i) resampler_load_data(resampler_id, i, (*buff)[i].real(), (*buff)[i].imag()); } //Vector cleanup delete buff; free(item); //Rational resampling API here char *rr_msg = NULL; int output_frames_gen = 0; int rr_retcode = do_resample(resampler_id, num_rx_samps, &output_frames_gen, rr_msg); //std::cerr << boost::format("output_frames_gen %d.") % output_frames_gen << std::endl; //TIME BECHMARKING //gettimeofday(tod1, NULL); //std::cerr << boost::format("After resampler: %d |") % (tod1->tv_usec - tod->tv_usec); if (rr_retcode == RRESAMPLER_NO_ERROR) { //Fetch resampled data into the Receiver input buffer for (int j=0; j<output_frames_gen ; ++j) { resampler_fetch_data(resampler_id, j, &pRec->input_buffer[pRec->samples], &pRec->input_buffer[pRec->samples+RECEIVE_BUFFER_SIZE]); pRec->samples++; if(pRec->samples==RECEIVE_BUFFER_SIZE) { //send I/Q data to client //std::cerr << boost::format("%s: sending data.") % __FUNCTION__ << std::endl; send_IQ_buffer(pRec); pRec->samples=0; } } } else { //A rational resampler error occurred! std::cerr << boost::format("RX Rational resampling error: %s") % rr_msg << std::endl; } } release_resampler(resampler_id); fprintf(stderr,"Exiting from USRP RX Forwarder thread\n"); return NULL; }
static int sco_open_output_stream(struct audio_hw_device *dev, audio_io_handle_t handle, audio_devices_t devices, audio_output_flags_t flags, struct audio_config *config, struct audio_stream_out **stream_out) { struct sco_dev *adev = (struct sco_dev *) dev; struct sco_stream_out *out; int fd = -1; int chan_num, ret; size_t resample_size; uint16_t mtu; DBG(""); if (ipc_connect_sco(&fd, &mtu) != SCO_STATUS_SUCCESS) { error("sco: cannot get fd"); return -EIO; } DBG("got sco fd %d mtu %u", fd, mtu); out = calloc(1, sizeof(struct sco_stream_out)); if (!out) return -ENOMEM; out->stream.common.get_sample_rate = out_get_sample_rate; out->stream.common.set_sample_rate = out_set_sample_rate; out->stream.common.get_buffer_size = out_get_buffer_size; out->stream.common.get_channels = out_get_channels; out->stream.common.get_format = out_get_format; out->stream.common.set_format = out_set_format; out->stream.common.standby = out_standby; out->stream.common.dump = out_dump; out->stream.common.set_parameters = out_set_parameters; out->stream.common.get_parameters = out_get_parameters; out->stream.common.add_audio_effect = out_add_audio_effect; out->stream.common.remove_audio_effect = out_remove_audio_effect; out->stream.get_latency = out_get_latency; out->stream.set_volume = out_set_volume; out->stream.write = out_write; out->stream.get_render_position = out_get_render_position; /* Configuration for Android */ out->cfg.format = AUDIO_STREAM_DEFAULT_FORMAT; out->cfg.channels = AUDIO_CHANNEL_OUT_STEREO; out->cfg.rate = AUDIO_STREAM_DEFAULT_RATE; out->cfg.frame_num = OUT_STREAM_FRAMES; out->cfg.mtu = mtu; out->downmix_buf = malloc(out_get_buffer_size(&out->stream.common)); if (!out->downmix_buf) { free(out); return -ENOMEM; } DBG("size %zd", out_get_buffer_size(&out->stream.common)); /* Channel numbers for resampler */ chan_num = 1; ret = create_resampler(out->cfg.rate, AUDIO_STREAM_SCO_RATE, chan_num, RESAMPLER_QUALITY_DEFAULT, NULL, &out->resampler); if (ret) { error("Failed to create resampler (%s)", strerror(ret)); goto failed; } DBG("Created resampler: input rate [%d] output rate [%d] channels [%d]", out->cfg.rate, AUDIO_STREAM_SCO_RATE, chan_num); out->resample_frame_num = get_resample_frame_num(AUDIO_STREAM_SCO_RATE, out->cfg.rate, out->cfg.frame_num, 1); if (!out->resample_frame_num) { error("frame num is too small to resample, discard it"); goto failed; } resample_size = sizeof(int16_t) * chan_num * out->resample_frame_num; out->resample_buf = malloc(resample_size); if (!out->resample_buf) { error("failed to allocate resample buffer for %u frames", out->resample_frame_num); goto failed; } DBG("resampler: frame num %u buf size %zd bytes", out->resample_frame_num, resample_size); *stream_out = &out->stream; adev->out = out; out->fd = fd; return 0; failed: if (out->resampler) release_resampler(out->resampler); free(out->downmix_buf); free(out); stream_out = NULL; adev->out = NULL; return ret; }