mid

package
v1.8.5 Latest Latest
Warning

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

Go to latest
Published: Feb 8, 2019 License: MIT Imports: 20 Imported by: 0

README

mid

Porcelain library for reading and writing MIDI and SMF (Standard MIDI File)

Description

Package mid provides an easy abstraction for reading and writing of "live" MIDI and SMF (Standard MIDI File) data.

MIDI data could be written the following ways:

  • NewWriter is used to write "live" MIDI to an io.Writer.
  • NewSMF is used to write SMF MIDI to an io.Writer.
  • NewSMFFile is used to write a complete SMF file.
  • WriteTo writes "live" MIDI to an connect.Out, aka MIDI out port

To read, create a Reader and attach callbacks to it. Then MIDI data could be read the following ways:

  • Reader.Read reads "live" MIDI from an io.Reader.
  • Reader.ReadSMF reads SMF MIDI from an io.Reader.
  • Reader.ReadSMFFile reads a complete SMF file.
  • Reader.ReadFrom reads "live" MIDI from an connect.In, aka MIDI in port

For a simple example with "live" MIDI and io.Reader and io.Writer see the example below.

Example

We use an io.Writer to write to and io.Reader to read from. They are connected by the same io.Pipe.

package main

import (
    "fmt"
    "gitlab.com/gomidi/midi/mid"
    "io"
    "time"
)

// callback for note on messages
func noteOn(p *mid.Position, channel, key, vel uint8) {
    fmt.Printf("NoteOn (ch %v: key %v vel: %v)\n", channel, key, vel)
}

// callback for note off messages
func noteOff(p *mid.Position, channel, key, vel uint8) {
    fmt.Printf("NoteOff (ch %v: key %v)\n", channel, key)
}

func main() {
    fmt.Println()

    // to disable logging, pass mid.NoLogger() as option
    rd := mid.NewReader()

    // set the functions for the messages you are interested in
    rd.Msg.Channel.NoteOn = noteOn
    rd.Msg.Channel.NoteOff = noteOff

    // to allow reading and writing concurrently in this example
    // we need a pipe
    piperd, pipewr := io.Pipe()

    go func() {
        wr := mid.NewWriter(pipewr)
        wr.SetChannel(11) // sets the channel for the next messages
        wr.NoteOn(120, 50)
        time.Sleep(time.Second) // let the note ring for 1 sec
        wr.NoteOff(120)
        pipewr.Close() // finishes the writing
    }()

    for {
        if rd.Read(piperd) == io.EOF {
            piperd.Close() // finishes the reading
            break
        }
    }

    // Output:
    // channel.NoteOn channel 11 key 120 velocity 50
    // NoteOn (ch 11: key 120 vel: 50)
    // channel.NoteOff channel 11 key 120
    // NoteOff (ch 11: key 120)
}

Documentation

Overview

Package mid provides an easy abstraction for reading and writing of "live" MIDI and SMF (Standard MIDI File) data.

MIDI data could be written the following ways:

  • WriteTo writes "live" MIDI to an OutConnection, aka MIDI out port
  • NewWriter is used to write "live" MIDI to an io.Writer.
  • NewSMF is used to write SMF MIDI to an io.Writer.
  • NewSMFFile is used to write a complete SMF file.

To read, create a Reader and attach callbacks to it. Then MIDI data could be read the following ways:

  • Reader.ReadFrom reads "live" MIDI from an InConnection, aka MIDI in port
  • Reader.Read reads "live" MIDI from an io.Reader.
  • Reader.ReadSMF reads SMF MIDI from an io.Reader.
  • Reader.ReadSMFFile reads a complete SMF file.

For a simple example with "live" MIDI and io.Reader and io.Writer see examples/simple/simple_test.go.

To connect with the MIDI ports of your computer (via InConnection and OutConnection), use it with the adapter packages for rtmidi and portaudio at https://github.com/gomidi/connect.

There you can find a simple example how to do it.

Example
package main

import (
	"bytes"
	"fmt"
	"io"
	"time"

	"gitlab.com/gomidi/midi/smf"
)

// makeSMF makes a SMF
func makeSMF() io.Reader {
	var bf bytes.Buffer
	wr := NewSMF(&bf, 1 /* number of tracks */)
	wr.TempoBPM(160 /* beats per minute */)
	wr.Meter(4, 4) /* set the meter of 4/4 */
	wr.SetChannel(2 /* valid: 0-15 */)
	wr.NoteOn(65 /* key */, 90 /* velocity */)
	wr.Forward(1, 0, 0) // forwards the cursor to the next bar (we make a whole note)
	wr.NoteOff(65 /* key */)
	wr.EndOfTrack() // required at the end of a track
	return bytes.NewReader(bf.Bytes())
}

// roundSec is a helper to round the duration to seconds
func roundSec(d time.Duration) time.Duration {
	return time.Second * time.Duration((d.Nanoseconds() / 1000000000))
}

type example struct {
	ticks smf.MetricTicks
	bpm   float64
	start time.Time
}

// SMFHeader tracks the ticks from the SMF file
func (e *example) SMFHeader(head smf.Header) {
	// here we ignore that the timeformat could also be SMPTE
	e.ticks = head.TimeFormat.(smf.MetricTicks)
}

// Tempo tracks a tempo change
func (e *example) TempoBPM(p Position, bpm float64) {
	e.bpm = bpm
}

// NoteOn responds to note on messages
func (e *example) NoteOn(p *Position, channel, key, vel uint8) {
	fmt.Printf("[%vs] NoteOn at channel %v: key %v velocity: %v\n",
		e.calcDuration(p).Seconds(), channel, key, vel)
}

func (e *example) NoteOff(p *Position, channel, key, vel uint8) {
	fmt.Printf("[%vs] NoteOff at channel %v: key %v velocity: %v\n",
		e.calcDuration(p).Seconds(),
		channel, key, vel)
}

// a helper to calculate the duration for both live and SMF messages
func (e *example) calcDuration(p *Position) (dur time.Duration) {
	// we are in a live setting
	if p == nil {
		dur = roundSec(time.Now().Sub(e.start))
		return
	}

	// here p is not nil - that means we are reading the SMF

	// calculate the time from the timeformat of the SMF file
	// to make it easy, we ignore the possibility that tempo information may be in another track
	// that is read after this track (the SMF spec recommends to write tempo changes to the first track)
	// however, since makeSMF just creates one track, we are safe
	return roundSec(e.ticks.FractionalDuration(e.bpm, uint32(p.AbsoluteTicks)))
}

func main() {
	// This example illustrates how the same handler can be used for live and SMF MIDI messages
	// It also illustrates how live and SMF midi can be written

	rd := NewReader(NoLogger() /* disable default logging*/)

	var ex example
	ex.bpm = 120 // default according to SMF spec

	// setup the callbacks
	rd.SMFHeader = ex.SMFHeader
	rd.Msg.Meta.TempoBPM = ex.TempoBPM
	rd.Msg.Channel.NoteOn = ex.NoteOn
	rd.Msg.Channel.NoteOff = ex.NoteOff

	// handle the smf
	fmt.Println("-- SMF data --")
	rd.ReadSMF(makeSMF())

	// handle the live data
	fmt.Println("-- live data --")

	// we need a pipe to read and write concurrently
	piperd, pipewr := io.Pipe()

	go func() {
		wr := NewWriter(pipewr)

		// reset the time
		ex.start = time.Now()

		wr.SetChannel(11)

		// now write some live data
		wr.NoteOn(120, 50)
		time.Sleep(time.Second * 2)
		wr.NoteOff(120)
		pipewr.Close() // close the pipe we're done writing
	}()

	for {
		if rd.Read(piperd) == io.EOF {
			piperd.Close() // we're done reading
			break
		}
	}

}
Output:

-- SMF data --
[0s] NoteOn at channel 2: key 65 velocity: 90
[1s] NoteOff at channel 2: key 65 velocity: 0
-- live data --
[0s] NoteOn at channel 11: key 120 velocity: 50
[2s] NoteOff at channel 11: key 120 velocity: 0

Index

Examples

Constants

View Source
const LiveResolution = smf.MetricTicks(1920)

LiveResolution is the resolution used for live over the wire reading with Reader.ReadFrom

Variables

View Source
var ErrClosed = fmt.Errorf("ERROR: port is closed")

ErrClosed should be returned from a driver when trying to write to a closed port.

Functions

func NewSMFFile

func NewSMFFile(file string, numtracks uint16, writer func(*SMFWriter) error, options ...smfwriter.Option) error

NewSMFFile creates a new SMF file and allows writer to write to it. The file is guaranteed to be closed when returning. The last track is closed automatically, if needed. It panics if numtracks is == 0.

Types

type Driver added in v1.7.4

type Driver interface {

	// Ins returns the available MIDI input ports
	Ins() ([]In, error)

	// Outs returns the available MIDI output ports
	Outs() ([]Out, error)

	// String returns the name of the driver
	String() string

	// Close closes the driver. Must be called for cleanup at the end of a session
	Close() error
}

Driver is a driver for MIDI connections.

type In added in v1.7.4

type In interface {
	Port

	// SetListener sets the callback function that is called when data arrives
	// println(big.NewRat(math.MaxInt64,1000 /* milliseonds */ *1000 /* seconds */ *60 /* minutes */ *60 /* hours */ *24 /* days */ *365 /* years */).FloatString(0))
	// output: 292471
	// => a ascending timestamp based on microseconds would wrap after 292471 years
	SetListener(func(data []byte, deltaMicroseconds int64)) error

	// StopListening stops the listening
	// When closing an MIDI input port, StopListening must be called before (from the driver)
	StopListening() error
}

In is an interface for a MIDI in port

func OpenIn added in v1.7.4

func OpenIn(d Driver, number int, name string) (in In, err error)

OpenIn opens a MIDI port with the help of the given driver To find the port by port number, pass a number >= 0. To find the port by port name, pass a number < 0 and a non empty string.

type Logger

type Logger interface {
	Printf(format string, vals ...interface{})
}

Logger is the inferface used by Reader for logging incoming messages.

type Out added in v1.7.4

type Out interface {
	Port

	// Send sends the given MIDI bytes over the wire.
	// If the port is closed, ErrClosed must be returned
	Send([]byte) error
}

Out is an interface for a MIDI out port

func OpenOut added in v1.7.4

func OpenOut(d Driver, number int, name string) (out Out, err error)

OpenOut opens a MIDI port with the help of the given driver To find the port by port number, pass a number >= 0. To find the port by port name, pass a number < 0 and a non empty string.

type Port added in v1.7.4

type Port interface {

	// Open opens the MIDI port. An implementation should save the open state to make it
	// save to call open when the port is already open without getting an error.
	Open() error

	// Close closes the MIDI port. An implementation should save the open state to make it
	// save to call close when the port is already closed without getting an error.
	Close() error

	// IsOpen returns wether the MIDI port is open
	IsOpen() bool

	// Number returns the number of the MIDI port. It is only guaranteed that the numbers are unique within
	// MIDI port groups i.e. within MIDI input ports and MIDI output ports. So there may be the same number
	// for a given MIDI input port and some MIDI output port. Or not - that depends on the underlying driver.
	// outport
	Number() int

	// String represents the MIDI port by a string, aka name.
	String() string

	// Underlying returns the underlying driver to allow further adjustments
	// When using the underlying driver, the use user must take care of proper opening/closing etc.
	Underlying() interface{}
}

Port is an interface for a MIDI port

type Position added in v1.7.0

type Position struct {

	// Track is the number of the track, starting with 0
	Track int16

	// DeltaTicks is number of ticks that passed since the previous message in the same track
	DeltaTicks uint32

	// AbsoluteTicks is the number of ticks that passed since the beginning of the track
	AbsoluteTicks uint64
}

Position is the position of the event inside a standard midi file (SMF) or since start listening on a connection.

type Reader added in v1.7.0

type Reader struct {

	// SMFHeader is the callback that gets SMF header data
	SMFHeader func(smf.Header)

	// Msg provides callbacks for MIDI messages
	Msg struct {

		// Each is called for every MIDI message in addition to the other callbacks.
		Each func(*Position, midi.Message)

		// Unknown is called for undefined or unknown messages
		Unknown func(p *Position, msg midi.Message)

		// Meta provides callbacks for meta messages (only in SMF files)
		Meta struct {

			// Copyright is called for the copyright message
			Copyright func(p Position, text string)

			// TempoBPM is called for the tempo (change) message, BPM is fractional
			TempoBPM func(p Position, bpm float64)

			// TimeSigis called for the time signature (change) message
			TimeSig func(p Position, num, denom uint8)

			// Key is called for the key signature (change) message
			Key func(p Position, key uint8, ismajor bool, num_accidentals uint8, accidentals_are_flat bool)

			// Track is called for the track (name) message
			Track func(p Position, name string)

			// Sequence is called for the sequence (name) message
			Sequence func(p Position, name string)

			// SequenceNo is called for the sequence number message
			SequenceNo func(p Position, number uint16)

			// Marker is called for the marker message
			Marker func(p Position, text string)

			// Cuepoint is called for the cuepoint message
			Cuepoint func(p Position, text string)

			// Text is called for the text message
			Text func(p Position, text string)

			// Lyric is called for the lyric message
			Lyric func(p Position, text string)

			// EndOfTrack is called for the end of a track message
			EndOfTrack func(p Position)

			// Device is called for the device port message
			Device func(p Position, name string)

			// Program is called for the program name message
			Program func(p Position, text string)

			// SMPTE is called for the smpte offset message
			SMPTE func(p Position, hour, minute, second, frame, fractionalFrame byte)

			// SequencerData is called for the sequencer specific message
			SequencerData func(p Position, data []byte)

			Deprecated struct {
				// Channel is called for the deprecated MIDI channel message
				Channel func(p Position, channel uint8)

				// Port is called for the deprecated MIDI port message
				Port func(p Position, port uint8)
			}
		}

		// Channel provides callbacks for channel messages
		// They may occur in SMF files and in live MIDI.
		// For live MIDI *Position is nil.
		Channel struct {

			// NoteOn is just called for noteon messages with a velocity > 0.
			// Noteon messages with velocity == 0 will trigger NoteOff with a velocity of 0.
			NoteOn func(p *Position, channel, key, velocity uint8)

			// NoteOff is called for noteoff messages (then the given velocity is passed)
			// and for noteon messages of velocity 0 (then velocity is 0).
			NoteOff func(p *Position, channel, key, velocity uint8)

			// Pitchbend is called for pitch bend messages
			Pitchbend func(p *Position, channel uint8, value int16)

			// ProgramChange is called for program change messages. Program numbers start with 0.
			ProgramChange func(p *Position, channel, program uint8)

			// Aftertouch is called for aftertouch messages  (aka "channel pressure")
			Aftertouch func(p *Position, channel, pressure uint8)

			// PolyAftertouch is called for polyphonic aftertouch messages (aka "key pressure").
			PolyAftertouch func(p *Position, channel, key, pressure uint8)

			// ControlChange deals with control change messages
			ControlChange struct {

				// Each is called for every control change message
				// If RPN or NRPN callbacks are defined, the corresponding control change messages will not
				// be passed to each and the corrsponding RPN/NRPN callback are called.
				Each func(p *Position, channel, controller, value uint8)

				// RPN deals with Registered Program Numbers (RPN) and their values.
				// If the callbacks are set, the corresponding control change messages will not be passed of ControlChange.Each.
				RPN struct {

					// MSB is called, when the MSB of a RPN arrives
					MSB func(p *Position, channel, typ1, typ2, msbVal uint8)

					// LSB is called, when the MSB of a RPN arrives
					LSB func(p *Position, channel, typ1, typ2, lsbVal uint8)

					// Increment is called, when the increment of a RPN arrives
					Increment func(p *Position, channel, typ1, typ2 uint8)

					// Decrement is called, when the decrement of a RPN arrives
					Decrement func(p *Position, channel, typ1, typ2 uint8)

					// Reset is called, when the reset or null RPN arrives
					Reset func(p *Position, channel uint8)
				}

				// NRPN deals with Non-Registered Program Numbers (NRPN) and their values.
				// If the callbacks are set, the corresponding control change messages will not be passed of ControlChange.Each.
				NRPN struct {

					// MSB is called, when the MSB of a NRPN arrives
					MSB func(p *Position, channel uint8, typ1, typ2, msbVal uint8)

					// LSB is called, when the LSB of a NRPN arrives
					LSB func(p *Position, channel uint8, typ1, typ2, msbVal uint8)

					// Increment is called, when the increment of a NRPN arrives
					Increment func(p *Position, channel, typ1, typ2 uint8)

					// Decrement is called, when the decrement of a NRPN arrives
					Decrement func(p *Position, channel, typ1, typ2 uint8)

					// Reset is called, when the reset or null NRPN arrives
					Reset func(p *Position, channel uint8)
				}
			}
		}

		// Realtime provides callbacks for realtime messages.
		// They are only used with "live" MIDI
		Realtime struct {

			// Clock is called for a clock message
			Clock func()

			// Tick is called for a tick message
			Tick func()

			// Activesense is called for a active sense message
			Activesense func()

			// Start is called for a start message
			Start func()

			// Stop is called for a stop message
			Stop func()

			// Continue is called for a continue message
			Continue func()

			// Reset is called for a reset message
			Reset func()
		}

		// SysCommon provides callbacks for system common messages.
		// They are only used with "live" MIDI
		SysCommon struct {

			// Tune is called for a tune request message
			Tune func()

			// SongSelect is called for a song select message
			SongSelect func(num uint8)

			// SPP is called for a song position pointer message
			SPP func(pos uint16)

			// MTC is called for a MIDI timing code message
			MTC func(frame uint8)
		}

		// SysEx provides callbacks for system exclusive messages.
		// They may occur in SMF files and in live MIDI.
		// For live MIDI *Position is nil.
		SysEx struct {

			// Complete is called for a complete system exclusive message
			Complete func(p *Position, data []byte)

			// Start is called for a starting system exclusive message
			Start func(p *Position, data []byte)

			// Continue is called for a continuing system exclusive message
			Continue func(p *Position, data []byte)

			// End is called for an ending system exclusive message
			End func(p *Position, data []byte)

			// Escape is called for an escaping system exclusive message
			Escape func(p *Position, data []byte)
		}
	}
	// contains filtered or unexported fields
}

Reader allows the reading of either "over the wire" MIDI data (via Read) or SMF MIDI data (via ReadSMF or ReadSMFFile).

Before any of the Read* methods are called, callbacks for the MIDI messages of interest need to be attached to the Reader. These callbacks are then invoked when the corresponding MIDI message arrives. They must not be changed while any of the Read* methods is running.

It is possible to share the same Reader for reading of the wire MIDI ("live") and SMF Midi data as long as not more than one Read* method is running at a point in time. However, only channel messages and system exclusive message may be used in both cases. To enable this, the corresponding callbacks receive a pointer to the Position of the MIDI message. This pointer is always nil for "live" MIDI data and never nil when reading from a SMF.

The SMF header callback and the meta message callbacks are only called, when reading data from an SMF. Therefore the Position is passed directly and can't be nil.

System common and realtime message callbacks will only be called when reading "live" MIDI, so they get no Position.

func NewReader added in v1.7.0

func NewReader(opts ...ReaderOption) *Reader

NewReader returns a new Reader

func (*Reader) Duration added in v1.7.0

func (r *Reader) Duration(deltaticks uint32) time.Duration

Duration returns the duration for the given delta ticks, respecting the current tempo

func (*Reader) Read added in v1.7.0

func (r *Reader) Read(src io.Reader) (err error)

Read reads midi messages from src until an error happens (for "live" MIDI data "over the wire"). io.EOF is the expected error that is returned when reading should stop.

Read does not close the src.

The messages are dispatched to the corresponding attached functions of the Reader.

They must be attached before Reader.Read is called and they must not be unset or replaced until Read returns. For more infomation about dealing with the MIDI messages, see Reader.

func (*Reader) ReadFrom added in v1.7.0

func (r *Reader) ReadFrom(in In) error

ReadFrom configures the Reader to read from to the given MIDI in connection.

func (*Reader) ReadSMF added in v1.7.0

func (r *Reader) ReadSMF(src io.Reader, options ...smfreader.Option) error

ReadSMF reads midi messages from src (which is supposed to be the content of a standard midi file (SMF)) until an error or io.EOF happens.

ReadSMF does not close the src.

If the read content was a valid midi file, nil is returned.

The messages are dispatched to the corresponding attached functions of the Reader.

They must be attached before Reader.ReadSMF is called and they must not be unset or replaced until ReadSMF returns. For more infomation about dealing with the SMF midi messages, see Reader and SMFPosition.

func (*Reader) ReadSMFFile added in v1.7.0

func (r *Reader) ReadSMFFile(file string, options ...smfreader.Option) error

ReadSMFFile open, reads and closes a complete SMF file. If the read content was a valid midi file, nil is returned.

The messages are dispatched to the corresponding attached functions of the handler.

They must be attached before Reader.ReadSMF is called and they must not be unset or replaced until ReadSMF returns. For more infomation about dealing with the SMF midi messages, see Reader and SMFPosition.

func (*Reader) ReadSMFFileHeader added in v1.7.0

func (r *Reader) ReadSMFFileHeader(file string, options ...smfreader.Option) (smf.Header, error)

ReadSMFFileHeader reads just the header of a SMF file

func (*Reader) Resolution added in v1.7.0

func (r *Reader) Resolution() uint32

Resolution returns the ticks of a quarternote If it can't be determined, 0 is returned

func (*Reader) TempoBPM added in v1.7.0

func (r *Reader) TempoBPM() float64

BPM returns the current tempo in BPM (beats per minute)

func (*Reader) Ticks added in v1.7.0

func (r *Reader) Ticks(d time.Duration) uint32

Ticks returns the ticks that correspond to a duration while respecting the current tempo If it can't be determined, 0 is returned

func (*Reader) TimeAt added in v1.7.0

func (r *Reader) TimeAt(absTicks uint64) *time.Duration

TimeAt returns the time.Duration at the given absolute position counted from the beginning of the file, respecting all the tempo changes in between. If the time format is not of type smf.MetricTicks, nil is returned.

type ReaderOption added in v1.7.0

type ReaderOption func(*Reader)

ReaderOption configures the reader

func IgnoreMIDIClock added in v1.7.0

func IgnoreMIDIClock() ReaderOption

IgnoreMIDIClock lets the reader not use MIDI clock to calculate the tempo

func NoLogger

func NoLogger() ReaderOption

NoLogger is an option to disable the defaut logging of a Reader

func ReadingOptions added in v1.7.0

func ReadingOptions(options ...midireader.Option) ReaderOption

func SetLogger

func SetLogger(l Logger) ReaderOption

SetLogger allows to set a custom logger for the Reader

type SMFWriter

type SMFWriter struct {
	smf.MetricTicks
	// contains filtered or unexported fields
}

SMFWriter writes SMF MIDI data. Its methods must not be called concurrently

func NewSMF added in v1.7.0

func NewSMF(dest io.Writer, numtracks uint16, options ...smfwriter.Option) *SMFWriter

NewSMF returns a new SMFWriter that writes to dest. It panics if numtracks is == 0.

func (SMFWriter) Aftertouch added in v1.7.0

func (w SMFWriter) Aftertouch(pressure uint8) error

Aftertouch writes a channel pressure message for the current channel

func (SMFWriter) CcOff added in v1.7.0

func (w SMFWriter) CcOff(controller uint8) error

CcOff writes a control change message with a value of 0 (=off) for the current channel

func (SMFWriter) CcOn added in v1.7.0

func (w SMFWriter) CcOn(controller uint8) error

CcOn writes a control change message with a value of 127 (=on) for the current channel

func (SMFWriter) CoarseTuningRPN added in v1.7.0

func (w SMFWriter) CoarseTuningRPN(msbVal, lsbVal uint8) error

CoarseTuningRPN

func (SMFWriter) ConsolidateNotes added in v1.7.0

func (w SMFWriter) ConsolidateNotes(on bool)

ConsolidateNotes enables/disables the midi note consolidation (default: enabled) When enabled, midi note on/off messages are consolidated, that means the on/off state of every possible note on every channel is tracked and note on messages are only written, if the corresponding note is off and vice versa. Note on messages with a velocity of 0 behave the same way as note offs. The tracking of the notes is not cross SMF tracks, i.e. a meta.EndOfTrack message will reset the tracking. The consolidation should prevent "hanging" notes in most cases. If on is true, the note will be started tracking again (fresh state), assuming no note is currently running.

func (SMFWriter) ControlChange

func (w SMFWriter) ControlChange(controller, value uint8) error

ControlChange writes a control change message for the current channel For more comfortable use, used it in conjunction with the gomidi/cc package

func (*SMFWriter) Copyright

func (w *SMFWriter) Copyright(text string) error

Copyright writes the copyright meta message

func (*SMFWriter) Cuepoint

func (w *SMFWriter) Cuepoint(text string) error

Cuepoint writes the cuepoint meta message

func (*SMFWriter) DeprecatedChannel added in v1.7.0

func (w *SMFWriter) DeprecatedChannel(ch uint8) error

DeprecatedChannel writes the deprecated MIDI channel meta message

func (*SMFWriter) DeprecatedPort added in v1.7.0

func (w *SMFWriter) DeprecatedPort(port uint8) error

DeprecatedPort writes the deprecated MIDI port meta message

func (*SMFWriter) Device added in v1.7.0

func (w *SMFWriter) Device(port string) error

Device writes the device port meta message

func (*SMFWriter) EndOfTrack

func (w *SMFWriter) EndOfTrack() error

EndOfTrack signals the end of a track

func (SMFWriter) FineTuningRPN added in v1.7.0

func (w SMFWriter) FineTuningRPN(msbVal, lsbVal uint8) error

FineTuningRPN

func (*SMFWriter) Forward added in v1.8.0

func (w *SMFWriter) Forward(nbars, num, denom uint32)

Forward sets the cursor based on the given number of bars and ratio of whole notes. The cursor is the current position where the next event will be inserted. In the background it sets the delta to the next event. The cursor can only move forward.

Examples:

To move the cursor to the 2nd next bar (respecting time signature changes), use

Forward(2,0,0)

To move the cursor by 23 8ths (independent from time signatures), use

Forward(0,23,8)

To move the cursor to the 3rd 4th of the next bar (respecting time signature changes), use

Forward(1,3,4)

Important notes:

  1. Always put time signature changes at the beginning of a bar.
  2. Never forward more than once without setting a event in between.

func (SMFWriter) GMReset added in v1.7.0

func (w SMFWriter) GMReset(prog uint8) error

GMReset resets the channel to some GM based standards (see Reset) and sets the given GM program.

func (*SMFWriter) Key

func (w *SMFWriter) Key(keysig meta.Key) error

Key writes the given key signature meta message. It is supposed to be used with the gomidi/midi/midimessage/meta/key package

func (*SMFWriter) KeySig added in v1.7.0

func (w *SMFWriter) KeySig(key uint8, ismajor bool, num uint8, isflat bool) error

KeySig writes the key signature meta message. A more comfortable way is to use the Key method in conjunction with the gomidi/midi/midimessage/meta/key package

func (*SMFWriter) Lyric

func (w *SMFWriter) Lyric(text string) error

Lyric writes the lyric meta message

func (*SMFWriter) Marker

func (w *SMFWriter) Marker(text string) error

Marker writes the marker meta message

func (*SMFWriter) Meter

func (w *SMFWriter) Meter(numerator, denominator uint8) error

Meter writes the time signature meta message in a more comfortable way. Numerator and Denominator are decimalw.

func (SMFWriter) MsbLsb added in v1.7.0

func (w SMFWriter) MsbLsb(msbControl, lsbControl uint8, value uint16) error

MsbLsb writes a Msb control change message, followed by a Lsb control change message for the current channel For more comfortable use, used it in conjunction with the gomidi/cc package

func (SMFWriter) NRPN added in v1.7.0

func (w SMFWriter) NRPN(val99, val98, msbVal, lsbVal uint8) error

NRPN message consisting of a val99 and val98 to identify the RPN and a msb and lsb for the value

func (SMFWriter) NRPNDecrement added in v1.7.0

func (w SMFWriter) NRPNDecrement(val99, val98 uint8) error

func (SMFWriter) NRPNIncrement added in v1.7.0

func (w SMFWriter) NRPNIncrement(val99, val98 uint8) error

func (SMFWriter) NoteOff

func (w SMFWriter) NoteOff(key uint8) error

NoteOff writes a note off message for the current channel By default, midi notes are consolidated (see ConsolidateNotes method)

func (SMFWriter) NoteOffVelocity added in v1.7.0

func (w SMFWriter) NoteOffVelocity(key, velocity uint8) error

NoteOffVelocity writes a note off message for the current channel with a velocity. By default, midi notes are consolidated (see ConsolidateNotes method)

func (SMFWriter) NoteOn

func (w SMFWriter) NoteOn(key, veloctiy uint8) error

NoteOn writes a note on message for the current channel By default, midi notes are consolidated (see ConsolidateNotes method)

func (SMFWriter) PitchBendSensitivityRPN added in v1.7.0

func (w SMFWriter) PitchBendSensitivityRPN(msbVal, lsbVal uint8) error

PitchBendSensitivityRPN sets the pitch bend range via RPN

func (SMFWriter) Pitchbend added in v1.7.0

func (w SMFWriter) Pitchbend(value int16) error

Pitchbend writes a pitch bend message for the current channel For reset value, use 0, for lowest -8191 and highest 8191 Or use the pitch constants of midimessage/channel

func (SMFWriter) PolyAftertouch added in v1.7.0

func (w SMFWriter) PolyAftertouch(key, pressure uint8) error

PolyAftertouch writes a key pressure message for the current channel

func (*SMFWriter) Program added in v1.7.0

func (w *SMFWriter) Program(text string) error

Program writes the program name meta message

func (SMFWriter) ProgramChange

func (w SMFWriter) ProgramChange(program uint8) error

ProgramChange writes a program change message for the current channel Program numbers start with 0 for program 1.

func (SMFWriter) RPN added in v1.7.0

func (w SMFWriter) RPN(val101, val100, msbVal, lsbVal uint8) error

RPN message consisting of a val101 and val100 to identify the RPN and a msb and lsb for the value

func (SMFWriter) RPNDecrement added in v1.7.0

func (w SMFWriter) RPNDecrement(val101, val100 uint8) error

func (SMFWriter) RPNIncrement added in v1.7.0

func (w SMFWriter) RPNIncrement(val101, val100 uint8) error

func (SMFWriter) Reset added in v1.7.0

func (w SMFWriter) Reset(bank uint8, prog uint8) error

Reset "resets" channel to some established defaults

bank select -> bank
program change -> prog
cc all controllers off
cc volume -> 100
cc expression -> 127
cc hold pedal -> off
cc pan position -> 64
cc RPN pitch bend sensitivity -> 2 (semitones)

func (SMFWriter) ResetNRPN added in v1.7.0

func (w SMFWriter) ResetNRPN() error

ResetNRPN aka Null

func (SMFWriter) ResetRPN added in v1.7.0

func (w SMFWriter) ResetRPN() error

ResetRPN aka Null

func (*SMFWriter) SMPTE added in v1.7.0

func (w *SMFWriter) SMPTE(hour, minute, second, frame, fractionalFrame byte) error

SMPTE writes the SMPTE offset meta message

func (*SMFWriter) Sequence

func (w *SMFWriter) Sequence(text string) error

Sequence writes the sequence (name) meta message

func (*SMFWriter) SequenceNo added in v1.7.0

func (w *SMFWriter) SequenceNo(no uint16) error

SequenceNo writes the sequence number meta message

func (*SMFWriter) SequencerData added in v1.7.0

func (w *SMFWriter) SequencerData(data []byte) error

SequencerData writes a custom sequences specific meta message

func (SMFWriter) SetChannel

func (w SMFWriter) SetChannel(no uint8)

SetChannel sets the channel for the following midi messages Channel numbers are counted from 0 to 15 (MIDI channel 1 to 16). The initial channel number is 0.

func (*SMFWriter) SetDelta

func (w *SMFWriter) SetDelta(deltatime uint32)

SetDelta sets the delta ticks to the next message It should mostly not be needed, use Forward instead to advance in musical time.

func (SMFWriter) Silence added in v1.7.0

func (w SMFWriter) Silence(ch int8, force bool) (err error)

Silence sends a note off message for every running note on the given channel. If the channel is -1, every channel is affected. If note consolidation is switched off, notes aren't tracked and therefor every possible note will get a note off. This could also be enforced by setting force to true. If force is true, additionally the cc messages AllNotesOff (123) and AllSoundOff (120) are send. If channel is > 15, the method panics. The error or not error of the last write is returned. (i.e. it does not return on the first error, but tries everything instead to make it silent)

func (SMFWriter) SysEx

func (w SMFWriter) SysEx(data []byte) error

SysEx writes system exclusive data

func (*SMFWriter) TempoBPM added in v1.7.0

func (w *SMFWriter) TempoBPM(bpm float64) error

Tempo writes the tempo meta message

func (*SMFWriter) Text

func (w *SMFWriter) Text(text string) error

Text writes the text meta message

func (*SMFWriter) TimeSig added in v1.7.0

func (w *SMFWriter) TimeSig(numerator, denominator, clocksPerClick, demiSemiQuaverPerQuarter uint8) error

TimeSig writes the time signature meta message. Numerator and Denominator are decimal. If you don't want to deal with clocks per click and demisemiquaverperquarter, user the Meter method instead.

func (*SMFWriter) Track

func (w *SMFWriter) Track(track string) error

Track writes the track name aka instrument name meta message

func (SMFWriter) TuningBankSelectRPN added in v1.7.0

func (w SMFWriter) TuningBankSelectRPN(msbVal, lsbVal uint8) error

TuningBankSelectRPN

func (SMFWriter) TuningProgramSelectRPN added in v1.7.0

func (w SMFWriter) TuningProgramSelectRPN(msbVal, lsbVal uint8) error

TuningProgramSelectRPN

func (SMFWriter) Write added in v1.7.0

func (w SMFWriter) Write(msg midi.Message) error

Write writes the given midi.Message. By default, midi notes are consolidated (see ConsolidateNotes method)

type Writer added in v1.7.0

type Writer struct {
	// contains filtered or unexported fields
}

Writer writes live MIDI data. Its methods must not be called concurrently

func NewWriter added in v1.7.0

func NewWriter(dest io.Writer, options ...midiwriter.Option) *Writer

NewWriter creates and new Writer for writing of "live" MIDI data ("over the wire") By default it makes no use of the running status.

func WriteTo added in v1.7.0

func WriteTo(out Out) *Writer

WriteTo returns a Writer that writes to the given MIDI out connection.

func (*Writer) Activesense added in v1.7.0

func (w *Writer) Activesense() error

ActiveSensing writes the active sensing realtime message

func (Writer) Aftertouch added in v1.7.0

func (w Writer) Aftertouch(pressure uint8) error

Aftertouch writes a channel pressure message for the current channel

func (Writer) CcOff added in v1.7.0

func (w Writer) CcOff(controller uint8) error

CcOff writes a control change message with a value of 0 (=off) for the current channel

func (Writer) CcOn added in v1.7.0

func (w Writer) CcOn(controller uint8) error

CcOn writes a control change message with a value of 127 (=on) for the current channel

func (*Writer) Clock added in v1.7.0

func (w *Writer) Clock() error

Clock writes the timing clock realtime message

func (Writer) CoarseTuningRPN added in v1.7.0

func (w Writer) CoarseTuningRPN(msbVal, lsbVal uint8) error

CoarseTuningRPN

func (Writer) ConsolidateNotes added in v1.7.0

func (w Writer) ConsolidateNotes(on bool)

ConsolidateNotes enables/disables the midi note consolidation (default: enabled) When enabled, midi note on/off messages are consolidated, that means the on/off state of every possible note on every channel is tracked and note on messages are only written, if the corresponding note is off and vice versa. Note on messages with a velocity of 0 behave the same way as note offs. The tracking of the notes is not cross SMF tracks, i.e. a meta.EndOfTrack message will reset the tracking. The consolidation should prevent "hanging" notes in most cases. If on is true, the note will be started tracking again (fresh state), assuming no note is currently running.

func (*Writer) Continue added in v1.7.0

func (w *Writer) Continue() error

Continue writes the continue realtime message

func (Writer) ControlChange added in v1.7.0

func (w Writer) ControlChange(controller, value uint8) error

ControlChange writes a control change message for the current channel For more comfortable use, used it in conjunction with the gomidi/cc package

func (Writer) FineTuningRPN added in v1.7.0

func (w Writer) FineTuningRPN(msbVal, lsbVal uint8) error

FineTuningRPN

func (Writer) GMReset added in v1.7.0

func (w Writer) GMReset(prog uint8) error

GMReset resets the channel to some GM based standards (see Reset) and sets the given GM program.

func (*Writer) MTC added in v1.7.0

func (w *Writer) MTC(code uint8) error

MTC writes the MIDI Timing Code system message

func (Writer) MsbLsb added in v1.7.0

func (w Writer) MsbLsb(msbControl, lsbControl uint8, value uint16) error

MsbLsb writes a Msb control change message, followed by a Lsb control change message for the current channel For more comfortable use, used it in conjunction with the gomidi/cc package

func (Writer) NRPN added in v1.7.0

func (w Writer) NRPN(val99, val98, msbVal, lsbVal uint8) error

NRPN message consisting of a val99 and val98 to identify the RPN and a msb and lsb for the value

func (Writer) NRPNDecrement added in v1.7.0

func (w Writer) NRPNDecrement(val99, val98 uint8) error

func (Writer) NRPNIncrement added in v1.7.0

func (w Writer) NRPNIncrement(val99, val98 uint8) error

func (Writer) NoteOff added in v1.7.0

func (w Writer) NoteOff(key uint8) error

NoteOff writes a note off message for the current channel By default, midi notes are consolidated (see ConsolidateNotes method)

func (Writer) NoteOffVelocity added in v1.7.0

func (w Writer) NoteOffVelocity(key, velocity uint8) error

NoteOffVelocity writes a note off message for the current channel with a velocity. By default, midi notes are consolidated (see ConsolidateNotes method)

func (Writer) NoteOn added in v1.7.0

func (w Writer) NoteOn(key, veloctiy uint8) error

NoteOn writes a note on message for the current channel By default, midi notes are consolidated (see ConsolidateNotes method)

func (Writer) PitchBendSensitivityRPN added in v1.7.0

func (w Writer) PitchBendSensitivityRPN(msbVal, lsbVal uint8) error

PitchBendSensitivityRPN sets the pitch bend range via RPN

func (Writer) Pitchbend added in v1.7.0

func (w Writer) Pitchbend(value int16) error

Pitchbend writes a pitch bend message for the current channel For reset value, use 0, for lowest -8191 and highest 8191 Or use the pitch constants of midimessage/channel

func (Writer) PolyAftertouch added in v1.7.0

func (w Writer) PolyAftertouch(key, pressure uint8) error

PolyAftertouch writes a key pressure message for the current channel

func (Writer) ProgramChange added in v1.7.0

func (w Writer) ProgramChange(program uint8) error

ProgramChange writes a program change message for the current channel Program numbers start with 0 for program 1.

func (Writer) RPN added in v1.7.0

func (w Writer) RPN(val101, val100, msbVal, lsbVal uint8) error

RPN message consisting of a val101 and val100 to identify the RPN and a msb and lsb for the value

func (Writer) RPNDecrement added in v1.7.0

func (w Writer) RPNDecrement(val101, val100 uint8) error

func (Writer) RPNIncrement added in v1.7.0

func (w Writer) RPNIncrement(val101, val100 uint8) error

func (*Writer) Reset added in v1.7.0

func (w *Writer) Reset() error

Reset writes the reset realtime message

func (Writer) ResetNRPN added in v1.7.0

func (w Writer) ResetNRPN() error

ResetNRPN aka Null

func (Writer) ResetRPN added in v1.7.0

func (w Writer) ResetRPN() error

ResetRPN aka Null

func (*Writer) SPP added in v1.7.0

func (w *Writer) SPP(ptr uint16) error

SPP writes the song position pointer system message

func (Writer) SetChannel added in v1.7.0

func (w Writer) SetChannel(no uint8)

SetChannel sets the channel for the following midi messages Channel numbers are counted from 0 to 15 (MIDI channel 1 to 16). The initial channel number is 0.

func (Writer) Silence added in v1.7.0

func (w Writer) Silence(ch int8, force bool) (err error)

Silence sends a note off message for every running note on the given channel. If the channel is -1, every channel is affected. If note consolidation is switched off, notes aren't tracked and therefor every possible note will get a note off. This could also be enforced by setting force to true. If force is true, additionally the cc messages AllNotesOff (123) and AllSoundOff (120) are send. If channel is > 15, the method panics. The error or not error of the last write is returned. (i.e. it does not return on the first error, but tries everything instead to make it silent)

func (*Writer) SongSelect added in v1.7.0

func (w *Writer) SongSelect(song uint8) error

SongSelect writes the song select system message

func (*Writer) Start added in v1.7.0

func (w *Writer) Start() error

Start writes the start realtime message

func (*Writer) Stop added in v1.7.0

func (w *Writer) Stop() error

Stop writes the stop realtime message

func (Writer) SysEx added in v1.7.0

func (w Writer) SysEx(data []byte) error

SysEx writes system exclusive data

func (*Writer) Tick added in v1.7.0

func (w *Writer) Tick() error

Tick writes the tick realtime message

func (*Writer) Tune added in v1.7.0

func (w *Writer) Tune() error

Tune writes the tune request system message

func (Writer) TuningBankSelectRPN added in v1.7.0

func (w Writer) TuningBankSelectRPN(msbVal, lsbVal uint8) error

TuningBankSelectRPN

func (Writer) TuningProgramSelectRPN added in v1.7.0

func (w Writer) TuningProgramSelectRPN(msbVal, lsbVal uint8) error

TuningProgramSelectRPN

func (Writer) Write added in v1.7.0

func (w Writer) Write(msg midi.Message) error

Write writes the given midi.Message. By default, midi notes are consolidated (see ConsolidateNotes method)

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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