标签: coremidi

支持iOS CoreMIDI的跨平台MIDI库

我正在寻找一个跨平台的C或C++ MIDI库.只是发送/接收MIDI音符事件,控制代码和时序,而不是发出声音.

主要目标是iOS/iPad,所以它必须支持iOS上的CoreMIDI,我知道这是最新的.我可以直接使用CoreMidi但是如果有轻量级的东西那么使用便携式的东西会很好,所以我可以很容易地将项目移植到PC上.

如果没有这个,请提一下,如果有一个好的,轻量级的开源,我可能更容易添加CoreMIDI支持而不是自己动手.

澄清:我正在寻找类似于具有良好iOS支持的MidiIOPortMIDI的东西.

c++ midi ipad ios coremidi

6
推荐指数
1
解决办法
4171
查看次数

如何从MIDISourceCreate()保留虚拟MIDI源的唯一性?

我正在使用RtMidi作为OS X上CoreMIDI的包装来从应用程序发送MIDI消息.我使用RtMidiOut::openVirtualPort("MyAwesomePort")这样我可以选择我的应用程序作为DAW中的输入源.

但是,如果我的程序关闭并且我再次打开它,我的DAW不会将输入设备识别为相同的端口,尽管给出了相同的名称.

我最初使用的是pyrtmidi,因此用RtMidi直接验证了用C++编写的行为.在这种情况下,"我的DAW"是Reaper 4,但我复制了Pro Tools,Logic和MuLab中的行为.

我知道可以保留虚拟midi端口的一些独特性,因为MidiKeys的行为就像我希望我的应用程序一样:即使MidiKeys在我的DAW仍在运行时关闭并重新打开,我的DAW也会记住它.

所以我挖掘了RtMidi源代码,CoreMIDI封装器看起来很简单.所MIDISourceCreate要求的只是一个字符串.客户端参数是(我在浏览文档后假设的)我的应用程序的标识符,它是CoreMIDI服务的客户端.

void RtMidiOut :: openVirtualPort( std::string portName )
{
  CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);

  if ( data->endpoint ) {
    errorString_ = "RtMidiOut::openVirtualPort: a virtual output port already exists!";
    error( RtError::WARNING );
    return;
  }

  // Create a virtual MIDI output source.
  MIDIEndpointRef endpoint;
  OSStatus result = MIDISourceCreate( data->client,
                                      CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ),
                                      &endpoint );
  if ( result != noErr ) {
    errorString_ = "RtMidiOut::initialize: error creating …
Run Code Online (Sandbox Code Playgroud)

macos midi core-audio ios coremidi

6
推荐指数
1
解决办法
1342
查看次数

AudioTimeStamp格式+'MusicDeviceMIDIEvent'

我可以得到一些帮助吗?

在测试项目中,我有一个AUSampler -> MixerUnit -> ioUnit并设置了渲染回调.一切正常.我正在使用MusicDeviceMIDIEvent定义的方法MusicDevice.h播放midi noteOn¬eOff.因此,在下面的黑客测试代码中,noteOn会发生.5秒.每2秒.

MusicDeviceMIDIEvent(下面)采用一个参数:inOffsetSampleFrame为了在未来的时间安排一个事件.我希望能够做的是播放noteOn并同时安排noteOff(没有黑客时间检查我在下面做).我只是不明白该inOffsetSampleFrame值应该是什么(例如:播放.5秒或.2秒音符.(换句话说,我不理解音频定时的基本知识......).

所以,如果有人可以引导我通过算术从传入中获取适当的值AudioTimeStamp,那就太棒了!也许也可以纠正我/澄清其中任何一个:

  1. AudioTimeStamp->mSampleTime - sampleTime是当前样本"切片"的时间?这是几毫秒?

  2. AudioTimeStamp->mHostTime - ?host是应用程序运行的计算机,这是计算机启动以来的时间(以毫秒为单位?)这是一个巨大的数字.是不是翻滚然后引起问题?

  3. inNumberFrames- 在iOS5上似乎是512(通过 kAudioUnitProperty_MaximumFramesPerSlice).样品是由512帧组成的?

  4. 我已经看到很多告诫不要重写渲染回调函数 - 特别是为了避免客观C调用 - 我理解原因,但是如何向UI发送消息或进行其他处理?

我猜就是这样.谢谢你的支持!

inOffsetSampleFrame 如果从音频单元的渲染线程调度MIDI事件,则可以提供音频单元在下一个音频单元渲染中应用该事件时可能应用的样本偏移.这允许您安排样本,应用MIDI命令的时间,并且在开始新笔记时尤其重要.如果您没有在音频单元的渲染线程中进行调度,则应将此值设置为0

// MusicDeviceMIDIEvent函数def:

extern OSStatus
MusicDeviceMIDIEvent(   MusicDeviceComponent    inUnit,
                    UInt32                  inStatus,
                    UInt32                  inData1,
                    UInt32                  inData2,
                    UInt32                  inOffsetSampleFrame)
Run Code Online (Sandbox Code Playgroud)

//我的回调

OSStatus  MyCallback(   void *                          inRefCon,
                 AudioUnitRenderActionFlags *   ioActionFlags,
                 const AudioTimeStamp *         inTimeStamp,
                 UInt32                         inBusNumber,
                 UInt32                         inNumberFrames,
                 AudioBufferList *              ioData)
{

Float64 …
Run Code Online (Sandbox Code Playgroud)

audio core-audio ios coremidi ios5

6
推荐指数
1
解决办法
2829
查看次数

在swift中使用MIDIPacketList

我正在看一些使用核心midi的midi输出的例子.

特别是 这个问题

而且这个

我在objC中有基于这些的代码,我现在想尝试将其转换为swift.

我最不了解的是这一行: MIDIPacketList* pktList = (MIDIPacketList*) pktBuffer;

我读这个是声明一个MIDIPacketList类型的指针pktlist,并为它赋值pktBuffer,强制转换为类型MIDIPacketList

我是C和objC的新手,这对我来说毫无意义.

MIDIPacketList是这里定义的结构:

以什么方式将bytearray强制转换为结构类型MIDIPacketList,这是什么意思?我想这是试图定义数据包列表的大小,但为什么我们需要在这里做到这一点,无论如何这样做呢?为什么用MIDIPacketListAdd来做这件事就好了几行呢?

这是我在swift的midi输出课程的尝试 - 谁能看到出错的地方?在运行之前,此代码在Xcode中不会出错.我在objC中有一个工作版本,但我无法获得swift中定义的数据包列表的大小.(至少我认为这是问题)

import Foundation
import CoreMIDI

class MidiOutClass {

var midiClient = MIDIClientRef()
var midiSource = MIDIEndpointRef()


func openOutput() {
    MIDIClientCreate("MIDI client", nil, nil, &midiClient)
    MIDISourceCreate(midiClient, "MIDI Source",&midiSource)
    println("midi out opened")//should only do this if successful
}

func noteOn(channel: Int, note: Int, velocity:Int) {
    midisend((0x90+channel), note: note, value: velocity)
}

func polyAfter(channel: Int, note: Int, value:Int) {
    midisend((0xA0+channel), note: note, value: …
Run Code Online (Sandbox Code Playgroud)

midi casting objective-c coremidi swift

6
推荐指数
1
解决办法
2441
查看次数

在swift中访问固定长度C数组的元素

我正在尝试将一些C代码转换为swift.(为什么? - 如果你问的话,在OS-X中使用CoreMIDI)

C代码是这样的

void printPacketInfo(const MIDIPacket* packet) {
   int i;
   for (i=0; i<packet->length; i++) {
      printf("%d ", packet->data[i]);
   }
 }
Run Code Online (Sandbox Code Playgroud)

而MIDIPacket的定义是这样的

struct MIDIPacket
 {
    MIDITimeStamp           timeStamp;
    UInt16                  length;
    Byte                    data[256];
 };
Run Code Online (Sandbox Code Playgroud)

我的斯威夫特是这样的

func printPacketInfo(packet: UnsafeMutablePointer<MIDIPacket>){
    // print some things
    print("length", packet.memory.length)
    print("time", packet.memory.timeStamp)
    print("data[0]", packet.memory.data.1)
    for i in 0 ..< packet.memory.length {
      print("data", i, packet.memory.data[i])
    }
  }
Run Code Online (Sandbox Code Playgroud)

但这会产生编译错误

错误:类型'(UInt8,UInt8,..剪切.. UInt8,UInt8,UInt8)'没有下标成员

那么如何取消引用固定大小数组的第i个元素呢?

coremidi swift

6
推荐指数
1
解决办法
1561
查看次数

MIDIPacketList,numPackets始终为1

我正在iPad上处理Midi,一切正常,我可以记录进来的所有东西,并且一切正常。但是,在尝试接收长消息(即Sysex)时,我只能得到一个最大为256字节的数据包,此后什么也没有。

使用Apple提供的代码:

MIDIPacket *packet = &packetList->packet[0];
for (int i = 0; i > packetList->numPackets; ++i) {
    // ...
    packet = MIDIPacketNext (packet);
}
Run Code Online (Sandbox Code Playgroud)

packetList->numPackets始终为1。收到第一条消息后,在发送“新” sysex消息之前,不会调用其他回调方法。我不认为我的MIDI处理方法可以用全packetList(可能是任意大小)来调用。我以为我会以流的形式接收数据。它是否正确?

深入研究后,我发现的唯一内容是:http : //lists.apple.com/archives/coreaudio-api/2010/May/msg00189.html,其中提到了完全相同的内容,但并没有太大帮助。我知道我可能需要实现缓冲,但是我什至看不到任何超出前256个字节的内容,因此我不确定从哪里开始。

midi cocoa sysex ipad coremidi

5
推荐指数
1
解决办法
1527
查看次数

使用CoreMIDI从ObjC中的MIDI时钟计算准确的BPM

我在接收MIDI时钟计算准确的BPM时遇到了一些麻烦(在我的测试中使用Ableton Live发送MIDI时钟).

我正在使用Pete Goodliffe的CoreMIDI和PGMidi.

在PGMidi lib中,有一种方法在接收MIDI消息时调用.从doc开始,这是从高优先级的后台线程发生的.

这是我当前用于计算BPM的实现

double BPM;
double currentClockInterval;
uint64_t startClockTime;

- (void) midiSource:(PGMidiSource*)input midiReceived:(const MIDIPacketList *)packetList
{
    [self onTick:nil];

    MIDIPacket  *packet = MIDIPacketListInit((MIDIPacketList*)packetList);
    int statusByte = packet->data[0];
    int status = statusByte >= 0xf0 ? statusByte : statusByte >> 4 << 4;

    switch (status) {
        case 0xb0: //cc
                   //NSLog(@"CC working!");
            break;
        case 0x90: // Note on, etc...
                   //NSLog(@"Note on/off working!");
            break;
        case 0xf8: // Clock tick


            if (startClockTime != 0)
            {
                uint64_t currentClockTime = mach_absolute_time();
                currentClockInterval = convertTimeInMilliseconds(currentClockTime …
Run Code Online (Sandbox Code Playgroud)

midi objective-c ios coremidi

5
推荐指数
1
解决办法
4503
查看次数

初始化MIDIMetaEvent结构

我正在努力用swift初始化MusicPlayer.h中的MIDIMetaEvent结构头文件定义结构如下:

struct MIDIMetaEvent {
  var metaEventType: UInt8
  var unused1: UInt8
  var unused2: UInt8
  var unused3: UInt8
  var dataLength: UInt32
  var data: (UInt8)
}
Run Code Online (Sandbox Code Playgroud)

在"数据"成员之前,这似乎相当简单.这是1元素元组定义吗?我可以很容易地初始化所有其他结构元素但是徒劳地试图将"数据"设置为除单个值之外的任何其他内容.在我的代码中,我使用了一个名为myData的UInt8数组,并试图像这样初始化结构:

var msg = MIDIMetaEvent(
  metaEventType : UInt8(0x7F),
  unused1       : UInt8(0),
  unused2       : UInt8(0),
  unused3       : UInt8(0),
  dataLength    : UInt32(myData.count),
  data          : UnsafeBufferPointer<UInt8>(start: UnsafePointer<UInt8>(myData), count:myData.count) )
Run Code Online (Sandbox Code Playgroud)

但编译器对此并不满意,并抱怨"UnsafeBufferPointer无法转换为UInt8".如果我只是将数据设置为单个值但将dataLength设置为大于1的值,则生成的MIDIEventData显示事件中的第一个值是"数据"中的第一个值,后跟符合"dataLength"字节的乱码数据字节.很明显,"数据"被视为某种连续记忆.

那么如何将'data'元素设置为数组中的UInt8元素?

macos ios coremidi swift

5
推荐指数
1
解决办法
739
查看次数

Swift中的CoreMIDI回调

我使用以下代码在Swift Playground中接收MIDI事件:

import Cocoa
import CoreMIDI
import XCPlayground

XCPSetExecutionShouldContinueIndefinitely(continueIndefinitely: true)

func notifyCallback(message:UnsafePointer<MIDINotification>,refCon:UnsafeMutablePointer<Void>)
{
    println("MIDI Notify")
}

func eventCallback(pktlist:UnsafePointer<MIDIPacketList>, refCon:UnsafeMutablePointer<Void>, connRefCon:UnsafeMutablePointer<Void>)
{
    println("MIDI Read")
}

var client = MIDIClientRef()
MIDIClientCreate("Core MIDI Callback Demo" as NSString, MIDINotifyProc(COpaquePointer([notifyCallback])), nil, &client)

var inPort = MIDIPortRef()
MIDIInputPortCreate(client, "Input port",MIDIReadProc(COpaquePointer([eventCallback])), nil, &inPort)

let sourceCount = MIDIGetNumberOfSources()
for var count:UInt = 0; count < sourceCount; ++count
{
    let src:MIDIEndpointRef = MIDIGetSource(count)
    MIDIPortConnectSource(inPort, src, nil)
}
Run Code Online (Sandbox Code Playgroud)

我通过将工作的Objective-C代码转换成我认为正确的Swift版本来实现这一点.

它编译并运行正常,直到其中一个回调触发,例如,当我拔下MIDI设备或按下其中一个键时.我总是得到一个BAD_EXEC.

任何想法如何使这项工作或Swift只是没有准备好作为网络上的一些博客文章.苹果官方的任何我忽视的事情都清楚地表明Swift尚未准备好进行CoreMIDI回调?

更新2015-03-10:相应的Objective-C代码可在http://www.digital-aud.io/blog/2015/03/10/on-coremidi-callbacks/找到

midi coremidi swift swift-playground

5
推荐指数
1
解决办法
1517
查看次数

如何使用 Swift 创建 MIDI 文件?

我目前正在学习如何快速使用 MIDI。我寻求如何创建 MIDI 文件,但这听起来并不那么容易。
我检查了像 AudioKit 这样的框架,但我也没有找到。
我需要学习哪些信息?(例如了解 MIDI 文件结构)。

midi audiotoolbox coremidi swift audiokit

5
推荐指数
1
解决办法
2522
查看次数