diff --git a/drmr.c b/drmr.c index 923a3be..3e8c335 100644 --- a/drmr.c +++ b/drmr.c @@ -31,7 +31,7 @@ static void* load_thread(void* arg) { DrMr* drmr = (DrMr*)arg; drmr_sample *loaded_samples,*old_samples; int loaded_count, old_scount; - char *request; + char *request, *request_orig; for(;;) { pthread_mutex_lock(&drmr->load_mutex); pthread_cond_wait(&drmr->load_cond, @@ -39,7 +39,9 @@ static void* load_thread(void* arg) { pthread_mutex_unlock(&drmr->load_mutex); old_samples = drmr->samples; old_scount = drmr->num_samples; - request = drmr->request_buf[drmr->curReq]; + request_orig = request = drmr->request_buf[drmr->curReq]; + if (!strncmp(request, "file://", 7)) + request += 7; loaded_samples = load_hydrogen_kit(request,drmr->rate,&loaded_count); if (!loaded_samples) { fprintf(stderr,"Failed to load kit at: %s\n",request); @@ -57,7 +59,7 @@ static void* load_thread(void* arg) { pthread_mutex_unlock(&drmr->load_mutex); } if (old_scount > 0) free_samples(old_samples,old_scount); - drmr->current_path = request; + drmr->current_path = request_orig; current_kit_changed = 1; } return 0; @@ -227,7 +229,7 @@ static inline void layer_to_sample(drmr_sample *sample, float gain) { sample->data = sample->layers[0].data; } -static inline void trigger_sample(DrMr *drmr, int nn, uint8_t* const data) { +static inline void trigger_sample(DrMr *drmr, int nn, uint8_t* const data, uint32_t offset) { // need to mutex this to avoid getting the samples array // changed after the check that the midi-note is valid pthread_mutex_lock(&drmr->load_mutex); @@ -244,11 +246,12 @@ static inline void trigger_sample(DrMr *drmr, int nn, uint8_t* const data) { drmr->samples[nn].active = 1; drmr->samples[nn].offset = 0; drmr->samples[nn].velocity = drmr->ignore_velocity?1.0f:((float)data[2])/VELOCITY_MAX; + drmr->samples[nn].dataoffset = offset; } pthread_mutex_unlock(&drmr->load_mutex); } -static inline void untrigger_sample(DrMr *drmr, int nn) { +static inline void untrigger_sample(DrMr *drmr, int nn, uint32_t offset) { pthread_mutex_lock(&drmr->load_mutex); if (nn >= 0 && nn < drmr->num_samples) { if (drmr->samples[nn].layer_count > 0) { @@ -257,7 +260,7 @@ static inline void untrigger_sample(DrMr *drmr, int nn) { fprintf(stderr,"Failed to find layer at: %i for %f\n",nn,*drmr->gains[nn]); } drmr->samples[nn].active = 0; - drmr->samples[nn].offset = 0; + drmr->samples[nn].dataoffset = offset; } pthread_mutex_unlock(&drmr->load_mutex); } @@ -284,23 +287,25 @@ static void run(LV2_Handle instance, uint32_t n_samples) { if (ev->body.type == drmr->uris.midi_event) { uint8_t nn; uint8_t* const data = (uint8_t* const)(ev + 1); + uint32_t offset = (ev->time.frames > 0 && ev->time.frames < n_samples) ? ev->time.frames : 0; //int channel = *data & 15; switch ((*data) >> 4) { case 8: if (!drmr->ignore_note_off) { nn = data[1]; nn-=baseNote; - untrigger_sample(drmr,nn); + untrigger_sample(drmr,nn,offset); } break; case 9: { nn = data[1]; nn-=baseNote; - trigger_sample(drmr,nn,data); + trigger_sample(drmr,nn,data,offset); break; } default: - printf("Unhandeled status: %i\n",(*data)>>4); + //printf("Unhandeled status: %i\n",(*data)>>4); + break; } } else if (ev->body.type == drmr->uris.atom_resource) { @@ -331,10 +336,11 @@ static void run(LV2_Handle instance, uint32_t n_samples) { if (trigger) { int32_t si = ((const LV2_Atom_Int*)trigger)->body; uint8_t mdata[3]; + uint32_t offset = (ev->time.frames > 0 && ev->time.frames < n_samples) ? ev->time.frames : 0; mdata[0] = 0x90; // note on mdata[1] = si+baseNote; mdata[2] = 0x7f; - trigger_sample(drmr,si,mdata); + trigger_sample(drmr,si,mdata,offset); } if (ignvel) drmr->ignore_velocity = ((const LV2_Atom_Bool*)ignvel)->body; @@ -347,7 +353,7 @@ static void run(LV2_Handle instance, uint32_t n_samples) { build_state_message(drmr); } } - else printf("unrecognized event\n"); + //else printf("unrecognized event\n"); } if ((drmr->curReq >= 0) && @@ -374,7 +380,7 @@ static void run(LV2_Handle instance, uint32_t n_samples) { for (i = 0;i < drmr->num_samples;i++) { int pos,lim; drmr_sample* cs = drmr->samples+i; - if (cs->active && (cs->limit > 0)) { + if ((cs->active || cs->dataoffset) && (cs->limit > 0)) { float coef_right, coef_left; if (i < 32) { float gain = DB_CO(*(drmr->gains[i])); @@ -387,9 +393,19 @@ static void run(LV2_Handle instance, uint32_t n_samples) { coef_right = coef_left = 1.0f; } + int datastart, dataend; + if (cs->active) { + datastart = cs->dataoffset; + dataend = n_samples; + } else { + datastart = 0; + dataend = cs->dataoffset; + } + cs->dataoffset = 0; + if (cs->info->channels == 1) { // play mono sample lim = (n_samples < (cs->limit - cs->offset)?n_samples:(cs->limit-cs->offset)); - for(pos = 0;pos < lim;pos++) { + for (pos = datastart; pos < lim && pos < dataend; pos++) { drmr->left[pos] += cs->data[cs->offset]*coef_left; drmr->right[pos] += cs->data[cs->offset]*coef_right; cs->offset++; @@ -397,7 +413,7 @@ static void run(LV2_Handle instance, uint32_t n_samples) { } else { // play stereo sample lim = (cs->limit-cs->offset)/cs->info->channels; if (lim > n_samples) lim = n_samples; - for (pos=0;posleft[pos] += cs->data[cs->offset++]*coef_left; drmr->right[pos] += cs->data[cs->offset++]*coef_right; } @@ -440,16 +456,18 @@ save_state(LV2_Handle instance, return LV2_STATE_ERR_NO_FEATURE; } - char* mapped_path = map_path->abstract_path(map_path->handle, - drmr->current_path); - - stat = store(handle, - drmr->uris.kit_path, - mapped_path, - strlen(mapped_path) + 1, - drmr->uris.string_urid, - LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); - if (stat) return stat; + if (drmr->current_path != NULL) { + char* mapped_path = map_path->abstract_path(map_path->handle, + drmr->current_path); + + stat = store(handle, + drmr->uris.kit_path, + mapped_path, + strlen(mapped_path) + 1, + drmr->uris.string_urid, + LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); + if (stat) return stat; + } flag = drmr->ignore_velocity?1:0; stat = store(handle, @@ -543,7 +561,7 @@ restore_state(LV2_Handle instance, static const void* extension_data(const char* uri) { static const LV2_State_Interface state_iface = { save_state, restore_state }; - if (!strcmp(uri, LV2_STATE_URI "#Interface")) return &state_iface; + if (!strcmp(uri, LV2_STATE__interface)) return &state_iface; return NULL; } diff --git a/drmr.h b/drmr.h index 1cf969c..036850a 100644 --- a/drmr.h +++ b/drmr.h @@ -61,6 +61,7 @@ typedef struct { float velocity; drmr_layer *layers; float* data; + int dataoffset; } drmr_sample; // lv2 stuff diff --git a/drmr.ttl b/drmr.ttl index 8479635..f171a5b 100644 --- a/drmr.ttl +++ b/drmr.ttl @@ -19,7 +19,7 @@ doap:license ; lv2:requiredFeature urid:map ; ui:ui ; - lv2:extensionData ; + lv2:extensionData ; lv2:port [ a lv2:InputPort , atom:AtomPort; atom:bufferType atom:Sequence ; diff --git a/drmr_hydrogen.c b/drmr_hydrogen.c index fe0f730..61124d9 100644 --- a/drmr_hydrogen.c +++ b/drmr_hydrogen.c @@ -90,6 +90,8 @@ struct hp_info { char in_instrument_list; char in_instrument; char in_layer; + char in_drumkit_component; + char counted_cur_inst; int cur_off; char cur_buf[MAX_CHAR_DATA]; @@ -106,7 +108,7 @@ startElement(void *userData, const char *name, const char **atts) info->cur_off = 0; if (info->in_info) { if (info->in_instrument) { - if (!strcmp(name,"layer") && !info->scan_only) { + if (!strcmp(name,"layer") && !info->scan_only) { info->in_layer = 1; info->cur_layer = malloc(sizeof(struct instrument_layer)); memset(info->cur_layer,0,sizeof(struct instrument_layer)); @@ -121,6 +123,10 @@ startElement(void *userData, const char *name, const char **atts) } else { if (!strcmp(name,"instrumentList")) info->in_instrument_list = 1; + + if (! strcmp (name,"drumkitComponent")) + info->in_drumkit_component = 1; + } } else { if (!strcmp(name,"drumkit_info")) @@ -135,7 +141,7 @@ endElement(void *userData, const char *name) if (info->cur_off == MAX_CHAR_DATA) info->cur_off--; info->cur_buf[info->cur_off]='\0'; - if (info->in_info && !info->in_instrument_list && !strcmp(name,"name")) + if (info->in_info && ! info->in_drumkit_component && !info->in_instrument_list && !strcmp(name,"name")) info->kit_info->name = strdup(info->cur_buf); if (info->scan_only && info->in_info && !info->in_instrument_list && !strcmp(name,"info")) info->kit_info->desc = strdup(info->cur_buf); @@ -188,6 +194,9 @@ endElement(void *userData, const char *name) info->in_instrument = 0; } if (info->in_instrument_list && !strcmp(name,"instrumentList")) info->in_instrument_list = 0; + if (info->in_drumkit_component && ! strcmp (name, "drumkitComponent")) + info->in_drumkit_component = 0; + if (info->in_info && !strcmp(name,"drumkit_info")) info->in_info = 0; } @@ -565,6 +574,7 @@ drmr_sample* load_hydrogen_kit(char *path, double rate, int *num_samples) { samples[i].data = NULL; } samples[i].active = 0; + samples[i].dataoffset = 0; i_to_free = cur_i; cur_i = cur_i->next; diff --git a/drmr_ui.c b/drmr_ui.c index 71c3a64..342a1be 100644 --- a/drmr_ui.c +++ b/drmr_ui.c @@ -723,6 +723,8 @@ port_event(LV2UI_Handle handle, lv2_atom_object_get(obj, ui->uris.kit_path, &path, 0); if (path) { char *kitpath = LV2_ATOM_BODY(path); + if (!strncmp(kitpath, "file://", 7)) + kitpath += 7; char *realp = realpath(kitpath,NULL); if (!realp) { fprintf(stderr,"Passed a path I can't resolve, bailing out\n");