Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audio refactor #8983

Draft
wants to merge 56 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
459c604
Everything
Filoppi Jul 25, 2020
d151525
Update AudioPane.cpp
Filoppi Jul 25, 2020
f817c63
Fixed test value
Filoppi Jul 25, 2020
1eeadca
Fix build errors and warnings
Filoppi Jul 25, 2020
f0c9017
Fixing
Filoppi Jul 25, 2020
784334a
const
Filoppi Jul 25, 2020
9ebae28
Stuff
Filoppi Jul 26, 2020
d095b32
Surround fixes
Filoppi Jul 26, 2020
eecac16
Fixed crackling on some loud samples
Filoppi Jul 26, 2020
0c383b4
Build fixes
Filoppi Jul 26, 2020
ad99b5c
Fixed asserts includes
Filoppi Jul 26, 2020
bd4a8c7
Finish audio panel improvements and descriptions.
Filoppi Jul 26, 2020
873661d
Fixed build
Filoppi Jul 26, 2020
1a166bf
FIxes: cubeb, mixer, coding standards
Filoppi Jul 27, 2020
fc3ad60
Fixed L and R audio being swapped
Filoppi Jul 27, 2020
221c871
Fixes
Filoppi Jul 27, 2020
2721c0a
Added relative input support.
Filoppi Jul 29, 2020
c995616
Fixes
Filoppi Jul 29, 2020
b870400
Fixed nonsense comment
Filoppi Jul 29, 2020
833c040
WIP (possibly worsened as of now)
Filoppi Aug 2, 2020
fc9aec7
Added ability to make input settings depend on each other
Filoppi Dec 5, 2020
0d8d716
Renaming audio config variables
Filoppi Dec 5, 2020
f6430d5
Fix some comments
Filoppi Dec 5, 2020
090f554
Restored DPLII highest quality
Filoppi Dec 6, 2020
8037645
Grammar error
Filoppi Dec 6, 2020
564a405
Audio Pane: UI improvements for DPLII
Filoppi Dec 6, 2020
c1b2004
Add audio latency UI suffix (ms)
Filoppi Dec 6, 2020
5096339
Small Audio Pane code cleanup
Filoppi Dec 6, 2020
4382b2a
Improved some bad audio panel code
Filoppi Dec 6, 2020
4648fdd
WASAPI: added support for devices that don't support 48kHz
Filoppi Dec 7, 2020
97d7ec1
DPLII added UI feedback to let users know if it was enabled successfully
Filoppi Dec 7, 2020
1ef4ca9
DPLII improvements
Filoppi Dec 8, 2020
9fef3ad
PulseAudio fix inverted bool check
Filoppi Dec 8, 2020
1d52233
Fixed line over 100 characters
Filoppi Dec 8, 2020
1ec6aa7
Audio Streams fixes
Filoppi Dec 8, 2020
f60017f
DPLII now automatically determines the best block size (latency) base…
Filoppi Dec 9, 2020
98b2cec
WASAPI fixed audio device being saved by name
Filoppi Dec 9, 2020
d0bc115
DPLII improvements
Filoppi Dec 10, 2020
dc9fa15
Sound backends improvements
Filoppi Dec 28, 2020
caa3656
Small change
Filoppi Dec 28, 2020
ebd0ee4
Fixing merge part 1
Filoppi Dec 29, 2020
fbc4091
Added a Hotkey to temporarly enable Audio Stretching.
Filoppi Feb 26, 2018
ee791b4
Fixing merge part 2
Filoppi Dec 29, 2020
69b6a1c
Fixing merge part 3 (it now builds)
Filoppi Dec 29, 2020
1ed6b0b
Improved DVDInterface comments
Filoppi Dec 29, 2020
f23d6ff
Updated all newer logs to use FMT
Filoppi Dec 29, 2020
ca4951d
More FMT LOG fixes
Filoppi Dec 30, 2020
745df5a
Merging and fixes
Filoppi Dec 30, 2020
f7d88e1
Updates from other PRs
Filoppi Dec 30, 2020
4abec48
WASAPI: sent silent buffer flag if volume is 0
Filoppi Jan 16, 2021
e9082d5
use std memory functions.
Filoppi Feb 13, 2021
56efd3e
Post merge fixup
Filoppi May 14, 2021
78d7281
Revert all input changes
Filoppi May 14, 2021
a62c4e0
Post merge fixup
Filoppi May 14, 2021
9bfae40
Update FixedSizeQueue
Filoppi May 15, 2021
0ed7758
Add const to vars and comments
Filoppi May 15, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 28 additions & 17 deletions Externals/FreeSurround/include/FreeSurround/FreeSurroundDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
// USA.

// Dolphin: taken from https://hydrogenaud.io/index.php?topic=52235.0 but heavily modified
// A more up to date version is available here:
// https://github.com/kodi-adsp/adsp.freesurround

#ifndef FREESURROUND_DECODER_H
#define FREESURROUND_DECODER_H
#include "KissFFTR.h"
Expand All @@ -27,25 +31,26 @@ typedef std::complex<double> cplx;
// right). The ordering here also determines the ordering of interleaved
// samples in the output signal.

// Dolphin: channels mapping modified to be the same as most audio backends
typedef 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_front_right = 1 << 2,
ci_front_center_left = 1 << 3,
ci_front_center = 1 << 4,
ci_front_center_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
ci_lfe = 1 << 12,
ci_back_left = 1 << 13,
ci_back_center_left = 1 << 14,
ci_back_center = 1 << 15,
ci_back_center_right = 1 << 16,
ci_back_right = 1 << 31
} channel_id;

// The supported output channel setups. A channel setup is defined by the set
Expand All @@ -68,10 +73,11 @@ class DPL2FSDecoder {
// @param setup The output channel setup -- determines the number of output
// channels and their place in the sound field.
// @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.
// function. Must be a multiple of two (better if power of) and should
// correspond to ca. 10ms worth of single-channel samples
// (default is 4096 at 44.1Khz data (Dolphin: ???)).
// Do not make it shorter or longer than 5ms to 20ms since the granularity
// at which locations are decoded changes with this (Dolphin: not true, 40+).
DPL2FSDecoder();
~DPL2FSDecoder();

Expand All @@ -86,7 +92,9 @@ class DPL2FSDecoder {
// @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.
float *decode(float *input);
// Modified by Dolphin to take a ring buffer in 2 parts
float* decode(const float* input_part_1, const float* input_part_2,
unsigned int part_1_num);

// Flush the internal buffer.
void flush();
Expand All @@ -105,7 +113,8 @@ class DPL2FSDecoder {
void set_bass_redirection(bool v);

// number of samples currently held in the buffer
unsigned int buffered();
unsigned int buffered() const;
float* input_buffer();

private:
// constants
Expand Down Expand Up @@ -157,7 +166,9 @@ class DPL2FSDecoder {
std::vector<cplx> lf, rf;

// FFT buffers
kiss_fftr_cfg forward, inverse;
// they used to be kiss_fftr_cfg but due to unsafe deletion Dolphin changed them to a char*
char* forward;
char* inverse;

// buffers
// whether the buffer is currently empty or dirty
Expand Down
2 changes: 1 addition & 1 deletion Externals/FreeSurround/include/FreeSurround/KissFFTR.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ extern "C" {

typedef struct kiss_fftr_state *kiss_fftr_cfg;

kiss_fftr_cfg kiss_fftr_alloc(int nfft, int inverse_fft, void *mem,
char* kiss_fftr_alloc(int nfft, int inverse_fft, void *mem,
size_t *lenmem);
/*
nfft must be even
Expand Down
150 changes: 98 additions & 52 deletions Externals/FreeSurround/source/FreeSurroundDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,70 +28,110 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
DPL2FSDecoder::DPL2FSDecoder() {
initialized = false;
buffer_empty = true;
forward = nullptr;
inverse = nullptr;
}

DPL2FSDecoder::~DPL2FSDecoder() {
#pragma warning(suppress : 4150)
delete forward;
#pragma warning(suppress : 4150)
delete inverse;
delete[] forward;
delete[] inverse;
}

void DPL2FSDecoder::Init(channel_setup chsetup, unsigned int blsize,
unsigned int sample_rate) {
if (!initialized) {
setup = chsetup;
N = blsize;
samplerate = sample_rate;
int prev_N = N;
setup = chsetup;
N = blsize;
bool N_changed = !initialized || C != prev_N;
samplerate = sample_rate;

// Initialize the parameters
wnd = std::vector<double>(N);
// Initialize the parameters
int prev_C = C;
C = static_cast<unsigned int>(chn_alloc[setup].size());
bool C_changed = !initialized || C != prev_C;
wnd = std::vector<double>(N);
if (N_changed)
{
inbuf = std::vector<float>(3 * N);
lt = std::vector<double>(N);
rt = std::vector<double>(N);
dst = std::vector<double>(N);
lf = std::vector<cplx>(N / 2 + 1);
rf = std::vector<cplx>(N / 2 + 1);
forward = kiss_fftr_alloc(N, 0, 0, 0);
inverse = kiss_fftr_alloc(N, 1, 0, 0);
C = static_cast<unsigned int>(chn_alloc[setup].size());
}
else
{
size_t prev_size = inbuf.size();
inbuf.resize(3 * N);
// Pad the data in the first third of the input buffer
if (prev_size > 0 && prev_size < inbuf.size())
{
//To finish
for (size_t i = prev_size; i < inbuf.size(); i += 2)
memcpy(&inbuf[i], &inbuf[prev_N - 2], sizeof(float) * 2);
}
}
lt = std::vector<double>(N);
rt = std::vector<double>(N);
dst = std::vector<double>(N);
lf = std::vector<cplx>(N / 2 + 1);
rf = std::vector<cplx>(N / 2 + 1);
delete[] forward;
delete[] inverse;
forward = kiss_fftr_alloc(N, 0, 0, 0);
inverse = kiss_fftr_alloc(N, 1, 0, 0);

// Allocate per-channel buffers
// Allocate per-channel buffers (pad if we already have data)
if (C_changed)
{
outbuf = std::vector<float>((N + N / 2) * C);
}
else
{
size_t prev_size = outbuf.size();
outbuf.resize((N + N / 2) * C);
signal.resize(C, std::vector<cplx>(N));
if (prev_size > 0)
{
//To review, probably not needed, the new output is never based on the old one, it's just to shift the memory quicker
for (size_t i = prev_size; i < outbuf.size(); i += C)
memcpy(&outbuf[i], &outbuf[prev_size - C], sizeof(float) * C);
}
}
for (unsigned int k = 0; k < std::min(C, static_cast<unsigned int>(signal.size())); k++)
signal[k].resize(N);
signal.resize(C, std::vector<cplx>(N));

// Init the window function
for (unsigned int k = 0; k < N; k++)
wnd[k] = sqrt(0.5 * (1 - cos(2 * pi * k / N)) / N);
// Init the window function
for (unsigned int k = 0; k < N; k++)
wnd[k] = sqrt(0.5 * (1 - cos(2 * pi * k / N)) / N);

// set default parameters
set_circular_wrap(90);
set_shift(0);
set_depth(1);
set_focus(0);
set_center_image(1);
set_front_separation(1);
set_rear_separation(1);
set_low_cutoff(40.0f / samplerate * 2);
set_high_cutoff(90.0f / samplerate * 2);
set_bass_redirection(false);
// set default parameters
set_circular_wrap(90);
set_shift(0);
set_depth(1);
set_focus(0);
set_center_image(1);
set_front_separation(1);
set_rear_separation(1);
set_low_cutoff(40.0f);
set_high_cutoff(90.0f);
set_bass_redirection(false);

initialized = true;
}
initialized = true;
}

// decode a stereo chunk, produces a multichannel chunk of the same size
// (lagged)
float *DPL2FSDecoder::decode(float *input) {
float* DPL2FSDecoder::decode(const float* input_part_1,
const float* input_part_2, unsigned int part_1_num) {
if (initialized) {
part_1_num = min(part_1_num, N);
// append incoming data to the end of the input buffer
memcpy(&inbuf[N], &input[0], 8 * N);
memcpy(&inbuf[N], &input_part_1[0], sizeof(float) * 2 * part_1_num);
if (part_1_num < N)
memcpy(&inbuf[N + part_1_num * 2], &input_part_2[0], sizeof(float) * 2
* (N - part_1_num));
// process first and second half, overlapped
buffered_decode(&inbuf[0]);
buffered_decode(&inbuf[N]);
// shift last half of the input to the beginning (for overlapping with a
// future block)
memcpy(&inbuf[0], &inbuf[2 * N], 4 * N);
// shift the third part of the input to the beginning (for overlapping with
// a future block)
memcpy(&inbuf[0], &inbuf[2 * N], sizeof(float) * N);
buffer_empty = false;
return &outbuf[0];
}
Expand All @@ -100,13 +140,15 @@ float *DPL2FSDecoder::decode(float *input) {

// flush the internal buffers
void DPL2FSDecoder::flush() {
memset(&outbuf[0], 0, outbuf.size() * 4);
memset(&inbuf[0], 0, inbuf.size() * 4);
memset(&outbuf[0], 0, outbuf.size() * sizeof(float));
memset(&inbuf[0], 0, inbuf.size() * sizeof(float));
buffer_empty = true;
}

// number of samples currently held in the buffer
unsigned int DPL2FSDecoder::buffered() { return buffer_empty ? 0 : N / 2; }
unsigned int DPL2FSDecoder::buffered() const { return buffer_empty ? 0 : N / 2; }

float* DPL2FSDecoder::input_buffer() { return &inbuf[0]; }

// set soundfield & rendering parameters
void DPL2FSDecoder::set_circular_wrap(float v) { circular_wrap = v; }
Expand All @@ -116,8 +158,12 @@ void DPL2FSDecoder::set_focus(float v) { focus = v; }
void DPL2FSDecoder::set_center_image(float v) { center_image = v; }
void DPL2FSDecoder::set_front_separation(float v) { front_separation = v; }
void DPL2FSDecoder::set_rear_separation(float v) { rear_separation = v; }
void DPL2FSDecoder::set_low_cutoff(float v) { lo_cut = v * (N / 2); }
void DPL2FSDecoder::set_high_cutoff(float v) { hi_cut = v * (N / 2); }
void DPL2FSDecoder::set_low_cutoff(float v) {
lo_cut = (v / (samplerate / 2.f)) * (N / 2);
}
void DPL2FSDecoder::set_high_cutoff(float v) {
hi_cut = (v / (samplerate / 2.f)) * (N / 2);
}
void DPL2FSDecoder::set_bass_redirection(bool v) { use_lfe = v; }

// helper functions
Expand Down Expand Up @@ -163,8 +209,8 @@ void DPL2FSDecoder::buffered_decode(float *input) {
}

// map into spectral domain
kiss_fftr(forward, &lt[0], (kiss_fft_cpx *)&lf[0]);
kiss_fftr(forward, &rt[0], (kiss_fft_cpx *)&rf[0]);
kiss_fftr((kiss_fftr_cfg)forward, &lt[0], (kiss_fft_cpx *)&lf[0]);
kiss_fftr((kiss_fftr_cfg)forward, &rt[0], (kiss_fft_cpx *)&rf[0]);

// compute multichannel output signal in the spectral domain
for (unsigned int f = 1; f < N / 2; f++) {
Expand Down Expand Up @@ -228,14 +274,14 @@ void DPL2FSDecoder::buffered_decode(float *input) {
}
}

// shift the last 2/3 to the first 2/3 of the output buffer
memcpy(&outbuf[0], &outbuf[C * N / 2], N * C * 4);
// shift the last 2/3 (a block) to the first 2/3 of the output buffer
memcpy(&outbuf[0], &outbuf[C * N / 2], N * C * sizeof(float));
// and clear the rest
memset(&outbuf[C * N], 0, C * 4 * N / 2);
memset(&outbuf[C * N], 0, C * sizeof(float) * N / 2);
// backtransform each channel and overlap-add
for (unsigned int c = 0; c < C; c++) {
// back-transform into time domain
kiss_fftri(inverse, (kiss_fft_cpx *)&signal[c][0], &dst[0]);
kiss_fftri((kiss_fftr_cfg)inverse, (kiss_fft_cpx *)&signal[c][0], &dst[0]);
// add the result to the last 2/3 of the output buffer, windowed (and
// remultiplex)
for (unsigned int k = 0; k < N; k++)
Expand Down
3 changes: 3 additions & 0 deletions Externals/FreeSurround/source/KissFFT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
functions.
*/

#include <cassert>

static void kf_bfly2(kiss_fft_cpx *Fout, const size_t fstride,
const kiss_fft_cfg st, int m) {
kiss_fft_cpx *Fout2;
Expand Down Expand Up @@ -379,6 +381,7 @@ kiss_fft_cfg kiss_fft_alloc(int nfft, int inverse_fft, void *mem,
sizeof(kiss_fft_cpx) * (nfft - 1); /* twiddle factors*/

if (lenmem == NULL) {
assert(false); // Support removed by Dolphin (unsafe)
st = (kiss_fft_cfg) new char[memneeded];
} else {
if (mem != NULL && *lenmem >= memneeded)
Expand Down
15 changes: 12 additions & 3 deletions Externals/FreeSurround/source/KissFFTR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FreeSurround/KissFFTR.h"
#include "FreeSurround/_KissFFTGuts.h"

#include <cassert>

struct kiss_fftr_state {
kiss_fft_cfg substate;
kiss_fft_cpx *tmpbuf;
Expand All @@ -48,10 +50,11 @@ struct kiss_fftr_state {
#endif
};

kiss_fftr_cfg kiss_fftr_alloc(int nfft, int inverse_fft, void *mem,
char* kiss_fftr_alloc(int nfft, int inverse_fft, void *mem,
size_t *lenmem) {
int i;
kiss_fftr_cfg st = NULL;
char* char_st = NULL;
size_t subsize = 65536 * 4, memneeded = 0;

if (nfft & 1) {
Expand All @@ -65,10 +68,16 @@ kiss_fftr_cfg kiss_fftr_alloc(int nfft, int inverse_fft, void *mem,
sizeof(kiss_fft_cpx) * (nfft * 3 / 2);

if (lenmem == NULL) {
st = (kiss_fftr_cfg) new char[memneeded];
assert(memneeded >= sizeof(kiss_fftr_state));
char_st = new char[memneeded];
st = (kiss_fftr_cfg)char_st;
} else {
if (*lenmem >= memneeded)
{
assert(false); // Support removed by Dolphin
st = (kiss_fftr_cfg)mem;
char_st = (char*)st;
}
*lenmem = memneeded;
}
if (!st)
Expand All @@ -86,7 +95,7 @@ kiss_fftr_cfg kiss_fftr_alloc(int nfft, int inverse_fft, void *mem,
phase *= -1;
kf_cexp(st->super_twiddles + i, phase);
}
return st;
return char_st;
}

void kiss_fftr(kiss_fftr_cfg st, const kiss_fft_scalar *timedata,
Expand Down
Loading