Safe Haskell | None |
---|---|
Language | Haskell2010 |
Threading notes for real-time applications:
Multiple instances of Stretcher
may be created and used
in separate threads concurrently. However, for any single instance
of Stretcher
, you may not call process
more than once
concurrently, and you may not change the time or pitch ratio while
a process
call is being executed (if the stretcher was created in
"real-time mode"; in "offline mode" you can't change the ratios
during use anyway).
So you can run process
in its own thread if you like, but if you
want to change ratios dynamically from a different thread, you will
need some form of mutex in your code. Changing the time or pitch
ratio is real-time safe except in extreme circumstances, so for
most applications that may change these dynamically it probably
makes most sense to do so from the same thread as calls process
,
even if that is a real-time thread.
Differences from Sound.RubberBand.Raw:
- The
Stretcher
object is garbage-collected by Haskell. - The
study
,process
, andretrieve
functions use storableVector
s instead of raw pointers. - Some error checking is done in cases like giving arrays of different
lengths to
study
andprocess
, or giving a different number of arrays from how many channels theStretcher
was constructed with.
- data Stretcher
- new :: SampleRate -> NumChannels -> Options -> TimeRatio -> PitchScale -> IO Stretcher
- reset :: Stretcher -> IO ()
- type SampleRate = Int
- type NumChannels = Int
- type TimeRatio = Double
- type PitchScale = Double
- withRaw :: Stretcher -> (Stretcher -> IO a) -> IO a
- setTimeRatio :: Stretcher -> TimeRatio -> IO ()
- setPitchScale :: Stretcher -> PitchScale -> IO ()
- getTimeRatio :: Stretcher -> IO TimeRatio
- getPitchScale :: Stretcher -> IO PitchScale
- getLatency :: Stretcher -> IO Int
- setTransientsOption :: Stretcher -> Transients -> IO ()
- setDetectorOption :: Stretcher -> Detector -> IO ()
- setPhaseOption :: Stretcher -> Phase -> IO ()
- setFormantOption :: Stretcher -> Formant -> IO ()
- setPitchOption :: Stretcher -> Pitch -> IO ()
- setExpectedInputDuration :: Stretcher -> Int -> IO ()
- setMaxProcessSize :: Stretcher -> Int -> IO ()
- getSamplesRequired :: Stretcher -> IO Int
- setKeyFrameMap :: Stretcher -> [(Int, Int)] -> IO ()
- study :: Stretcher -> [Vector Float] -> Bool -> IO ()
- process :: Stretcher -> [Vector Float] -> Bool -> IO ()
- available :: Stretcher -> IO (Maybe Int)
- retrieve :: Stretcher -> Int -> IO [Vector Float]
- getChannelCount :: Stretcher -> IO Int
- calculateStretch :: Stretcher -> IO ()
- setDebugLevel :: Stretcher -> Int -> IO ()
- setDefaultDebugLevel :: Int -> IO ()
Documentation
An audio stretching machine. This object is garbage-collected on the Haskell side, so it will be deleted automatically.
new :: SampleRate -> NumChannels -> Options -> TimeRatio -> PitchScale -> IO Stretcher Source
Construct a time and pitch stretcher object to run at the given sample rate, with the given number of channels. Processing options and the time and pitch scaling ratios may be provided. The time and pitch ratios may be changed after construction, but most of the options may not. See the Sound.RubberBand.Option documentation for more details.
reset :: Stretcher -> IO () Source
Reset the stretcher's internal buffers. The stretcher should subsequently behave as if it had just been constructed (although retaining the current time and pitch ratio).
type SampleRate = Int Source
Samples per second of the input and output audio.
type NumChannels = Int Source
The number of channels processed by a stretcher.
type PitchScale = Double Source
A ratio of output frequencies to input frequencies. For example, a ratio of 2 will increase the audio by one octave, and 0.5 will decrease it by one octave.
withRaw :: Stretcher -> (Stretcher -> IO a) -> IO a Source
Allows you to use the functions in Sound.RubberBand.Nice if needed.
setTimeRatio :: Stretcher -> TimeRatio -> IO () Source
Set the time ratio for the stretcher. This is the ratio of stretched to unstretched duration -- not tempo. For example, a ratio of 2.0 would make the audio twice as long (i.e. halve the tempo); 0.5 would make it half as long (i.e. double the tempo); 1.0 would leave the duration unaffected.
If the stretcher was constructed in Offline
mode, the time
ratio is fixed throughout operation; this function may be
called any number of times between construction (or a call to
reset
) and the first call to study
or process
, but may
not be called after study
or process
has been called.
If the stretcher was constructed in RealTime
mode, the time
ratio may be varied during operation; this function may be
called at any time, so long as it is not called concurrently
with process
. You should either call this function from the
same thread as process
, or provide your own mutex or similar
mechanism to ensure that setTimeRatio
and process
cannot be
run at once (there is no internal mutex for this purpose).
setPitchScale :: Stretcher -> PitchScale -> IO () Source
Set the pitch scaling ratio for the stretcher. This is the ratio of target frequency to source frequency. For example, a ratio of 2.0 would shift up by one octave; 0.5 down by one octave; or 1.0 leave the pitch unaffected.
To put this in musical terms, a pitch scaling ratio
corresponding to a shift of s
equal-tempered semitones (where s
is positive for an upwards shift and negative for downwards) is
2 ** (s / 12)
.
If the stretcher was constructed in Offline mode, the pitch
scaling ratio is fixed throughout operation; this function may
be called any number of times between construction (or a call
to reset
) and the first call to study
or process
, but may
not be called after study
or process
has been called.
If the stretcher was constructed in RealTime mode, the pitch
scaling ratio may be varied during operation; this function may
be called at any time, so long as it is not called concurrently
with process
. You should either call this function from the
same thread as process
, or provide your own mutex or similar
mechanism to ensure that setPitchScale and process
cannot be
run at once (there is no internal mutex for this purpose).
getTimeRatio :: Stretcher -> IO TimeRatio Source
Return the last time ratio value that was set (either on
construction or with setTimeRatio
).
getPitchScale :: Stretcher -> IO PitchScale Source
Return the last pitch scaling ratio value that was set (either
on construction or with setPitchScale
).
getLatency :: Stretcher -> IO Int Source
Return the processing latency of the stretcher. This is the
number of audio samples that one would have to discard at the
start of the output in order to ensure that the resulting audio
aligned with the input audio at the start. In Offline
mode,
latency is automatically adjusted for and the result is zero.
In RealTime
mode, the latency may depend on the time and pitch
ratio and other options.
setTransientsOption :: Stretcher -> Transients -> IO () Source
Change a Transients
configuration setting. This may be
called at any time in RealTime
mode. It may not be called in
Offline
mode (for which the Transients
option is fixed on
construction).
setDetectorOption :: Stretcher -> Detector -> IO () Source
setPhaseOption :: Stretcher -> Phase -> IO () Source
setFormantOption :: Stretcher -> Formant -> IO () Source
setPitchOption :: Stretcher -> Pitch -> IO () Source
setExpectedInputDuration :: Stretcher -> Int -> IO () Source
setMaxProcessSize :: Stretcher -> Int -> IO () Source
Tell the Stretcher
the maximum number of sample frames that you
will ever be passing in to a single process
call. If you
don't call this, the Stretcher
will assume that you are calling
getSamplesRequired
at each cycle and are never passing more
samples than are suggested by that function.
If your application has some external constraint that means you
prefer a fixed block size, then your normal mode of operation
would be to provide that block size to this function; to loop
calling process
with that size of block; after each call to
process
, test whether output has been generated by calling
available
; and, if so, call retrieve
to obtain it. See
getSamplesRequired
for a more suitable operating mode for
applications without such external constraints.
This function may not be called after the first call to study
or process
.
Note that this value is only relevant to process
, not to
study
(to which you may pass any number of samples at a time,
and from which there is no output).
getSamplesRequired :: Stretcher -> IO Int Source
Ask the stretcher how many audio sample frames should be provided as input in order to ensure that some more output becomes available.
If your application has no particular constraint on processing
block size and you are able to provide any block size as input
for each cycle, then your normal mode of operation would be to
loop querying this function; providing that number of samples
to process
; and reading the output using available
and
retrieve
. See setMaxProcessSize
for a more suitable
operating mode for applications that do have external block
size constraints.
Note that this value is only relevant to process
, not to
study
(to which you may pass any number of samples at a time,
and from which there is no output).
setKeyFrameMap :: Stretcher -> [(Int, Int)] -> IO () Source
Provide a set of mappings from "before" to "after" sample numbers so as to enforce a particular stretch profile. The argument is a map from audio sample frame number in the source material, to the corresponding sample frame number in the stretched output. The mapping should be for key frames only, with a "reasonable" gap between mapped samples.
This function cannot be used in RealTime
mode.
This function may not be called after the first call to
process
. It should be called after the time and pitch ratios
have been set; the results of changing the time and pitch
ratios after calling this function are undefined. Calling
reset
will clear this mapping.
The key frame map only affects points within the material; it
does not determine the overall stretch ratio (that is, the
ratio between the output material's duration and the source
material's duration). You need to provide this ratio
separately to setTimeRatio
, otherwise the results may be
truncated or extended in unexpected ways regardless of the
extent of the frame numbers found in the key frame map.
study :: Stretcher -> [Vector Float] -> Bool -> IO () Source
Provide a block of "samples" sample frames for the stretcher to study and calculate a stretch profile from.
This is only meaningful in Offline
mode, and is required if
running in that mode. You should pass the entire input through
study
before any process
calls are made, as a sequence of
blocks in individual study
calls, or as a single large block.
The input list should be de-interleaved audio data with one float vector
per channel. The Bool
should be True
if this is the last block of data
that will be provided to study
before the first process
call.
process :: Stretcher -> [Vector Float] -> Bool -> IO () Source
Provide a block of sample frames for processing.
See also getSamplesRequired
and setMaxProcessSize
.
Set the Bool
to True
if this is the last block of input data.
available :: Stretcher -> IO (Maybe Int) Source
Ask the stretcher how many audio sample frames of output data
are available for reading (via retrieve
).
This function returns Just 0
if no frames are available: this
usually means more input data needs to be provided, but if the
stretcher is running in threaded mode it may just mean that not
enough data has yet been processed. Call getSamplesRequired
to discover whether more input is needed.
This function returns Nothing
if all data has been fully processed
and all output read, and the stretch process is now finished.
retrieve :: Stretcher -> Int -> IO [Vector Float] Source
Obtain some processed output data from the stretcher. Up to
the given Int
of samples will be in the output vectors (one per
channel for de-interleaved audio data), though it may be
less than the given number.
getChannelCount :: Stretcher -> IO Int Source
Return the number of channels this stretcher was constructed with.
calculateStretch :: Stretcher -> IO () Source
Force the stretcher to calculate a stretch profile. Normally
this happens automatically for the first process
call in
offline mode.
This function is provided for diagnostic purposes only.
setDebugLevel :: Stretcher -> Int -> IO () Source
Set the level of debug output. The value may be from 0 (errors
only) to 3 (very verbose, with audible ticks in the output at
phase reset points). The default is whatever has been set
using setDefaultDebugLevel
, or 0 if that function has not been
called.
setDefaultDebugLevel :: Int -> IO () Source
Set the default level of debug output for subsequently constructed stretchers.