diff --git a/Makefile b/Makefile index bdb5fc9..1b970a4 100644 --- a/Makefile +++ b/Makefile @@ -8,10 +8,10 @@ $(BUNDLE): manifest.ttl drmr.ttl drmr.so drmr_ui.so cp manifest.ttl drmr.ttl drmr.so drmr_ui.so $(BUNDLE) drmr.so: drmr.c drmr_hydrogen.c - $(CC) -shared -fPIC -DPIC drmr.c drmr_hydrogen.c `pkg-config --cflags --libs lv2-plugin sndfile` -lexpat -lm -o drmr.so + $(CC) -shared -fPIC -DPIC drmr.c drmr_hydrogen.c `pkg-config --cflags --libs lv2-plugin sndfile samplerate` -lexpat -lm -o drmr.so drmr_ui.so: drmr_ui.c drmr_hydrogen.c - $(CC) -shared -fPIC -DPIC drmr_ui.c drmr_hydrogen.c `pkg-config --cflags --libs lv2-plugin gtk+-2.0 sndfile` -lexpat -lm -o drmr_ui.so + $(CC) -shared -fPIC -DPIC drmr_ui.c drmr_hydrogen.c `pkg-config --cflags --libs lv2-plugin gtk+-2.0 sndfile samplerate` -lexpat -lm -o drmr_ui.so install: $(BUNDLE) mkdir -p $(INSTALL_DIR) diff --git a/README.md b/README.md index 32f5a68..cc02cca 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ Compilation and Install You'll need the following libraries to build and install DrMr: - [libsndfile](http://www.mega-nerd.com/libsndfile/) +- [libsamplerate](http://www.mega-nerd.com/SRC/index.html) - [lv2](http://lv2plug.in/) - [libexpat](http://expat.sourceforge.net) diff --git a/drmr.c b/drmr.c index b5c0dde..6194ee9 100644 --- a/drmr.c +++ b/drmr.c @@ -52,6 +52,7 @@ instantiate(const LV2_Descriptor* descriptor, DrMr* drmr = malloc(sizeof(DrMr)); drmr->map = NULL; drmr->num_samples = 0; + drmr->rate = rate; if (pthread_mutex_init(&drmr->load_mutex, 0)) { fprintf(stderr, "Could not initialize load_mutex.\n"); diff --git a/drmr.h b/drmr.h index f55c2ff..b5714eb 100644 --- a/drmr.h +++ b/drmr.h @@ -147,6 +147,7 @@ typedef struct { float** gains; float** pans; float* kitReq; + double rate; // URIs LV2_URI_Map_Feature* map; diff --git a/drmr_hydrogen.c b/drmr_hydrogen.c index a5aaca1..0e937b9 100644 --- a/drmr_hydrogen.c +++ b/drmr_hydrogen.c @@ -22,7 +22,9 @@ #include #include #include +#include +#include "samplerate.h" #include "drmr.h" #include "drmr_hydrogen.h" #include "expat.h" @@ -36,6 +38,8 @@ static char* default_drumkit_locations[] = { NULL }; +#define RATE_CONV_QUALITY SRC_SINC_MEDIUM_QUALITY + #define MAX_CHAR_DATA 512 struct instrument_layer { @@ -339,9 +343,9 @@ void free_kits(kits* kits) { free(kits); } -int load_sample(char* path, drmr_layer* layer) { +int load_sample(char* path, drmr_layer* layer, double target_rate) { SNDFILE* sndf; - int size; + long size; //printf("Loading: %s\n",path); @@ -360,6 +364,7 @@ int load_sample(char* path, drmr_layer* layer) { free(layer->info); return 1; } + size = layer->info->frames * layer->info->channels; layer->limit = size; layer->data = malloc(size*sizeof(float)); @@ -371,6 +376,41 @@ int load_sample(char* path, drmr_layer* layer) { sf_read_float(sndf,layer->data,size); sf_close(sndf); + + // convert rate if needed + if (layer->info->samplerate != target_rate) { + SRC_DATA src_data; + int stat; + double ratio = (target_rate/layer->info->samplerate); + long out_frames = (long)ceil(layer->info->frames * ratio); + long out_size = out_frames*layer->info->channels; + float *data_out = malloc(sizeof(float)*out_size); + + src_data.data_in = layer->data; + src_data.input_frames = layer->info->frames; + src_data.data_out = data_out; + src_data.output_frames = out_frames; + src_data.src_ratio = ratio; + + stat = src_simple(&src_data,RATE_CONV_QUALITY,layer->info->channels); + if (stat) { + fprintf(stderr,"Failed to convert rate for %s: %s. Using original rate\n", + path,src_strerror(stat)); + free(data_out); + return 0; + } + + if (src_data.input_frames_used != layer->info->frames) + fprintf(stderr,"Didn't consume all input frames. used: %i had: %i gened: %i\n", + src_data.input_frames_used, layer->info->frames,src_data.output_frames_gen); + + free(layer->data); + + layer->data = data_out; + layer->limit = src_data.output_frames_gen*layer->info->channels; + layer->info->samplerate = target_rate; + layer->info->frames = src_data.output_frames_gen; + } return 0; } @@ -435,7 +475,7 @@ int load_hydrogen_kit(DrMr* drmr, char* path) { layer->min = 0; layer->max = 1; snprintf(buf,BUFSIZ,"%s/%s",path,cur_i->filename); - if (load_sample(buf,layer)) { + if (load_sample(buf,layer,drmr->rate)) { fprintf(stderr,"Could not load sample: %s\n",buf); // set limit to zero, will never try and play layer->info = NULL; @@ -463,7 +503,7 @@ int load_hydrogen_kit(DrMr* drmr, char* path) { j = 0; while(cur_l) { snprintf(buf,BUFSIZ,"%s/%s",path,cur_l->filename); - if (load_sample(buf,samples[i].layers+j)) { + if (load_sample(buf,samples[i].layers+j,drmr->rate)) { fprintf(stderr,"Could not load sample: %s\n",buf); // set limit to zero, will never try and play samples[i].layers[j].info = NULL; diff --git a/drmr_hydrogen.h b/drmr_hydrogen.h index 534db9c..7e64466 100644 --- a/drmr_hydrogen.h +++ b/drmr_hydrogen.h @@ -20,7 +20,7 @@ kits* scan_kits(); void free_samples(drmr_sample* samples, int num_samples); -int load_sample(char* path,drmr_layer* layer); +int load_sample(char* path,drmr_layer* layer,double target_rate); int load_hydrogen_kit(DrMr* drmr, char* path); #endif // DRMR_HYDRO_H