Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/111.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何将sysex数据添加到MusicTrack?(音频工具箱)_Ios_C_Midi_Audiotoolbox_Sysex - Fatal编程技术网

Ios 如何将sysex数据添加到MusicTrack?(音频工具箱)

Ios 如何将sysex数据添加到MusicTrack?(音频工具箱),ios,c,midi,audiotoolbox,sysex,Ios,C,Midi,Audiotoolbox,Sysex,我正试图用21点等工具编写我的midi音序器,但仍坚持将sysex数据写入MusicTrack。我使用以下代码插入sysex事件 // ---- Some code here --- // PatternData pattern = { sizeof(PatternData), i, signature.numerator, signature.denominator }; CABarBeatTime beattime = CABarBeatTime((i * signature.numera

我正试图用21点等工具编写我的midi音序器,但仍坚持将sysex数据写入MusicTrack。我使用以下代码插入sysex事件

// ---- Some code here --- //

PatternData pattern = { sizeof(PatternData), i, signature.numerator, signature.denominator };
CABarBeatTime beattime = CABarBeatTime((i * signature.numerator * signature.denominator) + 1, 1, 0, SUBBEAT_DIVISOR_DEFAULT);
// Convert beattime to timestamp 
if ((MusicSequenceBarBeatTimeToBeats(sequence, &beattime, &timestamp)) != noErr) 
{
return status; 
} 
// Add event 
if ((status = MusicTrackNewMIDIRawDataEvent(track, timestamp, (MIDIRawData*)&pattern)) != noErr) 
{ 
return status; 
}

// ---- Some code here --- //
模式数据是

typedef struct PatternData 
{ 
UInt32 length; // Struct length 
UInt8 index; // Pattern index 
UInt8 bars; // Number of bars in patten 
UInt8 beats; // Number of beats in pattern 
} PatternData;
我做了一些错误的事情,因为调用MusicSequenceFileCreate后,我得到了损坏的文件。
有没有人举过一个如何将sysex数据添加到音乐曲目的例子?

好的。我找到了一条正确的路,这就是:

    UInt8 data[] = { 0xF0, manufacturerId, databyte1, databyte2, databyte3, 0xF7 };
    MIDIRawData raw;
    memcpy(raw.data, data, 0, sizeof(data));
    raw.length = sizeof(data);

    if ((status = MusicTrackNewMIDIRawDataEvent(track, timestamp, &raw)) != noErr)
    {
        return status;
    }

下面是一个示例,如何在MIDI曲目中录制正常的MIDI和SYSEX消息,并将它们保存在共享iTunes文件夹中的MIDI文件中。set应用程序支持iTunes文件共享到YES in.plist: 请特别参阅代码中的calloc

#import "ViewController.h"
#import <CoreMIDI/MIDIServices.h>
#import <CoreMIDI/CoreMIDI.h>
#import "AppDelegate.h"
#include <sys/time.h>
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import <AVFoundation/AVFoundation.h>

@interface ViewController ()

@end

@implementation ViewController

@synthesize SYSEX_8;

long secTempA = 0;
float secTempB = 0;
long secStartA = 0;
float secStartB = 0;
MusicTimeStamp timeStamp = 0;
MusicSequence recordSequence;
MusicTrack recordTrack;
MusicTimeStamp lenRec = 0;
MIDINoteMessage noteMessage;
MusicTrack track;
NSString *fileNameForSave = @"";
NSString *midiFileWritePath = @"";
NSString *documentsDirectoryPath = @"";
UIAlertView *infoStore;
UIAlertView *infoStoreError;
MIDIRawData *sysexData;

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    // Get documents Directory
    // (don't forget the ".plist" entry "Application supports iTunes file sharing YES"
    NSArray *pathDocDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    documentsDirectoryPath = [pathDocDir objectAtIndex:0];

}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)SYSEX_8_touchdown:(id)sender { 
    NewMusicSequence(&recordSequence);
    MusicSequenceNewTrack(recordSequence, &recordTrack);
    MusicSequenceSetSequenceType(recordSequence, kMusicSequenceType_Beats);

    timeStamp = 0;
    struct timeval time;
    gettimeofday(&time, NULL);
    secStartA = time.tv_sec;
    secStartB = time.tv_usec * 0.000001;

    noteMessage.channel = 0x90; // Note ON 
    noteMessage.note = 0x3C;
    noteMessage.velocity = 0x7F;
    MusicTrackNewMIDINoteEvent(recordTrack, timeStamp, &noteMessage);
    NSLog(@"%02x %02x %02x", 0x90, 0x3C, 0x7F);

    usleep(10000);

    gettimeofday(&time, NULL);
    secTempA = time.tv_sec;
    secTempB = time.tv_usec * 0.000001;
    secTempA = secTempA - secStartA;
    secTempB = secTempB - secStartB;
    timeStamp = (secTempA + secTempB) * 2;

    noteMessage.channel = 0x90; // Note OFF
    noteMessage.note = 0x3C;
    noteMessage.velocity = 0x00;
    MusicTrackNewMIDINoteEvent(recordTrack, timeStamp, &noteMessage);
    NSLog(@"%02x %02x %02x", 0x90, 0x3C, 0x00);

    usleep(100000);

    gettimeofday(&time, NULL);
    secTempA = time.tv_sec;
    secTempB = time.tv_usec * 0.000001;
    secTempA = secTempA - secStartA;
    secTempB = secTempB - secStartB;
    timeStamp = (secTempA + secTempB) * 2;

    Byte datatest[8];
    UInt32 theSize = offsetof(MIDIRawData, data[0]) + (sizeof(UInt8) * sizeof(datatest));
    sysexData = (MIDIRawData *)calloc(1, theSize);
    sysexData->length = sizeof(datatest);

    datatest[0] = 0xF0;  // Start SYSEX
    datatest[1] = 0x26;
    datatest[2] = 0x79;
    datatest[3] = 0x0E;
    datatest[4] = 0x00;
    datatest[5] = 0x00;
    datatest[6] = 0x00;
    datatest[7] = 0xF7;  // End SYSEX

    for (int j = 0; j < sizeof(datatest); j++) {
        sysexData->data[j] = datatest[j];
        NSLog(@"%02x", sysexData->data[j]);
    }

    int status;
    if ((status = MusicTrackNewMIDIRawDataEvent(recordTrack, timeStamp, sysexData) != noErr)) {
        NSLog(@"error %i", status);
    }
    else {
        [self stopRecording];
    }
}

- (void) stopRecording {

    CAShow(recordSequence);  // To show all MIDI events !!!

    UInt32 sz = sizeof(MusicTimeStamp);
    lenRec = 0;
    MusicSequenceGetIndTrack(recordSequence, 0, &track);
    MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength, &lenRec, &sz);

    if (lenRec > 0.1){
        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
        [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss +zzzz"];
        NSDate *startDate = [NSDate date];

        NSTimeZone *zone = [NSTimeZone systemTimeZone];
        NSInteger interval = [zone secondsFromGMTForDate:startDate];
        startDate = [startDate dateByAddingTimeInterval:interval];
        //    NSLog(@"Date: %@", startDate);

        NSString *strDate = [[NSString alloc] initWithFormat:@"%@", startDate];
        NSArray *arr = [strDate componentsSeparatedByString:@" "];
        NSString *str;
        str = [arr objectAtIndex:0];
        NSArray *arr_date = [str componentsSeparatedByString:@"-"];

        int year = [[arr_date objectAtIndex:0] intValue];
        int month = [[arr_date objectAtIndex:1] intValue];
        int day = [[arr_date objectAtIndex:2] intValue];

        str = [arr objectAtIndex:1];
        NSArray *arr_time = [str componentsSeparatedByString:@":"];

        int hours = [[arr_time objectAtIndex:0] intValue];
        int minutes = [[arr_time objectAtIndex:1] intValue];
        int seconds = [[arr_time objectAtIndex:2] intValue];

        fileNameForSave = [NSString stringWithFormat:@"%@_%04d%02d%02d_%02d%02d%02d%@", @"$Record", year, month, day, hours, minutes, seconds, @".mid"];
        midiFileWritePath = [documentsDirectoryPath stringByAppendingPathComponent:fileNameForSave];

        infoStore = [[UIAlertView alloc]initWithTitle: @"Save as MIDI file ?"
                                              message: [NSString stringWithFormat:@"\n%@", fileNameForSave]
                                             delegate: self
                                    cancelButtonTitle: @"YES"
                                    otherButtonTitles: @"NO",nil];
        [infoStore show];  // rest siehe unten !!!!!
    }
    else {
        MusicSequenceDisposeTrack(recordSequence, track);
        DisposeMusicSequence(recordSequence);
    }

}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(int)buttonIndex {
    // deletion code here
    if (alertView == infoStore) {
        if (buttonIndex == 0) {
            NSURL *midiURL = [NSURL fileURLWithPath:midiFileWritePath];
            OSStatus status = 0;
            status = MusicSequenceFileCreate(recordSequence, (__bridge CFURLRef)(midiURL), kMusicSequenceFile_MIDIType, kMusicSequenceFileFlags_EraseFile, 0);
            if (status != noErr) {
                infoStoreError = [[UIAlertView alloc]initWithTitle: @"Information"
                                                           message: [NSString stringWithFormat:@"\nError storing MIDI file in: %@", documentsDirectoryPath]
                                                          delegate: self
                                                 cancelButtonTitle: nil
                                                 otherButtonTitles:@"OK",nil];
                [infoStoreError show];
            }
        }
        MusicSequenceDisposeTrack(recordSequence, track);
        DisposeMusicSequence(recordSequence);
    }

}

@end

为什么不使用midrawdata结构?@CL。使用midrawdata我得到了相同的结果。此外,我想使用我自己的数据结构。我获取我的结构并将其转换为midrawdata。在中发现此模式时,必须将数据包装到SysEx消息中,并且必须将该消息包装到与midrawData结构具有相同布局的结构中。无论如何,对于SysEx,您的?@CL.我没有制造商标识符。在我看来,sysex是在midi文件中存储自定义数据的好主意。你能给我一个例子,如何将sysex和sysex消息中的结构包装成MIDIRawData吗?如果你没有购买ID,你不能使用sysex消息。你不能使用memccpy,因为你的数据可能包含零字节。原始数据的大小只有一个字节;你有一个缓冲区溢出,正在破坏你的堆栈。在其他情况下,这几乎总是正确的,但这段代码很有用。使用MidiKit应用程序或“我的测试应用程序”成功打开保存的文件。但当数据中的字节数为0时,您是对的。我应该使用memcpy而不是memccpy。