Skip to content

Commit

Permalink
Upgrade to RubberBand v3.3.0 and expose extra options in `time_stretc…
Browse files Browse the repository at this point in the history
…h`. (#251)

* Add extra options to time_stretch.

* Upgrade to RubberBand v3.3.0 for higher quality output.

* Appropriately chunk audio for stretching.

* Add -latomic on Linux.
  • Loading branch information
psobot committed Sep 20, 2023
1 parent 6ba98d1 commit fe40ea6
Show file tree
Hide file tree
Showing 8 changed files with 325 additions and 26 deletions.
31 changes: 29 additions & 2 deletions docs/reference/pedalboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -2670,15 +2670,42 @@ <h1>The <code class="docutils literal notranslate"><span class="pre">pedalboard<

<dl class="py function">
<dt class="sig sig-object py" id="pedalboard.time_stretch">
<span class="sig-prename descclassname"><span class="pre">pedalboard.</span></span><span class="sig-name descname"><span class="pre">time_stretch</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">input_audio</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">ndarray</span><span class="p"><span class="pre">[</span></span><span class="pre">Any</span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">dtype</span><span class="p"><span class="pre">[</span></span><span class="pre">float32</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span></em>, <em class="sig-param"><span class="n"><span class="pre">samplerate</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">float</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">stretch_factor</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">float</span></span><span class="w"> </span><span class="o"><span class="pre">=</span></span><span class="w"> </span><span class="default_value"><span class="pre">1.0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">pitch_shift_in_semitones</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">float</span></span><span class="w"> </span><span class="o"><span class="pre">=</span></span><span class="w"> </span><span class="default_value"><span class="pre">0.0</span></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">ndarray</span><span class="p"><span class="pre">[</span></span><span class="pre">Any</span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">dtype</span><span class="p"><span class="pre">[</span></span><span class="pre">float32</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span></span><a class="headerlink" href="#pedalboard.time_stretch" title="Permalink to this definition">#</a></dt>
<span class="sig-prename descclassname"><span class="pre">pedalboard.</span></span><span class="sig-name descname"><span class="pre">time_stretch</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">input_audio</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">ndarray</span><span class="p"><span class="pre">[</span></span><span class="pre">Any</span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">dtype</span><span class="p"><span class="pre">[</span></span><span class="pre">float32</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span></em>, <em class="sig-param"><span class="n"><span class="pre">samplerate</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">float</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">stretch_factor</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">float</span></span><span class="w"> </span><span class="o"><span class="pre">=</span></span><span class="w"> </span><span class="default_value"><span class="pre">1.0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">pitch_shift_in_semitones</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">float</span></span><span class="w"> </span><span class="o"><span class="pre">=</span></span><span class="w"> </span><span class="default_value"><span class="pre">0.0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">high_quality</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">bool</span></span><span class="w"> </span><span class="o"><span class="pre">=</span></span><span class="w"> </span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">transient_mode</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">str</span></span><span class="w"> </span><span class="o"><span class="pre">=</span></span><span class="w"> </span><span class="default_value"><span class="pre">'crisp'</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">transient_detector</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">str</span></span><span class="w"> </span><span class="o"><span class="pre">=</span></span><span class="w"> </span><span class="default_value"><span class="pre">'compound'</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">retain_phase_continuity</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">bool</span></span><span class="w"> </span><span class="o"><span class="pre">=</span></span><span class="w"> </span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">use_long_fft_window</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">Optional</span><span class="p"><span class="pre">[</span></span><span class="pre">bool</span><span class="p"><span class="pre">]</span></span></span><span class="w"> </span><span class="o"><span class="pre">=</span></span><span class="w"> </span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">use_time_domain_smoothing</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">bool</span></span><span class="w"> </span><span class="o"><span class="pre">=</span></span><span class="w"> </span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">preserve_formants</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">bool</span></span><span class="w"> </span><span class="o"><span class="pre">=</span></span><span class="w"> </span><span class="default_value"><span class="pre">True</span></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">ndarray</span><span class="p"><span class="pre">[</span></span><span class="pre">Any</span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">dtype</span><span class="p"><span class="pre">[</span></span><span class="pre">float32</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">]</span></span></span></span><a class="headerlink" href="#pedalboard.time_stretch" title="Permalink to this definition">#</a></dt>
<dd><p>Time-stretch (and optionally pitch-shift) a buffer of audio, changing its length.</p>
<p>Using a higher <code class="docutils literal notranslate"><span class="pre">stretch_factor</span></code> will shorten the audio - i.e., a <code class="docutils literal notranslate"><span class="pre">stretch_factor</span></code>
of <code class="docutils literal notranslate"><span class="pre">2.0</span></code> will double the <em>speed</em> of the audio and halve the <em>length</em> fo the audio,
of <code class="docutils literal notranslate"><span class="pre">2.0</span></code> will double the <em>speed</em> of the audio and halve the <em>length</em> of the audio,
without changing the pitch of the audio.</p>
<p>This function allows for changing the pitch of the audio during the time stretching
operation. The <code class="docutils literal notranslate"><span class="pre">stretch_factor</span></code> and <code class="docutils literal notranslate"><span class="pre">pitch_shift_in_semitones</span></code> arguments are
independent and do not affect each other (i.e.: you can change one, the other, or both
without worrying about how they interact).</p>
<p>The additional arguments provided to this function allow for more fine-grained control
over the behavior of the time stretcher:</p>
<blockquote>
<div><ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">high_quality</span></code> (the default) enables a higher quality time stretching mode.
Set this option to <code class="docutils literal notranslate"><span class="pre">False</span></code> to use less CPU power.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">transient_mode</span></code> controls the behavior of the stretcher around transients
(percussive parts of the audio). Valid options are <code class="docutils literal notranslate"><span class="pre">&quot;crisp&quot;</span></code> (the default),
<code class="docutils literal notranslate"><span class="pre">&quot;mixed&quot;</span></code>, or <code class="docutils literal notranslate"><span class="pre">&quot;smooth&quot;</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">transient_detector</span></code> controls which method is used to detect transients in the
audio signal. Valid options are <code class="docutils literal notranslate"><span class="pre">&quot;compound&quot;</span></code> (the default), <code class="docutils literal notranslate"><span class="pre">&quot;percussive&quot;</span></code>,
or <code class="docutils literal notranslate"><span class="pre">&quot;soft&quot;</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">retain_phase_continuity</span></code> ensures that the phases of adjacent frequency bins in
the audio stream are kept as similar as possible. Set this to <code class="docutils literal notranslate"><span class="pre">False</span></code> for a
softer, phasier sound.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">use_long_fft_window</span></code> controls the size of the fast-Fourier transform window
used during stretching. The default (<code class="docutils literal notranslate"><span class="pre">None</span></code>) will result in a window size that
varies based on other parameters and should produce better results in most
situations. Set this option to <code class="docutils literal notranslate"><span class="pre">True</span></code> to result in a smoother sound (at the
expense of clarity and timing), or <code class="docutils literal notranslate"><span class="pre">False</span></code> to result in a crisper sound.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">use_time_domain_smoothing</span></code> can be enabled to produce a softer sound with
audible artifacts around sharp transients. This option mixes well with
<code class="docutils literal notranslate"><span class="pre">use_long_fft_window=False</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">preserve_formants</span></code> allows shifting the pitch of notes without substantially
affecting the pitch profile (formants) of a voice or instrument.</p></li>
</ul>
</div></blockquote>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>This is a function, not a <a class="reference internal" href="#pedalboard.Plugin" title="pedalboard.Plugin"><code class="xref py py-class docutils literal notranslate"><span class="pre">Plugin</span></code></a> instance, and cannot be
Expand Down
2 changes: 1 addition & 1 deletion docs/searchindex.js

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions pedalboard/StreamUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once
#include <iostream>

/**
* A tiny RAII helper class that suppresses all output to the provided ostream.
* Useful if calling into a third-party library that logs to std::cerr whose
* logs you want to suppress/ignore.
*/
class SuppressOutput {
public:
SuppressOutput(std::ostream &ostream)
: ostream(ostream), previousState(ostream.rdstate()) {
ostream.setstate(std::ios_base::failbit);
}

~SuppressOutput() { ostream.clear(previousState); }

private:
std::ostream &ostream;
std::ios_base::iostate previousState;
};
Loading

0 comments on commit fe40ea6

Please sign in to comment.