openFrameworks periodicSignalsExample 详解:用正弦、噪声、随机与取模绘制周期信号
图形学音视频【免费下载链接】openFrameworksopenFrameworks is a community-developed cross platform toolkit for creative coding in C.项目地址https://gitcode.com/gh_mirrors/op/openFrameworks点击查看免费下载导读periodicSignalsExample是 openFrameworks 官方示例库中位于examples/math/目录下的一个教学示例它用 8 条水平移动的轨迹直观对比了四类周期信号生成方式三角函数sin、柏林噪声ofNoise/ofSignedNoise、真随机ofRandom以及浮点取模fmod。通过阅读本文你将掌握这些信号函数在 openFrameworks 中的底层实现与取值范围差异理解“随机 ≠ 噪声”“伪随机噪声带缓动”的核心区别并学会用滑块实时调整振幅、速度与频率来观察每种信号的形态特征。这对于制作粒子系统、运动动画、程序化生成等创意编码场景都极具参考价值。示例概述与运行方式本示例的完整源码位于 examples/math/periodicSignalsExample核心文件为 ofApp.cpp 与 ofApp.h另附带一个自定义的 ofxSimpleSlider 滑块控件由 Golan Levin 于 2012 年编写。窗口尺寸在 main.cpp 中设置为1024 x 600标准窗口模式OF_WINDOW。应用启动后画面上会出现8 条水平移动的轨迹每条轨迹对应一种不同的周期信号函数右侧标注有函数名称。底部的时间轴刻度以秒s或像素p为单位标记当前 x 位置右上角实时显示帧率fps、运行时间t与当前 x 坐标便于对照观察。八种周期信号的核心实现在 ofApp.cpp 的update()中示例以运行时间t通过ofGetElapsedTimef()获取并减去初始时间得到作为输入为每条轨迹计算y值。时间变量t的求法为t ofGetElapsedTimef(); if(trail[0].size()0){ initTime t; } t t - initTime;而水平位置x由速度滑块的值与时间共同决定并取模限制在窗口宽度内x int(t*speed.getValue())%(ofGetWidth()-rightMargin);1. constant —— 常量基线y[0] 60*2;在setup()中直接赋值为常量代表一条水平的直线基线用于与其他波动信号形成参照。2. ofNoise(t) —— 柏林噪声0 ~ 1y[1] 60*3ofNoise(t*freq.getValue())*yFactor.getValue();ofNoise()基于柏林噪声Perlin noise算法返回0 到 1.0 之间的连续伪随机值。查看 ofMath.cpp 的底层实现可以看到float ofNoise(float x) { return _slang_library_noise1(x) * 0.5f 0.5f; }它先调用底层的_slang_library_noise1()值域约为 -1 ~ 1再通过* 0.5 0.5映射到 [0, 1] 区间。所谓“伪随机带缓动”是指噪声函数在相邻输入之间会产生平滑过渡的渐变值而非毫无关联的跳变因此适合模拟自然、有机的运动。3. ofSignedNoise(t) —— 带符号噪声-1 ~ 1y[2] 60*4ofSignedNoise(t*freq.getValue())*yFactor.getValue();ofSignedNoise()与ofNoise()共享同一个噪声内核但不做 0.5 偏移直接返回原始噪声值值域为-1.0 到 1.0float ofSignedNoise(float x) { return _slang_library_noise1(x); }两者对比如下函数底层调用值域用途特点ofNoise(x)_slang_library_noise1(x) * 0.5f 0.5f[0, 1]适合 alpha、比例等非负参数ofSignedNoise(x)_slang_library_noise1(x)[-1, 1]适合位移、旋转等对称变化在 ofMath.h 中两者都提供了 1~4 维重载分别接受float、glm::vec2、glm::vec3、glm::vec4参数。4. ofRandom(-1,1) —— 真随机-1 ~ 1y[3] 60*5ofRandom(-1,1)*yFactor.getValue(); // random cant be dependent on time or frequencyofRandom(min, max)返回 min 与 max 之间完全随机的浮点数每次调用结果彼此独立、没有连续性。其实现见 ofMath.cppfloat ofRandom(float min, float max) { return of::random::uniformfloat(min, max); }ofRandom与噪声函数有着本质区别噪声是伪随机但连续相邻值平滑过渡而ofRandom是完全不连续的跳跃值。因此示例代码特意注释“random cant be dependent on time or frequency”——由于随机值不受时间与频率影响这条轨迹看起来会不断跳变无法形成平滑的波形。5. sin(t) —— 标准正弦波-1 ~ 1y[4] 60*6 std::sin(t*freq.getValue()*glm::two_pifloat())*yFactor.getValue();这是最经典的周期信号。glm::two_pifloat()即 2π将时间乘以 2π 后每经过 1 秒恰好完成一个完整的正弦周期频率滑块的值单位 Hz直接决定每秒的振荡次数。返回值在-1 到 1 之间平滑往返。6. (sin(t)1)/2 —— 正弦波归一化0 ~ 1y[5] 60*7(std::sin(t*freq.getValue()*glm::two_pifloat())1)*.5*yFactor.getValue();将标准正弦结果1后除以 2把值域从 [-1, 1] 线性映射到[0, 1]方便驱动透明度、颜色分量等非负参数。从源码结构看这与ofNoise对底层噪声做* 0.5 0.5映射的思路如出一辙。7. fmod(t, 1) —— 浮点取模0 ~ 1y[6] 60*8std::fmod(t*freq.getValue(),1)*yFactor.getValue();std::fmod(a, b)返回 a 除以 b 的浮点余数。fmod(t, 1)的输出始终落在[0, 1)波形呈锯齿状每经过 1 个时间单位归零并重新攀升。它与整数取模运算符%语义相同但专门用于浮点数——这正是 README 中强调fmod“is the same as using %; however, it is for floats”的原因。8. fmod(t, 1)*2-1 —— 双锯齿波-1 ~ 1y[7] 60*9(std::fmod(t*freq.getValue(),1)*2-1)*yFactor.getValue();在fmod(t, 1)的基础上乘以 2 再减 1将值域映射到[-1, 1]形成上下对称的双向锯齿波。滑块实时控制振幅、速度与频率三个滑块的配置在setup()中创建了三个 ofxSimpleSlider 实例分别控制垂直振幅y amnt、水平速度x speed与频率frequencyyFactor.setup(130, 20, 100, 20, 0, 100, 20, false, false); yFactor.setLabelString(y amnt); speed.setup(130, 45, 100, 20, 1, 200, 30, false, false); speed.setLabelString(x speed (px/s)); freq.setup(130, 70, 100, 20, 0, 10, 1, false, false); freq.setLabelString(frequency (hz));setup()的完整参数签名为setup(float inx, float iny, float inw, float inh, float loVal, float hiVal, float initialPercent, bool bVert, bool bDrawNum)前 4 个参数是滑块的位置与尺寸loVal/hiVal是取值范围initialPercent为初始值内部通过ofMap映射为百分比并ofClamp到 [0,1]bVert表示是否垂直放置bDrawNum表示是否绘制数值。本例三个滑块均水平放置、不显示数值。各滑块参数汇总滑块标签取值范围默认值作用yFactory amnt0 ~ 10020信号的振幅垂直幅度speedx speed (px/s)1 ~ 20030轨迹的水平滚动速度像素/秒freqfrequency (hz)0 ~ 101信号的频率每秒周期数滑块的底层实现ofxSimpleSlider是一个不依赖任何 addon 的轻量滑块类其核心机制是setup()时通过ofAddListener把自己注册到ofEvents()的draw、mouseMoved、mousePressed、mouseReleased、mouseDragged事件上见 ofxSimpleSlider.cpp此后无需在ofApp中手动转发事件。拖拽时updatePercentFromMouse()把鼠标坐标映射为 0~1 的百分比void ofxSimpleSlider::updatePercentFromMouse (int mx, int my){ if (bVertical){ percent ofMap(my, y, yheight, 1,0, true); } else { percent ofMap(mx, x, xwidth, 0,1, true); } }读取当前值时再由百分比反向映射到loVal与hiVal之间float ofxSimpleSlider::getValue(){ // THIS IS THE MAIN WAY YOU GET THE VALUE FROM THE SLIDER! float out ofMap(percent, 0,1, lowValue,highValue, true); return out; }速度变化的轨迹清空机制update()中对速度变化做了特殊处理由于不能直接比较浮点数的相等性speed.getValue() ! preSpeed不可靠示例改用“变化量大于极小阈值”的方式检测if( fabs(speed.getValue() - preSpeed) 0.00001f ){ speedChanged(); } preSpeed speed.getValue();一旦速度改变speedChanged()会清空所有轨迹折线避免不同速度下的轨迹在同一个 x 轴上错位重叠void ofApp::speedChanged(){ for(unsigned int i0;itrail.size();i){ trail[i].clear(); } }此外由于x int(t*speed) % (ofGetWidth()-rightMargin)存在取模回绕当x小于上一帧的prevX时即发生回绕也会主动清空轨迹形成“换行重画”的效果for(int i0;i(int)trail.size();i){ if(xprevX){ trail[i].clear(); }else{ trail[i].addVertex(x,y[i]); } } prevX x;绘制细节轨迹、网格与标签draw()见 ofApp.cpp完成了以下绘制工作渐变背景使用ofBackgroundGradient(ofColor(240), ofColor(210), OF_GRADIENT_BAR)生成从浅灰到中灰的垂直渐变时间刻度线在左侧区域按speed值绘制垂直虚线底部标注以秒s或像素p为单位的刻度showPos布尔值控制刻度单位显示8 条轨迹每条轨迹用一个ofPolyline存储顶点序列并调用trail[i].draw()绘制轨迹头部绘制一个半径为 3 的圆点ofDrawCircle(x, y[i], radius)绘制时启用ofEnableSmoothing()抗锯齿绘制后关闭分隔线每条轨迹之间以水平直线分隔每条轨迹 60 像素的垂直间距右侧标签在右侧预留的 190 像素边距rightMargin 190内用ofDrawBitmapString标注每条轨迹对应的函数名例如constant、ofNoise(t)、ofSignedNoise(t)、ofRandom(-1,1)、sin(glm::two_pifloat()*t)、(sin(glm::two_pifloat()*t)1)/2、modulo(t,1)、modulo(t,1)*2-1状态信息右上角实时显示fps、运行时间t与当前位置x振幅指示每个轨迹右侧绘制一条从分隔线到当前y值的小矩形直观表示振幅大小。操作指南与关键注意事项交互方式应用运行后用鼠标直接拖拽右侧三个滑块即可实时调节y amnt振幅控制所有信号轨迹的垂直摆动幅度范围为 0 ~ 100x speed (px/s)速度控制轨迹水平滚动的速度范围为 1 ~ 200 像素/秒改变速度会触发轨迹清空重绘frequency (hz)频率控制每种周期信号的振荡频率范围为 0 ~ 10 Hz。需要特别注意的点ofRandom不依赖时间与频率由于随机值每次调用都是独立跳变改变频率滑块对它没有平滑效果这正是随机信号与噪声、三角函数最直观的差异。噪声 ≠ 随机ofNoise/ofSignedNoise是连续平滑的伪随机缓动适合有机运动ofRandom是离散跳变适合无规律的抖动。浮点比较陷阱不要用/!直接比较浮点滑块值应像示例那样使用阈值判断fabs(a - b) 0.00001f。值域决定用途0~1 的信号ofNoise、(sin1)/2、fmod(t,1)适合驱动比例类参数-1~1 的信号ofSignedNoise、sin、ofRandom(-1,1)、fmod(t,1)*2-1适合驱动位移、旋转等双向变化。延伸阅读三角函数专题examples/math/trigonometryExample与examples/math/trigonometricMotionExample后者同样位于 examples/mathREADME 中对三角函数的推荐深入阅读随机与噪声的更多组合玩法noise1dExample、noise1dOctaveExample、noiseField2dExample 与 randomExample运动应用实战particlesExample 展示了如何将周期与噪声信号用于粒子系统底层数学实现ofNoise/ofSignedNoise/ofRandom等函数的源码位于 libs/openFrameworks/math/ofMath.cpp 与 libs/openFrameworks/math/ofMath.h。通过运行本示例并拖动三个滑块你可以直观地感受到“平滑周期”“平滑伪随机”“离散随机”“锯齿周期”四类信号的形态差异——这是理解 openFrameworks 运动与生成式创作的重要基础。赞分享图形学音视频【免费下载链接】openFrameworksopenFrameworks is a community-developed cross platform toolkit for creative coding in C.项目地址https://gitcode.com/gh_mirrors/op/openFrameworks点击查看免费下载相关推荐GNU Radio信号源模块终极指南如何快速生成随机噪声、正弦波和方波信号GNU Radio信号源模块终极指南如何快速生成随机噪声、正弦波和方波信号 想要在GNU Radio中快速生成各种信号吗GNU Radio作为免费开源的软件通信科研Easy Effects 测试信号Test Signal完全指南用正弦波与噪声信号测量音箱频响Easy Effects 测试信号Test Signal完全指南用正弦波与噪声信号测量音箱频响 Easy Effects 内置的 Test Signal桌面应用音频处理Agent OS 信号处理机制详解用 POSIX 风格信号实现 AI Agent 生命周期治理Agent OS 信号处理机制详解用 POSIX 风格信号实现 AI Agent 生命周期治理 Agent OSagent governance toolk人工智能AI AgentAI 安全治理策略引擎Agent 沙箱认证鉴权上一篇VnCoreNLP二次开发指南自定义annotator扩展越南语NLP流水线下一篇超强大屏体验iCarousel打造iOS/MacOS双平台3D轮播组件创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

PaddleNLP LayoutXLMTokenizer 深度解析:基于 SentencePiece 的多模态文档理解分词器

PaddleNLP LayoutXLMTokenizer 深度解析:基于 SentencePiece 的多模态文档理解分词器

人工智能大模型预训练微调LoRARLHF强化学习分布式训练 【免费下载链接】PaddleNLP Easy-to-use and powerful LLM and SLM library with awesome model zoo. 项目地址: https://gitcode.com/gh_mirrors/pa/PaddleNLP 点击查看 免费下载 导读 本文以 PaddleNLP 仓库…

2026/9/25 17:39:55 阅读更多 →
GitHub Actions CI/CD 速查手册:Workflow 语法、事件触发与自动化实战(Reference 项目指南)

GitHub Actions CI/CD 速查手册:Workflow 语法、事件触发与自动化实战(Reference 项目指南)

GitHub Actions CI/CD 速查手册:Workflow 语法、事件触发与自动化实战(Reference 项目指南) 【免费下载链接】reference ⭕ Share quick reference cheat sheet for developers. 项目地址: https://gitcode.com/gh_mirrors/re/reference …

2026/9/24 14:21:47 阅读更多 →
RDMA驱动是什么:从TCP/IP驱动痛点到内核旁路设计哲学

RDMA驱动是什么:从TCP/IP驱动痛点到内核旁路设计哲学

📑 目录 一、前言/背景 二、核心概念与设计原理 三、驱动架构与代码实现 四、数据通路与性能关键点 五、实战配置与调优 六、调试方法与工具 七、最佳实践与常见问题 八、总结与展望 摘要:本文深度剖析RDMA驱动的内核旁路设计哲学。对比TCP/IP协议栈的软…

2026/9/24 14:20:46 阅读更多 →

最新新闻

PromptX Runtime架构剖析:Docker式Agent生命周期与事件驱动SystemBus设计

PromptX Runtime架构剖析:Docker式Agent生命周期与事件驱动SystemBus设计

PromptX Runtime架构剖析:Docker式Agent生命周期与事件驱动SystemBus设计 【免费下载链接】PromptX PromptX 领先的AI 智能体上下文平台 | PromptX Leading AI Agent Context Platform 项目地址: https://gitcode.com/Deepractice/PromptX Prom…

2026/9/25 17:39:49 阅读更多 →
Ubuntu 22.04 LTS开发环境实战配置指南

Ubuntu 22.04 LTS开发环境实战配置指南

1. 这不是“又一篇Ubuntu安装教程”,而是一份我亲手踩过27次坑、重装过14台机器后整理的22.04 LTS实战手册你搜“Ubuntu 22.04 LTS安装配置”时,看到的大多是截图堆砌、命令复制粘贴、步骤编号到5就戛然而止的“半成品”。有人装完连中文输入法都打不出字…

2026/9/25 17:39:49 阅读更多 →
Lottery 抽奖系统部署实战:Docker 安装 Nacos 注册中心并接入 Dubbo 服务注册

Lottery 抽奖系统部署实战:Docker 安装 Nacos 注册中心并接入 Dubbo 服务注册

文档教程后端 【免费下载链接】CodeGuide :books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总,旨在为大家提供一个清晰详细的学习教程,侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助,请给予支持(关注、…

2026/9/25 17:39:49 阅读更多 →
使用 GDB 与 SWD 调试探针对 PX4 固件进行交互式调试:从连接到实战

使用 GDB 与 SWD 调试探针对 PX4 固件进行交互式调试:从连接到实战

嵌入式物联网机器人自动驾驶智能硬件 【免费下载链接】PX4-Autopilot PX4 Autopilot Software 项目地址: https://gitcode.com/gh_mirrors/px/PX4-Autopilot 点击查看 免费下载 本指南以 PX4-Autopilot 官方调试文档(gdb_debugging.md)为核心…

2026/9/25 17:39:49 阅读更多 →
RisingWave 自定义 Lint 体系实战:基于 cargo dylint 的 Rust 代码规范与 Clippy 扩展

RisingWave 自定义 Lint 体系实战:基于 cargo dylint 的 Rust 代码规范与 Clippy 扩展

数据库流处理后端数据工程 【免费下载链接】risingwave Event streaming platform for agentic AI. Continuously ingest, transform, and serve event streams in real time, at scale. 项目地址: https://gitcode.com/gh_mirrors/ri/risingwave 点击查看 免费下载…

2026/9/25 17:39:48 阅读更多 →
AI提示词帮你搞定任务优先级排序,告别决策瘫痪

AI提示词帮你搞定任务优先级排序,告别决策瘫痪

1. 为什么“事情太多先做什么”是个真问题你有没有过这种早晨:闹钟响了第三遍才爬起来,手机一解锁,微信未读99,邮箱里躺着三封标红的“紧急”,待办清单上密密麻麻列了二十多条,脑子里同时转着“下午要交周报…

2026/9/25 17:38:48 阅读更多 →

日新闻

AI元人文:从工具使用到思维重构的深度探索

AI元人文:从工具使用到思维重构的深度探索

最近半年我一直在琢磨一件事:AI元人文到底是什么?说白了,就是“用元视角重新审视人与AI的关系”,也在“探索AI如何反向逼着我们发现自己的思考边界”。标题里的“元探索”,在我看就是一层套一层的追问——当你用AI解决…

2026/9/25 0:00:41 阅读更多 →
Python+CNN车牌识别实战:从数据预处理到模型训练与部署

Python+CNN车牌识别实战:从数据预处理到模型训练与部署

简介:基于Python与卷积神经网络的车牌识别项目,面向计算机视觉初学者及智能交通开发者,目标是帮助用户掌握从数据预处理、模型构建到实际部署的完整流程。压缩包共25个文件,包含jpg/png图像样本、py训练脚本、md说明文档、dat数据…

2026/9/25 0:00:41 阅读更多 →
Vim基础操作全攻略:保存退出、模式切换与高频命令实战

Vim基础操作全攻略:保存退出、模式切换与高频命令实战

1. 项目概述1.1 核心需求解析今天聊聊Vim。写这个题目的原因是:几乎每个后端开发者、运维人员、数据工程师某天都会遇到一个场景——深夜加班,服务器登录界面只有黑底白字,编辑器只有vi/vim,你必须在五分钟内完成一次配置修改并保…

2026/9/25 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/25 11:15:26 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →