func initMidi() { s, err := portmidi.NewInputStream(portmidi.DeviceId(*midiDevice), 1024) if err != nil { log.Println(err) return } go midiLoop(s) }
func (w *watcher) Run() (err error) { midiIn, err := portmidi.NewInputStream(w.midiport, 1024) if err != nil { return } events := midiIn.Listen() for e := range events { w.HandleEvent(&e) } return nil }
// Open opens a connection Launchpad and initializes an input and output // stream to the currently connected device. If there are no // devices are connected, it returns an error. func Open() (*Launchpad, error) { input, output, err := discover() if err != nil { return nil, err } var inStream, outStream *portmidi.Stream if inStream, err = portmidi.NewInputStream(input, 1024); err != nil { return nil, err } if outStream, err = portmidi.NewOutputStream(output, 1024, 0); err != nil { return nil, err } return &Launchpad{inputStream: inStream, outputStream: outStream}, nil }
func ExampleStream_ReadSysExBytes() { in, err := portmidi.NewInputStream(portmidi.DefaultInputDeviceID(), 1024) if err != nil { log.Fatal(err) } msg, err := in.Read(1024) if err != nil { log.Fatal(err) } for i, b := range msg { fmt.Printf("SysEx message byte %d = %02x\n", i, b) } }
func initMidi() { device := portmidi.DeviceId(*midiDevice) if device == -1 { device = portmidi.GetDefaultInputDeviceId() } s, err := portmidi.NewInputStream(device, 1024) if err != nil { log.Println(err) return } if s == nil { log.Println("could not initialize MIDI input device") return } go midiLoop(s) }
func ExampleStream_Poll() { in, err := portmidi.NewInputStream(portmidi.DefaultInputDeviceID(), 1024) if err != nil { log.Fatal(err) } result, err := in.Poll() if err != nil { log.Fatal(err) } if result { fmt.Println("New messages in the queue!") } else { fmt.Println("No new messages in the queue :(") } }
func midiOpen(argv []*ell.Object) (*ell.Object, error) { // defaultInput := "USB Oxygen 8 v2" // defaultOutput := "IAC Driver Bus 1" latency := int64(10) if !midiOpened { err := portmidi.Initialize() if err != nil { return nil, err } midiOpened = true midiInDevice = ell.StringValue(argv[0]) midiOutDevice = ell.StringValue(argv[1]) midiBufsize = ell.Int64Value(argv[2]) outdev, outname := findMidiOutputDevice(midiOutDevice) out, err := portmidi.NewOutputStream(outdev, midiBufsize, latency) if err != nil { return nil, err } midiOut = out midiOutDevice = outname if midiInDevice != "" { indev := findMidiInputDevice(midiInDevice) if indev >= 0 { in, err := portmidi.NewInputStream(indev, midiBufsize) if err != nil { return nil, err } midiIn = in } } midiBaseTime = ell.Now() } result := ell.MakeStruct(4) if midiInDevice != "" { ell.Put(result, inputKey, ell.String(midiInDevice)) } if midiOutDevice != "" { ell.Put(result, outputKey, ell.String(midiOutDevice)) } ell.Put(result, bufsizeKey, ell.Number(float64(midiBufsize))) return result, nil }
func main() { var synthID int32 const synthName = "sineTone" // Set up SuperCollider client. client, err := sc.NewClient("udp", "127.0.0.1:57121", "127.0.0.1:57120", 5*time.Second) if err != nil { log.Fatal(err) } _, err = client.AddDefaultGroup() if err != nil { log.Fatal(err) } err = client.DumpOSC(int32(1)) if err != nil { log.Fatal(err) } def := sc.NewSynthdef(synthName, func(p sc.Params) sc.Ugen { freq := p.Add("freq", 440) gain := p.Add("gain", 0.5) bus := sc.C(0) env := sc.EnvGen{ Env: sc.EnvPerc{}, Done: sc.FreeEnclosing, LevelScale: gain, }.Rate(sc.KR) sig := sc.SinOsc{Freq: freq}.Rate(sc.AR).Mul(env) return sc.Out{bus, sig}.Rate(sc.AR) }) err = client.SendDef(def) if err != nil { log.Fatal(err) } // initialize midi portmidi.Initialize() // this code can be uncommented to discover the // device ID's portmidi comes up with // deviceCount := portmidi.CountDevices() // enc := json.NewEncoder(os.Stdout) // for i := 0; i < deviceCount; i++ { // info := portmidi.GetDeviceInfo(portmidi.DeviceId(i)) // log.Printf("device %d - ", i) // err = enc.Encode(info) // if err != nil { // log.Fatal(err) // } // } // setup midi input stream and listen for midi events in, err := portmidi.NewInputStream(3, 1024) if err != nil { log.Fatal(err) } ch := in.Listen() for event := range ch { if event.Status == 144 { // MIDI note log.Printf("Note %-3d Velocity %-3d\n", event.Data1, event.Data2) if event.Data2 > 0 { // Note On synthID = client.NextSynthID() ctls := map[string]float32{ "freq": sc.Midicps(float32(event.Data1)), "gain": float32(event.Data2 / 127.0), } _, err = client.Synth(synthName, synthID, sc.AddToTail, sc.DefaultGroupID, ctls) } } } portmidi.Terminate() }
// Start begins the Sound by opening two goroutines - one to take a set of active notes and convert // it into sampled sine waves at the right frequencies, and the second to to listen to the midi input // stream of events and convert that into the live set of active notes. func (s *MidiInput) Start() { fmt.Println("Starting the MIDI sound's channel...") s.samples = make(chan float64) s.running = true // Goroutine to convert the s.notes set to samples. go func(midi *MidiInput) { fmt.Printf(" MIDI generation begun!\n") atNano := float64(time.Now().UnixNano()) ticker := time.NewTicker(tickerDuration) defer ticker.Stop() for now := range ticker.C { if !midi.running { break } nowNano := float64(now.UnixNano()) for ; atNano < nowNano && midi.running; atNano += nsPerCycle { if s.notes.IsEmpty() { if midi.running { midi.samples <- 0.0 } } else { cycleAtMult := atNano * nsToSeconds value := 0.0 for _, note := range s.notes.List() { // TODO(padster): Remove the * -> int64 -> int cast cps := midiToHz(int(note.(int64))) offset := math.Remainder(cps*cycleAtMult, 1.0) * math.Pi * 2.0 value += math.Sin(offset) } if midi.running { midi.samples <- value / float64(s.notes.Size()) } } } } close(s.samples) }(s) // Goroutine for reading from the input: go func() { fmt.Println(" Opening MIDI stream..") in, err := pm.NewInputStream(s.deviceId, 10) if err != nil { fmt.Printf("Error in reading midi device %d: Ensure portmidi is Initialized, and device is available.\n", s.deviceId) panic(err) } fmt.Println("Listening to stream") for event := range in.Listen() { // TODO - figure out what event.Data2 is (volumne?) and use it... fmt.Printf("Got: %v\n", event) if event.Status == noteStart { s.notes.Add(int64(event.Data1)) } else if event.Status == noteEnd { s.notes.Remove(int64(event.Data1)) } else if event.Status == pitchBend { s.Stop() } if !s.running { break } } }() // TODO(padster): Move goroutines into struct methods? }