Make MIDI transpose example functional
Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
This commit is contained in:
		
							parent
							
								
									ba6aaa22ab
								
							
						
					
					
						commit
						9bb9321dcb
					
				@ -1,6 +1,8 @@
 | 
			
		||||
## A simple MIDI event processor LV2 plugin
 | 
			
		||||
## A simple MIDI transpose LV2 plugin
 | 
			
		||||
 | 
			
		||||
import std/[math, strformat, strutils]
 | 
			
		||||
import std/math
 | 
			
		||||
#import std/strformat
 | 
			
		||||
#import std/strutils
 | 
			
		||||
import nymph/[atom, core, midi, util, urid]
 | 
			
		||||
import nymph/atom/util
 | 
			
		||||
 | 
			
		||||
@ -18,27 +20,17 @@ type
 | 
			
		||||
        midi_urid: Urid
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
proc printFeatures(features: ptr UncheckedArray[ptr Lv2Feature]) =
 | 
			
		||||
    if features != nil:
 | 
			
		||||
        var i = 0
 | 
			
		||||
        while true:
 | 
			
		||||
            let feature = features[i]
 | 
			
		||||
            if feature == nil:
 | 
			
		||||
                break
 | 
			
		||||
            echo &"URI: {feature[].uri}"
 | 
			
		||||
            echo &"Data: {cast[int](feature[].data)}"
 | 
			
		||||
            inc i
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
proc instantiate(descriptor: ptr Lv2Descriptor; sampleRate: cdouble;
 | 
			
		||||
                 bundlePath: cstring; features: ptr UncheckedArray[ptr Lv2Feature]):
 | 
			
		||||
                 Lv2Handle {.cdecl.} =
 | 
			
		||||
    printFeatures(features)
 | 
			
		||||
    let amp: ptr MidiTransposePlugin = createShared(MidiTransposePlugin)
 | 
			
		||||
    amp.map = cast[ptr UridMap](lv2FeaturesData(features, lv2UridMap))
 | 
			
		||||
    assert amp.map != nil
 | 
			
		||||
 | 
			
		||||
    if amp.map == nil:
 | 
			
		||||
        return nil
 | 
			
		||||
 | 
			
		||||
    amp.midi_urid = amp.map[].map(amp.map[].handle, lv2MidiMidiEvent)
 | 
			
		||||
    echo &"{lv2MidiMidiEvent} = {amp.midi_urid.int}"
 | 
			
		||||
 | 
			
		||||
    return cast[Lv2Handle](amp)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -53,18 +45,33 @@ proc connectPort(instance: Lv2Handle; port: cuint;
 | 
			
		||||
    of PluginPort.Transposition:
 | 
			
		||||
        amp.transposition = cast[ptr cfloat](dataLocation)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
proc activate(instance: Lv2Handle) {.cdecl.} =
 | 
			
		||||
    discard
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
proc run(instance: Lv2Handle; nSamples: cuint) {.cdecl.} =
 | 
			
		||||
    let amp = cast[ptr MidiTransposePlugin](instance)
 | 
			
		||||
    let outCapacity = amp.output.atom.size
 | 
			
		||||
    atomSequenceClear(amp.output)
 | 
			
		||||
    amp.output.atom.type = amp.input.atom.type
 | 
			
		||||
 | 
			
		||||
    if amp.input.atom.size > 8:
 | 
			
		||||
        #echo &"Event sequence size: {amp.input.atom.size}"
 | 
			
		||||
 | 
			
		||||
        for ev in items(amp.input):
 | 
			
		||||
            if Urid(ev.body.`type`) == amp.midi_urid:
 | 
			
		||||
                # TODO
 | 
			
		||||
                var msg = cast[ptr UncheckedArray[uint8]](ev.body.addr + 1)
 | 
			
		||||
                echo &"0x{toHex(msg[0], 2)} 0x{toHex(msg[1], 2)} 0x{toHex(msg[2], 2)}"
 | 
			
		||||
                var msg = cast[ptr UncheckedArray[uint8]](atomContents(AtomEvent, ev))
 | 
			
		||||
                #echo &"0x{toHex(msg[0], 2)} 0x{toHex(msg[1], 2)} 0x{toHex(msg[2], 2)}"
 | 
			
		||||
 | 
			
		||||
                case midiGetMessageType(msg[]):
 | 
			
		||||
                of midiMsgNoteOff, midiMsgNoteOn, midiMsgNotePressure:
 | 
			
		||||
                    let noteOffset = clamp(floor(amp.transposition[] + 0.5), -12, 12).uint8
 | 
			
		||||
                    msg[1] = clamp(msg[1] + noteOffset, 0, 127).uint8
 | 
			
		||||
                else:
 | 
			
		||||
                    discard
 | 
			
		||||
 | 
			
		||||
                discard atomSequenceAppendEvent(amp.output, outCapacity, ev)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
proc deactivate(instance: Lv2Handle) {.cdecl.} =
 | 
			
		||||
 | 
			
		||||
@ -6,6 +6,8 @@
 | 
			
		||||
## See <http://lv2plug.in/ns/ext/atom> for details.
 | 
			
		||||
##
 | 
			
		||||
 | 
			
		||||
import ptrmath
 | 
			
		||||
 | 
			
		||||
const
 | 
			
		||||
    lv2AtomBaseUri ="http://lv2plug.in/ns/ext/atom"
 | 
			
		||||
    lv2AtomPrefix = lv2AtomBaseUri & "#"
 | 
			
		||||
@ -51,29 +53,12 @@ const
 | 
			
		||||
template atomContents*(`type`, atom: untyped): pointer =
 | 
			
		||||
    cast[ptr uint8](atom) + sizeof(`type`)
 | 
			
		||||
 | 
			
		||||
#[
 | 
			
		||||
{.push header: "lv2/atom/atom.h".}
 | 
			
		||||
 | 
			
		||||
var atomReferenceType* {.importc: "LV2_ATOM_REFERENCE_TYPE".}: int
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
## Const version of LV2_ATOM_CONTENTS.
 | 
			
		||||
##
 | 
			
		||||
proc atomContentsConst*(`type`: untyped; atom: untyped) {.importc: "LV2_ATOM_CONTENTS_CONST".}
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
## Return a pointer to the body of an Atom.  The "body" of an atom is the
 | 
			
		||||
## data just past the LV2_Atom head (i.e. the same offset for all types).
 | 
			
		||||
## data just past the Atom head (i.e. the same offset for all types).
 | 
			
		||||
##
 | 
			
		||||
proc atomBody*(atom: untyped) {.importc: "LV2_ATOM_BODY".}
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
## Const version of LV2_ATOM_BODY.
 | 
			
		||||
##
 | 
			
		||||
proc atomBodyConst*(atom: untyped) {.importc: "LV2_ATOM_BODY_CONST".}
 | 
			
		||||
 | 
			
		||||
{.pop.}
 | 
			
		||||
]#
 | 
			
		||||
template atomBody*(atom: untyped): pointer =
 | 
			
		||||
    atomContents(Atom, atom)
 | 
			
		||||
 | 
			
		||||
type
 | 
			
		||||
    ## The header of an atom:Atom.
 | 
			
		||||
@ -81,35 +66,35 @@ type
 | 
			
		||||
        size*: uint32  ## Size in bytes, not including type and size.
 | 
			
		||||
        `type`*: uint32  ## of this atom (mapped URI).
 | 
			
		||||
 | 
			
		||||
    ## An atom:Int or atom:Bool.  May be cast to LV2_Atom.
 | 
			
		||||
    ## An atom:Int or atom:Bool.  May be cast to Atom.
 | 
			
		||||
    AtomInt* {.bycopy.} = object
 | 
			
		||||
        atom*: Atom  ## Atom header.
 | 
			
		||||
        body*: int32  ## Integer value.
 | 
			
		||||
 | 
			
		||||
    ## An atom:Long.  May be cast to LV2_Atom.
 | 
			
		||||
    ## An atom:Long.  May be cast to Atom.
 | 
			
		||||
    AtomLong* {.bycopy.} = object
 | 
			
		||||
        atom*: Atom  ## Atom header.
 | 
			
		||||
        body*: int64  ## Integer value.
 | 
			
		||||
 | 
			
		||||
    ## An atom:Float.  May be cast to LV2_Atom.
 | 
			
		||||
    ## An atom:Float.  May be cast to Atom.
 | 
			
		||||
    AtomFloat* {.bycopy.} = object
 | 
			
		||||
        atom*: Atom  ## Atom header.
 | 
			
		||||
        body*: cfloat  ## Floating point value.
 | 
			
		||||
 | 
			
		||||
    ## An atom:Double.  May be cast to LV2_Atom.
 | 
			
		||||
    ## An atom:Double.  May be cast to Atom.
 | 
			
		||||
    AtomDouble* {.bycopy.} = object
 | 
			
		||||
        atom*: Atom  ## Atom header.
 | 
			
		||||
        body*: cdouble  ## Floating point value.
 | 
			
		||||
 | 
			
		||||
    ## An atom:Bool.  May be cast to LV2_Atom.
 | 
			
		||||
    ## An atom:Bool.  May be cast to Atom.
 | 
			
		||||
    AtomBool* = distinct AtomInt
 | 
			
		||||
 | 
			
		||||
    ## An atom:URID.  May be cast to LV2_Atom.
 | 
			
		||||
    ## An atom:URID.  May be cast to Atom.
 | 
			
		||||
    AtomUrid* {.bycopy.} = object
 | 
			
		||||
        atom*: Atom  ## Atom header.
 | 
			
		||||
        body*: uint32  ## URID.
 | 
			
		||||
 | 
			
		||||
    ## An atom:String.  May be cast to LV2_Atom.
 | 
			
		||||
    ## An atom:String.  May be cast to Atom.
 | 
			
		||||
    AtomString* {.bycopy.} = object
 | 
			
		||||
        atom*: Atom  ## Atom header.
 | 
			
		||||
        ## Contents (a null-terminated UTF-8 string) follow here.
 | 
			
		||||
@ -120,12 +105,12 @@ type
 | 
			
		||||
        lang*: uint32  ## Language URID.
 | 
			
		||||
        ## Contents (a null-terminated UTF-8 string) follow here.
 | 
			
		||||
 | 
			
		||||
    ## An atom:Literal.  May be cast to LV2_Atom.
 | 
			
		||||
    ## An atom:Literal.  May be cast to Atom.
 | 
			
		||||
    AtomLiteral* {.bycopy.} = object
 | 
			
		||||
        atom*: Atom  ## Atom header.
 | 
			
		||||
        body*: AtomLiteralBody  ## Body.
 | 
			
		||||
 | 
			
		||||
    ## An atom:Tuple.  May be cast to LV2_Atom.
 | 
			
		||||
    ## An atom:Tuple.  May be cast to Atom.
 | 
			
		||||
    AtomTuple* {.bycopy.} = object
 | 
			
		||||
        atom*: Atom  ## Atom header.
 | 
			
		||||
        ## Contents (a series of complete atoms) follow here.
 | 
			
		||||
@ -136,7 +121,7 @@ type
 | 
			
		||||
        childType*: uint32  ## The of each element in the vector.
 | 
			
		||||
        ## Contents (a series of packed atom bodies) follow here.
 | 
			
		||||
 | 
			
		||||
    ## An atom:Vector.  May be cast to LV2_Atom.
 | 
			
		||||
    ## An atom:Vector.  May be cast to Atom.
 | 
			
		||||
    AtomVector* {.bycopy.} = object
 | 
			
		||||
        atom*: Atom  ## Atom header.
 | 
			
		||||
        body*: AtomVectorBody  ## Body.
 | 
			
		||||
@ -148,23 +133,23 @@ type
 | 
			
		||||
        value*: Atom  ## Value atom header.
 | 
			
		||||
        ## Value atom body follows here.
 | 
			
		||||
 | 
			
		||||
    ## An atom:Property.  May be cast to LV2_Atom.
 | 
			
		||||
    ## An atom:Property.  May be cast to Atom.
 | 
			
		||||
    AtomProperty* {.bycopy.} = object
 | 
			
		||||
        atom*: Atom  ## Atom header.
 | 
			
		||||
        body*: AtomPropertyBody  ## Body.
 | 
			
		||||
 | 
			
		||||
    ## The body of an atom:Object. May be cast to LV2_Atom.
 | 
			
		||||
    ## The body of an atom:Object. May be cast to Atom.
 | 
			
		||||
    AtomObjectBody* {.bycopy.} = object
 | 
			
		||||
        id*: uint32  ## URID, or 0 for blank.
 | 
			
		||||
        otype*: uint32  ## URID (same as rdf:type, for fast dispatch).
 | 
			
		||||
        ## Contents (a series of property bodies) follow here.
 | 
			
		||||
 | 
			
		||||
    ## An atom:Object.  May be cast to LV2_Atom.
 | 
			
		||||
    ## An atom:Object.  May be cast to Atom.
 | 
			
		||||
    AtomObject* {.bycopy.} = object
 | 
			
		||||
        atom*: Atom  ## Atom header.
 | 
			
		||||
        body*: AtomObjectBody  ## Body.
 | 
			
		||||
 | 
			
		||||
    ## The header of an atom:Event.  Note this is NOT an LV2_Atom.
 | 
			
		||||
    ## The header of an atom:Event.  Note this is NOT an Atom.
 | 
			
		||||
    AtomEventTime* {.bycopy, union.} = object
 | 
			
		||||
        frames*: int64  ## Time in audio frames.
 | 
			
		||||
        beats*: cdouble  ## Time in beats.
 | 
			
		||||
@ -175,13 +160,13 @@ type
 | 
			
		||||
        ## Body atom contents follow here.
 | 
			
		||||
 | 
			
		||||
    ##
 | 
			
		||||
    ## The body of an atom:Sequence (a sequence of events).
 | 
			
		||||
    ## The body of an AtomSequence (a sequence of events).
 | 
			
		||||
    ##
 | 
			
		||||
    ## The unit field is either a URID that described an appropriate time stamp
 | 
			
		||||
    ## The unit field is either a Urid that described an appropriate time stamp
 | 
			
		||||
    ## type, or may be 0 where a default stamp is known.  For
 | 
			
		||||
    ## LV2_Descriptor::run(), the default stamp is audio frames.
 | 
			
		||||
    ## lv2Descriptor.run(), the default stamp is audio frames.
 | 
			
		||||
    ##
 | 
			
		||||
    ## The contents of a sequence is a series of LV2_Atom_Event, each aligned
 | 
			
		||||
    ## The contents of a sequence is a series of AtomEvent, each aligned
 | 
			
		||||
    ## to 64-bits, for example:
 | 
			
		||||
    ## <pre>
 | 
			
		||||
    ## | Event 1 (size 6)                              | Event 2
 | 
			
		||||
 | 
			
		||||
@ -12,14 +12,7 @@
 | 
			
		||||
 | 
			
		||||
from system/ansi_c import c_memcmp, c_memcpy
 | 
			
		||||
import ../atom
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
## Increment pointer `p` by `offset` that jumps memory in increments of
 | 
			
		||||
## the size of `T`.
 | 
			
		||||
##
 | 
			
		||||
proc `+`*[T](p: ptr T, offset: SomeInteger): ptr T =
 | 
			
		||||
    return cast[ptr T](cast[int](p) +% (offset.int * sizeof(T)))
 | 
			
		||||
import ../ptrmath
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
## Pad a size to 64 bits.
 | 
			
		||||
@ -73,7 +66,7 @@ proc atomSequenceIsEnd*(body: ptr AtomSequenceBody; size: Natural; i: ptr AtomEv
 | 
			
		||||
## Return an iterator to the element following `i`.
 | 
			
		||||
##
 | 
			
		||||
proc atomSequenceNext*(i: ptr AtomEvent): ptr AtomEvent {.inline.} =
 | 
			
		||||
    return cast[ptr AtomEvent](i + sizeof(AtomEvent) + atomPadSize(i.body.size))
 | 
			
		||||
    return cast[ptr AtomEvent](cast[ptr uint8](i) + sizeof(AtomEvent) + atomPadSize(i.body.size))
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
## An iterator for looping over all events in a Sequence.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										6
									
								
								src/nymph/ptrmath.nim
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/nymph/ptrmath.nim
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
##
 | 
			
		||||
## Increment pointer `p` by `offset` that jumps memory in increments of
 | 
			
		||||
## the size of `T`.
 | 
			
		||||
##
 | 
			
		||||
proc `+`*[T](p: ptr T, offset: SomeInteger): ptr T =
 | 
			
		||||
    return cast[ptr T](cast[int](p) +% (offset.int * sizeof(T)))
 | 
			
		||||
@ -15,27 +15,23 @@ const
 | 
			
		||||
    lv2UridUnmap* = lv2UridPrefix & "unmap"
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
## Opaque pointer to host data for uridMap.
 | 
			
		||||
## Opaque pointer to host data for UridMap.
 | 
			
		||||
##
 | 
			
		||||
 | 
			
		||||
type UridMapHandle* = pointer
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
## Opaque pointer to host data for uridUnmap.
 | 
			
		||||
##
 | 
			
		||||
 | 
			
		||||
type UridUnmapHandle* = pointer
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
## URI mapped to an integer.
 | 
			
		||||
##
 | 
			
		||||
 | 
			
		||||
type Urid* = distinct uint32
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
## URID Map Feature (LV2_URID__map)
 | 
			
		||||
## URID Map Feature (lv2UridMap)
 | 
			
		||||
##
 | 
			
		||||
 | 
			
		||||
type UridMap* {.bycopy.} = object
 | 
			
		||||
    ##
 | 
			
		||||
    ## Opaque pointer to host data.
 | 
			
		||||
@ -67,11 +63,9 @@ type UridMap* {.bycopy.} = object
 | 
			
		||||
    ##
 | 
			
		||||
    map*: proc (handle: UridMapHandle; uri: cstring): Urid
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
## URI Unmap Feature (LV2_URID__unmap)
 | 
			
		||||
## URI Unmap Feature (lv2UridUnmap)
 | 
			
		||||
##
 | 
			
		||||
 | 
			
		||||
type UridUnmap* {.bycopy.} = object
 | 
			
		||||
    ##
 | 
			
		||||
    ## Opaque pointer to host data.
 | 
			
		||||
@ -97,4 +91,4 @@ type UridUnmap* {.bycopy.} = object
 | 
			
		||||
    ##
 | 
			
		||||
    unmap*: proc (handle: UridUnmapHandle; urid: Urid): cstring
 | 
			
		||||
 | 
			
		||||
proc `==`* (x: Urid, y: Urid): bool {.borrow.}
 | 
			
		||||
proc `==`* (x: Urid, y: Urid): bool {.borrow.}
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
import ../nymph
 | 
			
		||||
import core
 | 
			
		||||
 | 
			
		||||
## Return the data for a feature in a features array.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user