source: src/effects/timestretch_rubberband.c @ bde49c4a

sampler
Last change on this file since bde49c4a was 8688797, checked in by Paul Brossier <piem@piem.org>, 8 years ago

src/effects/timestretch*: move out threaded file reading stuff, add _push and _available

  • Property mode set to 100644
File size: 6.3 KB
RevLine 
[af195a5]1/*
2  Copyright (C) 2016 Paul Brossier <piem@aubio.org>
3
4  This file is part of aubio.
5
6  aubio is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10
11  aubio is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15
16  You should have received a copy of the GNU General Public License
17  along with aubio.  If not, see <http://www.gnu.org/licenses/>.
18
19*/
20
21#include "config.h"
22
23#ifdef HAVE_RUBBERBAND
24
25#include "aubio_priv.h"
26#include "fvec.h"
27#include "fmat.h"
28#include "io/source.h"
29#include "effects/timestretch.h"
30
31#include "rubberband/rubberband-c.h"
32
33#define MIN_STRETCH_RATIO 0.025
[fb5bd55]34#define MAX_STRETCH_RATIO 40.
[af195a5]35
[0202028]36#define HAVE_THREADS 1
37#if 0
38#undef HAVE_THREADS
39#endif
40
41#ifdef HAVE_THREADS
42#include <pthread.h>
43#endif
44
[af195a5]45/** generic time stretching structure */
46struct _aubio_timestretch_t
47{
48  uint_t samplerate;              /**< samplerate */
49  uint_t hopsize;                 /**< hop size */
50  smpl_t stretchratio;            /**< time ratio */
51  smpl_t pitchscale;              /**< pitch scale */
52
53  RubberBandState rb;
54  RubberBandOptions rboptions;
55};
56
57extern RubberBandOptions aubio_get_rubberband_opts(const char_t *mode);
58
[1e4b7f6]59static void aubio_timestretch_warmup (aubio_timestretch_t * p);
60
[af195a5]61aubio_timestretch_t *
[8688797]62new_aubio_timestretch (const char_t * mode, smpl_t stretchratio, uint_t hopsize,
63    uint_t samplerate)
[af195a5]64{
65  aubio_timestretch_t *p = AUBIO_NEW (aubio_timestretch_t);
66  p->hopsize = hopsize;
67  p->pitchscale = 1.;
68
69  if (stretchratio <= MAX_STRETCH_RATIO && stretchratio >= MIN_STRETCH_RATIO) {
70    p->stretchratio = stretchratio;
71  } else {
72    AUBIO_ERR("timestretch: stretchratio should be in the range [%.3f, %.3f], got %f\n",
73        MIN_STRETCH_RATIO, MAX_STRETCH_RATIO, stretchratio);
74    goto beach;
75  }
76
77  p->rboptions = aubio_get_rubberband_opts(mode);
78  if (p->rboptions < 0) {
79    AUBIO_ERR("timestretch: unknown time stretching method %s\n", mode);
80    goto beach;
81  }
82
[8688797]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);
[1e4b7f6]89
90  return p;
91
92beach:
93  del_aubio_timestretch(p);
94  return NULL;
95}
96
97static void
98aubio_timestretch_warmup (aubio_timestretch_t * p)
99{
[af195a5]100  // warm up rubber band
[61abfa4]101  //AUBIO_WRN("timestretch: warming-up\n");
[af195a5]102  unsigned int latency = MAX(p->hopsize, rubberband_get_latency(p->rb));
[8688797]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);
[af195a5]109}
110
111void
112del_aubio_timestretch (aubio_timestretch_t * p)
113{
114  if (p->rb) {
115    rubberband_delete(p->rb);
116  }
117  AUBIO_FREE (p);
118}
119
[16965d5]120uint_t
121aubio_timestretch_get_samplerate (aubio_timestretch_t * p)
122{
123  return p->samplerate;
124}
125
[af195a5]126uint_t aubio_timestretch_get_latency (aubio_timestretch_t * p) {
127  return rubberband_get_latency(p->rb);
128}
129
130uint_t
131aubio_timestretch_set_stretch (aubio_timestretch_t * p, smpl_t stretch)
132{
[61abfa4]133  if (!p->rb) {
134    AUBIO_WRN("timestretch: could not set stretch ratio, rubberband not created\n");
135    return AUBIO_FAIL;
136  }
[af195a5]137  if (stretch >= MIN_STRETCH_RATIO && stretch <= MAX_STRETCH_RATIO) {
138    p->stretchratio = stretch;
[fb5bd55]139    rubberband_set_time_ratio(p->rb, 1./p->stretchratio);
[af195a5]140    return AUBIO_OK;
141  } else {
[4acee97]142    AUBIO_WRN("timestretch: could not set stretch ratio to %.2f\n", stretch);
[af195a5]143    return AUBIO_FAIL;
144  }
145}
146
147smpl_t
148aubio_timestretch_get_stretch (aubio_timestretch_t * p)
149{
150  return p->stretchratio;
151}
152
153uint_t
154aubio_timestretch_set_pitchscale (aubio_timestretch_t * p, smpl_t pitchscale)
155{
[61abfa4]156  if (!p->rb) {
157    AUBIO_WRN("timestretch: could not set pitch scale, rubberband not created\n");
158    return AUBIO_FAIL;
159  }
[af195a5]160  if (pitchscale >= 0.0625  && pitchscale <= 4.) {
161    p->pitchscale = pitchscale;
162    rubberband_set_pitch_scale(p->rb, p->pitchscale);
163    return AUBIO_OK;
164  } else {
[4acee97]165    AUBIO_WRN("timestretch: could not set pitchscale to %.2f\n", pitchscale);
[af195a5]166    return AUBIO_FAIL;
167  }
168}
169
170smpl_t
171aubio_timestretch_get_pitchscale (aubio_timestretch_t * p)
172{
173  return p->pitchscale;
174}
175
176uint_t
177aubio_timestretch_set_transpose(aubio_timestretch_t * p, smpl_t transpose)
178{
179  if (transpose >= -24. && transpose <= 24.) {
180    smpl_t pitchscale = POW(2., transpose / 12.);
181    return aubio_timestretch_set_pitchscale(p, pitchscale);
182  } else {
[4acee97]183    AUBIO_WRN("timestretch: could not set transpose to %.2f\n", transpose);
[af195a5]184    return AUBIO_FAIL;
185  }
186}
187
188smpl_t
189aubio_timestretch_get_transpose(aubio_timestretch_t * p)
190{
191  return 12. * LOG(p->pitchscale) / LOG(2.0);
192}
193
[1e4b7f6]194sint_t
[8688797]195aubio_timestretch_push(aubio_timestretch_t *p, fvec_t *input, uint_t length)
[af195a5]196{
[8688797]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);
[30efdd0]204  return available;
[1e4b7f6]205}
206
[8688797]207sint_t
208aubio_timestretch_get_available(aubio_timestretch_t *p) {
209  return rubberband_available(p->rb);
210}
211
[1e4b7f6]212void
[8688797]213aubio_timestretch_do(aubio_timestretch_t * p, fvec_t * out, uint_t * read)
[1e4b7f6]214{
[af195a5]215  // now retrieve the samples and write them into out->data
[8688797]216  int available = rubberband_available(p->rb);
217  if (available >= (int)out->length) {
218    rubberband_retrieve(p->rb, (float* const*)&(out->data), out->length);
219    *read = out->length;
[4acee97]220  } else if (available > 0) {
[61abfa4]221    // this occurs each time the end of file is reached
222    //AUBIO_WRN("timestretch: short read\n");
[af195a5]223    rubberband_retrieve(p->rb, (float* const*)&(out->data), available);
[8688797]224    fvec_t zeros; zeros.length = out->length - available; zeros.data = out->data + available;
225    fvec_zeros(&zeros);
[af195a5]226    *read = available;
[4acee97]227  } else {
[61abfa4]228    // this may occur if the previous was a short read available == hopsize
[4acee97]229    fvec_zeros(out);
230    *read = 0;
[af195a5]231  }
232}
233
[0d4228d]234uint_t
[8688797]235aubio_timestretch_reset(aubio_timestretch_t *p)
[0d4228d]236{
[0202028]237  uint_t err = AUBIO_OK;
[61abfa4]238  if (p->rb) {
239    rubberband_reset(p->rb);
240  }
[0202028]241  return err;
[0d4228d]242}
243
[af195a5]244#endif
Note: See TracBrowser for help on using the repository browser.