source: src/effects/timestretch_rubberband.c @ 8688797

sampler
Last change on this file since 8688797 was 8688797, checked in by Paul Brossier <piem@piem.org>, 4 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
Line 
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
34#define MAX_STRETCH_RATIO 40.
35
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
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
59static void aubio_timestretch_warmup (aubio_timestretch_t * p);
60
61aubio_timestretch_t *
62new_aubio_timestretch (const char_t * mode, smpl_t stretchratio, uint_t hopsize,
63    uint_t samplerate)
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
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);
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{
100  // warm up rubber band
101  //AUBIO_WRN("timestretch: warming-up\n");
102  unsigned int latency = MAX(p->hopsize, rubberband_get_latency(p->rb));
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);
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
120uint_t
121aubio_timestretch_get_samplerate (aubio_timestretch_t * p)
122{
123  return p->samplerate;
124}
125
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{
133  if (!p->rb) {
134    AUBIO_WRN("timestretch: could not set stretch ratio, rubberband not created\n");
135    return AUBIO_FAIL;
136  }
137  if (stretch >= MIN_STRETCH_RATIO && stretch <= MAX_STRETCH_RATIO) {
138    p->stretchratio = stretch;
139    rubberband_set_time_ratio(p->rb, 1./p->stretchratio);
140    return AUBIO_OK;
141  } else {
142    AUBIO_WRN("timestretch: could not set stretch ratio to %.2f\n", stretch);
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{
156  if (!p->rb) {
157    AUBIO_WRN("timestretch: could not set pitch scale, rubberband not created\n");
158    return AUBIO_FAIL;
159  }
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 {
165    AUBIO_WRN("timestretch: could not set pitchscale to %.2f\n", pitchscale);
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 {
183    AUBIO_WRN("timestretch: could not set transpose to %.2f\n", transpose);
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
194sint_t
195aubio_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
207sint_t
208aubio_timestretch_get_available(aubio_timestretch_t *p) {
209  return rubberband_available(p->rb);
210}
211
212void
213aubio_timestretch_do(aubio_timestretch_t * p, fvec_t * out, uint_t * read)
214{
215  // now retrieve the samples and write them into out->data
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;
220  } else if (available > 0) {
221    // this occurs each time the end of file is reached
222    //AUBIO_WRN("timestretch: short read\n");
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);
226    *read = available;
227  } else {
228    // this may occur if the previous was a short read available == hopsize
229    fvec_zeros(out);
230    *read = 0;
231  }
232}
233
234uint_t
235aubio_timestretch_reset(aubio_timestretch_t *p)
236{
237  uint_t err = AUBIO_OK;
238  if (p->rb) {
239    rubberband_reset(p->rb);
240  }
241  return err;
242}
243
244#endif
Note: See TracBrowser for help on using the repository browser.