菜鸟教程小白 发表于 2022-12-12 13:37:54

ios - 获取使用 Logic 生成的 midi 序列 (MusicSequence) 标记


                                            <p><p>我正在开发一个应用程序,它可以播放带有音频单元的 midi 序列 (.mid)。
midi 文件是使用 Logic 创建的,它提供了在时间线上添加标记的可能性。</p>

<p>在代码中,我使用 MusicSequence MusicPlayer 读取文件,并使用 MIDIClientCreate MIDIDestinationCreate 解析 MIDI 数据包。</p>

<p><strong>主要方法</strong></p>

<pre><code>    OSStatus result = noErr;


// Initialise the music sequence
NewMusicSequence(&amp;_s);

// Get a string to the path of the MIDI file which
// should be located in the Resources folder
NSString *midiFilePath = [
                        pathForResource:@&#34;mymidifile&#34;
                        ofType:@&#34;mid&#34;];

// Create a new URL which points to the MIDI file
NSURL * midiFileURL = ;

// Load the file
MusicSequenceFileLoad(_s, (__bridge CFURLRef) midiFileURL, 0, 0);



// Initialise the music player
NewMusicPlayer(&amp;_p);


// Load the sound from EXS file
;

//Load Click
;


//Assign channel to tracks
MusicTrack track = NULL;
MusicTrack track2 = NULL;
MusicSequenceGetIndTrack(_s, 1, &amp;track);
MusicSequenceGetIndTrack(_s, 2, &amp;track2);

//Assign tracks to audio units
MusicTrackSetDestNode(track, _samplerNode);
MusicTrackSetDestNode(track2, _samplerNode2);


// Create a client
result = MIDIClientCreate(CFSTR(&#34;Virtual Client&#34;),MyMIDINotifyProc,(__bridge void *)(self),&amp;_virtualMidi);
NSAssert( result == noErr, @&#34;MIDIClientCreate failed. Error code: %d &#39;%.4s&#39;&#34;, (int) result, (const char *)&amp;result);


// Create an endpoint
result = MIDIDestinationCreate(_virtualMidi, (CFStringRef)@&#34;Virtual Destination&#34;, MyMIDIReadProc, (__bridge void *)(self), &amp;_virtualEndPoint);

NSAssert( result == noErr, @&#34;MIDIDestinationCreate failed. Error code: %d &#39;%.4s&#39;&#34;, (int) result, (const char *)&amp;result);


// ************* Set the endpoint of the sequence to be our virtual endpoint
MusicSequenceSetMIDIEndpoint(_s, _virtualEndPoint);




// Load the sequence into the music player
MusicPlayerSetSequence(_p, _s);
// Called to do some MusicPlayer setup. This just
// reduces latency when MusicPlayerStart is called
MusicPlayerPreroll(_p);
// Starts the music playing
MusicPlayerStart(_p);
</code></pre>

<p><strong>还有我的 readProc 函数</strong></p>

<pre><code>void MyMIDIReadProc(const MIDIPacketList *pktlist,
                AudioProcessor *refCon,
                void *connRefCon) {


AudioUnit *player = nil;

MIDIPacket *packet = (MIDIPacket *)pktlist-&gt;packet;
NSString *messageType;

for (int i=0; i &lt; pktlist-&gt;numPackets; i++) {


    Byte midiStatus = packet-&gt;data;
    Byte midiCommand = midiStatus &gt;&gt; 4;// mask off all but top 4 bits
    Byte note = packet-&gt;data &amp; 0x7F;
    Byte velocity = packet-&gt;data &amp; 0x7F;

    // find the channel by masking off all but the low 4 bits
    NSInteger midiChannel = midiStatus &amp; 0x0F;


    switch (midiStatus &amp; 0xF0) {
      case 0x80:
            messageType = @&#34;Note Off&#34;;
            break;

      case 0x90:
            messageType = @&#34;Note On&#34;;
            break;

      case 0xA0:
            messageType = @&#34;Aftertouch&#34;;
            break;

      case 0xB0:
            messageType = @&#34;Control change&#34;;
            break;

      case 0xC0:
            messageType = @&#34;Program Change&#34;;
            break;

      case 0xD0:
            messageType = @&#34;Channel Pressure&#34;;
            break;

      case 0xE0:
            messageType = @&#34;Pitch Wheel&#34;;
            break;

      default:
            messageType = @&#34;Unk&#34;;
            break;
    }
    NSLog(@&#34;%@&#34;,messageType);
    int noteNumber = ((int) note) % 12;
    NSString *noteType;
    switch (noteNumber) {
      case 0:
            noteType = @&#34;C&#34;;
            break;
      case 1:
            noteType = @&#34;C#/Db&#34;;
            break;
      case 2:
            noteType = @&#34;D&#34;;
            break;
      case 3:
            noteType = @&#34;D#/Eb&#34;;
            break;
      case 4:
            noteType = @&#34;E&#34;;
            break;
      case 5:
            noteType = @&#34;F&#34;;
            break;
      case 6:
            noteType = @&#34;F#/Gb&#34;;
            break;
      case 7:
            noteType = @&#34;G&#34;;
            break;
      case 8:
            noteType = @&#34;G#/Ab&#34;;
            break;
      case 9:
            noteType = @&#34;A&#34;;
            break;
      case 10:
            noteType = @&#34;A#/Bb&#34;;
            break;
      case 11:
            noteType = @&#34;B&#34;;
            break;
      default:
            break;
    }




    if( velocity == 0 ){

      UInt32 noteOff =    kMIDIMessage_NoteOff &lt;&lt; 4 | 0;
      if( midiChannel == 0 ){
            MusicDeviceMIDIEvent (refCon.samplerUnit, noteOff, note, 0, 0);
      }else if( midiChannel == 1 ){
            MusicDeviceMIDIEvent (refCon.samplerUnit2, noteOff, note, 0, 0);
      }

    }else{

      if( midiChannel == 0 ){
            MusicDeviceMIDIEvent (refCon.samplerUnit, midiStatus, note, velocity, 0);
      }else if( midiChannel == 1 ){
            MusicDeviceMIDIEvent (refCon.samplerUnit2, midiStatus, note, velocity, 0);
      }

    }

    packet = MIDIPacketNext(packet);
}
</code></pre>

<p>}</p>

<p>使用我的 readProc 函数,我可以看到所有的 midi 消息,但看不到标记...</p>

<p>如果我在 Logic 中重新打开 midi 文件,标记在文件中,但在哪里...我如何在代码中获取它?</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>标记作为标记元事件包含在 MIDI 文件中。所以你需要扩展你的解析来支持元事件。元事件的状态为 0xFF。对于标记,下一个字节是 0x06,然后是长度和字符数。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 获取使用 Logic 生成的 midi 序列 (MusicSequence) 标记,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/18275924/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/18275924/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 获取使用 Logic 生成的 midi 序列 (MusicSequence) 标记