用OSC实现纯数据与MATLAB的通信
我正在尝试接收通过OSC从纯数据(或Max/MSP)发送到MATLAB的消息用OSC实现纯数据与MATLAB的通信,matlab,udp,osc,puredata,max-msp-jitter,Matlab,Udp,Osc,Puredata,Max Msp Jitter,我正在尝试接收通过OSC从纯数据(或Max/MSP)发送到MATLAB的消息 我能够将OSC消息从纯数据发送到纯数据 我可以从MATLAB发送消息到MATLAB 我甚至可以从MATLAB向纯数据发送消息 …我真的很难得到纯数据来与MATLAB对话 下面是我从MATLAB发送消息的代码(我使用的是oscmex协议): 如果我使用主机“localhost”发送,那么使用上面的代码从MATLAB发送到MATLAB,一切都可以正常工作。如果我将其设置为“127.0.0.1”,MATLAB将发送纯数据
- 我能够将OSC消息从纯数据发送到纯数据
- 我可以从MATLAB发送消息到MATLAB
- 我甚至可以从MATLAB向纯数据发送消息
- …我真的很难得到纯数据来与MATLAB对话
/foo
表示来自MATLAB的消息,使用/test
表示来自纯数据的消息。然而,我的MATLAB代码不分青红皂白地接收通过OSC发送的所有内容,所以这没有什么区别
如果您能帮助PD与MATLAB交流,我们将不胜感激
更新:我解决了“localhost”问题,但似乎无法解决问题(我不得不将localhost添加到我的Windows“hosts”文件中)。所以,我担心localhost的事情可能是找错了方向。但是,我仍然无法让PD与MATLAB对话
更新#2:Amro在下面发布了一个优雅的解决方案,我仍然无法让MATLAB接收来自纯数据的消息。我已经安装了监控我的UDP连接,并注意到当MATLAB设置服务器时,它使用“接口”
[::0]
,而PD设置使用“接口”0.0.0
。由于PureData是成功接收消息的一个,也许我还需要让MATLAB监听0.0.0
?localhost
是127.0.0.1
的别名;它们实际上是相同的IP地址。因此,如果matlab只在发送到localhost
时接收到某些内容,而在发送到127.0.0.1
时没有接收到这些内容,那么它们可能有一个错误的OSC实现
只要补丁中有[udprective 2222]
,Pd就会阻塞端口UDP/2222,matlab将无法在该端口上接收任何内容
因此,简单的解决方案是:在使用
osc\u new\u服务器(2222)创建matlab服务器之前删除[udprective 2222]
代码>首先让我说,我以前从未使用过OSC或OSC,我只是复制了您显示的用于创建服务器/客户端的图形/补丁
1) PureData中的服务器,MATLAB中的客户端:
首先让我们在PureData中创建服务器:
下面是一个在MATLAB中作为GUI实现的简单客户端:
function example_osc_client()
handles = createGUI();
osc = [];
function h = createGUI()
h.fig = figure('Menubar','none', 'Resize','off', ...
'CloseRequestFcn',@onClose, ...
'Name','OSC Client', 'Position',[100 100 220 140]);
movegui(h.fig, 'center')
h.conn = uicontrol('Style','pushbutton', 'String','Connect', ...
'Callback',{@onClick,'connect'}, ...
'Parent',h.fig, 'Position',[20 20 80 20]);
h.disconn = uicontrol('Style','pushbutton', 'String','Disconnect', ...
'Callback',{@onClick,'disconnect'}, ...
'Parent',h.fig, 'Position',[120 20 80 20]);
h.slid = uicontrol('Style','slider', 'Callback',@onSlide, ...
'Min',-10, 'Max',10, 'Value',0, ...
'Parent',h.fig, 'Position',[30 60 160 20]);
h.txt = uicontrol('Style','text', 'String','0.0', ...
'Parent',h.fig, 'Position',[80 100 60 20]);
set([h.slid;h.disconn], 'Enable','off');
drawnow
end
function onClick(~,~,action)
switch lower(action)
case 'connect'
osc = osc_new_address('127.0.0.1', 2222);
set(handles.conn, 'Enable','off')
set(handles.disconn, 'Enable','on')
set(handles.slid, 'Enable','on')
case 'disconnect'
osc_free_address(osc); osc = [];
set(handles.conn, 'Enable','on')
set(handles.disconn, 'Enable','off')
set(handles.slid, 'Enable','off')
end
drawnow
end
function onSlide(~,~)
if isempty(osc), return; end
val = single(get(handles.slid,'Value'));
m = struct('path','/test', 'tt','f', 'data',{{val}});
osc_send(osc, m);
set(handles.txt, 'String',num2str(val))
drawnow
end
function onClose(~,~)
if ~isempty(osc)
osc_free_address(osc);
end
delete(handles.fig);
end
end
当您移动滑块时,消息被发送到服务器(使用接口),值显示在PureData模型中
在测试时,我注意到不支持double
类型,因为我在PD日志窗口中看到了以下消息:
解包OSC:PrintTypeTaggedArgs:[64位浮点]未实现
因此,有必要手动将值转换为single
,或者在传递给osc\u send
osc-MEX函数的结构中明确指定提示类型:
val = single(1);
m = struct('path','/test', 'tt','f', 'data',{{val}});
osc_send(osc, m);
2) MATLAB中的服务器,PureData中的客户端:
同样,我们在PureData中创建客户机:
同样,以下是作为MATLAB GUI实现的服务器:
function example_osc_server()
handles = createGUI();
osc = [];
function h = createGUI()
h.fig = figure('Menubar','none', 'Resize','off', ...
'CloseRequestFcn',@onClose, ...
'Name','OSC Server', 'Position',[100 100 220 140]);
movegui(h.fig, 'center')
h.start = uicontrol('Style','pushbutton', 'String','Start', ...
'Callback',{@onClick,'start'}, ...
'Parent',h.fig, 'Position',[20 20 80 20]);
h.stop = uicontrol('Style','pushbutton', 'String','Stop', ...
'Callback',{@onClick,'stop'}, ...
'Parent',h.fig, 'Position',[120 20 80 20]);
h.txt = uicontrol('Style','text', 'String','', ...
'Parent',h.fig, 'Position',[60 80 100 20]);
set(h.stop, 'Enable','off');
drawnow expose
h.timer = timer('TimerFcn',@receive, 'BusyMode','drop', ...
'ExecutionMode','fixedRate', 'Period',0.11);
end
function onClick(~,~,action)
switch lower(action)
case 'start'
set(handles.start, 'Enable','off')
set(handles.stop, 'Enable','on')
osc = osc_new_server(2222);
start(handles.timer);
case 'stop'
set(handles.start, 'Enable','on')
set(handles.stop, 'Enable','off')
osc_free_server(osc); osc = [];
stop(handles.timer);
end
drawnow expose
end
function receive(~,~)
if isempty(osc), return; end
m = osc_recv(osc, 0.1);
if isempty(m), return; end
set(handles.txt, 'String',num2str(m{1}.data{1}))
drawnow expose
end
function onClose(~,~)
if ~isempty(osc)
osc_free_server(osc);
end
stop(handles.timer); delete(handles.timer);
delete(handles.fig);
clear handles osc
end
end
在MATLAB中,服务器部分有点棘手。我们不希望MATLAB无限期地阻塞等待消息。所以我创建了一个计时器,它每0.11秒执行一次。在计时器函数中,我们尝试以阻塞方式接收消息,但超时时间为0.1秒。这样,GUI和MatlabIDE都能保持响应速度
3) 其他组合:
使用上述解决方案,您还可以在PureData中同时打开客户机和服务器,或者在MATLAB中同时打开客户机和服务器。这两种方式都应该有效
最后,我应该说,无论是将主机名用作localhost
,还是直接指定IP地址127.0.0.1
,都没有区别
嗯
编辑:
我自己设法编译了OSC-MEX包,下面是步骤。第一次下载及其依赖项。这包括:、可执行文件
1) 我们首先构建liblo库:
- 将“premake4.exe”复制到“build”目录中,然后运行:
premake4--platform=x32 vs2010
- 在VS2010中打开生成的“liblo.sln”解决方案文件。选择“liblo”项目并转到“项目>属性”。在“附加包含目录”字段中添加包含pthreads头文件的
include
文件夹。类似地,为链接器添加lib
文件夹,并指定pthreadVC2.lib
作为附加依赖项
- 选择“ReleaseLib”Win32 t
function example_osc_server()
handles = createGUI();
osc = [];
function h = createGUI()
h.fig = figure('Menubar','none', 'Resize','off', ...
'CloseRequestFcn',@onClose, ...
'Name','OSC Server', 'Position',[100 100 220 140]);
movegui(h.fig, 'center')
h.start = uicontrol('Style','pushbutton', 'String','Start', ...
'Callback',{@onClick,'start'}, ...
'Parent',h.fig, 'Position',[20 20 80 20]);
h.stop = uicontrol('Style','pushbutton', 'String','Stop', ...
'Callback',{@onClick,'stop'}, ...
'Parent',h.fig, 'Position',[120 20 80 20]);
h.txt = uicontrol('Style','text', 'String','', ...
'Parent',h.fig, 'Position',[60 80 100 20]);
set(h.stop, 'Enable','off');
drawnow expose
h.timer = timer('TimerFcn',@receive, 'BusyMode','drop', ...
'ExecutionMode','fixedRate', 'Period',0.11);
end
function onClick(~,~,action)
switch lower(action)
case 'start'
set(handles.start, 'Enable','off')
set(handles.stop, 'Enable','on')
osc = osc_new_server(2222);
start(handles.timer);
case 'stop'
set(handles.start, 'Enable','on')
set(handles.stop, 'Enable','off')
osc_free_server(osc); osc = [];
stop(handles.timer);
end
drawnow expose
end
function receive(~,~)
if isempty(osc), return; end
m = osc_recv(osc, 0.1);
if isempty(m), return; end
set(handles.txt, 'String',num2str(m{1}.data{1}))
drawnow expose
end
function onClose(~,~)
if ~isempty(osc)
osc_free_server(osc);
end
stop(handles.timer); delete(handles.timer);
delete(handles.fig);
clear handles osc
end
end
#define ENABLE_IPV6 1
mex -largeArrayDims -I../path/to/liblo-0.27 xxxxxx.c pthreadVC2.lib liblo.lib -lwsock32 -lws2_32 -liphlpapi