The Stereo Action Dimension
Network MIDI on iOS - Part 1

- Composing outgoing MIDI data in response to user input
- Processing incoming MIDI data in real time (with semaphores and lock free buffers)
- Finding network services with Bonjour
Please note you need to run this on a device rather than the simulator.
(Now seems to work OK on the iOS 7 simulator at least).
Network MIDI on iOS - Part 2
In this part, I will discuss finding and publishing network MIDI services using Bonjour, and creating the MIDI client using the CoreMIDI API. The source code for this project is available for download in
Part 1 of this article.
The network MIDI services in OS X and iOS can be discovered in the same way as any other Bonjour service. In the initialiser of the MIDIController class (see MIDIController.m) an instance of
NSNetServiceBrowser is created, and instructed to search for services of the type MIDINetworkBonjourServiceType i.e. @"_apple-midi._udp". By implementing the delegate protocol for this browser, a MIDIController instance can monitor available services of
this type on the network.
These services are exposed to the remainder of the application as a dictionary. In addition, various operations are provided to allow connection, disconnection etc. (see the section marked "Connection Management" in the implementation for details). The sample
application uses these methods to provide a simple UI to connect to any detected services. The settings page is displayed by flipping the main view. From here, we can select one or more of the remote MIDI services available on the current LAN.


Note that connections can also be made from the other end. By opening Audio MIDI Setup on a Mac on the same LAN, we can browse to the iPhone and initiate a connection from the computer. In this instance, the MIDIController instance will inform the UI that a
connection has been made via an NSNotification. If multiple connections are made to or from the same device, they are bridged in that:
- All incoming data from the network is merged as if it was coming from a single device
- Outgoing data from the device is sent to all network services
The MIDIController initialiser also sets up the shared MIDINetworkSession instance, which acts as a bridge between the network services and the CoreMIDI API. A MIDI client, input port and output port are then created. The input port is connected to the source endpoint of the MIDINetworkSession instance. Note
that these endpoints are named from the perspective of the iOS application; the "source" endpoint is where data will be received from the network, and the "destination" endpoint is where the application will send data to the network.
To send data to the output port once a connection has been made, the app invokes the methods in the section marked Sending in the implementation file, namely:
-(void) allNotesOffOnChannel:(NSUInteger)channel;
-(void) sendChangeForController:(NSUInteger)controller onChannel:(NSUInteger)channel withValue:(NSUInteger)value;
-(void) sendNote:(NSUInteger)note on:(BOOL)on onChannel:(NSUInteger)channel withVelocity:(NSUInteger)velocity;
-(void) sendMMCCommand:(NSUInteger)command toDevice:(NSUInteger)device;
data (for instance where the packet count is set too high) will typically result in disconnection by the remote service.
The sendNote:on:onChannel:withVelocity: method is invoked when the user presses the "keys" on the Notes tab:
The sendMMCCommand:toDevice: method is invoked in response to button presses on the MMC tab:
Please note that the MMC command output hasn't been tested as I don't have any devices that respond to this part of the MIDI protocol. Let me know via the comments if you have any problems.
The operation of the input port is described in Part 3 of this article.
Network MIDI on iOS - Part 3
In this part I will discuss how incoming MIDI is received into the application and subsequently processed. The source code for this project is available for download in
Part 1 of this article.
The MIDI controller class (see MIDIController.h) provides a formal protocol, MIDIReceivedDelegate, and a corresponding delegate property. This defines the following methods:
- (void) midiControllerUpdated:(Byte)controller onChannel:(Byte)channel toValue:(Byte)value;
- (void) midiNoteOnOff:(Byte)note onChannel:(Byte)channel withVelocity:(Byte)velocity on:(BOOL)on;
These methods encapsulate the complexity of receiving MIDI data - but how is this accomplished behind the scenes?
When we created the MIDI client in part 2 of this article, we also created a MIDI input port. This was passed a pointer to a callback function, MIDIInputReadProc. This callback function is called by the operating system when MIDI data is received at the port.
As a real time callback function which may be re-entrant when the system is under load, certain restrictions should be adhered to. In particular, this function should avoid:
- Allocating and deallocating memory
- Acquiring locks
- Performing lengthy operations
The function walks the list of MIDI packets received as follows:
For each MIDI packet received:
- The packet's length and data are written into a structured circular buffer (see MIDIPacketBuffer.h)
- A Mach semaphore is incremented to signal the rest of the application that another packet is available for processing.
Note that the structured buffer in this example disregards the timestamp of the MIDI packet. This will be covered in a later example.
Another thread (see midiInputThreadProc) waits on this semaphore. If the semaphore is signalled, the length of the next MIDI packet is retrieved from the circular buffer, and then that amount of data is copied into a regular buffer.
This data is then parsed from this buffer. The following MIDI commands are identified in this example:
- Control changes
- Note on/off
By these means, the application decouples the processing of MIDI data from its receipt, and conforms with the requirements placed on it by the CoreMIDI port model
The Stereo Action Dimension的更多相关文章
- 强化学习_PolicyGradient(策略梯度)_代码解析
使用策略梯度解决离散action space问题. 一.导入包,定义hyper parameter import gym import tensorflow as tf import numpy as ...
- Java基础之处理事件——使用动作Action(Sketcher 6 using Action objects)
控制台程序. 动作Action是任何实现了javax.swing.Action接口的类的对象.这个接口声明了操作Action对象的方法,例如,存储与动作相关的属性.启用和禁用动作.Action接口扩展 ...
- 微软BI 之SSIS 系列 - 数据仓库中实现 Slowly Changing Dimension 缓慢渐变维度的三种方式
开篇介绍 关于 Slowly Changing Dimension 缓慢渐变维度的理论概念请参看 数据仓库系列 - 缓慢渐变维度 (Slowly Changing Dimension) 常见的三种类型 ...
- 【论文笔记】Spatial Temporal Graph Convolutional Networks for Skeleton-Based Action Recognition
Spatial Temporal Graph Convolutional Networks for Skeleton-Based Action Recognition 2018-01-28 15:4 ...
- [libGDX游戏开发教程]使用libGDX进行游戏开发(12)-Action动画
前文章节列表: 使用libGDX进行游戏开发(11)-高级编程技巧 使用libGDX进行游戏开发(10)-音乐音效不求人,程序员也可以DIY 使用libGDX进行游戏开发(9)-场景过渡 ...
- redux-amrc:用更少的代码发起异步 action
很多人说 Redux 代码多,开发效率低.其实 Redux 是可以灵活使用以及拓展的,经过充分定制的 Redux 其实写不了几行代码.今天先介绍一个很好用的 Redux 拓展-- redux-amrc ...
- 尝试asp.net mvc 基于controller action 方式权限控制方案可行性
微软在推出mvc框架不久,短短几年里,版本更新之快,真是大快人心,微软在这种优秀的框架上做了大量的精力投入,是值得赞同的,毕竟程序员驾驭在这种框架上,能够强力的精化代码,代码层次也更加优雅,扩展较为方 ...
- ASP.NET Core 中文文档 第四章 MVC(4.1)Controllers, Actions 和 Action Results
原文:Controllers, Actions, and Action Results 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:许登洋(Seay) Action 和 acti ...
- java中Action层、Service层和Dao层的功能区分
Action/Service/DAO简介: Action是管理业务(Service)调度和管理跳转的. Service是管理具体的功能的. Action只负责管理,而Service负责实施. DAO只 ...
随机推荐
- JWFD开源项目官方网站预览
自己做的...感觉还比较正规哈....JWFD开源项目还是需要一个官方网站的...
- pyhton类集成
class SchoolMember: def __init__(self,name,age): self.name = name self.age = age print ...
- sass 常用函数的整理
@charset "utf-8"; @import "compass/css3/inline-block"; @import "compass/css ...
- SPOJ 694 (后缀数组) Distinct Substrings
将所有后缀按照字典序排序后,每新加进来一个后缀,它将产生n - sa[i]个前缀.这里和小罗论文里边有点不太一样. height[i]为和字典序前一个的LCP,所以还要减去,最终累计n - sa[i] ...
- Hadoop2配置详解
配置文件 hadoop的配置是由两种重要类型的配置文件进行驱动的: 默认是只读的配置: core-default.xml, hdfs-default.xml, yarn-default.xml and ...
- asp.net限时发送手机验证码
html代码 <p> <strong>手机验证码:</strong> <asp:TextBox ID="code" runat=" ...
- sql DROP 和DELETE、TRUNCATE用法
DROP:删除数据库已存在的表DROP TABLE tbname DELETE:删除记录delete from tbname truncate:清空表,重置索引truncate table tbnam ...
- hibernate一个注册小例子
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAXUAAAJ2CAIAAAAv44WsAAAgAElEQVR4nO29a3QUVaL33fPhfHrW8y
- activiti参考5-任务TASK
一.概要 1,设计TASK的表主要是:ACT_RU_TASK,ACT_HI_TASKINST(见参考-activiti表): 2,任务主要有:人工任务(usertask),服务任务(serviceta ...
- Javaweb里面的filter,listener,servlet
Filter 1Filter是什么:是过滤器简称 2Filter有什么作用:在filter中可以得到代表用户请求和响应的request.response对象,因此在编程中可以使用Decorator(装 ...