smfreader

package
v0.8.2 Latest Latest
Warning

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

Go to latest
Published: Aug 12, 2018 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package smfreader provides a reader of Standard MIDI Files (SMF).

There is also a more comfortable handler package:

github.com/gomidi/midi/midihandler    (reading MIDI messages live or from SMF files)

Usage

import (
	"github.com/gomidi/midi/smf/smfreader"
	"github.com/gomidi/midi/midimessage/channel"    // (Channel Messages)

	// you may also want to use these
	// github.com/gomidi/midi/midimessage/meta       (Meta Messages)
	// github.com/gomidi/midi/midimessage/cc         (Control Change Messages)
	// github.com/gomidi/midi/midimessage/syscommon  (System Common Messages)
	// github.com/gomidi/midi/midimessage/sysex      (System Exclusive Messages)
)

var err1, err2 error

readMIDI := func (rd smf.Reader) {

	var m midi.Message

	for {
		m, err1 = rd.Read()

		// to interrupt, the input.Read method must return io.EOF or any other error
		if err1 != nil {
			break
		}

		// deal with them based on a type switch
		switch msg := m.(type) {
		case channel.NoteOn:
			fmt.Printf(
			  "NoteOn at channel %v: key %v velocity: %v\n",
			  msg.Channel(), // MIDI channels 1-16 correspond to msg.Channel 0-15
			  msg.Key(),
			  msg.Velocity(),
			)
		case channel.NoteOff:
			...
		}
	}

}

err2 = smfreader.ReadFile("file.mid", readMIDI)

// deal with err1 and err2
Example
package main

import (
	"bytes"
	"fmt"
	"io"

	"github.com/gomidi/midi"
	"github.com/gomidi/midi/midimessage/channel"
	"github.com/gomidi/midi/midimessage/meta"
	"github.com/gomidi/midi/smf/smfreader"
	"github.com/gomidi/midi/smf/smfwriter"
)

func mkMIDI() io.Reader {
	var bf bytes.Buffer

	wr := smfwriter.New(&bf)
	wr.Write(channel.Ch2.NoteOn(65, 90))
	wr.SetDelta(2)
	wr.Write(channel.Ch2.NoteOff(65))
	wr.Write(meta.EndOfTrack)
	return bytes.NewReader(bf.Bytes())
}

func main() {

	rd := smfreader.New(mkMIDI())

	var m midi.Message
	var err error

	for {
		m, err = rd.Read()

		// breaking at least with io.EOF
		if err != nil {
			break
		}

		switch v := m.(type) {
		case channel.NoteOn:
			fmt.Printf("[%v] NoteOn at channel %v: key %v velocity %v\n", rd.Delta(), v.Channel(), v.Key(), v.Velocity())
		case channel.NoteOff:
			fmt.Printf("[%v] NoteOff at channel %v: key %v\n", rd.Delta(), v.Channel(), v.Key())
		}

	}

}
Output:

[0] NoteOn at channel 2: key 65 velocity 90
[2] NoteOff at channel 2: key 65

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrFinished = errors.New("SMF has been read")
	ErrMissing  = errors.New("incomplete, tracks missing")
)

Functions

func New

func New(src io.Reader, opts ...Option) smf.Reader

New returns a smf.Reader

func ReadFile

func ReadFile(file string, callback func(smf.Reader), options ...Option) error

ReadFile opens file, calls callback with a reader and closes file

Types

type Option

type Option func(*reader)

func NoteOffVelocity

func NoteOffVelocity() Option

NoteOffVelocity lets the reader differentiate between "fake" noteoff messages (which are in fact noteon messages (typ 9) with velocity of 0) and "real" noteoff messages (typ 8) that have a velocity. The former are returned as NoteOffVelocity messages and keep the given velocity, the later are returned as NoteOff messages without velocity. That means in order to get all noteoff messages, there must be checks for NoteOff and NoteOffVelocity (if this option is set). If this option is not set, both kinds are returned as NoteOff (default).

Jump to

Keyboard shortcuts

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