Path: blob/master/servers/audio/audio_rb_resampler.h
10277 views
/**************************************************************************/1/* audio_rb_resampler.h */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#pragma once3132#include "core/math/audio_frame.h"33#include "core/templates/safe_refcount.h"34#include "core/typedefs.h"3536struct AudioRBResampler {37uint32_t rb_bits;38uint32_t rb_len;39uint32_t rb_mask;40uint32_t read_buff_len;41uint32_t channels;42uint32_t src_mix_rate;43uint32_t target_mix_rate;44double playback_speed = 1.0;4546SafeNumeric<int> rb_read_pos;47SafeNumeric<int> rb_write_pos;4849int32_t offset; //contains the fractional remainder of the resampler50enum {51MIX_FRAC_BITS = 13,52MIX_FRAC_LEN = (1 << MIX_FRAC_BITS),53MIX_FRAC_MASK = MIX_FRAC_LEN - 1,54};5556float *read_buf = nullptr;57float *rb = nullptr;5859template <int C>60uint32_t _resample(AudioFrame *p_dest, int p_todo, int32_t p_increment);6162public:63_FORCE_INLINE_ void flush() {64rb_read_pos.set(0);65rb_write_pos.set(0);66offset = 0;67}6869_FORCE_INLINE_ bool is_ready() const {70return rb != nullptr;71}7273_FORCE_INLINE_ int get_total() const {74return rb_len - 1;75}7677_FORCE_INLINE_ int get_writer_space() const {78int space, r, w;7980r = rb_read_pos.get();81w = rb_write_pos.get();8283if (r == w) {84space = rb_len - 1;85} else if (w < r) {86space = r - w - 1;87} else {88space = (rb_len - w) + (r - 1);89}9091return space;92}9394_FORCE_INLINE_ int get_reader_space() const {95int space, r, w;9697r = rb_read_pos.get();98w = rb_write_pos.get();99100if (r == w) {101space = 0;102} else if (w < r) {103space = rb_len - r + w;104} else {105space = w - r;106}107108return space;109}110111_FORCE_INLINE_ bool has_data() const {112return rb && rb_read_pos.get() != rb_write_pos.get();113}114115_FORCE_INLINE_ float *get_write_buffer() { return read_buf; }116_FORCE_INLINE_ void write(uint32_t p_frames) {117ERR_FAIL_COND(p_frames >= rb_len);118119int wp = rb_write_pos.get();120121switch (channels) {122case 1: {123for (uint32_t i = 0; i < p_frames; i++) {124rb[wp] = read_buf[i];125wp = (wp + 1) & rb_mask;126}127} break;128case 2: {129for (uint32_t i = 0; i < p_frames; i++) {130rb[(wp << 1) + 0] = read_buf[(i << 1) + 0];131rb[(wp << 1) + 1] = read_buf[(i << 1) + 1];132wp = (wp + 1) & rb_mask;133}134} break;135case 4: {136for (uint32_t i = 0; i < p_frames; i++) {137rb[(wp << 2) + 0] = read_buf[(i << 2) + 0];138rb[(wp << 2) + 1] = read_buf[(i << 2) + 1];139rb[(wp << 2) + 2] = read_buf[(i << 2) + 2];140rb[(wp << 2) + 3] = read_buf[(i << 2) + 3];141wp = (wp + 1) & rb_mask;142}143} break;144case 6: {145for (uint32_t i = 0; i < p_frames; i++) {146rb[(wp * 6) + 0] = read_buf[(i * 6) + 0];147rb[(wp * 6) + 1] = read_buf[(i * 6) + 1];148rb[(wp * 6) + 2] = read_buf[(i * 6) + 2];149rb[(wp * 6) + 3] = read_buf[(i * 6) + 3];150rb[(wp * 6) + 4] = read_buf[(i * 6) + 4];151rb[(wp * 6) + 5] = read_buf[(i * 6) + 5];152wp = (wp + 1) & rb_mask;153}154} break;155case 8: {156for (uint32_t i = 0; i < p_frames; i++) {157rb[(wp << 3) + 0] = read_buf[(i << 3) + 0];158rb[(wp << 3) + 1] = read_buf[(i << 3) + 1];159rb[(wp << 3) + 2] = read_buf[(i << 3) + 2];160rb[(wp << 3) + 3] = read_buf[(i << 3) + 3];161rb[(wp << 3) + 4] = read_buf[(i << 3) + 4];162rb[(wp << 3) + 5] = read_buf[(i << 3) + 5];163rb[(wp << 3) + 6] = read_buf[(i << 3) + 6];164rb[(wp << 3) + 7] = read_buf[(i << 3) + 7];165wp = (wp + 1) & rb_mask;166}167} break;168}169170rb_write_pos.set(wp);171}172173int get_channel_count() const;174175Error setup(int p_channels, int p_src_mix_rate, int p_target_mix_rate, int p_buffer_msec, int p_minbuff_needed = -1);176void clear();177bool mix(AudioFrame *p_dest, int p_frames);178int get_num_of_ready_frames();179void set_playback_speed(double p_playback_speed);180double get_playback_speed() const;181182AudioRBResampler();183~AudioRBResampler();184};185186187