midi

package
v0.0.0-...-8ab7c96 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 22, 2016 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

MIDI package is a midi format parser that parses the content of a midi stream and asyncronously send the data to a provided channel or collect the data into an accessible struct,

Index

Constants

View Source
const (
	MetricalTF timeFormat = iota + 1
	TimeCodeTF
)
View Source
const (
	SingleTrack uint16 = iota
	Syncronous
	Asyncronous
)

Variables

View Source
var (

	// ErrFmtNotSupported is a generic error reporting an unknown format.
	ErrFmtNotSupported = errors.New("format not supported")
	// ErrUnexpectedData is a generic error reporting that the parser encountered unexpected data.
	ErrUnexpectedData = errors.New("unexpected data content")
)
View Source
var CCNames = map[int]string{}/* 128 elements not displayed */
View Source
var CCVals = map[string]int{
	"Bank Select":                             0,
	"Modulation Wheel or Lever":               1,
	"Breath Controller":                       2,
	"Undefined":                               3,
	"Foot Controller":                         4,
	"Portamento Time":                         5,
	"Data Entry MSB":                          6,
	"Channel Volume":                          7,
	"Balance":                                 8,
	"Pan":                                     10,
	"Expression Controller":                   11,
	"Effect Control 1":                        12,
	"Effect Control 2":                        13,
	"General Purpose Controller 1":            16,
	"General Purpose Controller 2":            17,
	"General Purpose Controller 3":            18,
	"General Purpose Controller 4":            19,
	"Control 0 Bank Select":                   32,
	"Control 1 Modulation Wheel or Lever":     33,
	"Control 2 Breath Controller":             34,
	"Control 4 Foot Controller":               36,
	"Control 5 Portamento Time":               37,
	"Control 6 Data Entry":                    38,
	"Control 7 Channel Volume":                39,
	"Control 8 Balance":                       40,
	"Control 10 Pan":                          42,
	"Control 11 Expression Controller":        43,
	"Control 12 Effect control 1":             44,
	"Control 13 Effect control 2":             45,
	"Control 16 General Purpose Controller 1": 48,
	"Control 17 General Purpose Controller 2": 49,
	"Control 18 General Purpose Controller 3": 50,
	"Control 19 General Purpose Controller 4": 51,
	"Sustain":                                 64,
	"Portamento":                              65,
	"Sostenuto":                               66,
	"Soft Pedal":                              66,
	"Legato Footswitch":                       68,
	"Hold 2":                                  69,
	"Sound Variation":                         70,
	"Timbre/Harmonic Intens.":                 71,
	"Release Time":                            72,
	"Attack Time":                             73,
	"Brightness":                              74,
	"Decay Time":                              75,
	"Vibrato Rate":                            76,
	"Vibrato Depth":                           77,
	"Vibrato Delay":                           78,
	"General Purpose Controller 5":            80,
	"General Purpose Controller 6":            81,
	"General Purpose Controller 7":            82,
	"General Purpose Controller 8":            83,
	"Portamento Control":                      84,
	"High Resolution Velocity Prefix":         88,
	"Effects 1 Depth":                         91,
	"Effects 2 Depth":                         92,
	"Effects 3 Depth":                         93,
	"Effects 4 Depth":                         94,
	"Effects 5 Depth":                         95,
	"Data Increment":                          96,
	"Data Decrement":                          97,
	"All Sound Off":                           120,
	"Reset All Controllers":                   121,
	"Local Control":                           122,
	"All Notes Off":                           123,
	"Omni Mode Off":                           124,
	"Omni Mode On":                            125,
	"Mono Mode On":                            126,
	"Poly Mode On":                            127,
}
View Source
var EventByteMap = map[string]byte{
	"NoteOff":           0x8,
	"NoteOn":            0x9,
	"AfterTouch":        0xA,
	"ControlChange":     0xB,
	"ProgramChange":     0xC,
	"ChannelAfterTouch": 0xD,
	"PitchWheelChange":  0xE,
	"Meta":              0xF,
}

EventByteMap takes an event name and returns its equivalent MIDI byte

View Source
var EventMap = map[byte]string{
	0x8: "NoteOff",
	0x9: "NoteOn",
	0xA: "AfterTouch",
	0xB: "ControlChange",
	0xC: "ProgramChange",
	0xD: "ChannelAfterTouch",
	0xE: "PitchWheelChange",
	0xF: "Meta",
}

EventMap takes a event byte and returns its matching event name. http://www.midi.org/techspecs/midimessages.php

View Source
var Notes = []string{"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"}

Functions

func DecodeVarint

func DecodeVarint(buf []byte) (x uint32, n int)

DecodeVarint reads a varint-encoded integer from the slice. It returns the integer and the number of bytes consumed, or zero if there is not enough.

func EncodeVarint

func EncodeVarint(x uint32) []byte

EncodeVarint returns the varint encoding of x.

func FreqToNote

func FreqToNote(freq float64) int

FreqToNote reports the associated midi node for a given frequency.

func KeyFreq

func KeyFreq(n string, octave int) float64

KeyFreq returns the frequency for the given key/octave combo https://en.wikipedia.org/wiki/MIDI_Tuning_Standard#Frequency_values

func KeyInt

func KeyInt(n string, octave int) int

KeyInt converts an A-G note notation to a midi note number value.

func NoteToFreq

func NoteToFreq(note int) float64

NoteToFreq returns the frequency of the passed midi note.

func NoteToName

func NoteToName(note int) string

NoteToName converts a midi note value into its English name

func Uint24

func Uint24(n uint32) []byte

Uint24 converts a uint32 into a uint24 (big endian)

Types

type ControlChangeEvent

type ControlChangeEvent struct {
	Channel int
	ID      int
	Value   int
	Name    string
}

type Decoder

type Decoder struct {
	Ch chan *Track
	/*
	   Format describes the tracks format

	   0	-	single-track
	   Format 0 file has a header chunk followed by one track chunk. It
	   is the most interchangable representation of data. It is very useful
	   for a simple single-track player in a program which needs to make
	   synthesizers make sounds, but which is primarily concerened with
	   something else such as mixers or sound effect boxes. It is very
	   desirable to be able to produce such a format, even if your program
	   is track-based, in order to work with these simple programs. On the
	   other hand, perhaps someone will write a format conversion from
	   format 1 to format 0 which might be so easy to use in some setting
	   that it would save you the trouble of putting it into your program.


	   Synchronous multiple tracks means that the tracks will all be vertically synchronous, or in other words,
	    they all start at the same time, and so can represent different parts in one song.
	    1	-	multiple tracks, synchronous
	    Asynchronous multiple tracks do not necessarily start at the same time, and can be completely asynchronous.
	    2	-	multiple tracks, asynchronous
	*/
	Format uint16

	// NumTracks represents the number of tracks in the midi file
	NumTracks uint16

	TicksPerQuarterNote uint16

	TimeFormat timeFormat
	Tracks     []*Track
	// contains filtered or unexported fields
}
  Decoder
 Format documented there: http://www.music.mcgill.ca/~ich/classes/mumt306/midiformat.pdf
 <Header Chunk> = <chunk type><length><format><ntrks><division>

				Division, specifies the meaning of the delta-times.
				It has two formats, one for metrical time, and one for time-code-based
				time:
				 +---+-----------------------------------------+
				 | 0 | ticks per quarter-note                  |
				 ==============================================|
				 | 1 | negative SMPTE format  | ticks per frame|
				 +---+-----------------------+-----------------+
				 |15 |14                    8 |7             0 |
				If bit 15 of <division> is zero, the bits 14 thru 0 represent the number
				of delta time "ticks" which make up a quarter-note. For instance, if
				division is 96, then a time interval of an eighth-note between two
				events in the file would be 48.
		    If bit 15 of <division> is a one, delta times in a file correspond
		    to subdivisions of a second, in a way consistent with SMPTE and MIDI
		    Time Code. Bits 14 thru 8 contain one of the four values -24, -25, -29,
		    or -30, corresponding to the four standard SMPTE and MIDI Time Code
		    formats (-29 corresponds to 30 drop frome), and represents the
		    number of frames per second. These negative numbers are stored in
		    two's compliment form. The second byte (stored positive) is the
		    resolution within a frame: typical values may be 4 (MIDI Time Code
		    resolution), 8, 10, 80 (bit resolution), or 100. This stream allows
		    exact specifications of time-code-based tracks, but also allows
		    milisecond-based tracks by specifying 25|frames/sec and a
		    resolution of 40 units per frame. If the events in a file are stored
		    with a bit resolution of thirty-framel time code, the division word
		    would be E250 hex.

func NewDecoder

func NewDecoder(r io.Reader) *Decoder

func NewParser

func NewParser(r io.Reader, ch chan *Track) *Decoder

func (*Decoder) CurrentTrack

func (d *Decoder) CurrentTrack() *Track

func (*Decoder) IDnSize

func (d *Decoder) IDnSize() ([4]byte, uint32, error)

IDnSize returns the next ID + block size

func (*Decoder) Parse

func (d *Decoder) Parse() error

func (*Decoder) Read

func (d *Decoder) Read(dst interface{}) error

read reads n bytes from the parser's reader and stores them into the provided dst, which must be a pointer to a fixed-size value.

func (*Decoder) ReadByte

func (d *Decoder) ReadByte() (byte, error)

func (*Decoder) Uint24

func (d *Decoder) Uint24() (uint32, error)

Uint24 reads 3 bytes and convert them into a uint32

func (*Decoder) Uint7

func (d *Decoder) Uint7() (uint8, error)

Uint7 reads a byte and converts the first 7 bits into an uint8

func (*Decoder) VarLen

func (d *Decoder) VarLen() (val uint32, readBytes uint32, err error)

VarLen returns the variable length value at the exact parser location.

func (*Decoder) VarLenTxt

func (d *Decoder) VarLenTxt() (string, uint32, error)

VarLengthTxt Returns a variable length text string as well as the amount of bytes read

type Encoder

type Encoder struct {

	/*
	   Format describes the tracks format

	   0	-	single-track
	   Format 0 file has a header chunk followed by one track chunk. It
	   is the most interchangable representation of data. It is very useful
	   for a simple single-track player in a program which needs to make
	   synthesizers make sounds, but which is primarily concerened with
	   something else such as mixers or sound effect boxes. It is very
	   desirable to be able to produce such a format, even if your program
	   is track-based, in order to work with these simple programs. On the
	   other hand, perhaps someone will write a format conversion from
	   format 1 to format 0 which might be so easy to use in some setting
	   that it would save you the trouble of putting it into your program.


	   Synchronous multiple tracks means that the tracks will all be vertically synchronous, or in other words,
	    they all start at the same time, and so can represent different parts in one song.
	    1	-	multiple tracks, synchronous
	    Asynchronous multiple tracks do not necessarily start at the same time, and can be completely asynchronous.
	    2	-	multiple tracks, asynchronous
	*/
	Format uint16

	// NumTracks represents the number of tracks in the midi file
	NumTracks uint16

	// resolution for delta timing
	TicksPerQuarterNote uint16

	TimeFormat timeFormat
	Tracks     []*Track
	// contains filtered or unexported fields
}

func NewEncoder

func NewEncoder(w io.WriteSeeker, format uint16, ppqn uint16) *Encoder

func (*Encoder) NewTrack

func (e *Encoder) NewTrack() *Track

NewTrack adds and return a new track (not thread safe)

func (*Encoder) Write

func (e *Encoder) Write() error

Write writes the binary representation to the writer

type Event

type Event struct {
	TimeDelta    uint32
	MsgType      uint8
	MsgChan      uint8
	Note         uint8
	Velocity     uint8
	Pressure     uint8
	Controller   uint8
	NewValue     uint8
	NewProgram   uint8
	Channel      uint8
	AbsPitchBend uint16
	RelPitchBend int16
	// Meta
	Cmd            uint8
	SeqNum         uint16
	Text           string
	Copyright      string
	SeqTrackName   string
	InstrumentName string
	Lyric          string
	Marker         string
	CuePoint       string
	MsPerQuartNote uint32
	Bpm            uint32
	TimeSignature  *TimeSignature
	// A positive value for the key specifies the number of sharps and a negative value specifies the number of flats.
	Key int32 //-7 to +7
	// A value of 0 for the scale specifies a major key and a value of 1 specifies a minor key.
	Scale uint32 // 0 or 1
	//
	SmpteOffset *SmpteOffset
}

Event <event> = <MIDI event> | <sysex event> | <meta-event> <MIDI event> is any MIDI channel message. Running status is used: status bytes of MIDI channel messages may be omitted if the preceding event is a MIDI channel message with the same status. The first event in each MTrk chunk must specifyy status. Delta-time is not considered an event itself: it is an integral part of the syntax for an MTrk event. Notice that running status occurs across delta-times. See http://www.indiana.edu/~emusic/etext/MIDI/chapter3_MIDI4.shtml

func Aftertouch

func Aftertouch(channel, key, vel int) *Event

AfterTouch returns a pointer to a new aftertouch event

func ChannelAfterTouch

func ChannelAfterTouch(channel, vel int) *Event

ChannelAfterTouch is a global aftertouch with a value from 0 to 127

func ControlChange

func ControlChange(channel, controller, newVal int) *Event

ControlChange sets a new value for a given controller The controller number is between 0-119. The new controller value is between 0-127.

func CopyrightEvent

func CopyrightEvent(txt string) *Event

CopyrightEvent returns a copyright event with the passed string in it.

func Meta

func Meta(channel int) *Event

TODO

func NoteOff

func NoteOff(channel, key int) *Event

NoteOff returns a pointer to a new event of type NoteOff (without the delta timing data)

func NoteOn

func NoteOn(channel, key, vel int) *Event

NoteOn returns a pointer to a new event of type NoteOn (without the delta timing data)

func PitchWheelChange

func PitchWheelChange(channel, int, val int) *Event

PitchWheelChange is sent to indicate a change in the pitch bender. The possible value goes between 0 and 16383 where 8192 is the center.

func ProgramChange

func ProgramChange(channel, controller, newVal int) *Event

ProgramChange sets a new value the same way as ControlChange but implements Mode control and special message by using reserved controller numbers 120-127.

func TempoEvent

func TempoEvent(bpmF float64) *Event

TempoEvent returns a new tempo event of the passed value.

func (*Event) Encode

func (e *Event) Encode() []byte

Encode converts an Event into a slice of bytes ready to be written to a file.

func (*Event) Size

func (e *Event) Size() uint32

Size represents the byte size to encode the event

func (*Event) String

func (e *Event) String() string

String implements the stringer interface

type Note

type Note struct {
	Channel  int
	Key      int
	Velocity int
}

type SmpteOffset

type SmpteOffset struct {
	Hour  uint8
	Min   uint8
	Sec   uint8
	Fr    uint8
	SubFr uint8
}

type TimeSignature

type TimeSignature struct {
	Numerator                   uint8
	Denominator                 uint8
	ClocksPerTick               uint8
	ThirtySecondNotesPerQuarter uint8
}

Time signature FF 58 04 nn dd cc bb Time Signature The time signature is expressed as four numbers. nn and dd represent the numerator and denominator of the time signature as it would be notated. The denominator is a negative power of two: 2 represents a quarter-note, 3 represents an eighth-note, etc. The cc parameter expresses the number of MIDI clocks in a metronome click. The bb parameter expresses the number of notated 32nd-notes in a MIDI quarter-note (24 MIDI clocks). This was added because there are already multiple programs which allow a user to specify that what MIDI thinks of as a quarter-note (24 clocks) is to be notated as, or related to in terms of, something else.

func (*TimeSignature) String

func (ts *TimeSignature) String() string

type Track

type Track struct {
	Size   uint32
	Events []*Event
	// contains filtered or unexported fields
}

Track <Track Chunk> = <chunk type><length><MTrk event> <MTrk event> = <delta-time><event>

func (*Track) Add

func (t *Track) Add(beatDelta float64, e *Event)

Add schedules the passed event after x beats (relative to the previous event)

func (*Track) ChunkData

func (t *Track) ChunkData() ([]byte, error)

ChunkData converts the track and its events into a binary byte slice (chunk header included)

Directories

Path Synopsis
cmd
gen

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL