代码之家  ›  专栏  ›  技术社区  ›  Greg

NSData与NSValue?如何在sendMIDISysExEvent:(NSData*)midiData中封装C结构

  •  1
  • Greg  · 技术社区  · 7 年前

    我在试着找出使用的方法 sendMIDISysExEvent:(NSData *)midiData 作为在音乐应用程序中重新调谐少数MIDI音符的一种方式。我想要 ViewController Synth 类更改10个音符的调谐。用于重新调谐一个音符的标准MIDI系统专用消息格式如下所示

                     F0 7F <device ID> 08 02 tt ll [kk xx yy zz] F7.
    

    legend: tt ll [kk xx yy zz] (注意:与MIDI 1.0详细规范4.2第49页略有不同)

    具有 typedef struct float uint8_t 表示调谐频率,例如。

        typedef struct
        {
        uint8_t SYSEX_SysexHeader;                // oxF0h;     // System Exclusive Header
        uint8_t SYSEX_UniversalRealTimeHeader;    // ox7Fh;     // Universal RealTime Header
        uint8_t SYSEX_myPhone;                    // ox00h;     // ID of target device (e.g. iPhone)
        uint8_t SYSEX_subID1;                     // ox08h;     // sub-ID #1 (MIDI Tuning Standard)
        uint8_t SYSEX_subID2;                     // ox02h;     // sub-ID #2 (note change)
        uint8_t SYSEX_tuningProgramNumber;        // ox0h;      // tuning program number (0 -127)
        uint8_t SYSEX_numberOfKeys;               // ox10h;     // number of changes
    
        uint8_t SYSEX_key0;
        float   TUNING_pitch_0;
    
        uint8_t SYSEX_key1;
        float   TUNING_pitch_1;
    
        uint8_t SYSEX_key2;
        float   TUNING_pitch_2;
    
        uint8_t SYSEX_key3;
        float   TUNING_pitch_3;
    
        uint8_t SYSEX_key4;
        float   TUNING_pitch_4;
    
        uint8_t SYSEX_key5;
        float   TUNING_pitch_5;
    
        uint8_t SYSEX_key6;
        float   TUNING_pitch_6;
    
        uint8_t SYSEX_key7;
        float   TUNING_pitch_7;
    
        uint8_t SYSEX_key8;
        float   TUNING_pitch_8;
    
        uint8_t SYSEX_key9;
        float   TUNING_pitch_9;
    
        uint8_t eox;                                // OxF7h;       //
    
        }
        TuneEvent;
    

    仍然在h

        typedef NS_ENUM(NSInteger, SYSEX)
        {
        SYSEX_SysexHeader               = 240,
        SYSEX_UniversalRealTimeHeader   = 127,
        SYSEX_myPhone                   = 0,
        SYSEX_subID1                    = 8,
        SYSEX_subID2                    = 2,
        SYSEX_tuningProgramNumber       = 0,
        SYSEX_numberOfKeysToBeChanged   = 1,
        SYSEX_key0                      = 61,
        SYSEX_key1                      = 62,
        SYSEX_key2                      = 63,
        SYSEX_key3                      = 64,
        SYSEX_key4                      = 65,
        SYSEX_key5                      = 66,
        SYSEX_key6                      = 67,
        SYSEX_key7                      = 68,
        SYSEX_key8                      = 69,
        SYSEX_key9                      = 70,
        SYSEX_eox                       = 247
        };
    
        typedef NS_ENUM(NSInteger, TUNING)
        {
        TUNING_pitch0,
        TUNING_pitch1,
        TUNING_pitch2,
        TUNING_pitch3,
        TUNING_pitch4,
        TUNING_pitch5,
        TUNING_pitch6,
        TUNING_pitch7,
        TUNING_pitch8,
        TUNING_pitch9
        };
    
        float TUNING_float(TUNING micro);
    

    最后,对于浮点值。。。 (thanks to this answer)

    PlayViewController.m

        float TUNING_float(TUNING micro) 
        {
        switch (micro) 
            {
            case TUNING_pitch0:
                return  579.4618f;
            case TUNING_pitch1:
                return  607.0552f;
            case TUNING_pitch2:
                return  662.2421f;
            case TUNING_pitch3:
                return  708.2311f;
            case TUNING_pitch4:
                return  772.6157f;
            case TUNING_pitch5:
                return  809.4070f;
            case TUNING_pitch6:
                return  882.9894f;
            case TUNING_pitch7:
                return  910.5828f;
            case TUNING_pitch8:
                return  993.3631f;
            case TUNING_pitch9:
                return  1030.1540f;
            default:
                return   0.0f;
            }
        }
    

    this answer 我开始问我如何根据 NSData sendMIDISysExEvent:(NSData*)midiData 将发送。和 this answer NSValue 这是封装C结构的更好方法,就像我试图创建的那样,所以我很困惑。如果真是这样,我很奇怪为什么苹果会推出这样的方法 sendMIDISysExEvent:(NSData *)midiData .

    我的问题是:基于消息格式 (在我上面的代码中概述) ,我该如何准备 midiData 为了用这种方法发送?

    字节数 数据类型 操作文件数据 NSValue公司 。这也意味着 仅设计用于处理字节数据,即。 uint8\u t 而不是 float. 换言之,明智的选择是根据以下MIDI调谐标准的摘录,使用字节表示频率值

        yy = MSB of fractional part (1/128 semitone = 100/128 cents = .78125 cent units)
        zz = LSB of fractional part (1/16384 semitone = 100/16384 cents = .0061 cent units)
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   Stephan Lechner    7 年前

    二者都 NSData NSValue 是围绕“原始二进制数据”的包装器,但在定义二进制数据长度时有不同的意图和方式。

    装箱标量类型中的目标,如 int float (但也是一个 struct ),以及 NSValue公司 cf. NSValue ):

    在NSValue中长度不确定。您应该使用NSString或 这些类型的NSData对象。

    不是在类型方面 ).

    sendMIDISysExEvent:(NSData *)midiData 需要一个 -对象,唯一(有意义的)方法是将对象作为 操作文件数据 -对象。

    希望有帮助。