1 /*
2  * Copyright (C) 2019-2020 Alexandros Theodotou <alex at zrythm dot org>
3  *
4  * This file is part of Zrythm
5  *
6  * Zrythm is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Affero 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  * Zrythm 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 Affero General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with Zrythm.  If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 /**
21  * \file
22  *
23  * Time and pitch stretching API.
24  */
25 
26 #ifndef __AUDIO_STRETCHER_H__
27 #define __AUDIO_STRETCHER_H__
28 
29 #include <stdbool.h>
30 #include <stddef.h>
31 #include <sys/types.h>
32 
33 #include "utils/types.h"
34 
35 #include <rubberband/rubberband-c.h>
36 
37 /**
38  * @addtogroup audio
39  *
40  * @{
41  */
42 
43 typedef enum StretcherBackend
44 {
45   /** Lib rubberband. */
46   STRETCHER_BACKEND_RUBBERBAND,
47 
48   /** Paulstretch. */
49   STRETCHER_BACKEND_PAULSTRETCH,
50 
51   /** SBSMS - Subband Sinusoidal Modeling
52    * Synthesis. */
53   STRETCHER_BACKEND_SBSMS,
54 } StretcherBackend;
55 
56 /**
57  * Stretcher interface.
58  */
59 typedef struct Stretcher
60 {
61   StretcherBackend  backend;
62 
63   /** For rubberband API. */
64   RubberBandState   rubberband_state;
65 
66   unsigned int      samplerate;
67   unsigned int      channels;
68 
69   bool              is_realtime;
70 
71   /**
72    * Size of the block to process in each
73    * iteration.
74    *
75    * Somewhere around 6k should be fine.
76    */
77   unsigned int      block_size;
78 } Stretcher;
79 
80 /**
81  * Create a new Stretcher using the rubberband
82  * backend.
83  *
84  * @param samplerate The new samplerate.
85  * @param time_ratio The ratio to multiply time by
86  *   (eg if the BPM is doubled, this will be 0.5).
87  * @param pitch_ratio The ratio to pitch by. This
88  *   will normally be 1.0 when time-stretching).
89  * @param realtime Whether to perform realtime
90  *   stretching (lower quality but fast enough to
91  *   be used real-time).
92  */
93 Stretcher *
94 stretcher_new_rubberband (
95   unsigned int   samplerate,
96   unsigned int   channels,
97   double         time_ratio,
98   double         pitch_ratio,
99   bool           realtime);
100 
101 /**
102  * Perform stretching.
103  *
104  * @param in_samples_l The left samples.
105  * @param in_samples_r The right channel samples. If
106  *   this is NULL, the audio is assumed to be mono.
107  * @param in_samples_size The number of input samples
108  *   per channel.
109  *
110  * @return The number of output samples generated per
111  *   channel.
112  */
113 ssize_t
114 stretcher_stretch (
115   Stretcher * self,
116   float *     in_samples_l,
117   float *     in_samples_r,
118   size_t      in_samples_size,
119   float *     out_samples_l,
120   float *     out_samples_r,
121   size_t      out_samples_wanted);
122 
123 /**
124  * Get latency in number of samples.
125  */
126 unsigned int
127 stretcher_get_latency (
128   Stretcher * self);
129 
130 void
131 stretcher_set_time_ratio (
132   Stretcher * self,
133   double      ratio);
134 
135 /**
136  * Perform stretching.
137  *
138  * @note Not real-time safe, does allocations.
139  *
140  * @param in_samples_size The number of input samples
141  *   per channel.
142  *
143  * @return The number of output samples generated per
144  *   channel.
145  */
146 ssize_t
147 stretcher_stretch_interleaved (
148   Stretcher * self,
149   float *     in_samples,
150   size_t      in_samples_size,
151   float **    _out_samples);
152 
153 /**
154  * Frees the resampler.
155  */
156 void
157 stretcher_free (
158   Stretcher * self);
159 
160 /**
161  * @}
162  */
163 
164 #endif
165