From eab850524ead092ed9fe22e57955e59eae373b79 Mon Sep 17 00:00:00 2001 From: Marcelo Fernandez Date: Thu, 17 Aug 2017 18:35:55 -0300 Subject: [PATCH] Add closest_power_of_2 func and implement mix_rate/latency on OS X --- core/image.cpp | 6 +- core/io/file_access_compressed.cpp | 20 ++-- core/io/packet_peer.cpp | 4 +- core/math/geometry.cpp | 4 +- core/typedefs.h | 21 +++- core/vector.h | 4 +- drivers/alsa/audio_driver_alsa.cpp | 2 +- drivers/gles2/rasterizer_gles2.cpp | 18 +-- drivers/gles3/rasterizer_scene_gles3.cpp | 12 +- .../pulseaudio/audio_driver_pulseaudio.cpp | 2 +- drivers/rtaudio/audio_driver_rtaudio.cpp | 2 +- drivers/xaudio2/audio_driver_xaudio2.cpp | 2 +- .../io_plugins/editor_font_import_plugin.cpp | 4 +- .../editor_texture_import_plugin.cpp | 4 +- editor/plugins/baked_light_baker.cpp | 4 +- modules/etc/image_etc.cpp | 2 +- modules/gdscript/gd_functions.cpp | 2 +- .../visual_script_builtin_funcs.cpp | 2 +- platform/android/audio_driver_jandroid.cpp | 2 +- platform/haiku/audio_driver_media_kit.cpp | 2 +- platform/osx/audio_driver_osx.cpp | 104 +++++++++++------- platform/osx/audio_driver_osx.h | 4 +- scene/resources/dynamic_font.cpp | 2 +- scene/resources/dynamic_font_stb.cpp | 2 +- servers/audio/audio_driver_dummy.cpp | 2 +- servers/visual/visual_server_canvas.cpp | 4 +- servers/visual/visual_server_raster.cpp | 2 +- 27 files changed, 144 insertions(+), 95 deletions(-) diff --git a/core/image.cpp b/core/image.cpp index 2db9cb157180..a4864458b568 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -676,8 +676,8 @@ void Image::resize_to_po2(bool p_square) { ERR_FAIL(); } - int w = nearest_power_of_2(width); - int h = nearest_power_of_2(height); + int w = next_power_of_2(width); + int h = next_power_of_2(height); if (w == width && h == height) { @@ -1060,7 +1060,7 @@ Error Image::generate_mipmaps() { PoolVector::Write wp = data.write(); - if (nearest_power_of_2(width) == uint32_t(width) && nearest_power_of_2(height) == uint32_t(height)) { + if (next_power_of_2(width) == uint32_t(width) && next_power_of_2(height) == uint32_t(height)) { //use fast code for powers of 2 int prev_ofs = 0; int prev_h = height; diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp index 4e802579c69c..34bce3f04f6c 100644 --- a/core/io/file_access_compressed.cpp +++ b/core/io/file_access_compressed.cpp @@ -43,16 +43,16 @@ void FileAccessCompressed::configure(const String &p_magic, Compression::Mode p_ block_size = p_block_size; } -#define WRITE_FIT(m_bytes) \ - { \ - if (write_pos + (m_bytes) > write_max) { \ - write_max = write_pos + (m_bytes); \ - } \ - if (write_max > write_buffer_size) { \ - write_buffer_size = nearest_power_of_2(write_max); \ - buffer.resize(write_buffer_size); \ - write_ptr = buffer.ptr(); \ - } \ +#define WRITE_FIT(m_bytes) \ + { \ + if (write_pos + (m_bytes) > write_max) { \ + write_max = write_pos + (m_bytes); \ + } \ + if (write_max > write_buffer_size) { \ + write_buffer_size = next_power_of_2(write_max); \ + buffer.resize(write_buffer_size); \ + write_ptr = buffer.ptr(); \ + } \ } Error FileAccessCompressed::open_after_magic(FileAccess *p_base) { diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp index f62ffd7183c7..66f8eea17130 100644 --- a/core/io/packet_peer.cpp +++ b/core/io/packet_peer.cpp @@ -265,12 +265,12 @@ void PacketPeerStream::set_input_buffer_max_size(int p_max_size) { ERR_EXPLAIN("Buffer in use, resizing would cause loss of data"); ERR_FAIL_COND(ring_buffer.data_left()); ring_buffer.resize(nearest_shift(p_max_size + 4)); - input_buffer.resize(nearest_power_of_2(p_max_size + 4)); + input_buffer.resize(next_power_of_2(p_max_size + 4)); } void PacketPeerStream::set_output_buffer_max_size(int p_max_size) { - output_buffer.resize(nearest_power_of_2(p_max_size + 4)); + output_buffer.resize(next_power_of_2(p_max_size + 4)); } PacketPeerStream::PacketPeerStream() { diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp index 2bea514d3789..9a5811244a7e 100644 --- a/core/math/geometry.cpp +++ b/core/math/geometry.cpp @@ -1076,8 +1076,8 @@ void Geometry::make_atlas(const Vector &p_rects, Vector &r_resu for (int i = 0; i < results.size(); i++) { - real_t h = nearest_power_of_2(results[i].max_h); - real_t w = nearest_power_of_2(results[i].max_w); + real_t h = next_power_of_2(results[i].max_h); + real_t w = next_power_of_2(results[i].max_w); real_t aspect = h > w ? h / w : w / h; if (aspect < best_aspect) { best = i; diff --git a/core/typedefs.h b/core/typedefs.h index 40d9ea37b57c..34a1a93a3b57 100644 --- a/core/typedefs.h +++ b/core/typedefs.h @@ -162,9 +162,9 @@ inline void __swap_tmpl(T &x, T &y) { #define _add_overflow __builtin_add_overflow #endif -/** Function to find the nearest (bigger) power of 2 to an integer */ +/** Function to find the next power of 2 to an integer */ -static _FORCE_INLINE_ unsigned int nearest_power_of_2(unsigned int x) { +static _FORCE_INLINE_ unsigned int next_power_of_2(unsigned int x) { --x; x |= x >> 1; @@ -176,6 +176,23 @@ static _FORCE_INLINE_ unsigned int nearest_power_of_2(unsigned int x) { return ++x; } +static _FORCE_INLINE_ unsigned int previous_power_of_2(unsigned int x) { + + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + return x - (x >> 1); +} + +static _FORCE_INLINE_ unsigned int closest_power_of_2(unsigned int x) { + + unsigned int nx = next_power_of_2(x); + unsigned int px = previous_power_of_2(x); + return (nx - x) > (x - px) ? px : nx; +} + // We need this definition inside the function below. static inline int get_shift_from_power_of_2(unsigned int p_pixel); diff --git a/core/vector.h b/core/vector.h index 9f523c567c09..966832ac5092 100644 --- a/core/vector.h +++ b/core/vector.h @@ -71,7 +71,7 @@ class Vector { _FORCE_INLINE_ size_t _get_alloc_size(size_t p_elements) const { //return nearest_power_of_2_templated(p_elements*sizeof(T)+sizeof(SafeRefCount)+sizeof(int)); - return nearest_power_of_2(p_elements * sizeof(T)); + return next_power_of_2(p_elements * sizeof(T)); } _FORCE_INLINE_ bool _get_alloc_size_checked(size_t p_elements, size_t *out) const { @@ -79,7 +79,7 @@ class Vector { size_t o; size_t p; if (_mul_overflow(p_elements, sizeof(T), &o)) return false; - *out = nearest_power_of_2(o); + *out = next_power_of_2(o); if (_add_overflow(o, static_cast(32), &p)) return false; //no longer allocated here return true; #else diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp index 4e6739e8c06a..a6b974812914 100644 --- a/drivers/alsa/audio_driver_alsa.cpp +++ b/drivers/alsa/audio_driver_alsa.cpp @@ -87,7 +87,7 @@ Error AudioDriverALSA::init() { CHECK_FAIL(status < 0); int latency = GLOBAL_DEF("audio/output_latency", 25); - buffer_size = nearest_power_of_2(latency * mix_rate / 1000); + buffer_size = closest_power_of_2(latency * mix_rate / 1000); // set buffer size from project settings status = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size); diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 7ad08ed7d5b2..6a6611ff8149 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -857,8 +857,8 @@ void RasterizerGLES2::texture_allocate(RID p_texture, int p_width, int p_height, GLenum internal_format; bool compressed; - int po2_width = nearest_power_of_2(p_width); - int po2_height = nearest_power_of_2(p_height); + int po2_width = next_power_of_2(p_width); + int po2_height = next_power_of_2(p_height); if (p_flags & VS::TEXTURE_FLAG_VIDEO_SURFACE) { p_flags &= ~VS::TEXTURE_FLAG_MIPMAPS; // no mipies for video @@ -977,7 +977,7 @@ void RasterizerGLES2::texture_set_data(RID p_texture, const Image &p_image, VS:: glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // raw Filtering } - bool force_clamp_to_edge = !(texture->flags & VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) && (nearest_power_of_2(texture->alloc_height) != texture->alloc_height || nearest_power_of_2(texture->alloc_width) != texture->alloc_width); + bool force_clamp_to_edge = !(texture->flags & VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) && (next_power_of_2(texture->alloc_height) != texture->alloc_height || next_power_of_2(texture->alloc_width) != texture->alloc_width); if (!force_clamp_to_edge && (texture->flags & VS::TEXTURE_FLAG_REPEAT || texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT) && texture->target != GL_TEXTURE_CUBE_MAP) { @@ -1234,7 +1234,7 @@ void RasterizerGLES2::texture_set_flags(RID p_texture, uint32_t p_flags) { uint32_t cube = texture->flags & VS::TEXTURE_FLAG_CUBEMAP; texture->flags = p_flags | cube; // can't remove a cube from being a cube - bool force_clamp_to_edge = !(p_flags & VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) && (nearest_power_of_2(texture->alloc_height) != texture->alloc_height || nearest_power_of_2(texture->alloc_width) != texture->alloc_width); + bool force_clamp_to_edge = !(p_flags & VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) && (next_power_of_2(texture->alloc_height) != texture->alloc_height || next_power_of_2(texture->alloc_width) != texture->alloc_width); if (!force_clamp_to_edge && (texture->flags & VS::TEXTURE_FLAG_REPEAT || texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT) && texture->target != GL_TEXTURE_CUBE_MAP) { @@ -2701,7 +2701,7 @@ void RasterizerGLES2::multimesh_set_instance_count(RID p_multimesh, int p_count) if (use_texture_instancing) { - if (nearest_power_of_2(p_count) != nearest_power_of_2(multimesh->elements.size())) { + if (next_power_of_2(p_count) != next_power_of_2(multimesh->elements.size())) { if (multimesh->tex_id) { glDeleteTextures(1, &multimesh->tex_id); multimesh->tex_id = 0; @@ -2709,7 +2709,7 @@ void RasterizerGLES2::multimesh_set_instance_count(RID p_multimesh, int p_count) if (p_count) { - uint32_t po2 = nearest_power_of_2(p_count); + uint32_t po2 = next_power_of_2(p_count); if (po2 & 0xAAAAAAAA) { //half width @@ -3333,7 +3333,7 @@ void RasterizerGLES2::skeleton_resize(RID p_skeleton, int p_bones) { }; if (use_hw_skeleton_xform) { - if (nearest_power_of_2(p_bones) != nearest_power_of_2(skeleton->bones.size())) { + if (next_power_of_2(p_bones) != next_power_of_2(skeleton->bones.size())) { if (skeleton->tex_id) { glDeleteTextures(1, &skeleton->tex_id); skeleton->tex_id = 0; @@ -3344,7 +3344,7 @@ void RasterizerGLES2::skeleton_resize(RID p_skeleton, int p_bones) { glGenTextures(1, &skeleton->tex_id); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, skeleton->tex_id); - int ps = nearest_power_of_2(p_bones * 3); + int ps = next_power_of_2(p_bones * 3); #ifdef GLEW_ENABLED glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, ps, 1, 0, GL_RGBA, GL_FLOAT, skel_default.ptr()); #else @@ -3998,7 +3998,7 @@ void RasterizerGLES2::begin_frame() { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, s->tex_id); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, nearest_power_of_2(s->bones.size() * 3), 1, GL_RGBA, GL_FLOAT, sk_float); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, next_power_of_2(s->bones.size() * 3), 1, GL_RGBA, GL_FLOAT, sk_float); _skeleton_dirty_list.remove(_skeleton_dirty_list.first()); } diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 30c0d65ff363..ac6ca1ec0cac 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -120,7 +120,7 @@ void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas, int p_size) { ERR_FAIL_COND(!shadow_atlas); ERR_FAIL_COND(p_size < 0); - p_size = nearest_power_of_2(p_size); + p_size = next_power_of_2(p_size); if (p_size == shadow_atlas->size) return; @@ -185,7 +185,7 @@ void RasterizerSceneGLES3::shadow_atlas_set_quadrant_subdivision(RID p_atlas, in ERR_FAIL_INDEX(p_quadrant, 4); ERR_FAIL_INDEX(p_subdivision, 16384); - uint32_t subdiv = nearest_power_of_2(p_subdivision); + uint32_t subdiv = next_power_of_2(p_subdivision); if (subdiv & 0xaaaaaaaa) { //sqrt(subdiv) must be integer subdiv <<= 1; } @@ -310,7 +310,7 @@ bool RasterizerSceneGLES3::shadow_atlas_update_light(RID p_atlas, RID p_light_in } uint32_t quad_size = shadow_atlas->size >> 1; - int desired_fit = MIN(quad_size / shadow_atlas->smallest_subdiv, nearest_power_of_2(quad_size * p_coverage)); + int desired_fit = MIN(quad_size / shadow_atlas->smallest_subdiv, next_power_of_2(quad_size * p_coverage)); int valid_quadrants[4]; int valid_quadrant_count = 0; @@ -479,7 +479,7 @@ void RasterizerSceneGLES3::reflection_atlas_set_size(RID p_ref_atlas, int p_size ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_ref_atlas); ERR_FAIL_COND(!reflection_atlas); - int size = nearest_power_of_2(p_size); + int size = next_power_of_2(p_size); if (size == reflection_atlas->size) return; @@ -554,7 +554,7 @@ void RasterizerSceneGLES3::reflection_atlas_set_subdivision(RID p_ref_atlas, int ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_ref_atlas); ERR_FAIL_COND(!reflection_atlas); - uint32_t subdiv = nearest_power_of_2(p_subdiv); + uint32_t subdiv = next_power_of_2(p_subdiv); if (subdiv & 0xaaaaaaaa) { //sqrt(subdiv) must be integer subdiv <<= 1; } @@ -4757,7 +4757,7 @@ void RasterizerSceneGLES3::initialize() { { //directional light shadow directional_shadow.light_count = 0; - directional_shadow.size = nearest_power_of_2(GLOBAL_GET("rendering/quality/directional_shadow/size")); + directional_shadow.size = next_power_of_2(GLOBAL_GET("rendering/quality/directional_shadow/size")); glGenFramebuffers(1, &directional_shadow.fbo); glBindFramebuffer(GL_FRAMEBUFFER, directional_shadow.fbo); glGenTextures(1, &directional_shadow.depth); diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp index fb04ef00886b..5acf9bf46e25 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp +++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp @@ -54,7 +54,7 @@ Error AudioDriverPulseAudio::init() { spec.rate = mix_rate; int latency = GLOBAL_DEF("audio/output_latency", 25); - buffer_size = nearest_power_of_2(latency * mix_rate / 1000); + buffer_size = closest_power_of_2(latency * mix_rate / 1000); pa_buffer_attr attr; // set to appropriate buffer size from global settings diff --git a/drivers/rtaudio/audio_driver_rtaudio.cpp b/drivers/rtaudio/audio_driver_rtaudio.cpp index 3de25c32ad4b..8466f55afc44 100644 --- a/drivers/rtaudio/audio_driver_rtaudio.cpp +++ b/drivers/rtaudio/audio_driver_rtaudio.cpp @@ -118,7 +118,7 @@ Error AudioDriverRtAudio::init() { int latency = GLOBAL_DEF("audio/output_latency", 25); // calculate desired buffer_size, taking the desired numberOfBuffers into account (latency depends on numberOfBuffers*buffer_size) - unsigned int buffer_size = nearest_power_of_2(latency * mix_rate / 1000 / target_number_of_buffers); + unsigned int buffer_size = closest_power_of_2(latency * mix_rate / 1000 / target_number_of_buffers); if (OS::get_singleton()->is_stdout_verbose()) { print_line("audio buffer size: " + itos(buffer_size)); diff --git a/drivers/xaudio2/audio_driver_xaudio2.cpp b/drivers/xaudio2/audio_driver_xaudio2.cpp index a1ca2c678e89..42c4c40300d2 100644 --- a/drivers/xaudio2/audio_driver_xaudio2.cpp +++ b/drivers/xaudio2/audio_driver_xaudio2.cpp @@ -50,7 +50,7 @@ Error AudioDriverXAudio2::init() { channels = 2; int latency = GLOBAL_DEF("audio/output_latency", 25); - buffer_size = nearest_power_of_2(latency * mix_rate / 1000); + buffer_size = closest_power_of_2(latency * mix_rate / 1000); samples_in = memnew_arr(int32_t, buffer_size * channels); for (int i = 0; i < AUDIO_BUFFERS; i++) { diff --git a/editor/io_plugins/editor_font_import_plugin.cpp b/editor/io_plugins/editor_font_import_plugin.cpp index 9831e08cf1e3..25d8a5b7eb61 100644 --- a/editor/io_plugins/editor_font_import_plugin.cpp +++ b/editor/io_plugins/editor_font_import_plugin.cpp @@ -1536,8 +1536,8 @@ Ref EditorFontImportPlugin::generate_font(const Ref res; Size2i res_size; EditorAtlas::fit(sizes,res,res_size); - res_size.x=nearest_power_of_2(res_size.x); - res_size.y=nearest_power_of_2(res_size.y); + res_size.x=next_power_of_2(res_size.x); + res_size.y=next_power_of_2(res_size.y); print_line("Atlas size: "+res_size); Image atlas(res_size.x,res_size.y,0,Image::FORMAT_RGBA8); diff --git a/editor/io_plugins/editor_texture_import_plugin.cpp b/editor/io_plugins/editor_texture_import_plugin.cpp index 095bc02fa0e4..1dc264147438 100644 --- a/editor/io_plugins/editor_texture_import_plugin.cpp +++ b/editor/io_plugins/editor_texture_import_plugin.cpp @@ -1280,8 +1280,8 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Refget_width(), imgh = p_img->get_height(); - ERR_FAIL_COND(nearest_power_of_2(imgw) != imgw || nearest_power_of_2(imgh) != imgh); + ERR_FAIL_COND(next_power_of_2(imgw) != imgw || next_power_of_2(imgh) != imgh); Image::Format etc_format = force_etc1_format ? Image::FORMAT_ETC : _get_etc2_mode(detected_channels); diff --git a/modules/gdscript/gd_functions.cpp b/modules/gdscript/gd_functions.cpp index 209bdadd675d..094dd287e602 100644 --- a/modules/gdscript/gd_functions.cpp +++ b/modules/gdscript/gd_functions.cpp @@ -446,7 +446,7 @@ void GDFunctions::call(Function p_func, const Variant **p_args, int p_arg_count, VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); int64_t num = *p_args[0]; - r_ret = nearest_power_of_2(num); + r_ret = next_power_of_2(num); } break; case OBJ_WEAKREF: { VALIDATE_ARG_COUNT(1); diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp index 203e0bb48315..9cbd70d4ca61 100644 --- a/modules/visual_script/visual_script_builtin_funcs.cpp +++ b/modules/visual_script/visual_script_builtin_funcs.cpp @@ -915,7 +915,7 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in VALIDATE_ARG_NUM(0); int64_t num = *p_inputs[0]; - *r_return = nearest_power_of_2(num); + *r_return = next_power_of_2(num); } break; case VisualScriptBuiltinFunc::OBJ_WEAKREF: { diff --git a/platform/android/audio_driver_jandroid.cpp b/platform/android/audio_driver_jandroid.cpp index d293f3ed3001..763eff2863c6 100644 --- a/platform/android/audio_driver_jandroid.cpp +++ b/platform/android/audio_driver_jandroid.cpp @@ -81,7 +81,7 @@ Error AudioDriverAndroid::init() { int latency = GLOBAL_DEF("audio/output_latency", 25); latency = 50; - unsigned int buffer_size = nearest_power_of_2(latency * mix_rate / 1000); + unsigned int buffer_size = next_power_of_2(latency * mix_rate / 1000); if (OS::get_singleton()->is_stdout_verbose()) { print_line("audio buffer size: " + itos(buffer_size)); } diff --git a/platform/haiku/audio_driver_media_kit.cpp b/platform/haiku/audio_driver_media_kit.cpp index 93351e079938..802f6b2d321c 100644 --- a/platform/haiku/audio_driver_media_kit.cpp +++ b/platform/haiku/audio_driver_media_kit.cpp @@ -43,7 +43,7 @@ Error AudioDriverMediaKit::init() { channels = 2; int latency = GLOBAL_DEF("audio/output_latency", 25); - buffer_size = nearest_power_of_2(latency * mix_rate / 1000); + buffer_size = next_power_of_2(latency * mix_rate / 1000); samples_in = memnew_arr(int32_t, buffer_size * channels); media_raw_audio_format format; diff --git a/platform/osx/audio_driver_osx.cpp b/platform/osx/audio_driver_osx.cpp index d7a91b165303..da5cd8f65e6e 100644 --- a/platform/osx/audio_driver_osx.cpp +++ b/platform/osx/audio_driver_osx.cpp @@ -30,6 +30,10 @@ #ifdef OSX_ENABLED #include "audio_driver_osx.h" +#include "core/project_settings.h" +#include "os/os.h" + +#define kOutputBus 0 static OSStatus outputDeviceAddressCB(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, void *__nullable inClientData) { AudioDriverOSX *driver = (AudioDriverOSX *)inClientData; @@ -40,42 +44,69 @@ static OSStatus outputDeviceAddressCB(AudioObjectID inObjectID, UInt32 inNumberA } Error AudioDriverOSX::initDevice() { - AudioStreamBasicDescription strdesc; - strdesc.mFormatID = kAudioFormatLinearPCM; - strdesc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; - strdesc.mChannelsPerFrame = channels; - strdesc.mSampleRate = 44100; - strdesc.mFramesPerPacket = 1; - strdesc.mBitsPerChannel = 16; - strdesc.mBytesPerFrame = strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8; - strdesc.mBytesPerPacket = strdesc.mBytesPerFrame * strdesc.mFramesPerPacket; - - OSStatus result; - AURenderCallbackStruct callback; AudioComponentDescription desc; - AudioComponent comp = NULL; - const AudioUnitElement output_bus = 0; - const AudioUnitElement bus = output_bus; - const AudioUnitScope scope = kAudioUnitScope_Input; - zeromem(&desc, sizeof(desc)); desc.componentType = kAudioUnitType_Output; desc.componentSubType = kAudioUnitSubType_HALOutput; desc.componentManufacturer = kAudioUnitManufacturer_Apple; - comp = AudioComponentFindNext(NULL, &desc); + AudioComponent comp = AudioComponentFindNext(NULL, &desc); ERR_FAIL_COND_V(comp == NULL, FAILED); - result = AudioComponentInstanceNew(comp, &audio_unit); + OSStatus result = AudioComponentInstanceNew(comp, &audio_unit); ERR_FAIL_COND_V(result != noErr, FAILED); - result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_StreamFormat, scope, bus, &strdesc, sizeof(strdesc)); + AudioStreamBasicDescription strdesc; + + // TODO: Implement this + /*zeromem(&strdesc, sizeof(strdesc)); + UInt32 size = sizeof(strdesc); + result = AudioUnitGetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kOutputBus, &strdesc, &size); ERR_FAIL_COND_V(result != noErr, FAILED); + switch (strdesc.mChannelsPerFrame) { + case 2: // Stereo + case 6: // Surround 5.1 + case 8: // Surround 7.1 + channels = strdesc.mChannelsPerFrame; + break; + + default: + // Unknown number of channels, default to stereo + channels = 2; + break; + }*/ + + mix_rate = GLOBAL_DEF("audio/mix_rate", 44100); + + zeromem(&strdesc, sizeof(strdesc)); + strdesc.mFormatID = kAudioFormatLinearPCM; + strdesc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; + strdesc.mChannelsPerFrame = channels; + strdesc.mSampleRate = mix_rate; + strdesc.mFramesPerPacket = 1; + strdesc.mBitsPerChannel = 16; + strdesc.mBytesPerFrame = strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8; + strdesc.mBytesPerPacket = strdesc.mBytesPerFrame * strdesc.mFramesPerPacket; + + result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &strdesc, sizeof(strdesc)); + ERR_FAIL_COND_V(result != noErr, FAILED); + + int latency = GLOBAL_DEF("audio/output_latency", 25); + unsigned int buffer_size = closest_power_of_2(latency * mix_rate / 1000); + + if (OS::get_singleton()->is_stdout_verbose()) { + print_line("audio buffer size: " + itos(buffer_size) + " calculated latency: " + itos(buffer_size * 1000 / mix_rate)); + } + + samples_in.resize(buffer_size); + buffer_frames = buffer_size / channels; + + AURenderCallbackStruct callback; zeromem(&callback, sizeof(AURenderCallbackStruct)); callback.inputProc = &AudioDriverOSX::output_callback; callback.inputProcRefCon = this; - result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_SetRenderCallback, scope, bus, &callback, sizeof(callback)); + result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, kOutputBus, &callback, sizeof(callback)); ERR_FAIL_COND_V(result != noErr, FAILED); result = AudioUnitInitialize(audio_unit); @@ -114,15 +145,10 @@ Error AudioDriverOSX::init() { result = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &outputDeviceAddress, &outputDeviceAddressCB, this); ERR_FAIL_COND_V(result != noErr, FAILED); - const int samples = 1024; - samples_in = memnew_arr(int32_t, samples); // whatever - buffer_frames = samples / channels; - return initDevice(); }; Error AudioDriverOSX::reopen() { - Error err; bool restart = false; lock(); @@ -131,7 +157,7 @@ Error AudioDriverOSX::reopen() { restart = true; } - err = finishDevice(); + Error err = finishDevice(); if (err != OK) { ERR_PRINT("finishDevice failed"); unlock(); @@ -179,7 +205,7 @@ OSStatus AudioDriverOSX::output_callback(void *inRefCon, while (frames_left) { int frames = MIN(frames_left, ad->buffer_frames); - ad->audio_server_process(frames, ad->samples_in); + ad->audio_server_process(frames, ad->samples_in.ptr()); for (int j = 0; j < frames * ad->channels; j++) { @@ -232,29 +258,33 @@ bool AudioDriverOSX::try_lock() { } void AudioDriverOSX::finish() { - OSStatus result; - finishDevice(); - result = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &outputDeviceAddress, &outputDeviceAddressCB, this); + OSStatus result = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &outputDeviceAddress, &outputDeviceAddressCB, this); if (result != noErr) { ERR_PRINT("AudioObjectRemovePropertyListener failed"); } + AURenderCallbackStruct callback; + zeromem(&callback, sizeof(AURenderCallbackStruct)); + result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, kOutputBus, &callback, sizeof(callback)); + if (result != noErr) { + ERR_PRINT("AudioUnitSetProperty failed"); + } + if (mutex) { memdelete(mutex); mutex = NULL; } - - if (samples_in) { - memdelete_arr(samples_in); - samples_in = NULL; - } }; AudioDriverOSX::AudioDriverOSX() { + active = false; mutex = NULL; - samples_in = NULL; + + mix_rate = 44100; + channels = 2; + samples_in.clear(); }; AudioDriverOSX::~AudioDriverOSX(){}; diff --git a/platform/osx/audio_driver_osx.h b/platform/osx/audio_driver_osx.h index 287c9d6cbfb6..4576100690e9 100644 --- a/platform/osx/audio_driver_osx.h +++ b/platform/osx/audio_driver_osx.h @@ -44,10 +44,12 @@ class AudioDriverOSX : public AudioDriver { bool active; Mutex *mutex; + int mix_rate; int channels; - int32_t *samples_in; int buffer_frames; + Vector samples_in; + static OSStatus output_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index fc0d80a9b7d2..e424ee48a8a9 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -524,7 +524,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) { if (mh > texsize) texsize = mh; //special case, adapt to it? - texsize = nearest_power_of_2(texsize); + texsize = next_power_of_2(texsize); texsize = MIN(texsize, 4096); diff --git a/scene/resources/dynamic_font_stb.cpp b/scene/resources/dynamic_font_stb.cpp index 8efad94b9a2e..fa8cf4723bc0 100644 --- a/scene/resources/dynamic_font_stb.cpp +++ b/scene/resources/dynamic_font_stb.cpp @@ -289,7 +289,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) { if (mh > texsize) texsize = mh; //special case, adapt to it? - texsize = nearest_power_of_2(texsize); + texsize = next_power_of_2(texsize); texsize = MIN(texsize, 4096); diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp index 0f15b43b4163..dfb6406b386f 100644 --- a/servers/audio/audio_driver_dummy.cpp +++ b/servers/audio/audio_driver_dummy.cpp @@ -45,7 +45,7 @@ Error AudioDriverDummy::init() { channels = 2; int latency = GLOBAL_DEF("audio/output_latency", 25); - buffer_size = nearest_power_of_2(latency * mix_rate / 1000); + buffer_size = next_power_of_2(latency * mix_rate / 1000); samples_in = memnew_arr(int32_t, buffer_size * channels); diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp index dcc16794e748..e4cda5500eec 100644 --- a/servers/visual/visual_server_canvas.cpp +++ b/servers/visual/visual_server_canvas.cpp @@ -1001,11 +1001,11 @@ void VisualServerCanvas::canvas_light_set_shadow_buffer_size(RID p_light, int p_ RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); ERR_FAIL_COND(!clight); - int new_size = nearest_power_of_2(p_size); + int new_size = next_power_of_2(p_size); if (new_size == clight->shadow_buffer_size) return; - clight->shadow_buffer_size = nearest_power_of_2(p_size); + clight->shadow_buffer_size = next_power_of_2(p_size); if (clight->shadow_buffer.is_valid()) { VSG::storage->free(clight->shadow_buffer); diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 4f16ae412553..e66c8a1e215a 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -4376,7 +4376,7 @@ void VisualServerRaster::canvas_light_set_shadow_buffer_size(RID p_light, int p_ ERR_FAIL_COND(p_size<32 || p_size>16384); - clight->shadow_buffer_size=nearest_power_of_2(p_size); + clight->shadow_buffer_size=next_power_of_2(p_size); if (clight->shadow_buffer.is_valid()) {