int Wave::resample(int quality, int newRate) { float ratio = newRate / (float) inHeader.samplerate; int newSize = ceil(size * ratio); if (newSize % 2 != 0) // libsndfile goes crazy with odd size in case of saving newSize++; float *tmp = (float *) malloc(newSize * sizeof(float)); if (!tmp) { gLog("[wave] unable to allocate memory for resampling\n"); return -1; } SRC_DATA src_data; src_data.data_in = data; src_data.input_frames = size/2; // in frames, i.e. /2 (stereo) src_data.data_out = tmp; src_data.output_frames = newSize/2; // in frames, i.e. /2 (stereo) src_data.src_ratio = ratio; gLog("[wave] resampling: new size=%d (%d frames)\n", newSize, newSize/2); int ret = src_simple(&src_data, quality, 2); if (ret != 0) { gLog("[wave] resampling error: %s\n", src_strerror(ret)); return 0; } free(data); data = tmp; size = newSize; inHeader.samplerate = newRate; return 1; }
static double find_attenuation (double freq, int converter, int verbose) { static float input [BUFFER_LEN] ; static float output [2 * BUFFER_LEN] ; SRC_DATA src_data ; double output_peak ; int error ; gen_windowed_sines (input, BUFFER_LEN, &freq, 1) ; src_data.end_of_input = 1 ; /* Only one buffer worth of input. */ src_data.data_in = input ; src_data.input_frames = BUFFER_LEN ; src_data.src_ratio = 1.999 ; src_data.data_out = output ; src_data.output_frames = ARRAY_LEN (output) ; if ((error = src_simple (&src_data, converter, 1))) { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; exit (1) ; } ; output_peak = find_peak (output, ARRAY_LEN (output)) ; if (verbose) printf ("\tFreq : %6f InPeak : %6f OutPeak : %6f Atten : %6.2f dB\n", freq, 1.0, output_peak, 20.0 * log10 (1.0 / output_peak)) ; return 20.0 * log10 (1.0 / output_peak) ; } /* find_attenuation */
void Resample::compute() { const std::vector<Real>& signal = _signal.get(); std::vector<Real>& resampled = _resampled.get(); if (_factor == 1.0) { resampled = signal; return; } if (signal.empty()) return; SRC_DATA src; src.input_frames = (long)signal.size(); src.data_in = const_cast<float*>(&(signal[0])); // add some samples to make sure we don't crash in a stupid way... src.output_frames = (long)((double)signal.size()*_factor + 100.0); resampled.resize(src.output_frames); src.data_out = &(resampled[0]); src.src_ratio = _factor; // do the conversion int error = src_simple(&src, _quality, 1); if (error) throw EssentiaException("Resample: Error in resampling: ", src_strerror(error)); resampled.resize(src.output_frames_gen); }
void fix_samplerate (t_sample *sample) { SRC_DATA data; int max_output_frames; int channels = sample->info->channels; //printf("start frames: %d\n", sample->info->frames); if (sample->info->samplerate == g_samplerate) { return; } data.src_ratio = (float) g_samplerate / (float) sample->info->samplerate; //printf("ratio: %d / %d = %f\n", sample->info->samplerate, samplerate, data.src_ratio); max_output_frames = sample->info->frames * data.src_ratio + 32; data.data_in = sample->items; data.input_frames = sample->info->frames; data.data_out = (float *) calloc(1, sizeof(float) * max_output_frames * channels ); data.output_frames = max_output_frames; src_simple(&data, SRC_SINC_BEST_QUALITY, channels); if (sample->items) free(sample->items); sample->items = data.data_out; sample->info->samplerate = g_samplerate; sample->info->frames = data.output_frames_gen; //printf("end samplerate: %d frames: %d\n", (int) sample->info->samplerate, sample->info->frames); }
util::aligned::vector<float> adjust_sampling_rate(const float* data, size_t size, double in_sr, double out_sr) { if (!(in_sr && out_sr)) { throw std::runtime_error{ "Sample rate of 0 gives few hints about how to proceed."}; } const auto ratio = out_sr / in_sr; util::aligned::vector<float> out_signal(ratio * size); SRC_DATA sample_rate_info{data, out_signal.data(), static_cast<long>(size), static_cast<long>(out_signal.size()), 0, 0, 0, out_sr / in_sr}; src_simple(&sample_rate_info, SRC_SINC_BEST_QUALITY, 1); // Correct output level. const auto volume_scale = 1 / ratio; for (auto& i : out_signal) { i *= volume_scale; } return out_signal; }
static void simple_test (int converter) { int ilen = 199030, olen = 1000, error ; { float in [ilen] ; float out [olen] ; double ratio = (1.0 * olen) / ilen ; SRC_DATA src_data = { in, out, ilen, olen, 0, 0, 0, ratio } ; error = src_simple (&src_data, converter, 1) ; if (error) { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; exit (1) ; } ; } ; return ; } /* simple_test */
static void resampleOnsetDetectionFunction(struct btrack * bt) { float output[512]; float * input = malloc(bt->onsetDFBufferSize * sizeof(float)); BTRACK_ASSERT(input); for (int i = 0;i < bt->onsetDFBufferSize;i++) { input[i] = (float) bt->onsetDF[i]; } double src_ratio = 512.0/((double) bt->onsetDFBufferSize); int BUFFER_LEN = bt->onsetDFBufferSize; int output_len; SRC_DATA src_data ; //output_len = (int) floor (((double) BUFFER_LEN) * src_ratio) ; output_len = 512; src_data.data_in = input; src_data.input_frames = BUFFER_LEN; src_data.src_ratio = src_ratio; src_data.data_out = output; src_data.output_frames = output_len; src_simple (&src_data, SRC_SINC_BEST_QUALITY, 1); for (int i = 0;i < output_len;i++) { bt->resampledOnsetDF[i] = (double) src_data.data_out[i]; } free(input); }
static void simple_test (int converter, double src_ratio) { static float input [BUFFER_LEN], output [BUFFER_LEN] ; SRC_DATA src_data ; int input_len, output_len, error, terminate ; printf ("\tsimple_test (SRC ratio = %6.4f) ........... ", src_ratio) ; fflush (stdout) ; /* Calculate maximun input and output lengths. */ if (src_ratio >= 1.0) { output_len = BUFFER_LEN ; input_len = (int) floor (BUFFER_LEN / src_ratio) ; } else { input_len = BUFFER_LEN ; output_len = (int) floor (BUFFER_LEN * src_ratio) ; } ; /* Reduce input_len by 10 so output is longer than necessary. */ input_len -= 10 ; if (output_len > BUFFER_LEN) { printf ("\n\nLine %d : output_len > BUFFER_LEN\n\n", __LINE__) ; exit (1) ; } ; memset (&src_data, 0, sizeof (src_data)) ; src_data.data_in = input ; src_data.input_frames = input_len ; src_data.src_ratio = src_ratio ; src_data.data_out = output ; src_data.output_frames = BUFFER_LEN ; if ((error = src_simple (&src_data, converter, 1))) { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; exit (1) ; } ; terminate = (int) ceil ((src_ratio >= 1.0) ? src_ratio : 1.0 / src_ratio) ; if (fabs (src_data.output_frames_gen - src_ratio * input_len) > 2 * terminate) { printf ("\n\nLine %d : bad output data length %ld should be %d.\n", __LINE__, src_data.output_frames_gen, (int) floor (src_ratio * input_len)) ; printf ("\tsrc_ratio : %.4f\n", src_ratio) ; printf ("\tinput_len : %d\n\toutput_len : %d\n\n", input_len, output_len) ; exit (1) ; } ; puts ("ok") ; return ; } /* simple_test */
bool Resampler22kHzMono::resample(uint32_t fromSampleRate, int16_t** samplePtr, unsigned int& sampleCount, unsigned int channelCount) const { //first convert to mono - we do not need stereo or more channels. unsigned int frameCount = sampleCount/channelCount; int16_t* monoSamples = new int16_t[frameCount]; if (!monoSamples) //failed to get memory return false; int16_t* samples = *samplePtr; for (unsigned int i = 0; i < frameCount; i++) { int32_t tmpVal = 0; int offset = channelCount * i; for (unsigned int j = 0; j < channelCount; j++) { tmpVal += samples[offset + j]; } monoSamples[i] = tmpVal / channelCount; } //should have mono samples now. we can discard the old samples. delete[] samples; samples = NULL; sampleCount = frameCount; *samplePtr = monoSamples; SRC_DATA srcdata; srcdata.data_in = new float[sampleCount]; src_short_to_float_array(*samplePtr, srcdata.data_in, sampleCount); delete *samplePtr; srcdata.input_frames = sampleCount; srcdata.output_frames = int(sampleCount * 22050.0 / double(fromSampleRate)) + 1; srcdata.data_out = new float[srcdata.output_frames]; srcdata.src_ratio = 22050.0 / double(fromSampleRate); //do some fast conversion at reasonable quality if (src_simple(&srcdata, SRC_SINC_FASTEST, 1) != 0) return false; delete srcdata.data_in; *samplePtr = new int16_t[srcdata.output_frames]; src_float_to_short_array(srcdata.data_out, *samplePtr, srcdata.output_frames); delete srcdata.data_out; sampleCount = srcdata.output_frames; return true; }
void AudioBuffer::convert_rate(AudioBuffer &_dest, unsigned _frames_count, SRC_STATE *_SRC) { AudioSpec destspec{AUDIO_FORMAT_F32, m_spec.channels, _dest.rate()}; if(m_spec.format != AUDIO_FORMAT_F32 || _dest.spec() != destspec) { throw std::logic_error("unsupported format"); } _frames_count = std::min(frames(),_frames_count); double rate_ratio = double(destspec.rate)/double(m_spec.rate); unsigned out_frames = unsigned(ceil(double(_frames_count) * rate_ratio)); if(out_frames==0) { return; } unsigned destpos = _dest.samples(); unsigned destframes = _dest.frames(); _dest.resize_frames(_dest.frames()+out_frames); #if HAVE_LIBSAMPLERATE SRC_DATA srcdata; srcdata.data_in = &at<float>(0); srcdata.data_out = &_dest.at<float>(destpos); srcdata.input_frames = _frames_count; srcdata.output_frames = out_frames; srcdata.src_ratio = rate_ratio; int srcresult; if(_SRC != nullptr) { srcdata.end_of_input = 0; srcresult = src_process(_SRC, &srcdata); } else { srcdata.end_of_input = 1; srcresult = src_simple(&srcdata, SRC_SINC_BEST_QUALITY, destspec.channels) ; } if(srcresult != 0) { throw std::runtime_error(std::string("error resampling: ") + src_strerror(srcresult)); } assert(srcdata.output_frames_gen>=0 && srcdata.output_frames_gen<=out_frames); if(srcdata.output_frames_gen != out_frames) { _dest.resize_frames(destframes + srcdata.output_frames_gen); } PDEBUGF(LOG_V2, LOG_MIXER, "convert rate: f-in: %d, f-out: %d, gen: %d\n", _frames_count, out_frames, srcdata.output_frames_gen); #else for(unsigned i=destpos; i<_dest.samples(); ++i) { _dest.operator[]<float>(i) = 0.f; } #endif }
static float* resample(float* samples, int rate, SF_INFO* sfinfo) { double ratio; int err; SRC_DATA src; float* tmp; ratio = rate / (sfinfo->samplerate * 1.0); debug("Resampling from %d to %d\n", rate, sfinfo->samplerate); src.src_ratio = ratio; src.data_in = samples; src.input_frames = sfinfo->frames; src.output_frames = sfinfo->frames * ratio; if (src.output_frames >= MAX_SAMPLE_FRAMES) { pf_error(PF_ERR_SAMPLE_RESAMPLE_MAX_FRAMES); return 0; } tmp = malloc(sizeof(float) * sfinfo->frames * sfinfo->channels * ratio); if (!tmp) { pf_error(PF_ERR_SAMPLE_RESAMPLE_ALLOC); return 0; } src.data_out = tmp; err = src_simple(&src, SRC_SINC_BEST_QUALITY, sfinfo->channels); if (err) { pf_error(PF_ERR_SAMPLE_SRC_SIMPLE); free(tmp); return 0; } sfinfo->frames = src.output_frames; return tmp; }
static void downsample_test (int converter) { static float in [1000], out [10] ; SRC_DATA data ; printf (" downsample_test (%-28s) ....... ", src_get_name (converter)) ; fflush (stdout) ; data.src_ratio = 1.0 / 255.0 ; data.input_frames = ARRAY_LEN (in) ; data.output_frames = ARRAY_LEN (out) ; data.data_in = in ; data.data_out = out ; if (src_simple (&data, converter, 1)) { puts ("src_simple failed.") ; exit (1) ; } ; puts ("ok") ; } /* downsample_test */
/* resample pv->[rl]_out[i] for i = 0 to pv->hop_syn * to [left,right][i] for i = 0 to pv->hop_res * INPUT * OUTPUT */ void pv_complex_resample (struct pv_complex * pv, double * left, double * right) { /* samplerate conversion */ SRC_DATA srdata; static float * fl_in = NULL; static float * fl_out = NULL; static int hop_syn0 = 0; static int hop_res0 = 0; int i; int status; if (fl_in == NULL) { fl_in = (float *)malloc (sizeof (float) * 2 * pv->hop_syn); fl_out = (float *)malloc (sizeof (float) * 2 * pv->hop_res); CHECK_MALLOC (fl_in, "pv_complex_resample"); CHECK_MALLOC (fl_out, "pv_complex_resample"); hop_syn0 = pv->hop_syn; hop_res0 = pv->hop_res; } else { if (hop_syn0 < pv->hop_syn) { fl_in = (float *)realloc (fl_in, sizeof (float) * 2 * pv->hop_syn); CHECK_MALLOC (fl_in, "pv_complex_resample"); hop_syn0 = pv->hop_syn; } if (hop_res0 < pv->hop_res) { fl_out = (float *)realloc (fl_out, sizeof (float) * 2 * pv->hop_res); CHECK_MALLOC (fl_out, "pv_complex_resample"); hop_res0 = pv->hop_res; } } srdata.input_frames = pv->hop_syn; srdata.output_frames = pv->hop_res; srdata.src_ratio = (double)(pv->hop_res) / (double)(pv->hop_syn); srdata.data_in = fl_in; srdata.data_out = fl_out; /* samplerate conversion (time fixed) */ for (i = 0; i < pv->hop_syn; i ++) { fl_in [i * 2 + 0] = (float)(pv->l_out [i]); fl_in [i * 2 + 1] = (float)(pv->r_out [i]); } /*status = src_simple (&srdata, SRC_SINC_BEST_QUALITY, 2); */ status = src_simple (&srdata, SRC_SINC_FASTEST, 2); /* this works better */ if (status != 0) { fprintf (stderr, "fail to samplerate conversion\n"); exit (1); } for (i = 0; i < pv->hop_res; i ++) { left [i] = (double)(fl_out [i * 2 + 0]); right [i] = (double)(fl_out [i * 2 + 1]); } }
static void simple_test (int converter, int channel_count, double target_snr) { SRC_DATA src_data ; double freq, snr ; int ch, error, frames ; printf ("\t%-22s (%d channel%c) ............. ", "simple_test", channel_count, channel_count > 1 ? 's' : ' ') ; fflush (stdout) ; memset (input_serial, 0, sizeof (input_serial)) ; memset (input_interleaved, 0, sizeof (input_interleaved)) ; memset (output_interleaved, 0, sizeof (output_interleaved)) ; memset (output_serial, 0, sizeof (output_serial)) ; frames = MIN (ARRAY_LEN (input_serial) / channel_count, 1 << 16) ; /* Calculate channel_count separate windowed sine waves. */ for (ch = 0 ; ch < channel_count ; ch++) { freq = (200.0 + 33.333333333 * ch) / 44100.0 ; gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ; } ; /* Interleave the data in preparation for SRC. */ interleave_data (input_serial, input_interleaved, frames, channel_count) ; /* Choose a converstion ratio <= 1.0. */ src_data.src_ratio = 0.95 ; src_data.data_in = input_interleaved ; src_data.input_frames = frames ; src_data.data_out = output_interleaved ; src_data.output_frames = frames ; if ((error = src_simple (&src_data, converter, channel_count))) { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; exit (1) ; } ; if (fabs (src_data.output_frames_gen - src_data.src_ratio * src_data.input_frames) > 2) { printf ("\n\nLine %d : bad output data length %ld should be %d.\n", __LINE__, src_data.output_frames_gen, (int) floor (src_data.src_ratio * src_data.input_frames)) ; printf ("\tsrc_ratio : %.4f\n", src_data.src_ratio) ; printf ("\tinput_len : %ld\n", src_data.input_frames) ; printf ("\toutput_len : %ld\n\n", src_data.output_frames_gen) ; exit (1) ; } ; /* De-interleave data so SNR can be calculated for each channel. */ deinterleave_data (output_interleaved, output_serial, frames, channel_count) ; for (ch = 0 ; ch < channel_count ; ch++) { snr = calculate_snr (output_serial + ch * frames, frames, 1) ; if (snr < target_snr) { printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__, ch, snr, target_snr) ; save_oct_float ("output.dat", input_serial, channel_count * frames, output_serial, channel_count * frames) ; exit (1) ; } ; } ; puts ("ok") ; return ; } /* simple_test */
static void init_term_test (int converter, double src_ratio) { static float input [SHORT_BUFFER_LEN], output [SHORT_BUFFER_LEN] ; SRC_DATA src_data ; int k, input_len, output_len, error, terminate ; printf ("\tinit_term_test (SRC ratio = %7.4f) .......... ", src_ratio) ; fflush (stdout) ; /* Calculate maximun input and output lengths. */ if (src_ratio >= 1.0) { output_len = SHORT_BUFFER_LEN ; input_len = (int) floor (SHORT_BUFFER_LEN / src_ratio) ; } else { input_len = SHORT_BUFFER_LEN ; output_len = (int) floor (SHORT_BUFFER_LEN * src_ratio) ; } ; /* Reduce input_len by 10 so output is longer than necessary. */ input_len -= 10 ; for (k = 0 ; k < ARRAY_LEN (input) ; k++) input [k] = 1.0 ; if (output_len > SHORT_BUFFER_LEN) { printf ("\n\nLine %d : output_len > SHORT_BUFFER_LEN\n\n", __LINE__) ; exit (1) ; } ; src_data.data_in = input ; src_data.input_frames = input_len ; src_data.src_ratio = src_ratio ; src_data.data_out = output ; src_data.output_frames = SHORT_BUFFER_LEN ; if ((error = src_simple (&src_data, converter, 1))) { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; exit (1) ; } ; terminate = (int) ceil ((src_ratio >= 1.0) ? 1 : 1.0 / src_ratio) ; if (fabs (src_ratio * input_len - src_data.output_frames_gen) > terminate) { printf ("\n\nLine %d : Bad output frame count.\n\n", __LINE__) ; printf ("\tterminate : %d\n", terminate) ; printf ("\tsrc_ratio : %.4f\n", src_ratio) ; printf ("\tinput_len : %d\n" "\tinput_len * src_ratio : %f\n", input_len, input_len * src_ratio) ; printf ("\toutput_frames_gen : %ld\n\n", src_data.output_frames_gen) ; exit (1) ; } ; if (abs (src_data.input_frames_used - input_len) > 1) { printf ("\n\nLine %d : input_frames_used should be %d, is %ld.\n\n", __LINE__, input_len, src_data.input_frames_used) ; printf ("\tsrc_ratio : %.4f\n", src_ratio) ; printf ("\tinput_len : %d\n\tinput_used : %ld\n\n", input_len, src_data.input_frames_used) ; exit (1) ; } ; if (fabs (output [0]) < 0.1) { printf ("\n\nLine %d : First output sample is bad.\n\n", __LINE__) ; printf ("\toutput [0] == %f\n\n", output [0]) ; exit (1) ; } puts ("ok") ; return ; } /* init_term_test */
void *VideoLayer::feed() { int got_picture=0; int len1=0 ; int ret=0; bool got_it=false; double now = get_master_clock(); if(paused) return rgba_picture->data[0]; /** * follow user video loop */ if(mark_in!=NO_MARK && mark_out!=NO_MARK && seekable) { if (now >= mark_out) seek((int64_t)mark_in * AV_TIME_BASE); } // operate seek if was requested if(to_seek>=0) { seek(to_seek); to_seek = -1; } got_it=false; while (!got_it) { if(packet_len<=0) { /** * Read one packet from the media and put it in pkt */ while(1) { #ifdef DEBUG func("av_read_frame ..."); #endif ret = av_read_frame(avformat_context, &pkt); #ifdef DEBUG if(pkt.stream_index == video_index) std::cout << "video read packet"; else if(pkt.stream_index == audio_index) std::cout << "audio read packet"; std::cout << " pkt.data=" << pkt.data; std::cout << " pkt.size=" << pkt.size; std::cout << " pkt.pts/dts=" << pkt.pts << "/" << pkt.dts << std::endl; std::cout << "pkt.duration=" << pkt.duration; std::cout << " avformat_context->start_time=" << avformat_context->start_time; std::cout << " avformat_context->duration=" << avformat_context->duration/AV_TIME_BASE << std::endl; std::cout << "avformat_context->duration=" << avformat_context->duration << std::endl; #endif /* TODO(shammash): this may be good for streams but breaks * looping in files, needs fixing. */ // if(!pkt.duration) continue; // if(!pkt.size || !pkt.data) { // return NULL; // } /** * check eof and loop */ if(ret!= 0) { //does not enter if data are available eos->notify(); // eos->dispatcher->do_jobs(); /// XXX hack hack hack ret = seek(avformat_context->start_time); if (ret < 0) { error("VideoLayer::could not loop file"); return rgba_picture->data[0]; } continue; } else if( (pkt.stream_index == video_index) || (pkt.stream_index == audio_index) ) break; /* exit loop */ } } // loop break after a known index is found frame_number++; //std::cout << "frame_number :" << frame_number << std::endl; /** * Decode video */ if(pkt.stream_index == video_index) { len1 = decode_video_packet(&got_picture); AVFrame *yuv_picture=&av_frame; if(len1<0) { // error("VideoLayer::Error while decoding frame"); func("one frame only?"); return NULL; } else if (len1 == 0) { packet_len=0; return NULL; } /** * We've found a picture */ ptr += len1; packet_len -= len1; if (got_picture!=0) { got_it=true; avformat_stream=avformat_context->streams[video_index]; /** Deinterlace input if requested */ if(deinterlaced) deinterlace((AVPicture *)yuv_picture); #ifdef WITH_SWSCALE sws_scale(img_convert_ctx, yuv_picture->data, yuv_picture->linesize, 0, video_codec_ctx->height, rgba_picture->data, rgba_picture->linesize); #else /** * yuv2rgb */ img_convert(rgba_picture, PIX_FMT_RGB32, (AVPicture *)yuv_picture, video_codec_ctx->pix_fmt, //avformat_stream.codec->pix_fmt, video_codec_ctx->width, video_codec_ctx->height); #endif // memcpy(frame_fifo.picture[fifo_position % FIFO_SIZE]->data[0],rgba_picture->data[0],geo.size); /* TODO move */ if(fifo_position == FIFO_SIZE) fifo_position=0; /* workaround since sws_scale conversion from YUV returns an buffer RGBA with alpha set to 0x0 */ { register int bufsize = ( rgba_picture->linesize[0] * video_codec_ctx->height ) /4; int32_t *pbuf = (int32_t*)rgba_picture->data[0]; for(; bufsize>0; bufsize--) { *pbuf = (*pbuf | alpha_bitmask); pbuf++; } } jmemcpy(frame_fifo.picture[fifo_position]->data[0], rgba_picture->data[0], rgba_picture->linesize[0] * video_codec_ctx->height); // avpicture_get_size(PIX_FMT_RGBA32, enc->width, enc->height)); fifo_position++; } } // end video packet decoding //////////////////////// // audio packet decoding else if(pkt.stream_index == audio_index) { // XXX(shammash): audio decoding seems to depend on screen properties, so // we skip decoding audio frames if there's no screen // long unsigned int m_SampleRate = screen->m_SampleRate?*(screen->m_SampleRate):48000; // ringbuffer_write(screen->audio, (const char*)audio_float_buf, samples*sizeof(float)); // ... and so on ... if(use_audio && screen) { int data_size; len1 = decode_audio_packet(&data_size); if (len1 > 0) { int samples = data_size/sizeof(uint16_t); long unsigned int m_SampleRate = screen->m_SampleRate?*(screen->m_SampleRate):48000; double m_ResampleRatio = (double)(m_SampleRate)/(double)audio_samplerate; long unsigned max_buf = ceil(AVCODEC_MAX_AUDIO_FRAME_SIZE * m_ResampleRatio * audio_channels); if (audio_resampled_buf_len < max_buf) { if (audio_resampled_buf) free (audio_resampled_buf); audio_resampled_buf = (float*) malloc(max_buf * sizeof(float)); audio_resampled_buf_len = max_buf; } src_short_to_float_array ((const short*) audio_buf, audio_float_buf, samples); if (m_ResampleRatio == 1.0) { ringbuffer_write(screen->audio, (const char*)audio_float_buf, samples*sizeof(float)); time_t *tm = (time_t *)malloc(sizeof(time_t)); time (tm); // std::cerr << "-- VL:" << asctime(localtime(tm)); } else { src_short_to_float_array ((const short*) audio_buf, audio_float_buf, samples); SRC_DATA src_data; int offset = 0; do { src_data.input_frames = samples/audio_channels; src_data.output_frames = audio_resampled_buf_len/audio_channels - offset; src_data.end_of_input = 0; src_data.src_ratio = m_ResampleRatio; src_data.input_frames_used = 0; src_data.output_frames_gen = 0; src_data.data_in = audio_float_buf + offset; src_data.data_out = audio_resampled_buf + offset; src_simple (&src_data, SRC_SINC_MEDIUM_QUALITY, audio_channels) ; ringbuffer_write(screen->audio, (const char*)audio_resampled_buf, src_data.output_frames_gen * audio_channels *sizeof(float)); offset += src_data.input_frames_used * audio_channels; samples -= src_data.input_frames_used * audio_channels; if (samples>0) warning("resampling left: %i < %i", src_data.input_frames_used, samples/audio_channels); } while (samples > audio_channels); } } } } av_free_packet(&pkt); /* sun's good. love's bad */ } // end of while(!got_it) return frame_fifo.picture[fifo_position-1]->data[0]; }
static boolean ExpandSoundData_SRC(sfxinfo_t *sfxinfo, byte *data, int samplerate, int length) { SRC_DATA src_data; uint32_t i, abuf_index=0, clipped=0; uint32_t alen; int retn; int16_t *expanded; Mix_Chunk *chunk; src_data.input_frames = length; src_data.data_in = malloc(length * sizeof(float)); src_data.src_ratio = (double)mixer_freq / samplerate; // We include some extra space here in case of rounding-up. src_data.output_frames = src_data.src_ratio * length + (mixer_freq / 4); src_data.data_out = malloc(src_data.output_frames * sizeof(float)); assert(src_data.data_in != NULL && src_data.data_out != NULL); // Convert input data to floats for (i=0; i<length; ++i) { // Unclear whether 128 should be interpreted as "zero" or whether a // symmetrical range should be assumed. The following assumes a // symmetrical range. src_data.data_in[i] = data[i] / 127.5 - 1; } // Do the sound conversion retn = src_simple(&src_data, SRC_ConversionMode(), 1); assert(retn == 0); // Allocate the new chunk. alen = src_data.output_frames_gen * 4; chunk = AllocateSound(sfxinfo, src_data.output_frames_gen * 4); if (chunk == NULL) { return false; } expanded = (int16_t *) chunk->abuf; // Convert the result back into 16-bit integers. for (i=0; i<src_data.output_frames_gen; ++i) { // libsamplerate does not limit itself to the -1.0 .. 1.0 range on // output, so a multiplier less than INT16_MAX (32767) is required // to avoid overflows or clipping. However, the smaller the // multiplier, the quieter the sound effects get, and the more you // have to turn down the music to keep it in balance. // 22265 is the largest multiplier that can be used to resample all // of the Vanilla DOOM sound effects to 48 kHz without clipping // using SRC_SINC_BEST_QUALITY. It is close enough (only slightly // too conservative) for SRC_SINC_MEDIUM_QUALITY and // SRC_SINC_FASTEST. PWADs with interestingly different sound // effects or target rates other than 48 kHz might still result in // clipping--I don't know if there's a limit to it. // As the number of clipped samples increases, the signal is // gradually overtaken by noise, with the loudest parts going first. // However, a moderate amount of clipping is often tolerated in the // quest for the loudest possible sound overall. The results of // using INT16_MAX as the multiplier are not all that bad, but // artifacts are noticeable during the loudest parts. float cvtval_f = src_data.data_out[i] * libsamplerate_scale * INT16_MAX; int32_t cvtval_i = cvtval_f + (cvtval_f < 0 ? -0.5 : 0.5); // Asymmetrical sound worries me, so we won't use -32768. if (cvtval_i < -INT16_MAX) { cvtval_i = -INT16_MAX; ++clipped; } else if (cvtval_i > INT16_MAX) { cvtval_i = INT16_MAX; ++clipped; } // Left and right channels expanded[abuf_index++] = cvtval_i; expanded[abuf_index++] = cvtval_i; } free(src_data.data_in); free(src_data.data_out); if (clipped > 0) { fprintf(stderr, "Sound '%s': clipped %u samples (%0.2f %%)\n", sfxinfo->name, clipped, 400.0 * clipped / chunk->alen); } return true; }
static long throughput_test (int converter, int channels, long best_throughput) { SRC_DATA src_data ; clock_t start_time, clock_time ; double duration ; long total_frames = 0, throughput ; int error ; printf (" %-30s %2d ", src_get_name (converter), channels) ; fflush (stdout) ; src_data.data_in = input ; src_data.input_frames = ARRAY_LEN (input) / channels ; src_data.data_out = output ; src_data.output_frames = ARRAY_LEN (output) / channels ; src_data.src_ratio = 0.99 ; sleep (2) ; start_time = clock () ; do { if ((error = src_simple (&src_data, converter, channels)) != 0) { puts (src_strerror (error)) ; exit (1) ; } ; total_frames += src_data.output_frames_gen ; clock_time = clock () - start_time ; duration = (1.0 * clock_time) / CLOCKS_PER_SEC ; } while (duration < 5.0) ; if (src_data.input_frames_used != src_data.input_frames) { printf ("\n\nLine %d : input frames used %ld should be %ld\n", __LINE__, src_data.input_frames_used, src_data.input_frames) ; exit (1) ; } ; if (fabs (src_data.src_ratio * src_data.input_frames_used - src_data.output_frames_gen) > 2) { printf ("\n\nLine %d : input / output length mismatch.\n\n", __LINE__) ; printf (" input len : %d\n", ARRAY_LEN (input) / channels) ; printf (" output len : %ld (should be %g +/- 2)\n\n", src_data.output_frames_gen, floor (0.5 + src_data.src_ratio * src_data.input_frames_used)) ; exit (1) ; } ; throughput = lrint (floor (total_frames / duration)) ; if (best_throughput == 0) { best_throughput = MAX (throughput, best_throughput) ; printf ("%5.2f %10ld\n", duration, throughput) ; } else { best_throughput = MAX (throughput, best_throughput) ; printf ("%5.2f %10ld %10ld\n", duration, throughput, best_throughput) ; } return best_throughput ; } /* throughput_test */
/* Sound data resampling */ static int raw_resample(char *fname, double ratio) { int res = 0; FILE *fl; struct stat st; int in_size; short *in_buff, *out_buff; long in_frames, out_frames; float *inp, *outp; SRC_DATA rate_change; if ((fl = fopen(fname, "r")) == NULL) { ast_log(LOG_ERROR, "eSpeak: Failed to open file for resampling.\n"); return -1; } if ((stat(fname, &st) == -1)) { ast_log(LOG_ERROR, "eSpeak: Failed to stat file for resampling.\n"); fclose(fl); return -1; } in_size = st.st_size; if ((in_buff = ast_malloc(in_size)) == NULL) { fclose(fl); return -1; } if ((fread(in_buff, 1, in_size, fl) != (size_t)in_size)) { ast_log(LOG_ERROR, "eSpeak: Failed to read file for resampling.\n"); fclose(fl); res = -1; goto CLEAN1; } fclose(fl); in_frames = in_size / 2; if ((inp = (float *)(ast_malloc(in_frames * sizeof(float)))) == NULL) { res = -1; goto CLEAN1; } src_short_to_float_array(in_buff, inp, in_size/sizeof(short)); out_frames = (long)((double)in_frames * ratio); if ((outp = (float *)(ast_malloc(out_frames * sizeof(float)))) == NULL) { res = -1; goto CLEAN2; } rate_change.data_in = inp; rate_change.data_out = outp; rate_change.input_frames = in_frames; rate_change.output_frames = out_frames; rate_change.src_ratio = ratio; if ((res = src_simple(&rate_change, SRC_SINC_FASTEST, 1)) != 0) { ast_log(LOG_ERROR, "eSpeak: Failed to resample sound file '%s': '%s'\n", fname, src_strerror(res)); res = -1; goto CLEAN3; } if ((out_buff = ast_malloc(out_frames*sizeof(float))) == NULL) { res = -1; goto CLEAN3; } src_float_to_short_array(rate_change.data_out, out_buff, out_frames); if ((fl = fopen(fname, "w+")) != NULL) { if ((fwrite(out_buff, 1, 2*out_frames, fl)) != (size_t)(2*out_frames)) { ast_log(LOG_ERROR, "eSpeak: Failed to write resampled output file.\n"); res = -1; } fclose(fl); } else { ast_log(LOG_ERROR, "eSpeak: Failed to open output file for resampling.\n"); res = -1; } ast_free(out_buff); CLEAN3: ast_free(outp); CLEAN2: ast_free(inp); CLEAN1: ast_free(in_buff); return res; }
RawFile::RawFile(const std::string& name, sfl::AudioCodec *codec, unsigned int sampleRate) : AudioFile(name), audioCodec_(codec) { if (filepath_.empty()) throw AudioFileException("Unable to open audio file: filename is empty"); std::fstream file; file.open(filepath_.c_str(), std::fstream::in); if (!file.is_open()) throw AudioFileException("Unable to open audio file"); file.seekg(0, std::ios::end); size_t length = file.tellg(); file.seekg(0, std::ios::beg); std::vector<char> fileBuffer(length); file.read(&fileBuffer[0], length); file.close(); const unsigned int frameSize = audioCodec_->getFrameSize(); const unsigned int bitrate = audioCodec_->getBitRate() * 1000 / 8; const unsigned int audioRate = audioCodec_->getClockRate(); const unsigned int encFrameSize = frameSize * bitrate / audioRate; const unsigned int decodedSize = length * (frameSize / encFrameSize); SFLDataFormat *monoBuffer = new SFLDataFormat[decodedSize]; SFLDataFormat *bufpos = monoBuffer; unsigned char *filepos = reinterpret_cast<unsigned char *>(&fileBuffer[0]); size_ = decodedSize; while (length >= encFrameSize) { bufpos += audioCodec_->decode(bufpos, filepos, encFrameSize); filepos += encFrameSize; length -= encFrameSize; } if (sampleRate == audioRate) buffer_ = monoBuffer; else { double factord = (double) sampleRate / audioRate; float* floatBufferIn = new float[size_]; int sizeOut = ceil(factord * size_); src_short_to_float_array(monoBuffer, floatBufferIn, size_); delete [] monoBuffer; delete [] buffer_; buffer_ = new SFLDataFormat[sizeOut]; SRC_DATA src_data; src_data.data_in = floatBufferIn; src_data.input_frames = size_; src_data.output_frames = sizeOut; src_data.src_ratio = factord; float* floatBufferOut = new float[sizeOut]; src_data.data_out = floatBufferOut; src_simple(&src_data, SRC_SINC_BEST_QUALITY, 1); src_float_to_short_array(floatBufferOut, buffer_, src_data.output_frames_gen); delete [] floatBufferOut; delete [] floatBufferIn; size_ = src_data.output_frames_gen; } }
static void shmsrc_tilde_try_pop_audio_buf (t_shmsrc_tilde *x) { //g_print ("length %d\n", g_async_queue_length (x->x_audio_queue)); x->x_current_audio_buf = g_async_queue_try_pop (x->x_audio_queue); if (x->x_current_audio_buf == NULL) return; double src_ratio; if (x->x_sample_duration < 1.0 || x->x_stream_sample_duration < 1.0) src_ratio = (double) x->x_pd_samplerate / (double)x->x_current_audio_buf->sample_rate; else src_ratio = x->x_stream_sample_duration / x->x_sample_duration; /* g_print ("x->x_pd_samplerate %d x->x_current_audio_buf->sample_rate %d\n", x->x_pd_samplerate, x->x_current_audio_buf->sample_rate); */ /* g_print ("x->x_sample_duration %f x->x_stream_sample_duration %f\n", x->x_sample_duration, x->x_stream_sample_duration); */ /* g_print ("%f queue length %d, stream sample dur %f, sample duration %f\n", */ /* src_ratio, */ /* g_async_queue_length (x->x_audio_queue), */ /* x->x_stream_sample_duration, */ /* x->x_sample_duration); */ if (src_ratio == 1 ) return; SRC_DATA src_data ; int error, terminate ; int input_len = x->x_current_audio_buf->remaining_samples; int output_len = floor (input_len * src_ratio); if (output_len == 0) return; //g_print ("%d, %d\n",output_len,input_len); src_data.data_in = x->x_current_audio_buf->audio_data ; src_data.input_frames = input_len ; src_data.src_ratio = src_ratio; //g_print ("outputlen %d channels %d\n", output_len, x->x_current_audio_buf->num_channels_in_buf); t_float *output = g_malloc0 (sizeof (t_float) * output_len * x->x_current_audio_buf->num_channels_in_buf); src_data.data_out = output ; src_data.output_frames = output_len; //SRC_ZERO_ORDER_HOLD SRC_LINEAR SRC_SINC_FASTEST if ((error = src_simple (&src_data, SRC_SINC_FASTEST, x->x_current_audio_buf->num_channels_in_buf))) printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; terminate = (int) ceil ((src_ratio >= 1.0) ? src_ratio : 1.0 / src_ratio) ; if (fabs (src_data.output_frames_gen - src_ratio * input_len) > 2 * terminate) { printf ("\n\nLine %d : bad output data length %ld should be %d.\n", __LINE__, src_data.output_frames_gen, (int) floor (src_ratio * input_len)) ; printf ("\tsrc_ratio : %.4f\n", src_ratio) ; printf ("\tinput_len : %d\n\toutput_len : %d\n\n", input_len, output_len) ; } if (x->x_current_audio_buf->free_audio_data) g_free (x->x_current_audio_buf->audio_data); x->x_current_audio_buf->free_audio_data = TRUE; x->x_current_audio_buf->audio_data = output; x->x_current_audio_buf->remaining_samples = output_len; }
static void* convertAudio(void* srcBuffer, int srcSampleCount, int srcFreq, int srcBits, bool srcIsSigned, int &dstSampleCount, int dstFreq, int dstBits, bool dstIsSigned) { std::unique_ptr<float[]> srcFloatBuffer, dstFloatBuffer; srcFloatBuffer = std::unique_ptr<float[]>(new float[srcSampleCount]); void* outputBuffer = nullptr; switch (srcBits) { case 8: { if (srcIsSigned) { int8_t *i8SrcBuffer = static_cast<int8_t*>(srcBuffer); for (int i = 0; i < srcSampleCount; i++) { srcFloatBuffer[i] = (float)i8SrcBuffer[i] / 127.0f; } } else { assert(0); } break; } default: assert(0); } double resampleRatio = (double)dstFreq/(double)srcFreq; dstSampleCount = srcSampleCount*resampleRatio; dstFloatBuffer = std::unique_ptr<float[]>(new float[dstSampleCount]); SRC_DATA resampleSrc; resampleSrc.data_in = srcFloatBuffer.get(); resampleSrc.data_out = dstFloatBuffer.get(); resampleSrc.input_frames = srcSampleCount; resampleSrc.output_frames = dstSampleCount; resampleSrc.src_ratio = resampleRatio; int ret = src_simple(&resampleSrc, SRC_SINC_BEST_QUALITY, 1); if (ret != 0) { std::cerr << "Failed to resample data, error: " << src_strerror(ret) << std::endl; return nullptr; } assert(resampleSrc.output_frames_gen == dstSampleCount); assert(resampleSrc.input_frames_used == srcSampleCount); switch (dstBits) { case 16: { if (dstIsSigned) { int16_t* dstBuffer = new int16_t[dstSampleCount]; for (int i = 0; i < dstSampleCount; i++) { dstBuffer[i] = dstFloatBuffer[i]*(1<<15); } outputBuffer = dstBuffer; } else { assert(0); } break; } default: assert(0); } return outputBuffer; }
int load_waveform_sample(int wavenum, int num_cycles, double octaves) { float *in_buf; float *out_buf; char filename[PATH_MAX]; struct stat statbuf; SRC_DATA src_data; FILE *rawfile; unsigned int sample; unsigned int input_len; float pos_max; float neg_max; float offset; float scalar; size_t sample_t_size = sizeof(sample_t); if ((in_buf = malloc(2 * WAVEFORM_SIZE * sizeof(float))) == NULL) { phasex_shutdown("Out of Memory!\n"); } if ((out_buf = malloc(WAVEFORM_SIZE * sizeof(float))) == NULL) { phasex_shutdown("Out of Memory!\n"); } /* get file size */ snprintf(filename, PATH_MAX, "%s/%s.raw", SAMPLE_DIR, wave_names[wavenum]); if (stat(filename, &statbuf) != 0) { PHASEX_ERROR("Unable to load raw sample file '%s'\n", filename); } input_len = (unsigned int)((unsigned int) statbuf.st_size / sizeof(float)); PHASEX_DEBUG(DEBUG_CLASS_INIT, "Loading raw waveform '%s': %d samples\n", filename, input_len); /* open raw sample file */ if ((rawfile = fopen(filename, "rb")) != 0) { /* read sample data */ if (fread(in_buf, sizeof(float), input_len, rawfile) == input_len) { fclose(rawfile); /* normalize sample to [-1,1] */ pos_max = neg_max = 0; for (sample = 0; sample < input_len; sample++) { if (in_buf[sample] > pos_max) { pos_max = in_buf[sample]; } if (in_buf[sample] < neg_max) { neg_max = in_buf[sample]; } } offset = (pos_max + neg_max) / -2.0; scalar = 1.0 / (float)((pos_max - neg_max) / 2.0); for (sample = 0; sample < input_len; sample++) { in_buf[sample] = (in_buf[sample] + offset) * scalar; } /* resample to fit WAVEFORM_SIZE */ src_data.input_frames = (long int) input_len; src_data.output_frames = WAVEFORM_SIZE; src_data.src_ratio = F_WAVEFORM_SIZE / (double) input_len; src_data.data_in = in_buf; src_data.data_out = (sample_t_size == 4) ? (float *) & (wave_table[wavenum][0]) : & (out_buf[0]); src_simple(&src_data, SRC_SINC_BEST_QUALITY, 1); if (sample_t_size != 4) { for (sample = 0; sample < input_len; sample++) { wave_table[wavenum][sample] = (sample_t)(out_buf[sample]); } } /* filter resampled data */ filter_wave_table_24dB(wavenum, num_cycles, octaves); /* all done */ return 0; } fclose(rawfile); } /* copy sine data on failure */ PHASEX_ERROR("Error reading '%s'!\n", filename); for (sample = 0; sample < WAVEFORM_SIZE; sample++) { wave_table[wavenum][sample] = wave_table[WAVE_SINE][sample]; } return -1; }
void SamplePlayer::loadSampleData(QString path) { SF_INFO info; SNDFILE *file; size_t samples = 0; float *tmpFrames, *tmpSamples, *tmpResamples, *tmpOld; size_t i; info.format = 0; file = sf_open(path.toLocal8Bit().data(), SFM_READ, &info); if (!file) { std::cerr << "SamplePlayer::loadSampleData: Failed to open file " << path.toLocal8Bit().data() << ": " << sf_strerror(file) << std::endl; return; } samples = info.frames; tmpFrames = (float *)malloc(info.frames * info.channels * sizeof(float)); if (!tmpFrames) return; sf_readf_float(file, tmpFrames, info.frames); sf_close(file); tmpResamples = 0; if (info.samplerate != m_sampleRate) { double ratio = (double)m_sampleRate / (double)info.samplerate; size_t target = (size_t)(info.frames * ratio); SRC_DATA data; tmpResamples = (float *)malloc(target * info.channels * sizeof(float)); if (!tmpResamples) { free(tmpFrames); return; } memset(tmpResamples, 0, target * info.channels * sizeof(float)); data.data_in = tmpFrames; data.data_out = tmpResamples; data.input_frames = info.frames; data.output_frames = target; data.src_ratio = ratio; if (!src_simple(&data, SRC_SINC_BEST_QUALITY, info.channels)) { free(tmpFrames); tmpFrames = tmpResamples; samples = target; } else { free(tmpResamples); } } /* add an extra sample for linear interpolation */ tmpSamples = (float *)malloc((samples + 1) * sizeof(float)); if (!tmpSamples) { free(tmpFrames); return; } for (i = 0; i < samples; ++i) { int j; tmpSamples[i] = 0.0f; for (j = 0; j < info.channels; ++j) { tmpSamples[i] += tmpFrames[i * info.channels + j]; } } free(tmpFrames); /* add an extra sample for linear interpolation */ tmpSamples[samples] = 0.0f; QMutexLocker locker(&m_mutex); tmpOld = m_sampleData; m_sampleData = tmpSamples; m_sampleCount = samples; for (i = 0; i < Polyphony; ++i) { m_ons[i] = -1; m_offs[i] = -1; m_velocities[i] = 0; } if (tmpOld) free(tmpOld); printf("%s: loaded %s (%ld samples from original %ld channels resampled from %ld frames at %ld Hz)\n", "sampler", path.toLocal8Bit().data(), (long)samples, (long)info.channels, (long)info.frames, (long)info.samplerate); }
char *samplerLoad(Sampler *plugin_data, const char *path) { SF_INFO info; SNDFILE *file; size_t samples = 0; float *tmpFrames, *tmpSamples[2], *tmpResamples, *tmpOld[2]; char *revisedPath = 0; size_t i; info.format = 0; file = sf_open(path, SFM_READ, &info); if (!file) { const char *filename = strrchr(path, '/'); if (filename) ++filename; else filename = path; if (*filename && plugin_data->projectDir) { revisedPath = (char *)malloc(strlen(filename) + strlen(plugin_data->projectDir) + 2); sprintf(revisedPath, "%s/%s", plugin_data->projectDir, filename); file = sf_open(revisedPath, SFM_READ, &info); if (!file) { free(revisedPath); } } if (!file) { return dssi_configure_message ("error: unable to load sample file '%s'", path); } } if (info.frames > Sampler_FRAMES_MAX) { return dssi_configure_message ("error: sample file '%s' is too large (%ld frames, maximum is %ld)", path, info.frames, Sampler_FRAMES_MAX); } //!!! complain also if more than 2 channels samples = info.frames; tmpFrames = (float *)malloc(info.frames * info.channels * sizeof(float)); sf_readf_float(file, tmpFrames, info.frames); sf_close(file); tmpResamples = 0; if (info.samplerate != plugin_data->sampleRate) { double ratio = (double)plugin_data->sampleRate / (double)info.samplerate; size_t target = (size_t)(info.frames * ratio); SRC_DATA data; tmpResamples = (float *)malloc(target * info.channels * sizeof(float)); memset(tmpResamples, 0, target * info.channels * sizeof(float)); data.data_in = tmpFrames; data.data_out = tmpResamples; data.input_frames = info.frames; data.output_frames = target; data.src_ratio = ratio; if (!src_simple(&data, SRC_SINC_BEST_QUALITY, info.channels)) { free(tmpFrames); tmpFrames = tmpResamples; samples = target; } else { free(tmpResamples); } } /* add an extra sample for linear interpolation */ tmpSamples[0] = (float *)malloc((samples + 1) * sizeof(float)); if (plugin_data->channels == 2) { tmpSamples[1] = (float *)malloc((samples + 1) * sizeof(float)); } else { tmpSamples[1] = NULL; } if (plugin_data->channels == 2) { for (i = 0; i < samples; ++i) { int j; for (j = 0; j < 2; ++j) { if (j == 1 && info.frames < 2) { tmpSamples[j][i] = tmpSamples[0][i]; } else { tmpSamples[j][i] = tmpFrames[i * info.channels + j]; } } } } else { for (i = 0; i < samples; ++i) { int j; tmpSamples[0][i] = 0.0f; for (j = 0; j < info.channels; ++j) { tmpSamples[0][i] += tmpFrames[i * info.channels + j]; } } } free(tmpFrames); /* add an extra sample for linear interpolation */ tmpSamples[0][samples] = 0.0f; if (plugin_data->channels == 2) { tmpSamples[1][samples] = 0.0f; } pthread_mutex_lock(&plugin_data->mutex); tmpOld[0] = plugin_data->sampleData[0]; tmpOld[1] = plugin_data->sampleData[1]; plugin_data->sampleData[0] = tmpSamples[0]; plugin_data->sampleData[1] = tmpSamples[1]; plugin_data->sampleCount = samples; for (i = 0; i < Sampler_NOTES; ++i) { plugin_data->ons[i] = -1; plugin_data->offs[i] = -1; plugin_data->velocities[i] = 0; } pthread_mutex_unlock(&plugin_data->mutex); if (tmpOld[0]) free(tmpOld[0]); if (tmpOld[1]) free(tmpOld[1]); printf("%s: loaded %s (%ld samples from original %ld channels resampled from %ld frames at %ld Hz)\n", (plugin_data->channels == 2 ? Sampler_Stereo_LABEL : Sampler_Mono_LABEL), path, (long)samples, (long)info.channels, (long)info.frames, (long)info.samplerate); if (revisedPath) { char *message = dssi_configure_message("warning: sample file '%s' not found: loading from '%s' instead", path, revisedPath); free(revisedPath); return message; } return NULL; }