游戏引擎学习第九天

视频参考:https://www.bilibili.com/video/BV1ouUPYAErK/

修改之前的方波数据,改播放正弦波

在这里插入图片描述

下面主要讲关于浮点数

1. char(字符类型)

  • 大小:1 字节(8 位)
  • 表示方式char 存储的是一个字符的 ASCII 值。由于它是一个整数类型,它在内存中是以 二进制 形式存储的。
    • 有符号 char:表示的值范围通常是 -128127,其符号位决定了值的正负。
    • 无符号 char:范围从 0255

存储示例

  • char c = 'A'; 对应的 ASCII 值是 65,其二进制表示为 01000001

内存示意:

  字符 'A'(ASCII 65)
  十六进制: 0x41
  二进制:   01000001

3. int(整数类型)

  • 大小:4 字节(32 位)
  • 表示方式int 存储的是一个整数,采用 二进制补码 表示。
    • 有符号 int:范围通常为 -2,147,483,6482,147,483,647,最高位为符号位。
    • 无符号 int:表示的范围从 04,294,967,295

存储示例

  • int i = -123456; 使用 32 位二进制补码表示:
    • -123456 的二进制补码表示:11111111 11111110 00011101 11000000
      123456 0b00000000 00000001 11100010 01000000
      ~123456 0b11111111 11111110 00011101 10111111 取反
      ~123456+1 0b11111111 11111110 00011101 11000000 +1

在这里插入图片描述

内存示意:

  int i = -123456;
  二进制补码表示: 11111111 11111110 00011101 11000000
  十六进制表示: 0xFFFE1DC0

负数补码表示,按位取反+1

5. float(单精度浮点数)

  • 大小:4 字节(32 位)
  • 表示方式float 按照 IEEE 754 标准表示为 32 位浮点数,包括 符号位指数部分尾数(有效数字) 部分。表示方法如下:
    • 符号位(1 位):表示数字的正负。
    • 指数部分(8 位):表示数字的范围,通过偏移量调整。
    • 尾数部分(23 位):表示数字的精度。

表示为:
( − 1 ) 符号 × 1. 尾数 × 2 指数 − 127 (-1)^{\text{符号}} \times 1.\text{尾数} \times 2^{\text{指数}-127} (1)符号×1.尾数×2指数127

存储示例

  • float f = 3.14f; 的 IEEE 754 单精度表示:
    • 3.14 的二进制表示为:0 10000000 10010001111010111000011
#include <cstring>
#include <iostream>

void printBinary(float num) {
  // 将 float 转换为 int(按字节复制)
  int bits;
  std::memcpy(&bits, &num, sizeof(bits));

  // 打印二进制表示
  for (int i = 31; i >= 0; --i) {
    std::cout << ((bits >> i) & 1); // 逐位打印
    if (i == 31 || i == 23)
      std::cout << " "; // 分隔符,用于区分符号位、指数位、尾数位
  }
  std::cout << std::endl;
}

int main() {
  float num = 3.14f;
  std::cout << "Binary representation of " << num << " is: ";
  printBinary(num);
  return 0;
}

在这里插入图片描述

float 32 位

内存示意:

  float f = 3.14f;
  符号位:0
  指数部分:10000000
  尾数部分:10010001111010111000011
  十六进制表示: 0x4048F5C3

在这里插入图片描述

6. double(双精度浮点数)

在这里插入图片描述

  • 大小:8 字节(64 位)
  • 表示方式double 也按照 IEEE 754 标准表示,但它使用 64 位,包括 符号位指数部分尾数部分。它的精度比 float 更高,具体结构如下:
    • 符号位(1 位)
    • 指数部分(11 位)
    • 尾数部分(52 位)

表示为:
( − 1 ) 符号 × 1. 尾数 × 2 指数 − 1023 (-1)^{\text{符号}} \times 1.\text{尾数} \times 2^{\text{指数}-1023} (1)符号×1.尾数×2指数1023

存储示例

  • double d = 3.141592653589793; 的 IEEE 754 双精度表示:
    • 3.141592653589793 的二进制表示为:0 10000000000 1001001000011111101101010100010001000010110100011000

内存示意:

  double d = 3.141592653589793;
  符号位:0
  指数部分:10000000000
  尾数部分:1001001000011111101101010100010001000010110100011000

double类似只是表示的位数更多了

继续上面修改写入正弦数据

在这里插入图片描述

示例:

假设采样率为 44100 Hz(即每秒采样 44100 个样本),频率为 440 Hz(比如这是标准 A 音符的频率)。

  • 每秒钟你会采集 44100 个样本。
  • 每秒钟会有 440 个周期。

那么一个周期的持续时间(即波周期)就是:

W a v e P e r i o d = 44100 440 ≈ 100.23  毫秒 WavePeriod = \frac{44100}{440} \approx 100.23 \text{ 毫秒} WavePeriod=44044100100.23 毫秒

这意味着,每一个周期(即波的一个完整振荡)需要约 100.23 毫秒的时间。

  • 波周期(WavePeriod) 是波形完成一个周期所需的时间,单位是秒(s)。
  • 采样率(S) 是每秒钟采样多少个点,单位是 样本/秒(Hz)
  • 频率(f) 是波形每秒钟振荡多少次,单位是 赫兹(Hz)

波周期 = 采样率 / 频率 表示了 一个周期占用的时间,即波形完成一个振荡所需要的时间,反映了波形的 频率与采样细节的关系

在这里插入图片描述

优化一下代码把声音写缓存相关代码提出来

在这里插入图片描述

vs watch技巧

在这里插入图片描述

添加模拟手柄改变音频调试

在这里插入图片描述

模拟手柄软件

因为我没有手柄只能用模拟器进行调试
游戏手柄模拟器Gaming Keyboard Splitter
可以到这个完整下载对应的软件Gaming Keyboard Splitter
https://softlookup.com/download.asp?id=280311

我已经传到CSDN
https://download.csdn.net/download/TM1695648164/89982708

软件第一次运行会安装驱动会重启电脑

  1. debug运行程序
  2. 打开模拟手柄软件Gaming Keyboard Splitter
    在这里插入图片描述

在这里插入图片描述

上面测试会听到撕裂的声音切换时

“相位跳变”是指在切换频率时,波形的相位发生了不连续的变化,导致声音出现不自然的突变。为了理解这一点,我们需要从正弦波的相位频率切换时的平滑性角度来分析。

1. 什么是相位?

在波形中,相位指的是波形在某个时间点的状态,通常用一个角度来表示。例如,对于正弦波 sin(θ),其中 θ 表示相位,θ 通常是通过时间、频率和波速来计算的。

对于音频信号,波形的相位描述的是波形的位置(比如峰值、零交点等),以及波形如何在时间轴上前进。不同频率的正弦波具有不同的波长(周期),而相位描述的是这些波形的“开始位置”。

2. 什么是相位跳变?

相位跳变是指在两个连续的波形之间,相位发生了突然变化。当你在播放音频时切换频率时,如果没有处理好相位,就可能会导致新的波形与旧的波形在相位上的不对齐。

  • 相位对齐:指的是两个不同频率的波形在切换时,其相位(起始位置)要相同,或者在一个平滑的过渡过程中对齐。相位对齐确保了波形的过渡是平滑的,没有断裂感。

  • 相位跳变:如果你在切换频率时,新的波形从一个不对齐的相位开始(比如,原本的波形处于一个正半周期,而新的波形从零交点开始),那么这两个波形之间会出现不连续性。这种不连续性会导致音频信号的突变或毛刺声。

3. 为什么频率切换会导致相位跳变?

在频率切换时,如果频率的变化过于突兀,那么相位可能会发生跳变。例如:

  • 假设你正在播放一个频率为 256Hz 的正弦波,这意味着每秒钟播放 256 个完整的波形周期。如果你突然切换到 512Hz 的频率,意味着每秒钟播放的周期数是原来的两倍。如果没有对相位进行平滑过渡,新的频率波形的起始位置可能会不一致(比如一个正弦波的峰值和下一个波形的零交点不对齐),导致两个波形之间的过渡不连贯。

  • 当波形的相位不一致时,你就会听到一种不自然的“呲”声或毛刺声,因为音频信号的突然变化让耳朵感受到强烈的突变。

4. 如何理解和避免相位跳变?

  • 平滑过渡:为了避免相位跳变,最常见的做法是在切换频率时,确保新的频率从平滑过渡的相位开始。这意味着你可以在切换频率之前记录当前频率的相位,并确保新的频率从当前的相位状态开始播放。

  • 相位对齐:如果频率变化较大(比如从 256Hz 跳到 512Hz),你可以通过计算当前的相位并将其对齐到新频率来避免跳变。这样,新的波形从一个平滑的相位开始,不会有突然的相位变化。

  • 渐变过渡:另一种方法是通过渐变的方式逐步调整频率,而不是直接跳到新的频率。通过线性插值或其他平滑过渡方法,可以在一段时间内平滑地过渡到目标频率,从而避免突如其来的波形跳跃。

5. 示例:

假设你有一个频率为 256Hz 的正弦波:

y = sin(2π * 256 * t)

在某一时刻,t = 0 时,sin(0) = 0t = 1/256 时,sin(2π) = 0,等等。

如果你突然从 256Hz 切换到 512Hz:

y = sin(2π * 512 * t)

这时,相位的变化会更加快速。假如没有正确处理相位,那么切换时,新的频率可能从一个不连续的位置开始。例如,之前的正弦波刚刚完成一个周期,而新的频率波形从零交点开始,从而导致两个波形之间的断裂感(即“呲”声)。

6. 避免相位跳变的方法:

  • 记录当前的相位:在频率切换时,记录下当前时刻的相位,然后确保新的频率从该相位继续播放。例如,如果你在 t = 0.1s 时切换频率,可以将当前的相位(例如 2π * 256 * 0.1)保存下来,切换到新的频率时,新的波形从相同的相位位置继续计算。

  • 平滑过渡:在频率变化的过程中,使用渐变方式逐步过渡到目标频率,这样可以避免相位的突变。例如,可以在每个采样周期调整频率增量,而不是直接跳到新频率。

通过这些方法,可以避免频率切换时产生不自然的“呲”声或毛刺声。

在这里插入图片描述

为了解决这个问题
在这里插入图片描述

下面用模拟手柄 StickY 对 上面代码进行测试

基于 AButton 按钮的操作来改变音频频率(ToneHz)和音频波形的周期(WavePeriod),并可能结合了控制器的 Y 轴摇杆 (StickY) 来微调频率。

更新 ToneHz(音频频率)

 // 获取摇杆的 X 和 Y 坐标值(-32768 到 32767)
  int16 StickX = Pad->sThumbLX;
  int16 StickY = Pad->sThumbLY;

  // 根据摇杆的 Y 坐标值调整音调和声音
  xOffset += StickX >> 12;
  yOffset += StickY >> 12;

  // 更新音调频率 (ToneHz),通过摇杆的 Y 值来调节
  // 这里是将 StickY 映射到频率范围内,使得频率与摇杆的上下运动相关。
  // 512 是基准频率,StickY 值影响音频频率的变化范围。
  SoundOutput.ToneHz =
      512 + (int)(256.0f * ((real32)StickY / 30000.0f));
  // 计算波周期,基于频率,决定波形的周期
  SoundOutput.WavePeriod =
      SoundOutput.SamplesPerSecond / SoundOutput.ToneHz;
  std::cout << "ToneHz " << SoundOutput.ToneHz << " sThumbLY "
            << StickY << std::endl; // 输出音调频率和摇杆值
  • SoundOutput.ToneHz = 512 + (int)(256.0f * ((real32)StickY / 30000.0f));

    • 这行代码根据摇杆的 Y 值 (StickY) 动态计算音频的频率 ToneHz
    • StickY 的值范围是 -32768 到 32767(即摇杆的 Y 轴范围)。将它除以 30000.0f 来归一化到[-1, 1],然后乘以 256.0f 来决定音频频率变化的幅度。
    • 512 是基准频率,通过摇杆的上下动作来改变频率。
  • SoundOutput.WavePeriod = SoundOutput.SamplesPerSecond / SoundOutput.ToneHz;

    • 这行代码计算音频波的周期。波周期是根据音频的采样率 (SamplesPerSecond) 和音调频率 (ToneHz) 来决定的。波周期越短,频率越高,声音听起来越尖锐。

在这里插入图片描述

上面的测试中会出现延时的现象,键盘按下到音频改变有延时

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/916581.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C#设计模式(12)——享元模式(Flyweight Pattern)

前言 享元模式通过共享对象来减少内存使用和提高性能。 代码 public abstract class Flyweight {public abstract void Control(); }public class ComputerFlyweight : Flyweight {private string _operator;public ComputerFlyweight(string name){_operator name;}public o…

upload-labs通关练习

目录 环境搭建 第一关 第二关 第三关 第四关 第五关 第六关 第七关 第八关 第九关 第十关 第十一关 第十二关 第十三关 第十四关 第十五关 第十六关 第十七关 第十八关 第十九关 第二十关 总结 环境搭建 upload-labs是一个使用php语言编写的&#xff0c…

【云原生系列--Longhorn的部署】

Longhorn部署手册 1.部署longhorn longhorn架构图&#xff1a; 1.1部署环境要求 kubernetes版本要大于v1.21 每个节点都必须装open-iscsi &#xff0c;Longhorn依赖于 iscsiadm主机为 Kubernetes 提供持久卷。 apt-get install -y open-iscsiRWX 支持要求每个节点都安装 N…

Elastic Agent:可灵活地在任何地方发送和处理任何数据

作者&#xff1a;来自 Elastic Nima Rezainia Elastic Agent 是一款功能强大且用途广泛的工具&#xff0c;可用于从各种数据源&#xff08;包括自定义用户应用程序&#xff09;收集日志和指标。现在&#xff0c;Elastic Agent 提供了无与伦比的灵活性&#xff0c;可以将数据准确…

一、HTML

一、基础概念 1、浏览器相关知识 这五个浏览器市场份额都非常大&#xff0c;且都有自己的内核。 什么是内核&#xff1a; 内核是浏览器的核心&#xff0c;用于处理浏览器所得到的各种资源。 例如&#xff0c;服务器发送图片、视频、音频的资源&#xff0c;浏览…

IDEA旗舰版编辑器器快速⼊门(笔记)

简介&#xff1a;javaweb开发必备软件之IDEA期间版介绍 DEA编辑器器版本介绍 官⽹网&#xff1a;https://www.jetbrains.com/地址&#xff1a;https://www.jetbrains.com/idea/download/#sectionmac DEA 分社区版(Community) 和 旗舰版(Ultimate)&#xff0c;我们做JavaWeb开…

【鸿蒙开发】第十五章 H5与端侧交互、Cookies以及Web调试

目录 1. H5与端侧交互 1.1 应用侧调用前端页面函数 1.2 前端页面调用应用侧函数 1.2.1 复杂类型使用方法 1.3 建立应用侧与前端页面数据通道 2 管理页面跳转及浏览记录导航 2.1 历史记录导航 2.2 页面跳转 2.3 跨应用跳转 3 管理Cookie及数据存储 3.1 Cookie管理 3…

【优选算法】双指针

目录 一、[移动零](https://leetcode.cn/problems/move-zeroes/description/)二、[复写零](https://leetcode.cn/problems/duplicate-zeros/description/)三、[快乐数](https://leetcode.cn/problems/happy-number/)四、 [盛最多水的容器](https://leetcode.cn/problems/contai…

C++常用的特性-->day05

友元的拓展语法 声明一个类为另外一个类的友元时&#xff0c;不再需要使用class关键字&#xff0c;并且还可以使用类的别名&#xff08;使用 typedef 或者 using 定义&#xff09;。 #include <iostream> using namespace std;// 类声明 class Tom; // 定义别名 using …

Vue3 + Vite 构建组件库的整体流程

Vue3 Vite 构建组件库的流程 本文教你如何用 Vue Vite&#xff0c;一步一步构建一个组件库并发布到 npm 的整体流程 1. 通过 vite 命令创建一个基本的项目结构&#xff08;这里选用 vue ts 的项目&#xff09; npm create vitelatest2. 在项目中创建一个 lib 目录&#xf…

Ubuntu22.04.2 k8s部署

k8s介绍 简单介绍 通俗易懂的解释&#xff1a; Kubernetes&#xff08;也被称为 K8s&#xff09;就像是一个大管家&#xff0c;帮你管理你的云计算服务。想象一下&#xff0c;你有很多个小程序&#xff08;我们称之为“容器”&#xff09;&#xff0c;每个都在做不同的事情&…

UniApp的Vue3版本中H5配置代理的最佳方法

UniApp的Vue3版本中H5项目在本地开发时需要配置跨域请求调试 最开始在 manifest.json中配置 总是报404&#xff0c;无法通过代理请求远程的接口并返回404错误。 经过验证在项目根目录创建 vite.config.js文件 vite.config.js内容: // vite.config.js import {defineConfig }…

Android OpenGL ES详解——实例化

目录 一、实例化 1、背景 2、概念 实例化、实例数量 gl_InstanceID 应用举例 二、实例化数组 1、概念 2、应用举例 三、应用举例——小行星带 1、不使用实例化 2、使用实例化 四、总结 一、实例化 1、背景 假如你有一个有许多模型的场景&#xff0c;而这些模型的…

2024数维杯问题C:脉冲星定时噪声推断和大气时间信号的时间延迟推断的建模完整思路 模型 代码结果

&#xff08;Modeling of pulsar timing noise deduction and atmospheric time delay deduction of time signals&#xff09; 脉冲星是一种连续而稳定的快速旋转的中子星&#xff0c;为它们赢得了“宇宙的李温室”的绰号。脉冲星的空间观测对深空航天器的导航和时间标准的维…

Shell基础2

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团…

基于微信小程序的校园超市购物系统设计与实现,LW+源码+讲解

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本超市购物系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&a…

【golang-技巧】-线上死锁问题排查-by pprof

1.背景 由于目前项目使用 cgo golang 本地不能debug, 发生死锁问题&#xff0c;程序运行和期待不一致&#xff0c;通过日志排查可以大概率找到 阻塞范围&#xff0c;但是不能找到具体问题在哪里&#xff0c;同时服务器 通过k8s daemonset 部署没有更好的方式暴露端口 获取ppr…

【Visual Studio】设置文件目录

打开属性 输出目录&#xff1a;$(SolutionDir)bin\$(Platform)\$(Cinfiguration)\ 中间目录&#xff1a;$(SolutionDir)bin\intermediates\$(Platform)\$(Cinfiguration)\

智谱AI清影升级:引领AI视频进入音效新时代

前几天智谱推出了新清影,该版本支持4k、60帧超高清画质、任意尺寸&#xff0c;并且自带音效的10秒视频,让ai生视频告别了"哑巴时代"。 智谱AI视频腾空出世&#xff0c;可灵遭遇强劲挑战&#xff01;究竟谁是行业翘楚&#xff1f;(附测评案例)之前智谱出世那时体验了一…

Datawhale模型压缩技术Task2之模型剪枝

模型剪枝 模型剪枝介绍何为剪枝&#xff08;What is Pruning?&#xff09;剪枝类型非结构化剪枝结构化剪枝半结构化剪枝 剪枝范围局部剪枝全局剪枝 剪枝粒度细粒度剪枝基于模式的剪枝向量级剪枝内核级剪枝通道级剪枝 为何剪枝&#xff08;Why Pruning?&#xff09;剪枝标准&a…