MAX/MSP SDK学习09:重要示例1

news2024/12/25 1:08:57

本示例涉及到单个MSP对象同时使用Signal类型、Message类型的入口;代理入口的使用。

注意:MSP对象的入口默认为代理入口,因此Signal类型、Message类型的数据都可接收;

#include "ext.h"			
#include "ext_obex.h"		
#include "z_dsp.h"			

typedef struct _butterFilterTest {
	t_pxobject		ob;			// the object itself (t_pxobject in MSP instead of t_object)

	long iirOrder;			// 滤波器阶数   n
	t_atom* iirState;		// 存储滤波器状态   n
	int fltStateParaNum;	// 滤波器状态参数个数   n

	t_atom* a;				// 滤波器参数a   (n+1)
	t_atom* b;				// 滤波器参数b
	int fltParaNum;			// 滤波器参数个数    (n+1)

	int sampleframes;    // 帧大小

	long lastVectorSize; // 用以判定signal vector size是否有变
	//void* outLet;

	/*** 用以测试 ***/
	t_atom* sigList;     // 存储滤波后的单帧信号
	t_atom* tmpList;     // 暂存到来的单帧信号
	/***************/
} t_butterFilterTest;

void* butterFilterTest_new(t_symbol* s, long argc, t_atom* argv);
void butterFilterTest_free(t_butterFilterTest* x);
void butterFilterTest_assist(t_butterFilterTest* x, void* b, long m, long a, char* s);
void butterFilterTest_dsp64(t_butterFilterTest* x, t_object* dsp64, short* count, double samplerate, long maxvectorsize, long flags);
void butterFilterTest_perform64(t_butterFilterTest* x, t_object* dsp64, double** ins, long numins, double** outs, long numouts, long sampleframes, long flags, void* userparam);
void butterFilterTest_perform64_list(t_butterFilterTest* x, t_object* dsp64, double** ins, long numins, double** outs, long numouts, long sampleframes, long flags, void* userparam);
void butterFilterTest_feed(t_butterFilterTest* x, t_double* inSig, int sampleframes);

void butterFilterTest_recvList(t_butterFilterTest* x, t_symbol* s, long argc, t_atom* argv);
void butterFilterTest_feed_test(t_butterFilterTest* x, long sampleframes);

static t_class* butterFilterTest_class = NULL;

void ext_main(void* r) {
	t_class* c = class_new("butterFilterTest~", (method)butterFilterTest_new, (method)butterFilterTest_free, (long)sizeof(t_butterFilterTest), 0L, A_GIMME, 0);

	class_addmethod(c, (method)butterFilterTest_dsp64, "dsp64", A_CANT, 0);
	class_addmethod(c, (method)butterFilterTest_assist, "assist", A_CANT, 0);
	class_addmethod(c, (method)butterFilterTest_recvList, "list", A_GIMME, 0);

	class_dspinit(c); // 初始化 & 加入通用处理方法
	class_register(CLASS_BOX, c);
	butterFilterTest_class = c;
}

void* butterFilterTest_new(t_symbol* s, long argc, t_atom* argv) {
	t_butterFilterTest* x = (t_butterFilterTest*)object_alloc(butterFilterTest_class);

	dsp_setup((t_pxobject*)x, 3);	// MSP inlets: arg is # of inlets and is REQUIRED!  信号入口数为1,3则信号入口数为3
	// use 0 if you don't need inlets
	outlet_new(x, "signal"); 		// signal outlet (note "signal" rather than NULL)   信号出口
	//x->outLet = listout(x);

	x->a = NULL;
	x->b = NULL;
	x->fltParaNum = 0;

	x->iirState = NULL;
	x->fltStateParaNum = 0;

	x->sigList = NULL;
	x->tmpList = NULL;

	x->lastVectorSize = 0;
	return (x);
}

void butterFilterTest_free(t_butterFilterTest* x) {
	dsp_free((t_pxobject*)x);
	sysmem_freeptr(x->a);
	sysmem_freeptr(x->b);
	sysmem_freeptr(x->iirState);
	sysmem_freeptr(x->sigList);
	sysmem_freeptr(x->tmpList);
}

void butterFilterTest_assist(t_butterFilterTest* x, void* b, long m, long a, char* s) {
	if (m == ASSIST_INLET) { //inlet
		sprintf(s, "I am inlet %ld", a);
	} else {	// outlet
		sprintf(s, "I am outlet %ld", a);
	}
}

void butterFilterTest_recvList(t_butterFilterTest* x, t_symbol* s, long argc, t_atom* argv) {
	long inNum = proxy_getinlet((t_object*)x);
	post("inNum: %d. list recv.", inNum);

	x->iirOrder = argc - 1;				// 滤波器阶数
	x->fltStateParaNum = argc - 1;		// 滤波器状态参数个数

	if (x->a == NULL || x->fltParaNum != argc) {
		if (x->a != NULL) {
			sysmem_freeptr(x->a);
			sysmem_freeptr(x->iirState);
		}
		x->a = (t_atom*)sysmem_newptr(sizeof(t_atom) * argc);
		x->iirState = (t_atom*)sysmem_newptr(sizeof(t_atom) * x->fltStateParaNum);
		if (x->a == NULL || x->iirState == NULL) {
			return;
		}
	}

	if (x->b == NULL || x->fltParaNum != argc) {
		if (x->b != NULL) {
			sysmem_freeptr(x->b);
		}
		x->b = (t_atom*)sysmem_newptr(sizeof(t_atom) * argc);
		if (x->b == NULL) {
			return;
		}
	}
	x->fltParaNum = argc;				// 更新滤波器参数个数

	switch (inNum) {
	case 0:
		post("List size: %d", argc);
		for (int i = 0; i < argc; i++) {
			atom_setfloat(&(x->tmpList[i]), atom_getfloat(&(argv[i])));
		}
		break;
	case 1:
		post("List size: %d", argc);
		for (int i = 0; i < argc; i++) {
			atom_setfloat(&(x->a[i]), atom_getfloat(&(argv[i])));
		}
		post("AAAA");
		for (int i = 0; i < argc; i++) {
			post("%lf", atom_getfloat(&(x->a[i])));
		}
		break;
	case 2:
		post("List size: %d", argc);
		for (int i = 0; i < argc; i++) {
			atom_setfloat(&(x->b[i]), atom_getfloat(&(argv[i])));
		}
		post("AAAA");
		for (int i = 0; i < argc; i++) {
			post("%lf", atom_getfloat(&(x->a[i])));
		}
		post("BBB");
		for (int i = 0; i < argc; i++) {
			post("%lf", atom_getfloat(&(x->b[i])));
		}
		post("recv iirState:");
		for (int i = 0; i < x->fltStateParaNum; i++) {
			post("%lf", atom_getfloat(&(x->iirState[i])));
		}
		break;
	}
}

// registers a function for the signal chain in Max
void butterFilterTest_dsp64(t_butterFilterTest* x, t_object* dsp64, short* count, double samplerate, long maxvectorsize, long flags) {
	post("my sample rate is: %f,vector size is: %ld", samplerate, maxvectorsize);   // 和Audio status中设置相同
	x->sampleframes = maxvectorsize;
	/* 滤波器状态初始化*/
	for (int i = 0; i < x->fltStateParaNum; i++) {
		atom_setfloat(&(x->iirState[i]), 0);
	}

	post("dsp64 iirstate:");
	for (int i = 0; i < x->fltStateParaNum; i++) {
		post("%lf", atom_getfloat(&(x->iirState[i])));
	}

	if (x->sigList == NULL || x->lastVectorSize != maxvectorsize) {
		if (x->sigList != NULL) {
			sysmem_freeptr(x->sigList);
		}
		x->sigList = (t_atom*)sysmem_newptr(sizeof(t_atom) * maxvectorsize);
		if (x->sigList == NULL) {
			return;
		}
	}
	if (x->tmpList == NULL || x->lastVectorSize != maxvectorsize) {
		if (x->tmpList != NULL) {
			sysmem_freeptr(x->tmpList);
		}
		x->tmpList = (t_atom*)sysmem_newptr(sizeof(t_atom) * maxvectorsize);
		if (x->tmpList == NULL) {
			return;
		}
	}
	x->lastVectorSize = maxvectorsize;

	post("%d", count[0]);
	post("%d", count[1]);

	if (count[0]) {
		post("Signal come.");
		object_method(dsp64, gensym("dsp_add64"), x, butterFilterTest_perform64, 0, NULL);
	} else {
		//post("List come.");
		//object_method(dsp64, gensym("dsp_add64"), x, butterFilterTest_perform64_list, 0, NULL);
	}

	if (count[1]) {}
	if (count[2]) {}
}

/*******************************************************逐帧验证**********************************************************/
void butterFilterTest_perform64_list(t_butterFilterTest* x, t_object* dsp64, double** ins, long numins, double** outs, long numouts,
	long sampleframes, long flags, void* userparam) {
	butterFilterTest_feed_test(x, sampleframes);
	//outlet_anything(x->outLet, gensym("list"), x->sampleframes, x->sigList);
	//post("%lf, %lf", x->iirState[0], x->iirState[1]);
}

void butterFilterTest_feed_test(t_butterFilterTest* x, long sampleframes) {
	//post("%lf, %lf", x->iirState[0], x->iirState[1]);
	for (int k = 0; k < x->fltParaNum; k++) { //归一化
		atom_setfloat(&(x->b[k]), atom_getfloat(&(x->b[k])) / atom_getfloat(&(x->a[0])));
		atom_setfloat(&(x->a[k]), atom_getfloat(&(x->a[k])) / atom_getfloat(&(x->a[0])));
	}
	//Sleep(2000);
	for (int i = 0; i < sampleframes; i++) {
		atom_setfloat(&(x->sigList[i]), (atom_getfloat(&(x->b[0])) * atom_getfloat(&(x->tmpList[i])) + atom_getfloat(&(x->iirState[0]))));
		//post("sampleframs:%d, x->sigList[%d]: %lf, x->tmpList[%d]: %lf, x->iirState[0]: %lf", sampleframes, i, atom_getfloat(&(x->sigList[i])), i, atom_getfloat(&(x->tmpList[i])), x->iirState[0]);

		for (int j = 1; j < x->fltParaNum - 1; j++) { // j = 1
			atom_setfloat(&(x->iirState[j - 1]), (atom_getfloat(&(x->iirState[j])) + atom_getfloat(&(x->b[j])) * atom_getfloat(&(x->tmpList[i])) - atom_getfloat(&(x->a[j])) * atom_getfloat(&(x->sigList[i]))));
			//x->iirState[j - 1] = x->iirState[j] + x->b[j] * atom_getfloat(&(x->tmpList[i])) - x->a[j] * atom_getfloat(&(x->sigList[i]));
		}
		atom_setfloat(&(x->iirState[x->fltParaNum - 2]), (atom_getfloat(&(x->b[x->fltParaNum - 1])) * atom_getfloat(&(x->tmpList[i])) - atom_getfloat(&(x->a[x->fltParaNum - 1])) * atom_getfloat(&(x->sigList[i]))));
		//x->iirState[x->fltParaNum - 2] = x->b[x->fltParaNum - 1] * atom_getfloat(&(x->tmpList[i])) - x->a[x->fltParaNum - 1] * atom_getfloat(&(x->sigList[i]));
	}
}
/*************************************************************************************************************************/

void butterFilterTest_perform64(t_butterFilterTest* x, t_object* dsp64, double** ins, long numins, double** outs, long numouts,
	long sampleframes, long flags, void* userparam) {  // this is the 64-bit perform method audio vectors
	t_double* inL = ins[0];		// we get audio for each inlet of the object from the **ins argument
	t_double* outL = outs[0];	// we get audio for each outlet of the object from the **outs argument
	int n = sampleframes;       // vector size

	butterFilterTest_feed(x, inL, sampleframes);

	post("perform64 iirstate:");
	for (int i = 0; i < x->fltStateParaNum; i++) {
		post("%lf", atom_getfloat(&(x->iirState[i])));
	}

	while (n--) {
		*outL++ = *inL++;
	}
}

void butterFilterTest_feed(t_butterFilterTest* x, t_double* inSig, int sampleframes) {
	for (int k = 0; k < x->fltParaNum; k++) { // 归一化
		atom_setfloat(&(x->b[k]), atom_getfloat(&(x->b[k])) / atom_getfloat(&(x->a[0])));
		atom_setfloat(&(x->a[k]), atom_getfloat(&(x->a[k])) / atom_getfloat(&(x->a[0])));
	}

	for (int i = 0; i < sampleframes; i++) {
		t_double tmp = inSig[i];
		inSig[i] = atom_getfloat(&(x->b[0])) * tmp + atom_getfloat(&(x->iirState[0]));
		for (int j = 1; j < x->fltParaNum - 1; j++) {
			atom_setfloat(&(x->iirState[j - 1]), atom_getfloat(&(x->iirState[j])) + atom_getfloat(&(x->b[j])) * tmp - atom_getfloat(&(x->a[j])) * inSig[i]);
			//x->iirState[j - 1] = atom_getfloat(&(x->iirState[j])) + atom_getfloat(&(x->b[j])) * tmp - atom_getfloat(&(x->a[j])) * inSig[i];
		}
		atom_setfloat(&(x->iirState[x->fltParaNum - 2]), atom_getfloat(&(x->b[x->fltParaNum - 1])) * tmp - atom_getfloat(&(x->a[x->fltParaNum - 1])) * inSig[i]);
		//x->iirState[x->fltParaNum - 2] = x->b[x->fltParaNum - 1] * tmp - x->a[x->fltParaNum - 1] * inSig[i];
	}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何应对网站的Canvas等高级指纹和MAC地址检测?

随着互联网技术的发展&#xff0c;网站和应用程序采用了越来越多的高级指纹和MAC地址检测技术来追踪用户和识别其身份。其中&#xff0c;Canvas指纹是一种常见的高级指纹检测技术&#xff0c;而MAC地址是设备的唯一标识符。在本文中&#xff0c;我们将了解Canvas指纹和MAC地址的…

C/C++常见面试知识总结(三)

C语言是一种通用计算机&#xff08;高级&#xff09;编程语言&#xff1b;面向过程&#xff1b;广泛应用于计算机系统设计以及应用程序编写&#xff1b;设计目标&#xff0c;是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行…

快速解决Edge浏览器常见问题:完整教程

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 目录 文章目录 前言 一、Edge浏览器是什么&#xff1f; 二、常见的问题 1. DNS服务器出错 解决方案一&#xff1a;清除浏览器缓存和Cookie 2.网络问题 3.缓存和Cook…

C# | CountdownEvent使用教程 (通过与ManualResetEvent对比,快速了解其特性)

C# CountdownEvent使用教程 对于熟悉ManualResetEvent的同学来说&#xff0c;了解CountdownEvent的差异对于更好地利用它们是非常重要的。通过对ManualResetEvent和CountdownEvent的对比&#xff0c;我们可以更好地理解CountdownEvent的特点和使用场景。 ManualResetEvent回顾…

TIM清理C盘记录

TIM文件储存的位置可以在这找到&#xff1a; 设置▶文件管理▶打开个人文件夹 这里是TIM一般的缓存位置&#xff1a; #群聊图片 \Tencent Files\对应QQ号\Image\Group2#好友图片 \Tencent Files\对应QQ号\Image\C2C#接收语音 \Tencent Files\对应QQ号\Audio#视频封面 \Tencent…

【Anaconda】Ubuntu anaconda使用(新建环境、最小化安装Tensorflow)

Ubuntu anaconda使用&#xff08;新建环境、最小化安装Tensorflow&#xff09; 清华源地址&#xff1a; https://pypi.tuna.tsinghua.edu.cn/simplepip安装使用的时候&#xff0c; pip install xxx(库名) -i https://pypi.tuna.tsinghua.edu.cn/simple请先安装好anaconda&am…

详解TCP报文格式以及TCP相关特性

✏️✏️✏️今天给大家分享的是TCP报文格式的解释以及TCP协议的一些重要特性。 清风的CSDN博客 &#x1f6e9;️&#x1f6e9;️&#x1f6e9;️希望我的文章能对你有所帮助&#xff0c;有不足的地方还请各位看官多多指教&#xff0c;大家一起学习交流&#xff01; ✈️✈️✈…

VR全景直播来临,沉浸式代入吸引百万人目光

如今&#xff0c;VR技术正在不断改变着直播行业的面貌&#xff0c;为观众提供沉浸式的观看体验。在5G技术的快速发展背景下&#xff0c;VR全景直播作为5G应用的场景&#xff0c;被广泛应用在体育赛事、新闻会议、演唱会、教育医疗等场景&#xff0c;通过VR技术进行全景直播&…

k8s详细教程(二)

—————————————————————————————————————————————— 博主介绍&#xff1a;Java领域优质创作者,博客之星城市赛道TOP20、专注于前端流行技术框架、Java后端技术领域、项目实战运维以及GIS地理信息领域。 &#x1f345;文末获取源码…

C#的线程技术及操作(Thread类)

目录 一、线程基础 1.单线程 2.多线程 &#xff08;1&#xff09;多线程的缺点 &#xff08;2&#xff09;多线程的缺点 二、线程操作之Thread类 1. Thread类的相关方法和属性 &#xff08;1&#xff09;示例源码 &#xff08;2&#xff09;生成效果 2.创建线程Star…

机器人制作开源方案 | “AIBOT”-多功能货物搬运机

作者&#xff1a;王晨曦、敖鑫、王威威、安尚琦 单位&#xff1a;北京理工大学 指导老师&#xff1a;李忠新、朱杰 一、场景调研 如今搬运机在我们的生产作业及生活中都起着比较重要的作用&#xff0c;在现代社会对升降机需求的增多&#xff0c;市场的不断扩大&#xff0c;使…

2.5 常规游戏中模型通用要求介绍

一、布线和理性 多星点&#xff08;4个及4个以上边的交点&#xff09; 如果是在中模阶段&#xff0c;减少使用多星点&#xff0c;因为会在细分是时出现凸点问题&#xff0c;如果要使用多星点&#xff0c;需要通过布线技巧把它移动至平面处&#xff0c;不要让他出现在倒角边缘。…

基于SSM医院员工考勤管理系统,请假系统,员工管理系统,部门管理系统(Java毕业设计)

大家好&#xff0c;我是DeBug&#xff0c;很高兴你能来阅读&#xff01;作为一名热爱编程的程序员&#xff0c;我希望通过这些教学笔记与大家分享我的编程经验和知识。在这里&#xff0c;我将会结合实际项目经验&#xff0c;分享编程技巧、最佳实践以及解决问题的方法。无论你是…

电流测量原理

由于直接测量电流信号是很难的&#xff0c;但是测试电压信号比较容易&#xff0c;因此通常都是先将电流信号转换为电压信号&#xff0c;将电压信号进行调理后送至 CPU&#xff0c;CPU 通过 AD 转换得到一个码值&#xff0c;软件读出该码值&#xff0c;先根据主控的硬件设计参数…

1688一件采购实现指南:含代码实现采购流程

一、引言 1688是中国最大的B2B电子商务平台之一&#xff0c;提供了丰富的商品信息和采购服务。一键采购是1688平台的一项便捷功能&#xff0c;可以帮助用户快速完成采购流程&#xff0c;提高采购效率。本文将详细介绍如何使用1688一键采购功能&#xff0c;并通过代码示例演示如…

语音群呼有哪些常见的应用场景?

事务通知提醒 银行信用卡还款通知、帐户进出帐通知等&#xff1b;供电部门电费收缴通知、客户查询、公告通知等&#xff1b;通信企业话费欠费通知。其他行业如&#xff1a;物业行业、自来水行业、人社局、法院等事务通知。 预警通知 譬如台风、防汛、防洪、地震、海啸、泥石…

AppLink+WMS,实现仓储管理一体化

WMS像全能的库管员&#xff0c;可以在线还原真实仓库&#xff0c;让企业进行科学化、条理化、俯视化的仓库管理。 随着移动互联网和物流行业的快速发展&#xff0c;如何提高仓储管理的效率和准确性成为了企业关注的焦点。在这个背景下&#xff0c;结合AppLink和WMS系统&#x…

windows 网卡设备收包禁止自动剥掉VLAN

windows网卡驱动默认会在接收数据包的时候剥掉vlan tag&#xff0c;使得用wireshark抓到的数据包中不含vlan tag&#xff0c;此时需要通过修改注册表让驱动保留vlan tag。 1. 打开网络连接 找到需要修改的网卡。属性-配置-详细信息-驱动程序关键字。复制{4d36e972-e325-11ce-…

10款AI绘画软件,一次性打包给你!

科技的发展如疾风骤雨&#xff0c;人工智能的影响已渗透到我们生活的各个角落。其中&#xff0c;艺术界同样在这股大潮中得到了翻天覆地的改变。人工智能与艺术的结合&#xff0c;开辟出了科技与艺术融合的全新视野。例如&#xff0c;人工智能绘画软件&#xff0c;这种类型的软…

使用@ExceptionHandler对数据库异常进行统一处理

使用ExceptionHandler对数据库异常进行统一处理 数据库插入异常信息,插入字段长短超时数据库设置字段长度 ### Error updating database. Cause: com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Data too long for column remark at row 1捕获异常处理…