Changeset 8688797 for src/effects/timestretch_rubberband.c
- Timestamp:
- Nov 28, 2016, 2:30:40 PM (7 years ago)
- Branches:
- sampler
- Children:
- 5382846
- Parents:
- a125fb9a
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/effects/timestretch_rubberband.c
ra125fb9a r8688797 51 51 smpl_t pitchscale; /**< pitch scale */ 52 52 53 aubio_source_t *source;54 uint_t source_hopsize; /**< hop size at which the source is read */55 fvec_t *in;56 uint_t eof;57 58 53 RubberBandState rb; 59 54 RubberBandOptions rboptions; 60 61 uint_t opened;62 const char_t *uri;63 #ifdef HAVE_THREADS64 pthread_t read_thread;65 pthread_mutex_t read_mutex;66 pthread_cond_t read_avail;67 pthread_cond_t read_request;68 pthread_t open_thread;69 pthread_mutex_t open_mutex;70 uint_t open_thread_running;71 sint_t available;72 uint_t started;73 uint_t finish;74 #endif75 55 }; 76 56 … … 78 58 79 59 static void aubio_timestretch_warmup (aubio_timestretch_t * p); 80 static sint_t aubio_timestretch_fetch(aubio_timestretch_t *p, uint_t fetch);81 #ifdef HAVE_THREADS82 static void *aubio_timestretch_readfn(void *p);83 static void *aubio_timestretch_openfn(void *z);84 #endif85 60 86 61 aubio_timestretch_t * 87 new_aubio_timestretch (const char_t * uri, const char_t * mode,88 smpl_t stretchratio, uint_t hopsize,uint_t samplerate)62 new_aubio_timestretch (const char_t * mode, smpl_t stretchratio, uint_t hopsize, 63 uint_t samplerate) 89 64 { 90 65 aubio_timestretch_t *p = AUBIO_NEW (aubio_timestretch_t); 91 66 p->hopsize = hopsize; 92 //p->source_hopsize = 2048;93 p->source_hopsize = hopsize;94 67 p->pitchscale = 1.; 95 68 … … 108 81 } 109 82 110 p->in = new_fvec(p->source_hopsize); 111 112 #ifndef HAVE_THREADS 113 if (aubio_timestretch_queue(p, uri, samplerate)) goto beach; 114 aubio_timestretch_warmup(p); 115 #else 116 p->started = 0; 117 p->finish = 0; 118 p->open_thread_running = 0; 119 //p->uri = uri; 120 p->eof = 0; 121 //p->samplerate = samplerate; 122 //if (aubio_timestretch_open(p, uri, samplerate)) goto beach; 123 pthread_mutex_init(&p->open_mutex, 0); 124 pthread_mutex_init(&p->read_mutex, 0); 125 pthread_cond_init (&p->read_avail, 0); 126 pthread_cond_init (&p->read_request, 0); 127 //AUBIO_WRN("timestretch: creating thread\n"); 128 pthread_create(&p->read_thread, 0, aubio_timestretch_readfn, p); 129 //AUBIO_DBG("timestretch: new_ waiting for warmup, got %d available\n", p->available); 130 pthread_mutex_lock(&p->read_mutex); 131 aubio_timestretch_queue(p, uri, samplerate); 132 #if 0 133 pthread_cond_wait(&p->read_avail, &p->read_mutex); 134 if (!p->opened) { 135 goto beach; 136 } 137 #endif 138 pthread_mutex_unlock(&p->read_mutex); 139 //AUBIO_DBG("timestretch: new_ warm up success, got %d available\n", p->available); 140 #endif 83 p->rb = rubberband_new(samplerate, 1, p->rboptions, p->stretchratio, p->pitchscale); 84 if (!p->rb) goto beach; 85 86 p->samplerate = samplerate; 87 88 //aubio_timestretch_warmup(p); 141 89 142 90 return p; … … 147 95 } 148 96 149 #define HAVE_OPENTHREAD 1150 //#undef HAVE_OPENTHREAD151 152 uint_t153 aubio_timestretch_queue(aubio_timestretch_t *p, const char_t* uri, uint_t samplerate)154 {155 #ifdef HAVE_THREADS156 #ifdef HAVE_OPENTHREAD157 if (p->open_thread_running) {158 #if 1159 if (pthread_cancel(p->open_thread)) {160 AUBIO_WRN("timestretch: cancelling open thread failed\n");161 return AUBIO_FAIL;162 } else {163 AUBIO_WRN("timestretch: previous open of '%s' cancelled\n", p->uri);164 }165 p->open_thread_running = 0;166 #else167 void *threadfn;168 if (pthread_join(p->open_thread, &threadfn)) {169 AUBIO_WRN("timestretch: failed joining existing open thread\n");170 return AUBIO_FAIL;171 }172 #endif173 }174 //AUBIO_WRN("timestretch: queueing %s\n", uri);175 //pthread_mutex_lock(&p->read_mutex);176 p->opened = 0;177 p->started = 0;178 p->available = 0;179 p->uri = uri;180 p->samplerate = samplerate;181 //AUBIO_WRN("timestretch: creating thread\n");182 pthread_create(&p->open_thread, 0, aubio_timestretch_openfn, p);183 #endif184 //pthread_mutex_unlock(&p->read_mutex);185 return AUBIO_OK;186 }187 188 uint_t189 aubio_timestretch_open(aubio_timestretch_t *p, const char_t* uri, uint_t samplerate)190 {191 uint_t err = AUBIO_FAIL;192 p->available = 0;193 pthread_mutex_lock(&p->open_mutex);194 p->open_thread_running = 1;195 #else196 uint_t err = AUBIO_FAIL;197 #endif198 p->opened = 0;199 if (p->source) del_aubio_source(p->source);200 p->source = new_aubio_source(uri, samplerate, p->source_hopsize);201 if (!p->source) goto fail;202 p->uri = uri;203 p->samplerate = aubio_source_get_samplerate(p->source);204 p->eof = 0;205 206 if (p->rb == NULL) {207 AUBIO_WRN("timestretch: creating with stretch: %.2f pitchscale: %.2f\n",208 p->stretchratio, p->pitchscale);209 p->rb = rubberband_new(p->samplerate, 1, p->rboptions, p->stretchratio, p->pitchscale);210 //rubberband_set_debug_level(p->rb, 10);211 rubberband_set_max_process_size(p->rb, p->source_hopsize);212 } else {213 if (samplerate != p->samplerate) {214 AUBIO_WRN("timestretch: samplerate change requested, but not implemented\n");215 }216 rubberband_reset(p->rb);217 }218 p->opened = 1;219 err = AUBIO_OK;220 goto unlock;221 fail:222 p->opened = 2;223 AUBIO_ERR("timestretch: opening %s failed\n", uri);224 unlock:225 #ifdef HAVE_THREADS226 p->open_thread_running = 0;227 pthread_mutex_unlock(&p->open_mutex);228 //AUBIO_WRN("timestretch: failed opening %s at %dHz\n", uri, samplerate);229 #endif230 return err;231 }232 233 #ifdef HAVE_THREADS234 void *235 aubio_timestretch_openfn(void *z) {236 aubio_timestretch_t *p = z;237 int oldtype;238 pthread_setcancelstate(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);239 //AUBIO_WRN("timestretch: creating thread\n");240 void *ret;241 uint_t err = aubio_timestretch_open(p, p->uri, p->samplerate);242 ret = &err;243 pthread_exit(ret);244 }245 #endif246 247 uint_t248 aubio_timestretch_get_opened(aubio_timestretch_t *p)249 {250 if (p == NULL) return 0;251 else return p->opened;252 }253 254 #ifdef HAVE_THREADS255 void *256 aubio_timestretch_readfn(void *z)257 {258 aubio_timestretch_t *p = z;259 //AUBIO_WRN("timestretch: entering thread with %s at %dHz\n", p->uri, p->samplerate);260 while(1) { //p->available < (int)p->hopsize && p->eof != 1) {261 //AUBIO_WRN("timestretch: locking in readfn\n");262 pthread_mutex_lock(&p->read_mutex);263 #if 1264 if (p->opened == 2) {265 pthread_cond_signal(&p->read_avail);266 } else267 if (p->opened == 0) {268 #ifdef HAVE_OPENTHREAD269 //(!aubio_timestretch_open(p, p->uri, p->samplerate)) {270 void * threadfn;271 if (p->open_thread_running && pthread_join(p->open_thread, &threadfn)) {272 AUBIO_WRN("timestretch: failed to join opening thread %s at %dHz in thread "273 "(opened: %d, playing: %d, eof: %d)\n",274 p->uri, p->samplerate, p->opened, p->started, p->eof);275 }276 #else277 //AUBIO_WRN("timestretch: opening source %s\n", p->uri);278 if (!aubio_timestretch_open(p, p->uri, p->samplerate)) {279 AUBIO_WRN("timestretch: opened %s at %dHz in thread "280 "(opened: %d, playing: %d, eof: %d)\n",281 p->uri, p->samplerate, p->opened, p->started, p->eof);282 //pthread_cond_signal(&p->read_avail);283 } else {284 AUBIO_WRN("timestretch: failed opening %s, exiting thread\n", p->uri);285 //pthread_cond_signal(&p->read_avail);286 //pthread_mutex_unlock(&p->read_mutex);287 //goto end;288 }289 #endif290 } else291 if (!p->started && !p->eof) {292 #endif293 // fetch the first few samples and mark as started294 aubio_timestretch_warmup(p);295 pthread_cond_signal(&p->read_avail);296 //pthread_cond_wait(&p->read_request, &p->read_mutex);297 p->started = 1;298 } else if (!p->eof) {299 // fetch at least p->hopsize stretched samples300 p->available = aubio_timestretch_fetch(p, p->hopsize);301 // signal available frames302 pthread_cond_signal(&p->read_avail);303 if (p->eof != 1) {304 // the end of file was not reached yet, wait for the next read_request305 pthread_cond_wait(&p->read_request, &p->read_mutex);306 } else {307 // eof was reached, do not wait for a read request and mark as stopped308 p->started = 0;309 }310 } else {311 //pthread_cond_signal(&p->read_avail);312 pthread_cond_wait(&p->read_request, &p->read_mutex);313 //AUBIO_WRN("timestretch: finished idle in readfn\n");314 if (p->finish) pthread_exit(NULL);315 }316 //AUBIO_WRN("timestretch: unlocking in readfn\n");317 pthread_mutex_unlock(&p->read_mutex);318 }319 end:320 //AUBIO_WRN("timestretch: exiting readfn\n");321 pthread_exit(NULL);322 }323 #endif324 325 97 static void 326 98 aubio_timestretch_warmup (aubio_timestretch_t * p) … … 329 101 //AUBIO_WRN("timestretch: warming-up\n"); 330 102 unsigned int latency = MAX(p->hopsize, rubberband_get_latency(p->rb)); 331 #ifdef HAVE_THREADS 332 p->available = aubio_timestretch_fetch(p, latency);333 #else 334 aubio_timestretch_fetch(p, latency);335 #endif 336 //AUBIO_WRN("timestretch: warmup got %d\n", latency);103 fvec_t *input = new_fvec(p->hopsize); 104 while (aubio_timestretch_push(p, input, input->length) < (int)latency) { 105 //sint_t available = aubio_timestretch_get_available(p); 106 //AUBIO_WRN("timestretch: warmup got %d, latency: %d\n", available, latency); 107 } 108 del_fvec(input); 337 109 } 338 110 … … 340 112 del_aubio_timestretch (aubio_timestretch_t * p) 341 113 { 342 #ifdef HAVE_THREADS343 void *threadfn;344 //AUBIO_WRN("timestretch: entering delete\n");345 if (p->open_thread_running) {346 if (pthread_cancel(p->open_thread)) {347 AUBIO_WRN("timestretch: cancelling open thread failed\n");348 }349 if (pthread_join(p->open_thread, &threadfn)) {350 AUBIO_WRN("timestretch: joining open thread failed\n");351 }352 }353 if (!p->opened) goto cleanup;354 pthread_mutex_lock(&p->read_mutex);355 p->finish = 1;356 pthread_cond_signal(&p->read_request);357 //pthread_cond_wait(&p->read_avail, &p->read_mutex);358 pthread_mutex_unlock(&p->read_mutex);359 if ((p->eof == 0) && (pthread_cancel(p->read_thread))) {360 AUBIO_WRN("timestretch: cancelling thread failed\n");361 }362 if (pthread_join(p->read_thread, &threadfn)) {363 AUBIO_WRN("timestretch: joining thread failed\n");364 }365 pthread_mutex_destroy(&p->read_mutex);366 pthread_cond_destroy(&p->read_avail);367 pthread_cond_destroy(&p->read_request);368 cleanup:369 #endif370 if (p->in) del_fvec(p->in);371 if (p->source) del_aubio_source(p->source);372 114 if (p->rb) { 373 115 rubberband_delete(p->rb); … … 451 193 452 194 sint_t 453 aubio_timestretch_fetch(aubio_timestretch_t *p, uint_t length) 454 { 455 uint_t source_read = p->source_hopsize; 456 if (p->source == NULL) { 457 AUBIO_ERR("timestretch: trying to fetch on NULL source\n"); 458 return 0; 459 } 460 // read more samples from source until we have enough available or eof is reached 195 aubio_timestretch_push(aubio_timestretch_t *p, fvec_t *input, uint_t length) 196 { 197 // push new samples to rubberband, return available 198 int available; 199 int eof = (input->length != length) ? 1 : 0; 200 rubberband_process(p->rb, (const float* const*)&(input->data), length, eof); 201 available = rubberband_available(p->rb); 202 //AUBIO_WRN("timestretch: processed %d, %d available, eof: %d\n", 203 // length, available, eof); 204 return available; 205 } 206 207 sint_t 208 aubio_timestretch_get_available(aubio_timestretch_t *p) { 209 return rubberband_available(p->rb); 210 } 211 212 void 213 aubio_timestretch_do(aubio_timestretch_t * p, fvec_t * out, uint_t * read) 214 { 215 // now retrieve the samples and write them into out->data 461 216 int available = rubberband_available(p->rb); 462 while ((available < (int)length) && (p->eof == 0)) { 463 aubio_source_do(p->source, p->in, &source_read); 464 if (source_read < p->source_hopsize) { 465 p->eof = 1; 466 } 467 rubberband_process(p->rb, (const float* const*)&(p->in->data), source_read, p->eof); 468 available = rubberband_available(p->rb); 469 } 470 return available; 471 } 472 473 void 474 aubio_timestretch_do (aubio_timestretch_t * p, fvec_t * out, uint_t * read) 475 { 476 #ifndef HAVE_THREADS 477 int available = aubio_timestretch_fetch(p, p->hopsize); 478 #else /* HAVE_THREADS */ 479 int available; 480 pthread_mutex_lock(&p->read_mutex); 481 #if 1 482 if (!p->opened) { 483 // this may occur if _do was was called while being opened 484 //AUBIO_WRN("timestretch: calling _do before opening a file\n"); 485 pthread_cond_signal(&p->read_request); 486 //available = 0; 487 //pthread_cond_wait(&p->read_avail, &p->read_mutex); 488 available = 0; //p->available; 489 } else 490 #endif 491 if (p->eof != 1) { 492 //AUBIO_WRN("timestretch: calling _do after opening a file\n"); 493 // signal a read request 494 pthread_cond_signal(&p->read_request); 495 // wait for an available signal 496 pthread_cond_wait(&p->read_avail, &p->read_mutex); 497 available = p->available; 498 } else { 499 available = rubberband_available(p->rb); 500 //AUBIO_WRN("timestretch: reached eof (%d/%d)\n", p->hopsize, available); 501 } 502 pthread_mutex_unlock(&p->read_mutex); 503 #endif /* HAVE_THREADS */ 504 // now retrieve the samples and write them into out->data 505 if (available >= (int)p->hopsize) { 506 rubberband_retrieve(p->rb, (float* const*)&(out->data), p->hopsize); 507 *read = p->hopsize; 217 if (available >= (int)out->length) { 218 rubberband_retrieve(p->rb, (float* const*)&(out->data), out->length); 219 *read = out->length; 508 220 } else if (available > 0) { 509 221 // this occurs each time the end of file is reached 510 222 //AUBIO_WRN("timestretch: short read\n"); 511 223 rubberband_retrieve(p->rb, (float* const*)&(out->data), available); 224 fvec_t zeros; zeros.length = out->length - available; zeros.data = out->data + available; 225 fvec_zeros(&zeros); 512 226 *read = available; 513 227 } else { … … 516 230 *read = 0; 517 231 } 518 #ifdef HAVE_THREADS 519 //pthread_mutex_unlock(&p->read_mutex); 520 #endif 521 } 522 523 uint_t 524 aubio_timestretch_seek (aubio_timestretch_t *p, uint_t pos) 232 } 233 234 uint_t 235 aubio_timestretch_reset(aubio_timestretch_t *p) 525 236 { 526 237 uint_t err = AUBIO_OK; 527 #if HAVE_THREADS528 if (p == NULL) {529 AUBIO_WRN("seeking but object not set yet (ignoring)\n");530 return AUBIO_FAIL;531 }532 pthread_mutex_lock(&p->read_mutex);533 if (p->open_thread_running) {534 //AUBIO_WRN("seeking but opening thread not completed yet (ignoring)\n");535 err = AUBIO_OK;536 goto beach;537 }538 if (!p->opened || !p->source) {539 //AUBIO_WRN("timestretch: seeking but source not opened yet (ignoring)\n");540 err = AUBIO_OK;541 goto beach;542 }543 #endif544 p->eof = 0;545 238 if (p->rb) { 546 239 rubberband_reset(p->rb); 547 240 } 548 #ifdef HAVE_THREADS 549 #ifdef HAVE_OPENTHREAD 550 pthread_mutex_lock(&p->open_mutex); 241 return err; 242 } 243 551 244 #endif 552 #endif553 if (p->source) {554 err = aubio_source_seek(p->source, pos);555 } else {556 AUBIO_WRN("timestretch: seeking but p->source not created?!\n");557 err = AUBIO_FAIL;558 goto beach;559 }560 #if HAVE_THREADS561 pthread_mutex_unlock(&p->open_mutex);562 p->available = 0;563 p->started = 1;564 beach:565 pthread_mutex_unlock(&p->read_mutex);566 #else567 beach:568 #endif569 return err;570 }571 572 #endif
Note: See TracChangeset
for help on using the changeset viewer.