You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
219 lines
8.6 KiB
C++
219 lines
8.6 KiB
C++
/*
|
|
Copyright (C) 2007-2010 Christian Kothe
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#ifndef FREESURROUND_DECODER_H
|
|
#define FREESURROUND_DECODER_H
|
|
|
|
#include <utility>
|
|
|
|
/**
|
|
* Identifiers for the supported output channels (from front to back, left to right).
|
|
* The ordering here also determines the ordering of interleaved samples in the output signal.
|
|
*/
|
|
enum channel_id {
|
|
ci_none = 0,
|
|
ci_front_left = 1<<1,
|
|
ci_front_center_left = 1<<2,
|
|
ci_front_center = 1<<3,
|
|
ci_front_center_right = 1<<4,
|
|
ci_front_right = 1<<5,
|
|
ci_side_front_left = 1<<6,
|
|
ci_side_front_right = 1<<7,
|
|
ci_side_center_left = 1<<8,
|
|
ci_side_center_right = 1<<9,
|
|
ci_side_back_left = 1<<10,
|
|
ci_side_back_right = 1<<11,
|
|
ci_back_left = 1<<12,
|
|
ci_back_center_left = 1<<13,
|
|
ci_back_center = 1<<14,
|
|
ci_back_center_right = 1<<15,
|
|
ci_back_right = 1<<16,
|
|
ci_lfe = 1<<31
|
|
};
|
|
|
|
/**
|
|
* The supported output channel setups.
|
|
* A channel setup is defined by the set of channels that are present. Here is a graphic
|
|
* of the cs_5point1 setup: http://en.wikipedia.org/wiki/File:5_1_channels_(surround_sound)_label.svg
|
|
*/
|
|
enum channel_setup {
|
|
cs_stereo = ci_front_left | ci_front_right | ci_lfe,
|
|
cs_3stereo = ci_front_left | ci_front_center | ci_front_right | ci_lfe,
|
|
cs_5stereo = ci_front_left | ci_front_center_left | ci_front_center | ci_front_center_right | ci_front_right | ci_lfe,
|
|
cs_4point1 = ci_front_left | ci_front_right | ci_back_left | ci_back_right | ci_lfe,
|
|
cs_5point1 = ci_front_left | ci_front_center | ci_front_right | ci_back_left | ci_back_right | ci_lfe,
|
|
cs_6point1 = ci_front_left | ci_front_center | ci_front_right | ci_side_center_left | ci_side_center_right | ci_back_center | ci_lfe,
|
|
cs_7point1 = ci_front_left | ci_front_center | ci_front_right | ci_side_center_left | ci_side_center_right | ci_back_left | ci_back_right | ci_lfe,
|
|
cs_7point1_panorama = ci_front_left | ci_front_center_left | ci_front_center | ci_front_center_right | ci_front_right |
|
|
ci_side_center_left | ci_side_center_right | ci_lfe,
|
|
cs_7point1_tricenter = ci_front_left | ci_front_center_left | ci_front_center | ci_front_center_right | ci_front_right |
|
|
ci_back_left | ci_back_right | ci_lfe,
|
|
cs_8point1 = ci_front_left | ci_front_center | ci_front_right | ci_side_center_left | ci_side_center_right |
|
|
ci_back_left | ci_back_center | ci_back_right | ci_lfe,
|
|
cs_9point1_densepanorama = ci_front_left | ci_front_center_left | ci_front_center | ci_front_center_right | ci_front_right |
|
|
ci_side_front_left | ci_side_front_right | ci_side_center_left | ci_side_center_right | ci_lfe,
|
|
cs_9point1_wrap = ci_front_left | ci_front_center_left | ci_front_center | ci_front_center_right | ci_front_right |
|
|
ci_side_center_left | ci_side_center_right | ci_back_left | ci_back_right | ci_lfe,
|
|
cs_11point1_densewrap = ci_front_left | ci_front_center_left | ci_front_center | ci_front_center_right | ci_front_right |
|
|
ci_side_front_left | ci_side_front_right | ci_side_center_left | ci_side_center_right |
|
|
ci_side_back_left | ci_side_back_right | ci_lfe,
|
|
cs_13point1_totalwrap = ci_front_left | ci_front_center_left | ci_front_center | ci_front_center_right | ci_front_right |
|
|
ci_side_front_left | ci_side_front_right | ci_side_center_left | ci_side_center_right |
|
|
ci_side_back_left | ci_side_back_right | ci_back_left | ci_back_right | ci_lfe,
|
|
cs_16point1 = ci_front_left | ci_front_center_left | ci_front_center | ci_front_center_right | ci_front_right |
|
|
ci_side_front_left | ci_side_front_right | ci_side_center_left | ci_side_center_right | ci_side_back_left |
|
|
ci_side_back_right | ci_back_left | ci_back_center_left | ci_back_center | ci_back_center_right | ci_back_right | ci_lfe,
|
|
cs_legacy = 0 // same channels as cs_5point1 but different upmixing transform; does not support the focus control
|
|
};
|
|
|
|
|
|
/**
|
|
* The FreeSurround decoder.
|
|
*/
|
|
class freesurround_decoder {
|
|
public:
|
|
|
|
/**
|
|
* Create an instance of the decoder.
|
|
* @param setup The output channel setup -- determines the number of output channels
|
|
* and their place in the sound field.
|
|
* U3 NOTE: 4096@44.1kHz is 92.9ms...
|
|
* @param blocksize Granularity at which data is processed by the decode() function.
|
|
* Must be a power of two and should correspond to ca. 10ms worth of single-channel
|
|
* samples (default is 4096 for 44.1Khz data). Do not make it shorter or longer
|
|
* than 5ms to 20ms since the granularity at which locations are decoded
|
|
* changes with this.
|
|
*/
|
|
freesurround_decoder(channel_setup setup=cs_5point1, unsigned blocksize=4096);
|
|
~freesurround_decoder();
|
|
|
|
freesurround_decoder(freesurround_decoder&& o) noexcept : impl{std::exchange(o.impl, nullptr)} {}
|
|
freesurround_decoder& operator=(freesurround_decoder o) noexcept
|
|
{
|
|
std::swap(impl, o.impl);
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* Decode a chunk of stereo sound. The output is delayed by half of the blocksize.
|
|
* This function is the only one needed for straightforward decoding.
|
|
* @param input Contains exactly blocksize (multiplexed) stereo samples, i.e. 2*blocksize numbers.
|
|
* @return A pointer to an internal buffer of exactly blocksize (multiplexed) multichannel samples.
|
|
* The actual number of values depends on the number of output channels in the chosen
|
|
* channel setup.
|
|
*/
|
|
const float* decode(const float* input);
|
|
|
|
/**
|
|
* Flush the internal buffer.
|
|
*/
|
|
void flush();
|
|
|
|
|
|
// --- soundfield transformations
|
|
// These functions allow to set up geometric transformations of the sound field after it has been decoded.
|
|
// The sound field is best pictured as a 2-dimensional square with the listener in its
|
|
// center which can be shifted or stretched in various ways before it is sent to the
|
|
// speakers. The order in which these transformations are applied is as listed below.
|
|
|
|
/**
|
|
* Allows to wrap the soundfield around the listener in a circular manner.
|
|
* Determines the angle of the frontal sound stage relative to the listener, in degrees.
|
|
* A setting of 90° corresponds to standard surround decoding, 180° stretches the front stage from
|
|
* ear to ear, 270° wraps it around most of the head. The side and rear content of the sound
|
|
* field is compressed accordingly behind the listerer. (default: 90, range: [0°..360°])
|
|
*/
|
|
void circular_wrap(float v);
|
|
|
|
/**
|
|
* Allows to shift the soundfield forward or backward.
|
|
* Value range: [-1.0..+1.0]. 0 is no offset, positive values move the sound
|
|
* forward, negative values move it backwards. (default: 0)
|
|
*/
|
|
void shift(float v);
|
|
|
|
/**
|
|
* Allows to scale the soundfield backwards.
|
|
* Value range: [0.0..+5.0] -- 0 is all compressed to the front, 1 is no change, 5 is scaled 5x backwards (default: 1)
|
|
*/
|
|
void depth(float v);
|
|
|
|
/**
|
|
* Allows to control the localization (i.e., focality) of sources.
|
|
* Value range: [-1.0..+1.0] -- 0 means unchanged, positive means more localized, negative means more ambient (default: 0)
|
|
*/
|
|
void focus(float v);
|
|
|
|
|
|
// --- rendering parameters
|
|
// These parameters control how the sound field is mapped onto speakers.
|
|
|
|
/**
|
|
* Set the front stereo separation.
|
|
* Value range: [0.0..inf] -- 1.0 is default, 0.0 is mono.
|
|
*/
|
|
void front_separation(float v);
|
|
|
|
/**
|
|
* Set the rear stereo separation.
|
|
* Value range: [0.0..inf] -- 1.0 is default, 0.0 is mono.
|
|
*/
|
|
void rear_separation(float v);
|
|
|
|
|
|
// --- bass redirection (to LFE)
|
|
|
|
/**
|
|
* Enable/disable LFE channel (default: false = disabled)
|
|
*/
|
|
void bass_redirection(bool v);
|
|
|
|
/**
|
|
* Set the lower end of the transition band, in Hz/Nyquist (default: 40/22050).
|
|
*/
|
|
void low_cutoff(float v);
|
|
|
|
/**
|
|
* Set the upper end of the transition band, in Hz/Nyquist (default: 90/22050).
|
|
*/
|
|
void high_cutoff(float v);
|
|
|
|
|
|
// --- info
|
|
|
|
/**
|
|
* Number of samples currently held in the buffer.
|
|
*/
|
|
unsigned buffered();
|
|
|
|
/**
|
|
* Number of channels in the given setup.
|
|
*/
|
|
static unsigned num_channels(channel_setup s);
|
|
|
|
/**
|
|
* Channel id of the i'th channel in the given setup.
|
|
*/
|
|
static channel_id channel_at(channel_setup s, unsigned i);
|
|
|
|
private:
|
|
class decoder_impl *impl; // private implementation
|
|
};
|
|
|
|
#endif
|