Skip to content

Commit

Permalink
Merge pull request #3 from oplS17projects/rtmidi-interface-dev
Browse files Browse the repository at this point in the history
Experimental set of rtmidi interface procedures
  • Loading branch information
probune authored Apr 10, 2017
2 parents 4a854aa + 9e9d54e commit 7ea989d
Showing 1 changed file with 163 additions and 45 deletions.
208 changes: 163 additions & 45 deletions rtmidi_interface.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -25,68 +25,186 @@
;; - install --mode=644 RtMidi.h RtError.h $(PREFIX)/include



; to set up a port use the following call sequence

; (define in (make-in-port))
; (define out (make-out-port))
; (open-in-port in "MIDI-DEVICE")
; (open-out-port out "MIDI-DEVICE")

; replace "MIDI-DEVICE" with the appropriate midi device by calling the
; following procedures to find the name of the available devices
; the (open-in-port) and (open-out-port) procedures pick the first
; available port that has a name that contains "MIDI-DEVICE" as a substring

; (list-in-ports in)
; (list-out-ports out)

; the usb to midi cable I have is shown as

; "a2j:Turtle Beach USB MIDI 1x1 [20] (capture): Turtle Beach USB MIDI 1x1 MIDI "
; and
; "a2j:Turtle Beach USB MIDI 1x1 [20] (playback): Turtle Beach USB MIDI 1x1 MIDI "



; for mor information about the midi specifications, see www.midi.org/specifications
; refer to the General midi specification level 1


; Create RtMidiIn and RtMidiOut
(define in (make-rtmidi-in))
(define out (make-rtmidi-out))

; List input and output ports
(define in-ports (rtmidi-ports in))
(printf "Input ports: ~a~n" in-ports)

(define out-ports (rtmidi-ports out))
(printf "Output ports: ~a~n" out-ports)

; Open the first input and output port, if any

(match in-ports
[(cons a-port other-ports) (rtmidi-open-port in 0)]
;; [other (printf (current-error-port) "no input ports\n")])
[other (printf "no input ports\n")])

(match out-ports
[(cons a-port other-ports) (rtmidi-open-port out 0)]
;; [other (printf (current-error-port) "no output ports\n")])
[other (printf "no output ports\n")])
(define (make-in-port) (make-rtmidi-in))
(define (make-out-port) (make-rtmidi-out))

;list input and output ports
(define (list-in-ports in) (rtmidi-ports in))

(define (list-out-ports out) (rtmidi-ports out))


; Open the specified midi ports for input and output
(define (in-ports-length in) (length (list-in-ports in)))
(define (out-ports-length out) (length (list-out-ports out)))


(define (open-in-port in-port name)
(define i 0)
(for ([j (in-range (in-ports-length in-port))])
#:break (string-contains? (list-ref (list-in-ports in-port) i) name)
(set! i j))
(if (not (= i (in-ports-length in-port)))
(rtmidi-open-port in-port i)
(printf "Port ~a not found" name)))


(define (open-out-port out-port name)
(define i 0)
(for ([j (in-range (out-ports-length out-port))])
#:break (string-contains? (list-ref (list-out-ports out-port) i) name)
(set! i j))
(if (not (= i (out-ports-length out-port)))
(rtmidi-open-port out-port i)
(printf "Port ~a not found" name)))

; Close the in port
(define (close-in-port in-port) (rtmidi-close-port in-port))

; Close the out port
(define (close-out-port out-port) (rtmidi-close-port out-port))

; Sends a midi message to the port
(define (send-midi-message port status data1 data2)
(rtmidi-send-message port (list status data1 data2)))

(define (send-midi-message status data1 data2) (rtmidi-send-message out (list status data1 data2)))
; Read a midi message from the port
(define (read-midi-message port)
(sync port))

(define (play-midi-note length note on-veloc off-veloc channel) (thread (lambda () (begin (send-midi-message (+ channel 144) note on-veloc)
(sleep length)
(send-midi-message (+ channel 128) note off-veloc)
(printf "note sent (play-midi-note)\n")))))

(sleep 15)

(play-midi-note 2 64 93 64 0)
;; all values start from 0
;; channel 1 is channel number 0, channel 10 (purcusion) is channel number 9

(printf "note sent (main)\n")
; Procedures for sending midi messages

(define (note-off port channel note) (send-midi-message port (+ 128 channel) note 0))
(define (note-on port channel note velocity) (send-midi-message port (+ 144 channel) note velocity))

; plays a note for a specified length of time in seconds, length can have arbitrary precision
(define (play-note port channel note velocity length)
(thread (lambda () (note-on port channel note velocity)(sleep length)(note-off port channel note))))

; polyphonic key pressure (aftertouch)
(define (poly-key-pressure port channel note pressure) (send-midi-message port (+ 160 channel) note pressure))
(define (control-change port channel controller value) (send-midi-message port (+ 176 channel) controller value))
; program change is tone select
(define (program-change port channel program) (send-midi-message port (+ 192 channel) program 0))
; channel-pressure (aftertouch)
(define (channel-pressure port channel pressure) (send-midi-message port (+ 208 channel) pressure 0))
; pitch bend value is a 14 bit value, center (no change) is 8192 or lsb=0 msb=40
(define (pitch-bend port channel lsb msb) (send-midi-message port (+ 224 channel) lsb msb))


; control changes and mode changes
(define (bank-select port channel bank tone)
(thread (lambda ()
(send-midi-message port (+ 176 channel) 0 bank)
(send-midi-message port (+ 176 channel) 32 0)
(program-change port channel tone))))

(define (channel-volume-change port channel volume)
(send-midi-message port (+ 176 channel) 7 volume))

;left-right balance
(define (set-pan port channel pan)
(send-midi-message port (+ 176 channel) 10 pan))


; expression controller
(define (set-expression-controller port channel expression-value)
(send-midi-message port (+ 176 channel) 11 expression-value))


; hold1 (sustain) pedal. set on to #t to enable sustain, set on argument to #f to turn off
(define (set-sustain port channel on)
(send-midi-message port (+ 176 channel) 64 (if on 64 0)))

; Sostenuto pedal
(define (set-sostenuto port channel on)
(send-midi-message port (+ 176 channel) 66 (if on 64 0)))

; Soft pedal
(define (set-soft-pedal port channel on)
(send-midi-message port (+ 176 channel) 67 (if on 64 0)))






;;(define (play-midi-message-list lst) (begin (sleep (car lst)) (send-midi-message (cadr lst) (caddr lst) (cadddr lst)) (if (null? (cddddr lst)) 0 (play-midi-message-list (cddddr lst)))))

;;(define (parse-midi-message-list lst (
;; this will eventually be able to take a list of midi messages and create a list of midi notes and other midi messages


;(sleep 15)

;(play-midi-note 2 64 93 64 0)

;(printf "note sent (main)\n")

(define (play-note note)
;(define (play-note note)
; Send a note
(rtmidi-send-message out (list (* 11 16) 7 128))
(printf "sending note~n")
(rtmidi-send-message out (list 144 65 96))
(sleep 2)
(rtmidi-send-message out (list 128 65 64))
(printf "note sent~n"))
;(rtmidi-send-message out (list (* 11 16) 7 128))
;(printf "sending note~n")
;(rtmidi-send-message out (list 144 65 96))
;(sleep 2)
;(rtmidi-send-message out (list 128 65 64))
;(printf "note sent~n"))


;(sleep 10)

;(play-note)


(define (listen-midi-events)
;(define (listen-midi-events)
; Read incoming messages until break
(let loop ()
(pretty-print (sync in))
;(let loop ()
; (pretty-print (sync in))
; (play-note)
(loop))
)
; (loop)))

;(define listenthread (thread listen-midi-events))

;(sleep 60)

(define listenthread (thread listen-midi-events))
;(kill-thread listenthread)

(sleep 60)
;(define (echo-midi-events)
; (let loop ()
; ((lambda (evnt) (pretty-print evnt)(sleep (car evnt))(send-midi-message (cadr evnt) (caddr evnt) (cadddr evnt))) (sync in))
; (loop)))

(kill-thread listenthread)
;(define echothread (thread echo-midi-events))

0 comments on commit 7ea989d

Please sign in to comment.