int samplerate(jack_nframes_t rate, void *arg) { JackCard* obj = (JackCard*) arg; int error; obj->rate = rate; if (obj->read.open) { obj->read.data.src_ratio = (double)obj->read.rate / (double)obj->rate; obj->read.data.input_frames = (long)((double)obj->read.frames/obj->read.data.src_ratio); g_free(obj->read.data.data_in); obj->read.data.data_in = malloc(obj->read.data.input_frames*sizeof(float)); if (obj->read.src_state) if ((error = src_set_ratio(obj->read.src_state, obj->read.data.src_ratio)) != 0) g_warning("Error while resetting the write samplerate: %s", src_strerror(error)); } if (obj->write.open) { obj->write.data.src_ratio = (double)obj->rate / (double)obj->write.rate; obj->write.data.output_frames = (long)((double)obj->write.frames*obj->write.data.src_ratio); g_free(obj->write.data.data_out); obj->write.data.data_out = malloc(obj->write.data.output_frames*sizeof(float)); if (obj->write.src_state) if ((error = src_set_ratio(obj->write.src_state, obj->write.data.src_ratio)) != 0) g_warning("Error while resetting the write samplerate: %s", src_strerror(error)); } return 0; }
int Resample::Process(double factor, float *inBuffer, int inBufferLen, bool lastFlag, int *inBufferUsed, float *outBuffer, int outBufferLen) { if (mInitial) { src_set_ratio((SRC_STATE *)mHandle, factor); mInitial = false; } SRC_DATA data; data.data_in = inBuffer; data.data_out = outBuffer; data.input_frames = inBufferLen; data.output_frames = outBufferLen; data.input_frames_used = 0; data.output_frames_gen = 0; data.end_of_input = (int)lastFlag; data.src_ratio = factor; int err = src_process((SRC_STATE *)mHandle, &data); if (err) { wxFprintf(stderr, _("Libsamplerate error: %d\n"), err); return 0; } *inBufferUsed = (int)data.input_frames_used; return (int)data.output_frames_gen; }
void ddb_src_set_ratio (ddb_dsp_context_t *_src, float ratio) { ddb_src_libsamplerate_t *src = (ddb_src_libsamplerate_t*)_src; if (src->srcdata.src_ratio != ratio) { src->srcdata.src_ratio = ratio; src_set_ratio (src->src, ratio); } }
void* decOpen( const char* inputurl, size_t* bitspersample, size_t* channels, size_t* samplerate) { int i; for(i = 0; decoders[i].open != NULL ; i++) { int err; void* data; dec_data* ret; if((data = decoders[i].open( inputurl, bitspersample, channels, samplerate, &err)) == NULL) { if(err != INVALID_FORMAT) return NULL; else continue; } if((ret = (dec_data*)malloc(sizeof(dec_data))) == NULL) { decoders[i].close(data); return NULL; } ret->decoder = &decoders[i]; ret->data = data; if((ret->converter = src_new(SRC_LINEAR, audio_channels, &err)) == NULL) { LOG(L"libsamplerate: " MB_FORMAT "\n", src_strerror(err)); decoders[i].close(data); free(ret); return NULL; } ret->ratio = ((double)audio_samplerate / (double)*samplerate); src_set_ratio((SRC_STATE*)ret->converter, ret->ratio); ret->samplerate = *samplerate; ret->channels = *channels; return ret; } return NULL; }
void SampleChannel::setPitch(float v) { pitch = v; rsmp_data.src_ratio = 1/pitch; /* if status is off don't slide between frequencies */ if (status & (STATUS_OFF | STATUS_WAIT)) src_set_ratio(rsmp_state, 1/pitch); }
static block_t *Resample (filter_t *filter, block_t *in) { block_t *out = NULL; const size_t framesize = filter->fmt_out.audio.i_bytes_per_frame; SRC_STATE *s = (SRC_STATE *)filter->p_sys; SRC_DATA src; src.src_ratio = (double)filter->fmt_out.audio.i_rate / (double)filter->fmt_in.audio.i_rate; int err = src_set_ratio (s, src.src_ratio); if (err != 0) { msg_Err (filter, "cannot update resampling ratio: %s", src_strerror (err)); goto error; } src.input_frames = in->i_nb_samples; src.output_frames = ceil (src.src_ratio * src.input_frames); src.end_of_input = 0; out = block_Alloc (src.output_frames * framesize); if (unlikely(out == NULL)) goto error; src.data_in = (float *)in->p_buffer; src.data_out = (float *)out->p_buffer; err = src_process (s, &src); if (err != 0) { msg_Err (filter, "cannot resample: %s", src_strerror (err)); block_Release (out); out = NULL; goto error; } if (src.input_frames_used < src.input_frames) msg_Err (filter, "lost %ld of %ld input frames", src.input_frames - src.input_frames_used, src.input_frames); out->i_buffer = src.output_frames_gen * framesize; out->i_nb_samples = src.output_frames_gen; out->i_pts = in->i_pts; out->i_length = src.output_frames_gen * CLOCK_FREQ / filter->fmt_out.audio.i_rate; error: block_Release (in); return out; }
int ResampleSRC::Do(int chns,Fifo<float> *input,float *const *output,int need,double ratio) { if(ratio == 1) return Resample::Do(chns,input,output,frames,1); assert(chns <= channels); SRC_DATA src_data; src_data.src_ratio = ratio; src_data.end_of_input = 0; int count = -1; // hopefully all channel fifos advance uniformly..... for(int i = 0; i < chns; ++i) { src_set_ratio(state[i],ratio); for(int got = 0; got < frames; ) { src_data.data_out = output[i]+got; src_data.output_frames = frames-got; if(decoded[i].Have()) { src_data.data_in = input[i].ReadPtr(); src_data.input_frames = input[i].ReadSamples(); int err = src_process(state[i],&src_data); if(err) post("src_process error %i",err); // advance buffer decoded[i].Read(src_data.input_frames_used,NULL); } else { schedWait(); if(debug) post("fifo underrun"); // Buffer underrun!! -> zero output buffer memset(src_data.data_out,0,src_data.output_frames*sizeof(*src_data.data_out)); src_data.output_frames_gen = src_data.output_frames; } got += src_data.output_frames_gen; } assert(count < 0 || got == count); count = got; } return count; }
int VarRateResample::Process(double factor, float *inBuffer, int inBufferLen, bool lastFlag, int *inBufferUsed, float *outBuffer, int outBufferLen) { src_set_ratio((SRC_STATE *)mHandle, factor); SRC_DATA data; if(mShouldReset) { if(inBufferLen > mSamplesLeft) { mShouldReset = false; src_reset((SRC_STATE *)mHandle); } else { mSamplesLeft -= inBufferLen; } } data.data_in = inBuffer; data.data_out = outBuffer; data.input_frames = inBufferLen; data.output_frames = outBufferLen; data.input_frames_used = 0; data.output_frames_gen = 0; data.end_of_input = (int)lastFlag; data.src_ratio = factor; int err = src_process((SRC_STATE *)mHandle, &data); if (err) { wxFprintf(stderr, _("Libsamplerate error: %d\n"), err); return 0; } if(lastFlag) { mShouldReset = true; mSamplesLeft = inBufferLen - (int)data.input_frames_used; } *inBufferUsed = (int)data.input_frames_used; return (int)data.output_frames_gen; }
void CDVDPlayerResampler::Add(DVDAudioFrame &audioframe, double pts) { //check if nr of channels changed so we can allocate new buffers if necessary CheckResampleBuffers(audioframe.channel_count); //value to divide samples by to get them into -1.0:1.0 range float scale = (float)(1 << (audioframe.bits_per_sample - 1)); int nrframes = audioframe.size / audioframe.channel_count / (audioframe.bits_per_sample / 8); //resize sample buffer if necessary //we want the buffer to be large enough to hold the current frames in it, //the number of frames needed for libsamplerate's input //and the maximum number of frames libsamplerate might generate, times 2 for safety ResizeSampleBuffer(m_bufferfill + nrframes + nrframes * MathUtils::round_int(m_ratio + 0.5) * 2); //assign samplebuffers m_converterdata.input_frames = nrframes; m_converterdata.output_frames = m_buffersize - m_bufferfill - m_converterdata.input_frames; //output buffer starts at the place where the buffer doesn't hold samples m_converterdata.data_out = m_buffer + m_bufferfill * m_nrchannels; //intput buffer is a block of data at the end of the buffer m_converterdata.data_in = m_converterdata.data_out + m_converterdata.output_frames * m_nrchannels; //add samples to the resample input buffer int16_t* inputptr = (int16_t*)audioframe.data; float* outputptr = m_converterdata.data_in; for (int i = 0; i < nrframes * m_nrchannels; i++) *outputptr++ = (float)*inputptr++ / scale; //resample m_converterdata.src_ratio = m_ratio; src_set_ratio(m_converter, m_ratio); src_process(m_converter, &m_converterdata); //calculate a pts for each sample for (int i = 0; i < m_converterdata.output_frames_gen; i++) { m_ptsbuffer[m_bufferfill] = pts + i * (audioframe.duration / (double)m_converterdata.output_frames_gen); m_bufferfill++; } }
static bool pcm_resample_set(struct pcm_resample_state *state, uint8_t channels, unsigned src_rate, unsigned dest_rate, GError **error_r) { static int convalgo = -1; int error; SRC_DATA *data = &state->data; if (convalgo < 0) convalgo = pcm_resample_get_converter(); /* (re)set the state/ratio if the in or out format changed */ if (channels == state->prev.channels && src_rate == state->prev.src_rate && dest_rate == state->prev.dest_rate) return true; state->error = 0; state->prev.channels = channels; state->prev.src_rate = src_rate; state->prev.dest_rate = dest_rate; if (state->state) state->state = src_delete(state->state); state->state = src_new(convalgo, channels, &error); if (!state->state) { g_set_error(error_r, libsamplerate_quark(), state->error, "libsamplerate initialization has failed: %s", src_strerror(error)); return false; } data->src_ratio = (double)dest_rate / (double)src_rate; g_debug("setting samplerate conversion ratio to %.2lf", data->src_ratio); src_set_ratio(state->state, data->src_ratio); return true; }
int JackProcess(jack_nframes_t nframes, void *arg) { DevJack *dev=(DevJack *)arg; static unsigned i; static jack_nframes_t j; static float pcm_s1[MAX_AUDIO_CHANNELS*RINGBUFFER_SIZE]; static float pcm_s2[MAX_AUDIO_CHANNELS*RINGBUFFER_SIZE]; static unsigned ring_frames; static unsigned n; static int err; static unsigned pcm_start=0; static int pcm_offset=0; static float lvls[MAX_AUDIO_CHANNELS]; // // Wait for PCM Buffer to Fill // if(!dev->jack_started) { if(dev->codec()->ring()->readSpace()<2*dev->codec()->samplerate()) { return 0; } dev->jack_pll_setpoint_frames=2*dev->codec()->samplerate(); dev->jack_started=true; } // // Update PLL // ring_frames=dev->codec()->ring()->readSpace(); if(ring_frames>dev->jack_pll_setpoint_frames) { if(dev->jack_pll_offset>(-PLL_CORRECTION_LIMIT)) { dev->jack_pll_offset-=PLL_CORRECTION; } } else { if(dev->jack_pll_offset<(PLL_CORRECTION_LIMIT)) { dev->jack_pll_offset+=PLL_CORRECTION; } } dev->jack_data.src_ratio=dev->jack_pll_setpoint_ratio+dev->jack_pll_offset; src_set_ratio(dev->jack_src,dev->jack_data.src_ratio); // // Get Buffers // for(i=0;i<dev->codec()->channels();i++) { jack_cb_buffers[i]=(jack_default_audio_sample_t *) jack_port_get_buffer(dev->jack_jack_ports[i],nframes); } // // Read Codec Output // n=nframes/dev->jack_data.src_ratio+pcm_offset; if(dev->codec()->ring()->readSpace()>=n) { n=dev->codec()->ring()->read(pcm_s1,n); // // SRC // dev->jack_data.data_in=pcm_s1; dev->jack_data.input_frames=n; dev->jack_data.data_out=pcm_s2+pcm_start*dev->codec()->channels(); dev->jack_data.output_frames= MAX_AUDIO_CHANNELS*RINGBUFFER_SIZE/dev->codec()->channels()-pcm_start; dev->jack_play_position+=n; if((err=src_process(dev->jack_src,&dev->jack_data))<0) { fprintf(stderr,"SRC processing error [%s]\n",src_strerror(err)); exit(GLASS_EXIT_SRC_ERROR); } n=dev->jack_data.output_frames_gen+pcm_start; // // De-interleave Channels and Write to Jack Buffers // for(i=0;i<dev->codec()->channels();i++) { if(jack_cb_buffers[i]!=NULL) { for(j=0;j<nframes;j++) { jack_cb_buffers[i][j]=pcm_s2[dev->codec()->channels()*j+i]; } } } // // Update Meters // dev->peakLevels(lvls,pcm_s2,nframes,dev->codec()->channels()); for(i=0;i<dev->codec()->channels();i++) { dev->jack_meter_avg[i]->addValue(lvls[i]); } dev->setMeterLevels(lvls); // // Move left-overs to start of buffer // if(n>nframes) { pcm_start=n-nframes; for(i=0;i<pcm_start;i++) { for(j=0;j<dev->codec()->channels();j++) { pcm_s2[dev->codec()->channels()*i+j]= pcm_s2[(nframes+i)*dev->codec()->channels()+j]; } } } else { pcm_start=0; } if(pcm_start<2) { pcm_offset=1; } else { pcm_offset=0; } } return 0; }
/*! Get sample frames \param buf pointer array to channel buffers \param frames number of maximum frames to get \return frames put into buffers */ int Stream::doGet(int ch,float *const *buf,int frames,float sr) { ASSERT(ch > 0 && frames >= 0 && sr > 0); if(isOk() && !isInitializing()) { // signal thread worker pthread_cond_signal(&cond); // check/(re)allocate buffers int strch = getChannels(); if(bufs && bufch < strch) { delete[] decoded; for(int i = 0; i < bufch; ++i) src_delete(src_state[i]); delete[] src_state; delete[] bufs; bufs = NULL; } if(!bufs) { if(bufch < strch) bufch = strch; bufs = new float *[bufch]; decoded = new Fifo<float>[bufch]; src_state = new SRC_STATE *[bufch]; for(int i = 0; i < bufch; ++i) { int error; src_state[i] = src_new(SRC_ZERO_ORDER_HOLD,1,&error); if(!src_state[i]) post("src init error %i",error); } } // get frames float ratio = sr/getSamplerate(); int frneed = (int)(frames/ratio)+DECMORE; // number of frames to read from decoder fifo if(decoded[0].Size() < frneed) { // fifos are too small -> resize them (while keeping their contents) for(int i = 0; i < bufch; ++i) decoded[i].Resize(frneed,true); } // how many frames do we need to get from decoder? int frread = frneed-decoded[0].Have(); int ret = state == ST_WAIT?0:DataRead(frread); if(ret < 0) { if(debug) post("read error"); // clear output for(int c = 0; c < ch; ++c) memset(buf[c],0,frames*sizeof *buf[c]); return 0; } else { // how many channels do we really need for output? // this should be set elsewhere, because we can't change anyway!!! // (SRC_STATE for dangling channels would be incorrect) int cmin = strch; if(ch < cmin) cmin = ch; // write data to fifo for(int i = 0; i < cmin; ++i) { int wr = decoded[i].Write(ret,bufs[i]); if(wr < ret) post("fifo overflow"); } // state = ST_PROCESS; if(ratio == 1) { // no resampling necessary // hopefully all channel fifos advance uniformly..... for(int i = 0; i < cmin; ++i) { for(int got = 0; got < frames; ) { int cnt = frames-got; if(decoded[i].Have()) { got += decoded[i].Read(cnt,buf[i]+got); } else { state = ST_WAIT; if(debug) post("fifo underrun"); // Buffer underrun!! -> zero output buffer memset(buf[i]+got,0,cnt*sizeof(*buf[i])); got += cnt; } } } } else { SRC_DATA src_data; src_data.src_ratio = ratio; src_data.end_of_input = 0; // hopefully all channel fifos advance uniformly..... for(int i = 0; i < cmin; ++i) { src_set_ratio(src_state[i],ratio); for(int got = 0; got < frames; ) { src_data.data_out = buf[i]+got; src_data.output_frames = frames-got; if(decoded[i].Have()) { src_data.data_in = decoded[i].ReadPtr(); src_data.input_frames = decoded[i].ReadSamples(); int err = src_process(src_state[i],&src_data); if(err) post("src_process error %i",err); // advance buffer decoded[i].Read(src_data.input_frames_used,NULL); } else { state = ST_WAIT; if(debug) post("fifo underrun"); // Buffer underrun!! -> zero output buffer memset(src_data.data_out,0,src_data.output_frames*sizeof(*src_data.data_out)); src_data.output_frames_gen = src_data.output_frames; } got += src_data.output_frames_gen; } } } // zero remaining channels for(int c = cmin; c < ch; ++c) memset(buf[c],0,frames*sizeof *buf[c]); return ret; } } else { for(int c = 0; c < ch; ++c) memset(buf[c],0,frames*sizeof *buf[c]); return 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; }
static void callback_reset_test (int converter) { static TEST_CB_DATA test_callback_data ; static float output [BUFFER_LEN] ; SRC_STATE *src_state ; double src_ratio = 1.1 ; long read_count, read_total ; int k, error ; printf ("\tcallback_reset_test (%-28s) ....... ", src_get_name (converter)) ; fflush (stdout) ; for (k = 0 ; k < ARRAY_LEN (data_one) ; k++) { data_one [k] = 1.0 ; data_zero [k] = 0.0 ; } ; if ((src_state = src_callback_new (test_callback_func, converter, 1, &error, &test_callback_data)) == NULL) { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; exit (1) ; } ; /* Process a bunch of 1.0 valued samples. */ test_callback_data.channels = 1 ; test_callback_data.count = 0 ; test_callback_data.total = ARRAY_LEN (data_one) ; test_callback_data.data = data_one ; read_total = 0 ; do { read_count = (ARRAY_LEN (output) - read_total > CB_READ_LEN) ? CB_READ_LEN : ARRAY_LEN (output) - read_total ; read_count = src_callback_read (src_state, src_ratio, read_count, output + read_total) ; read_total += read_count ; } while (read_count > 0) ; /* Check for errors. */ if ((error = src_error (src_state)) != 0) { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; exit (1) ; } ; /* Reset the state of the converter.*/ src_reset (src_state) ; /* Process a bunch of 0.0 valued samples. */ test_callback_data.channels = 1 ; test_callback_data.count = 0 ; test_callback_data.total = ARRAY_LEN (data_zero) ; test_callback_data.data = data_zero ; /* Now process some zero data. */ read_total = 0 ; do { read_count = (ARRAY_LEN (output) - read_total > CB_READ_LEN) ? CB_READ_LEN : ARRAY_LEN (output) - read_total ; read_count = src_callback_read (src_state, src_ratio, read_count, output + read_total) ; read_total += read_count ; } while (read_count > 0) ; /* Check for errors. */ if ((error = src_error (src_state)) != 0) { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; exit (1) ; } ; /* Finally make sure that the output data is zero ie reset was sucessful. */ for (k = 0 ; k < BUFFER_LEN / 2 ; k++) if (output [k] != 0.0) { printf ("\n\nLine %d : output [%d] should be 0.0, is %f.\n\n", __LINE__, k, output [k]) ; save_oct_float ("output.dat", data_one, ARRAY_LEN (data_one), output, ARRAY_LEN (output)) ; exit (1) ; } ; /* Make sure that this function has been exported. */ src_set_ratio (src_state, 1.0) ; /* Delete converter. */ src_state = src_delete (src_state) ; puts ("ok") ; } /* callback_reset_test */
void *AlsaCallback(void *ptr) { #ifdef ALSA static DevAlsa *dev=NULL; static float pcm_s1[32768]; static float *pcm_s2; static float *pcm_s3; static int16_t pcm16[32768]; static int32_t pcm32[32768]; static int n; static SRC_STATE *src=NULL; static SRC_DATA data; static int err; static unsigned ring_frames=0; static unsigned count=0; static bool show_xrun=false; static double pll_setpoint_ratio; static float lvls[MAX_AUDIO_CHANNELS]; static unsigned i; dev=(DevAlsa *)ptr; src=NULL; pll_setpoint_ratio=1.0; dev->alsa_pll_setpoint_frames=0; dev->alsa_pll_offset=0.0; ring_frames=0; count=0; show_xrun=false; dev->alsa_play_position=0; // // Initialize sample rate converter // pcm_s2=new float[262144]; memset(&data,0,sizeof(data)); data.data_in=pcm_s1; data.data_out=pcm_s2; data.output_frames=262144/dev->alsa_channels; pll_setpoint_ratio= (double)dev->alsa_samplerate/(double)dev->codec()->samplerate(); data.src_ratio=pll_setpoint_ratio; if((src=src_new(SRC_LINEAR,dev->codec()->channels(),&err))==NULL) { fprintf(stderr,"SRC initialization error [%s]\n",src_strerror(err)); exit(GLASS_EXIT_SRC_ERROR); } // // Initialize channel mixdown buffer // if(dev->codec()->channels()==dev->alsa_channels) { pcm_s3=pcm_s2; } else { pcm_s3=new float[32768]; } // // Wait for PCM buffer to fill // while((!dev->alsa_stopping)&& (dev->codec()->ring()->readSpace()<2*dev->codec()->samplerate())) { usleep(36); } while(count<PLL_SETTLE_INTERVAL) { // Allow ringbuffer to stabilize if((ring_frames=dev->codec()->ring()->readSpace())>dev->alsa_pll_setpoint_frames) { dev->alsa_pll_setpoint_frames=ring_frames; } dev->alsa_pll_setpoint_frames=ring_frames; count++; } while(!dev->alsa_stopping) { ring_frames=dev->codec()->ring()->readSpace(); if(ring_frames>dev->alsa_pll_setpoint_frames) { if(dev->alsa_pll_offset>(-PLL_CORRECTION_LIMIT)) { dev->alsa_pll_offset-=PLL_CORRECTION; } } else { if(dev->alsa_pll_offset<(PLL_CORRECTION_LIMIT)) { dev->alsa_pll_offset+=PLL_CORRECTION; } } data.src_ratio=pll_setpoint_ratio+dev->alsa_pll_offset; src_set_ratio(src,data.src_ratio); if(snd_pcm_state(dev->alsa_pcm)!=SND_PCM_STATE_RUNNING) { if(show_xrun) { fprintf(stderr,"*** XRUN ***\n"); snd_pcm_drop(dev->alsa_pcm); snd_pcm_prepare(dev->alsa_pcm); show_xrun=false; } } else { show_xrun=!dev->codec()->ring()->isFinished(); } if((n=dev->codec()->ring()-> read(pcm_s1,dev->alsa_buffer_size/(dev->alsa_period_quantity*2)))>0) { if(src!=NULL) { data.input_frames=n; dev->alsa_play_position+=n; if((err=src_process(src,&data))<0) { fprintf(stderr,"SRC processing error [%s]\n",src_strerror(err)); exit(GLASS_EXIT_SRC_ERROR); } n=data.output_frames_gen; } if(dev->codec()->channels()!=dev->alsa_channels) { dev->remixChannels(pcm_s3,dev->alsa_channels, pcm_s2,dev->codec()->channels(),n); } switch(dev->alsa_format) { case AudioDevice::S16_LE: dev->convertFromFloat(pcm16,pcm_s3,n,dev->alsa_channels); snd_pcm_writei(dev->alsa_pcm,pcm16,n); break; case AudioDevice::S32_LE: dev->convertFromFloat(pcm32,pcm_s3,n,dev->alsa_channels); snd_pcm_writei(dev->alsa_pcm,pcm32,n); break; case AudioDevice::FLOAT: snd_pcm_writei(dev->alsa_pcm,pcm_s3,n); break; case AudioDevice::LastFormat: break; } dev->peakLevels(lvls,pcm_s3,n,dev->codec()->channels()); for(i=0;i<dev->codec()->channels();i++) { dev->alsa_meter_avg[i]->addValue(lvls[i]); } dev->setMeterLevels(lvls); } } // // Shutdown // snd_pcm_drain(dev->alsa_pcm); snd_pcm_close(dev->alsa_pcm); if((pcm_s3!=pcm_s2)&&(pcm_s3!=pcm_s1)) { delete pcm_s3; } pcm_s3=NULL; if(pcm_s2!=pcm_s1) { delete pcm_s2; } pcm_s2=NULL; #endif // ALSA return NULL; }
PJ_DEF(pj_status_t) pjmedia_resample_create( pj_pool_t *pool, pj_bool_t high_quality, pj_bool_t large_filter, unsigned channel_count, unsigned rate_in, unsigned rate_out, unsigned samples_per_frame, pjmedia_resample **p_resample) { pjmedia_resample *resample; int type, err; PJ_ASSERT_RETURN(pool && p_resample && rate_in && rate_out && samples_per_frame, PJ_EINVAL); resample = PJ_POOL_ZALLOC_T(pool, pjmedia_resample); PJ_ASSERT_RETURN(resample, PJ_ENOMEM); /* Select conversion type */ if (high_quality) { type = large_filter ? SRC_SINC_BEST_QUALITY : SRC_SINC_MEDIUM_QUALITY; } else { type = large_filter ? SRC_SINC_FASTEST : SRC_LINEAR; } /* Create converter */ resample->state = src_new(type, channel_count, &err); if (resample->state == NULL) { PJ_LOG(4,(THIS_FILE, "Error creating resample: %s", src_strerror(err))); return PJMEDIA_ERROR; } /* Calculate ratio */ resample->ratio = rate_out * 1.0 / rate_in; /* Calculate number of samples for input and output */ resample->in_samples = samples_per_frame; resample->out_samples = rate_out / (rate_in / samples_per_frame); resample->frame_in = (float*) pj_pool_calloc(pool, resample->in_samples + 8, sizeof(float)); resample->frame_out = (float*) pj_pool_calloc(pool, resample->out_samples + 8, sizeof(float)); /* Set the converter ratio */ err = src_set_ratio(resample->state, resample->ratio); if (err != 0) { PJ_LOG(4,(THIS_FILE, "Error creating resample: %s", src_strerror(err))); return PJMEDIA_ERROR; } /* Done */ PJ_LOG(5,(THIS_FILE, "Resample using libsamplerate %s, type=%s (%s), " "ch=%d, in/out rate=%d/%d", src_get_version(), src_get_name(type), src_get_description(type), channel_count, rate_in, rate_out)); *p_resample = resample; return PJ_SUCCESS; }
static void process_reset_test (int converter) { static float output [BUFFER_LEN] ; SRC_STATE *src_state ; SRC_DATA src_data ; int k, error ; printf ("\tprocess_reset_test (%-28s) ....... ", src_get_name (converter)) ; fflush (stdout) ; for (k = 0 ; k < BUFFER_LEN ; k++) { data_one [k] = 1.0 ; data_zero [k] = 0.0 ; } ; /* Get a converter. */ if ((src_state = src_new (converter, 1, &error)) == NULL) { printf ("\n\nLine %d : src_new() failed : %s.\n\n", __LINE__, src_strerror (error)) ; exit (1) ; } ; /* Process a bunch of 1.0 valued samples. */ src_data.data_in = data_one ; src_data.data_out = output ; src_data.input_frames = BUFFER_LEN ; src_data.output_frames = BUFFER_LEN ; src_data.src_ratio = 0.9 ; src_data.end_of_input = 1 ; if ((error = src_process (src_state, &src_data)) != 0) { printf ("\n\nLine %d : src_simple () returned error : %s\n\n", __LINE__, src_strerror (error)) ; exit (1) ; } ; /* Reset the state of the converter.*/ src_reset (src_state) ; /* Now process some zero data. */ src_data.data_in = data_zero ; src_data.data_out = output ; src_data.input_frames = BUFFER_LEN ; src_data.output_frames = BUFFER_LEN ; src_data.src_ratio = 0.9 ; src_data.end_of_input = 1 ; if ((error = src_process (src_state, &src_data)) != 0) { printf ("\n\nLine %d : src_simple () returned error : %s\n\n", __LINE__, src_strerror (error)) ; exit (1) ; } ; /* Finally make sure that the output data is zero ie reset was sucessful. */ for (k = 0 ; k < BUFFER_LEN / 2 ; k++) if (output [k] != 0.0) { printf ("\n\nLine %d : output [%d] should be 0.0, is %f.\n", __LINE__, k, output [k]) ; exit (1) ; } ; /* Make sure that this function has been exported. */ src_set_ratio (src_state, 1.0) ; /* Delete converter. */ src_state = src_delete (src_state) ; puts ("ok") ; } /* process_reset_test */