{
    "content": [
        {
            "type": "text",
            "text": "# MIDI::Event (perldoc)\n\n## NAME\n\nMIDI::Event - MIDI events\n\n## SYNOPSIS\n\n# Dump a MIDI file's text events\ndie \"No filename\" unless @ARGV;\nuse MIDI;  # which \"use\"s MIDI::Event;\nMIDI::Opus->new( {\n\"fromfile\" => $ARGV[0],\n\"exclusiveeventcallback\" => sub{print \"$[2]\\n\"},\n\"include\" => \\@MIDI::Event::Textevents\n} ); # These options percolate down to MIDI::Event::decode\nexit;\n\n## DESCRIPTION\n\nFunctions and lists to do with MIDI events and MIDI event structures.\n\n## Sections\n\n- **NAME**\n- **SYNOPSIS**\n- **DESCRIPTION**\n- **GOODIES**\n- **FUNCTIONS**\n- **EVENTS AND THEIR DATA TYPES**\n- **MIDI BNF**\n- **COPYRIGHT**\n- **AUTHOR**\n\nUse structuredContent.sections for detailed options, examples, and full documentation.\n"
        }
    ],
    "structuredContent": {
        "command": "MIDI::Event",
        "section": "",
        "mode": "perldoc",
        "summary": "MIDI::Event - MIDI events",
        "synopsis": "# Dump a MIDI file's text events\ndie \"No filename\" unless @ARGV;\nuse MIDI;  # which \"use\"s MIDI::Event;\nMIDI::Opus->new( {\n\"fromfile\" => $ARGV[0],\n\"exclusiveeventcallback\" => sub{print \"$[2]\\n\"},\n\"include\" => \\@MIDI::Event::Textevents\n} ); # These options percolate down to MIDI::Event::decode\nexit;",
        "tldr_summary": null,
        "tldr_examples": [],
        "tldr_source": null,
        "flags": [],
        "examples": [],
        "see_also": [],
        "section_outline": [
            {
                "name": "NAME",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "SYNOPSIS",
                "lines": 10,
                "subsections": []
            },
            {
                "name": "DESCRIPTION",
                "lines": 12,
                "subsections": []
            },
            {
                "name": "GOODIES",
                "lines": 17,
                "subsections": []
            },
            {
                "name": "FUNCTIONS",
                "lines": 102,
                "subsections": []
            },
            {
                "name": "EVENTS AND THEIR DATA TYPES",
                "lines": 91,
                "subsections": []
            },
            {
                "name": "MIDI BNF",
                "lines": 58,
                "subsections": []
            },
            {
                "name": "COPYRIGHT",
                "lines": 5,
                "subsections": []
            },
            {
                "name": "AUTHOR",
                "lines": 2,
                "subsections": []
            }
        ],
        "sections": {
            "NAME": {
                "content": "MIDI::Event - MIDI events\n",
                "subsections": []
            },
            "SYNOPSIS": {
                "content": "# Dump a MIDI file's text events\ndie \"No filename\" unless @ARGV;\nuse MIDI;  # which \"use\"s MIDI::Event;\nMIDI::Opus->new( {\n\"fromfile\" => $ARGV[0],\n\"exclusiveeventcallback\" => sub{print \"$[2]\\n\"},\n\"include\" => \\@MIDI::Event::Textevents\n} ); # These options percolate down to MIDI::Event::decode\nexit;\n",
                "subsections": []
            },
            "DESCRIPTION": {
                "content": "Functions and lists to do with MIDI events and MIDI event structures.\n\nAn event is a list, like:\n\n( 'noteon', 141, 4, 50, 64 )\n\nwhere the first element is the event name, the second is the delta-time, and the remainder are\nfurther parameters, per the event-format specifications below.\n\nAn *event structure* is a list of references to such events -- a \"LoL\". If you don't know how to\ndeal with LoLs, you *must* read perllol.\n",
                "subsections": []
            },
            "GOODIES": {
                "content": "For your use in code (as in the code in the Synopsis), this module provides a few lists:\n\n@MIDIevents\na list of all \"MIDI events\" AKA voice events -- e.g., 'noteon'\n\n@Textevents\na list of all text meta-events -- e.g., 'trackname'\n\n@Nontextmetaevents\nall other meta-events (plus 'rawdata' and F-series events like 'tunerequest').\n\n@Metaevents\nthe combination of Textevents and Nontextmetaevents.\n\n@Allevents\nthe combination of all the above lists.\n",
                "subsections": []
            },
            "FUNCTIONS": {
                "content": "This module provides three functions of interest, which all act upon event structures. As an end\nuser, you probably don't need to use any of these directly, but note that options you specify\nfor MIDI::Opus->new with a fromfile or fromhandle options will percolate down to these\nfunctions; so you should understand the options for the first two of the below functions. (The\ncasual user should merely skim this section.)\n\nMIDI::Event::decode( \\$data, { ...options... } )\nThis takes a *reference* to binary MIDI data and decodes it into a new event structure (a\nLoL), a *reference* to which is returned. Options are:\n\n'include' => LISTREF\n*If specified*, listref is interpreted as a reference to a list of event\nnames (e.g., 'cuepoint' or 'noteoff') such that only these events will be\nparsed from the binary data provided. Events whose names are NOT in this\nlist will be ignored -- i.e., they won't end up in the event structure, and\nthey won't be each passed to any callbacks you may have specified.\n\n'exclude' => LISTREF\n*If specified*, listref is interpreted as a reference to a list of event\nnames (e.g., 'cuepoint' or 'noteoff') that will NOT be parsed from the\nbinary stream; they'll be ignored -- i.e., they won't end up in the event\nstructure, and they won't be passed to any callbacks you may have specified.\nDon't specify both an include and an exclude list. And if you specify\n*neither*, all events will be decoded -- this is what you probably want most\nof the time. I've created this include/exclude functionality mainly so you\ncan scan a file rather efficiently for just a few specific event types,\ne.g., just text events, or just sysexes.\n\n'noeotmagic' => 0 or 1\nSee the description of 'endtrack', in \"EVENTS\", below.\n\n'eventcallback' => CODEREF\nIf defined, the code referred to (whether as \"\\&wanted\" or as \"sub { BLOCK\n}\") is called on every event after it's been parsed into an event list (and\nany EOT magic performed), but before it's added to the event structure. So\nif you want to alter the event stream on the way to the event structure\n(which counts as deep voodoo), define 'eventcallback' and have it modify\nits @.\n\n'exclusiveeventcallback' => CODEREF\nJust like 'eventcallback'; but if you specify this, the callback is called\n*instead* of adding the events to the event structure. (So the event\nstructure returned by decode() at the end will always be empty.) Good for\ncases like the text dumper in the Synopsis, above.\n\nMIDI::Event::encode( \\@events, {...options...})\nThis takes a *reference* to an event structure (a LoL) and encodes it as binary data, which\nit returns a *reference* to. Options:\n\n'unknowncallback' => CODEREF\nIf this is specified, it's interpreted as a reference to a subroutine to be\ncalled when an unknown event name (say, 'macro10' or something), is seen by\nencode(). The function is fed all of the event (its name, delta-time, and\nwhatever parameters); the return value of this function is added to the\nencoded data stream -- so if you don't want to add anything, be sure to\nreturn ''.\n\nIf no 'unknowncallback' is specified, encode() will \"warn\" (well, \"carp\")\nof the unknown event. To merely block that, just set 'unknowncallback' to\n\"sub{return('')}\"\n\n'noeotmagic' => 0 or 1\nDetermines whether a track-final 0-length text event is encoded as a\nend-track event -- since a track-final 0-length text event probably started\nlife as an end-track event read in by decode(), above.\n\n'neveraddeot' => 0 or 1\nIf 1, \"encode()\" never ever *adds* an end-track (EOT) event to the encoded\ndata generated unless it's *explicitly* there as an 'endtrack' in the given\nevent structure. You probably don't ever need this unless you're encoding\nfor *straight* writing to a MIDI port, instead of to a file.\n\n'norunningstatus' => 0 or 1\nIf 1, disables MIDI's \"running status\" compression. Probably never necessary\nunless you need to feed your MIDI data to a strange old sequencer that\ndoesn't understand running status.\n\nNote: If you're encoding just a single event at a time or less than a whole trackful in any\ncase, then you probably want something like:\n\n$datar = MIDI::Event::encode(\n[\n[ 'noteon', 141, 4, 50, 64 ]\n],\n{ 'neveraddeot' => 1} );\n\nwhich just encodes that one event *as* an event structure of one event -- i.e., an LoL\nthat's just a list of one list.\n\nBut note that running status will not always apply when you're encoding less than a whole\ntrackful at a time, since running status works only within a LoL encoded all at once.\nThis'll result in non-optimally compressed, but still effective, encoding.\n\nMIDI::Event::copystructure()\nThis takes a *reference* to an event structure, and returns a *reference* to a copy of it.\nIf you're thinking about using this, you probably should want to use the more\nstraightforward\n\n$track2 = $track->copy\n\ninstead. But it's here if you happen to need it.\n",
                "subsections": []
            },
            "EVENTS AND THEIR DATA TYPES": {
                "content": "DATA TYPES\nEvents use these data types:\n\nchannel = a value 0 to 15\nnote = a value 0 to 127\ndtime = a value 0 to 268,435,455 (0x0FFFFFFF)\nvelocity = a value 0 to 127\nchannel = a value 0 to 15\npatch = a value 0 to 127\nsequence = a value 0 to 65,535 (0xFFFF)\ntext = a string of 0 or more bytes of of ASCII text\nraw = a string of 0 or more bytes of binary data\npitchwheel = a value -8192 to 8191 (0x1FFF)\nsongpos = a value 0 to 16,383 (0x3FFF)\nsongnumber = a value 0 to 127\ntempo = microseconds, a value 0 to 16,777,215 (0x00FFFFFF)\n\nFor data types not defined above, (e.g., *sf* and *mi* for 'keysignature'), consult\nMIDI::Filespec and/or the source for \"MIDI::Event.pm\". And if you don't see it documented, it's\nprobably because I don't understand it, so you'll have to consult a real MIDI reference.\n\nEVENTS\nAnd these are the events:\n\n('noteoff', *dtime*, *channel*, *note*, *velocity*)\n('noteon', *dtime*, *channel*, *note*, *velocity*)\n('keyaftertouch', *dtime*, *channel*, *note*, *velocity*)\n('controlchange', *dtime*, *channel*, *controller(0-127)*, *value(0-127)*)\n('patchchange', *dtime*, *channel*, *patch*)\n('channelaftertouch', *dtime*, *channel*, *velocity*)\n('pitchwheelchange', *dtime*, *channel*, *pitchwheel*)\n('setsequencenumber', *dtime*, *sequence*)\n('textevent', *dtime*, *text*)\n('copyrighttextevent', *dtime*, *text*)\n('trackname', *dtime*, *text*)\n('instrumentname', *dtime*, *text*)\n('lyric', *dtime*, *text*)\n('marker', *dtime*, *text*)\n('cuepoint', *dtime*, *text*)\n('textevent08', *dtime*, *text*)\n('textevent09', *dtime*, *text*)\n('textevent0a', *dtime*, *text*)\n('textevent0b', *dtime*, *text*)\n('textevent0c', *dtime*, *text*)\n('textevent0d', *dtime*, *text*)\n('textevent0e', *dtime*, *text*)\n('textevent0f', *dtime*, *text*)\n('endtrack', *dtime*)\n('settempo', *dtime*, *tempo*)\n('smpteoffset', *dtime*, *hr*, *mn*, *se*, *fr*, *ff*)\n('timesignature', *dtime*, *nn*, *dd*, *cc*, *bb*)\n('keysignature', *dtime*, *sf*, *mi*)\n('sequencerspecific', *dtime*, *raw*)\n('rawmetaevent', *dtime*, *command*(0-255), *raw*)\n('sysexf0', *dtime*, *raw*)\n('sysexf7', *dtime*, *raw*)\n('songposition', *dtime*)\n('songselect', *dtime*, *songnumber*)\n('tunerequest', *dtime*)\n('rawdata', *dtime*, *raw*)\n\nThree of the above events are represented a bit oddly from the point of view of the file spec:\n\nThe parameter *pitchwheel* for 'pitchwheelchange' is a value -8192 to 8191, although the\nactual encoding of this is as a value 0 to 16,383, as per the spec.\n\nSysex events are represented as either 'sysexf0' or 'sysexf7', depending on the status byte\nthey are encoded with.\n\n'endtrack' is a bit stranger, in that it is almost never actually found, or needed. When the\nMIDI decoder sees an EOT (i.e., an end-track status: FF 2F 00) with a delta time of 0, it is\n*ignored*! If in the unlikely event that it has a nonzero delta-time, it's decoded as a\n'textevent' with whatever that delta-time is, and a zero-length text parameter. (This happens\nbefore the 'eventcallback' or 'exclusiveeventcallback' callbacks are given a crack at it.) On\nthe encoding side, an EOT is added to the end of the track as a normal part of the encapsulation\nof track data.\n\nI chose to add this special behavior so that you could add events to the end of a track without\nhaving to work around any track-final 'endtrack' event.\n\nHowever, if you set \"noeotmagic\" as a decoding parameter, none of this magic happens on the\ndecoding side -- 'endtrack' is decoded just as it is.\n\nAnd if you set \"noeotmagic\" as an encoding parameter, then a track-final 0-length 'textevent'\nwith non-0 delta-times is left as is. Normally, such an event would be converted from a\n'textevent' to an 'endtrack' event with thath delta-time.\n\nNormally, no user needs to use the \"noeotmagic\" option either in encoding or decoding. But it\nis provided in case you need your event LoL to be an absolutely literal representation of the\nbinary data, and/or vice versa.\n",
                "subsections": []
            },
            "MIDI BNF": {
                "content": "For your reference (if you can make any sense of it), here is a copy of the MIDI BNF, as I found\nit in a text file that's been floating around the Net since the late 1980s.\n\nNote that this seems to describe MIDI events as they can occur in MIDI-on-the-wire. I *think*\nthat realtime data insertion (i.e., the ability to have <realtime byte>s popping up in the\n*middle* of messages) is something that can't happen in MIDI files.\n\nIn fact, this library, as written, *can't* correctly parse MIDI data that has such realtime\nbytes inserted in messages. Nor does it support representing such insertion in a MIDI event\nstructure that's encodable for writing to a file. (Although you could theoretically represent\nevents with embedded <realtime byte>s as just \"rawdata\" events; but then, you can always stow\nanything at all in a \"rawdata\" event.)\n\n1.  <MIDI Stream> ::=           <MIDI msg> < MIDI Stream>\n2.  <MIDI msg> ::=              <sys msg> | <chan msg>\n3.  <chan msg> ::=              <chan 1byte msg> |\n| <chan 2byte msg>\n4.  <chan 1byte msg> ::=        <chan stat1 byte> <data singlet>\n<running singlets>\n5.  <chan 2byte msg> ::=        <chan stat2 byte> <data pair>\n<running pairs>\n6.  <chan stat1 byte> ::=       <chan voice stat1 nibble>\n<hex nibble>\n7.  <chan stat2 byte> ::=       <chan voice stat2 nibble>\n<hex nibble>\n8.  <chan voice stat1 nyble>::= C | D\n9.  <chan voice stat2 nyble>::= 8 | 9 | A | B | E\n10. <hex nyble> ::=             0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |\n| 8 | 9 | A | B | C | D | E | F\n11. <data pair> ::=             <data singlet> <data singlet>\n12. <data singlet> ::=          <realtime byte> <data singlet> |\n| <data byte>\n13. <running pairs> ::=         <empty> | <data pair> <running pairs>\n14. <running singlets> ::=      <empty> |\n| <data singlet> <running singlets>\n15. <data byte> ::=             <data MSD> <hex nyble>\n16. <data MSD> ::=              0 | 1 | 2 | 3 | 4 | 5 | 6 | 7\n17. <realtime byte> ::=         F8 | FA | FB | FC | FE | FF\n18. <sys msg> ::=               <sys common msg> |\n| <sysex msg> |\n| <sys realtime msg>\n19. <sys realtime msg> ::=      <realtime byte>\n20. <sysex msg> ::=             <sysex data byte>\n<data singlet> <running singlets>\n<eox byte>\n21. <sysex stat byte> ::=       F0\n22. <eox byte> ::=              F7\n23. <sys common msg> ::=        <song position msg> |\n| <song select msg> |\n| <tune request>\n24. <tune request> ::=          F6\n25. <song position msg> ::=     <song position stat byte>\n<data pair>\n26. <song select msg> ::=       <song select stat byte>\n<data singlet>\n27. <song position stat byte>::=F2\n28. <song select stat byte> ::= F3\n",
                "subsections": []
            },
            "COPYRIGHT": {
                "content": "Copyright (c) 1998-2005 Sean M. Burke. All rights reserved.\n\nThis library is free software; you can redistribute it and/or modify it under the same terms as\nPerl itself.\n",
                "subsections": []
            },
            "AUTHOR": {
                "content": "Sean M. Burke \"sburke@cpan.org\" (Except the BNF -- who knows who's behind that.)\n",
                "subsections": []
            }
        }
    }
}