예제 #1
0
    def fill_port_info(plugin, port):
        global index
        index += 1

        # port types
        types = [typ.rsplit("#",1)[-1].replace("Port","",1) for typ in get_port_data(port, rdf.type_)]

        # unit block
        uunit = lilv.lilv_nodes_get_first(port.get_value(units.unit.me))

        # contains unit
        if "Control" in types and uunit is not None:
            uuri = lilv.lilv_node_as_uri(uunit)

            # using pre-existing lv2 unit
            if uuri is not None and uuri.startswith("http://lv2plug.in/ns/extensions/units#"):
                ulabel, urender, usymbol = get_port_unit(uuri.replace("http://lv2plug.in/ns/extensions/units#","",1))

            # using custom unit
            else:
                xlabel  = world.find_nodes(uunit, rdfs  .label.me, None).get_first()
                xrender = world.find_nodes(uunit, units.render.me, None).get_first()
                xsymbol = world.find_nodes(uunit, units.symbol.me, None).get_first()

                ulabel  = xlabel .as_string() if xlabel .me else ""
                urender = xrender.as_string() if xrender.me else ""
                usymbol = xsymbol.as_string() if xsymbol.me else ""

        # no unit
        else:
            ulabel  = ""
            urender = ""
            usymbol = ""

        return {
            'index' : index,
            'name'  : lilv.lilv_node_as_string(port.get_name()),
            'symbol': lilv.lilv_node_as_string(port.get_symbol()),
            'type'  : types,
            'range' : {
                'default': lilv.lilv_node_as_float(lilv.lilv_nodes_get_first(port.get_value(lv2core.default.me))),
                'minimum': lilv.lilv_node_as_float(lilv.lilv_nodes_get_first(port.get_value(lv2core.minimum.me))),
                'maximum': lilv.lilv_node_as_float(lilv.lilv_nodes_get_first(port.get_value(lv2core.maximum.me))),
            } if ("Control", "Input") == types else {},
            'units' : {
                'label' : ulabel,
                'render': urender,
                'symbol': usymbol,
            } if "Control" in types and (ulabel or urender or usymbol) else {},
            'designation': (get_port_data(port, lv2core.designation) or [None])[0],
            'properties' : [typ.rsplit("#",1)[-1] for typ in get_port_data(port, lv2core.portProperty)],
            'rangeSteps' : (get_port_data(port, pprops.rangeSteps) or [None])[0],
            "scalePoints": [],
        }
예제 #2
0
    def generate_psname(self):
        portname = self.portname

        psname = lilv.lilv_nodes_get_first(
            self.port.get_value(self.ns_lv2core.shortName.me)
        )

        if psname is not None:
            psname = lilv.lilv_node_as_string(psname) or ""

        if not psname:
            psname = self.get_short_port_name(portname)
            if len(psname) > Port.SHORT_NAME_SIZE:
                self.warnings.append("port '%s' name is too big, reduce the name size or provide a shortName" % portname)

        elif len(psname) > Port.SHORT_NAME_SIZE:
            psname = psname[:Port.SHORT_NAME_SIZE]
            self.register_error("short name has more than %d characters", Port.SHORT_NAME_SIZE)

        # check for old style shortName
        if self.port.get_value(self.ns_lv2core.shortname.me) is not None:
            self.register_error("short name is using old style 'shortname' instead of 'shortName'")

        return psname
예제 #3
0
def main():
    # Read command line arguments
    if len(sys.argv) != 4:
        print('USAGE: lv2_apply.py PLUGIN_URI INPUT_WAV OUTPUT_WAV')
        sys.exit(1)

    # Initialise Lilv
    world = lilv.World()
    world.load_all()

    plugin_uri   = sys.argv[1]
    wav_in_path  = sys.argv[2]
    wav_out_path = sys.argv[3]

    # Find plugin
    plugin_uri_node = world.new_uri(plugin_uri)
    plugin          = world.get_all_plugins().get_by_uri(plugin_uri_node)
    if not plugin:
        print("Unknown plugin `%s'\n" % plugin_uri)
        sys.exit(1)

    lv2_InputPort   = world.new_uri(lilv.LILV_URI_INPUT_PORT)
    lv2_OutputPort  = world.new_uri(lilv.LILV_URI_OUTPUT_PORT)
    lv2_AudioPort   = world.new_uri(lilv.LILV_URI_AUDIO_PORT)
    lv2_ControlPort = world.new_uri(lilv.LILV_URI_CONTROL_PORT)
    lv2_default     = world.new_uri("http://lv2plug.in/ns/lv2core#default")

    n_audio_in  = plugin.get_num_ports_of_class(lv2_InputPort,  lv2_AudioPort)
    n_audio_out = plugin.get_num_ports_of_class(lv2_OutputPort, lv2_AudioPort)
    if n_audio_out == 0:
        print("Plugin has no audio outputs\n")
        sys.exit(1)

    # Open input file
    try:
        wav_in = WavFile(wav_in_path)
    except:
        print("Failed to open input `%s'\n" % wav_in_path)
        sys.exit(1)

    if wav_in.nchannels != n_audio_in:
        print("Input has %d channels, but plugin has %d audio inputs\n" % (
            wav_in.nchannels, n_audio_in))
        sys.exit(1)

    # Open output file
    wav_out = wave.open(wav_out_path, 'w')
    if not wav_out:
        print("Failed to open output `%s'\n" % wav_out_path)
        sys.exit(1)

    # Set output file to same format as input (except possibly nchannels)
    wav_out.setparams(wav_in.wav_in.getparams())
    wav_out.setnchannels(n_audio_out)

    print('%s => %s => %s @ %d Hz'
          % (wav_in_path, plugin.get_name(), wav_out_path, wav_in.framerate))

    instance = lilv.Instance(plugin, wav_in.framerate)

    channels = wav_in.read()
    wav_in.close()

    # Connect all ports to buffers. NB if we fail to connect any buffer, lilv
    # will segfault.
    audio_input_buffers    = []
    audio_output_buffers   = []
    control_input_buffers  = []
    control_output_buffers = []
    for index in range(plugin.get_num_ports()):
        port = plugin.get_port_by_index(index)
        if port.is_a(lv2_InputPort):
            if port.is_a(lv2_AudioPort):
                audio_input_buffers.append(numpy.array(channels[len(audio_input_buffers)], numpy.float32))
                instance.connect_port(index, audio_input_buffers[-1])
            elif port.is_a(lv2_ControlPort):
                #if port.has_property(lv2_default):  # Doesn't seem to work
                default = lilv.lilv_node_as_float(lilv.lilv_nodes_get_first(port.get_value(lv2_default)))
                control_input_buffers.append(numpy.array([default], numpy.float32))
                instance.connect_port(index, control_input_buffers[-1])
            else:
                raise ValueError("Unhandled port type")
        elif port.is_a(lv2_OutputPort):
            if port.is_a(lv2_AudioPort):
                audio_output_buffers.append(numpy.array([0] * wav_in.nframes, numpy.float32))
                instance.connect_port(index, audio_output_buffers[-1])
            elif port.is_a(lv2_ControlPort):
                control_output_buffers.append(numpy.array([0], numpy.float32))
                instance.connect_port(index, control_output_buffers[-1])
            else:
                raise ValueError("Unhandled port type")

    # Run the plugin:
    instance.run(wav_in.nframes)

    # Interleave output buffers:
    data = numpy.dstack(audio_output_buffers).flatten()

    # Return to original int range:
    if wav_in.signed:
        data = data * float(wav_in.range / 2)
    else:
        data = (data + 1) * float(wav_in.range/2)

    # Write output file in chunks to stop memory usage getting out of hand:
    CHUNK_SIZE = 8192
    for chunk in numpy.array_split(data, CHUNK_SIZE):
        wav_out.writeframes(wave.struct.pack("%u%s" % (len(chunk), wav_in.struct_fmt_code), *chunk))
    wav_out.close()
예제 #4
0
    def fill_port_info(port):
        # base data
        portname = lilv.lilv_node_as_string(port.get_name()) or ""

        if not portname:
            portname = "_%i" % index
            errors.append("port with index %i has no name" % index)

        portsymbol = lilv.lilv_node_as_string(port.get_symbol()) or ""

        if not portsymbol:
            portsymbol = "_%i" % index
            errors.append("port with index %i has no symbol" % index)

        # check for duplicate names
        if portname in portsymbols:
            warnings.append("port name '%s' is not unique" % portname)
        else:
            portnames.append(portname)

        # check for duplicate symbols
        if portsymbol in portsymbols:
            errors.append("port symbol '%s' is not unique" % portsymbol)
        else:
            portsymbols.append(portsymbol)

        # short name
        psname = lilv.lilv_nodes_get_first(port.get_value(ns_lv2core.shortname.me))

        if psname is not None:
            psname = lilv.lilv_node_as_string(psname) or ""

        if not psname:
            psname = get_short_port_name(portname)
            warnings.append("port '%s' has no short name" % portname)

        elif len(psname) > 16:
            psname = psname[:16]
            errors.append("port '%s' short name has more than 16 characters" % portname)

        # port types
        types = [typ.rsplit("#",1)[-1].replace("Port","",1) for typ in get_port_data(port, ns_rdf.type_)]

        if "Atom" in types \
            and port.supports_event(ns_midi.MidiEvent.me) \
            and lilv.Nodes(port.get_value(ns_atom.bufferType.me)).get_first() == ns_atom.Sequence:
                types.append("MIDI")

        # port properties
        properties = [typ.rsplit("#",1)[-1] for typ in get_port_data(port, ns_lv2core.portProperty)]

        # data
        ranges      = {}
        scalepoints = []

        # unit block
        ulabel  = ""
        urender = ""
        usymbol = ""

        # control and cv must contain ranges, might contain scale points
        if "Control" in types or "CV" in types:
            isInteger = "integer" in properties

            if isInteger and "CV" in types:
                errors.append("port '%s' has integer property and CV type" % portname)

            xdefault = lilv.lilv_nodes_get_first(port.get_value(ns_lv2core.default.me))
            xminimum = lilv.lilv_nodes_get_first(port.get_value(ns_lv2core.minimum.me))
            xmaximum = lilv.lilv_nodes_get_first(port.get_value(ns_lv2core.maximum.me))

            if xminimum is not None and xmaximum is not None:
                if isInteger:
                    if is_integer(lilv.lilv_node_as_string(xminimum)):
                        ranges['minimum'] = lilv.lilv_node_as_int(xminimum)
                    else:
                        ranges['minimum'] = lilv.lilv_node_as_float(xminimum)
                        if fmod(ranges['minimum'], 1.0) == 0.0:
                            warnings.append("port '%s' has integer property but minimum value is float" % portname)
                        else:
                            errors.append("port '%s' has integer property but minimum value has non-zero decimals" % portname)
                        ranges['minimum'] = int(ranges['minimum'])

                    if is_integer(lilv.lilv_node_as_string(xmaximum)):
                        ranges['maximum'] = lilv.lilv_node_as_int(xmaximum)
                    else:
                        ranges['maximum'] = lilv.lilv_node_as_float(xmaximum)
                        if fmod(ranges['maximum'], 1.0) == 0.0:
                            warnings.append("port '%s' has integer property but maximum value is float" % portname)
                        else:
                            errors.append("port '%s' has integer property but maximum value has non-zero decimals" % portname)
                        ranges['maximum'] = int(ranges['maximum'])

                else:
                    ranges['minimum'] = lilv.lilv_node_as_float(xminimum)
                    ranges['maximum'] = lilv.lilv_node_as_float(xmaximum)

                    if is_integer(lilv.lilv_node_as_string(xminimum)):
                        warnings.append("port '%s' minimum value is an integer" % portname)

                    if is_integer(lilv.lilv_node_as_string(xmaximum)):
                        warnings.append("port '%s' maximum value is an integer" % portname)

                if ranges['minimum'] >= ranges['maximum']:
                    ranges['maximum'] = ranges['minimum'] + (1 if isInteger else 0.1)
                    errors.append("port '%s' minimum value is equal or higher than its maximum" % portname)

                if xdefault is not None:
                    if isInteger:
                        if is_integer(lilv.lilv_node_as_string(xdefault)):
                            ranges['default'] = lilv.lilv_node_as_int(xdefault)
                        else:
                            ranges['default'] = lilv.lilv_node_as_float(xdefault)
                            if fmod(ranges['default'], 1.0) == 0.0:
                                warnings.append("port '%s' has integer property but default value is float" % portname)
                            else:
                                errors.append("port '%s' has integer property but default value has non-zero decimals" % portname)
                            ranges['default'] = int(ranges['default'])
                    else:
                        ranges['default'] = lilv.lilv_node_as_float(xdefault)

                        if is_integer(lilv.lilv_node_as_string(xdefault)):
                            warnings.append("port '%s' default value is an integer" % portname)

                    testmin = ranges['minimum']
                    testmax = ranges['maximum']

                    if "sampleRate" in properties:
                        testmin *= 48000
                        testmax *= 48000

                    if not (testmin <= ranges['default'] <= testmax):
                        ranges['default'] = ranges['minimum']
                        errors.append("port '%s' default value is out of bounds" % portname)

                else:
                    ranges['default'] = ranges['minimum']

                    if "Input" in types:
                        errors.append("port '%s' is missing default value" % portname)

            else:
                if isInteger:
                    ranges['minimum'] = 0
                    ranges['maximum'] = 1
                    ranges['default'] = 0
                else:
                    ranges['minimum'] = -1.0 if "CV" in types else 0.0
                    ranges['maximum'] = 1.0
                    ranges['default'] = 0.0

                if "CV" not in types:
                    errors.append("port '%s' is missing value ranges" % portname)

            nodes = port.get_scale_points()

            if nodes is not None:
                it = lilv.lilv_scale_points_begin(nodes)
                while not lilv.lilv_scale_points_is_end(nodes, it):
                    sp = lilv.lilv_scale_points_get(nodes, it)
                    it = lilv.lilv_scale_points_next(nodes, it)

                    if sp is None:
                        continue

                    label = lilv.lilv_scale_point_get_label(sp)
                    value = lilv.lilv_scale_point_get_value(sp)

                    if label is None:
                        errors.append("a port scalepoint is missing its label")
                        continue

                    label = lilv.lilv_node_as_string(label) or ""

                    if not label:
                        errors.append("a port scalepoint is missing its label")
                        continue

                    if value is None:
                        errors.append("port scalepoint '%s' is missing its value" % label)
                        continue

                    if isInteger:
                        if is_integer(lilv.lilv_node_as_string(value)):
                            value = lilv.lilv_node_as_int(value)
                        else:
                            value = lilv.lilv_node_as_float(value)
                            if fmod(value, 1.0) == 0.0:
                                warnings.append("port '%s' has integer property but scalepoint '%s' value is float" % (portname, label))
                            else:
                                errors.append("port '%s' has integer property but scalepoint '%s' value has non-zero decimals" % (portname, label))
                            value = int(value)
                    else:
                        if is_integer(lilv.lilv_node_as_string(value)):
                            warnings.append("port '%s' scalepoint '%s' value is an integer" % (portname, label))
                        value = lilv.lilv_node_as_float(value)

                    if ranges['minimum'] <= value <= ranges['maximum']:
                        scalepoints.append({'label': label, 'value': value})
                    else:
                        errors.append(("port scalepoint '%s' has an out-of-bounds value:\n" % label) +
                                      ("%d < %d < %d" if isInteger else "%f < %f < %f") % (ranges['minimum'], value, ranges['maximum']))

            if "enumeration" in properties and len(scalepoints) <= 1:
                errors.append("port '%s' wants to use enumeration but doesn't have enough values" % portname)
                properties.remove("enumeration")

        # control ports might contain unit
        if "Control" in types:
            # unit
            uunit = lilv.lilv_nodes_get_first(port.get_value(ns_units.unit.me))

            if uunit is not None:
                uuri = lilv.lilv_node_as_uri(uunit)

                # using pre-existing lv2 unit
                if uuri is not None and uuri.startswith("http://lv2plug.in/ns/"):
                    uuri  = uuri.replace("http://lv2plug.in/ns/extensions/units#","",1)
                    alnum = uuri.isalnum()

                    if not alnum:
                        errors.append("port '%s' has wrong lv2 unit uri" % portname)
                        uuri = uuri.rsplit("#",1)[-1].rsplit("/",1)[-1]

                    ulabel, urender, usymbol = get_port_unit(uuri)

                    if alnum and not (ulabel and urender and usymbol):
                        errors.append("port '%s' has unknown lv2 unit (our bug?, data is '%s', '%s', '%s')" % (portname,
                                                                                                               ulabel,
                                                                                                               urender,
                                                                                                               usymbol))

                # using custom unit
                else:
                    xlabel  = world.find_nodes(uunit, ns_rdfs  .label.me, None).get_first()
                    xrender = world.find_nodes(uunit, ns_units.render.me, None).get_first()
                    xsymbol = world.find_nodes(uunit, ns_units.symbol.me, None).get_first()

                    if xlabel.me is not None:
                        ulabel = xlabel.as_string()
                    else:
                        errors.append("port '%s' has custom unit with no label" % portname)

                    if xrender.me is not None:
                        urender = xrender.as_string()
                    else:
                        errors.append("port '%s' has custom unit with no render" % portname)

                    if xsymbol.me is not None:
                        usymbol = xsymbol.as_string()
                    else:
                        errors.append("port '%s' has custom unit with no symbol" % portname)

        return (types, {
            'name'   : portname,
            'symbol' : portsymbol,
            'ranges' : ranges,
            'units'  : {
                'label' : ulabel,
                'render': urender,
                'symbol': usymbol,
            } if "Control" in types and ulabel and urender and usymbol else {},
            'designation': (get_port_data(port, ns_lv2core.designation) or [None])[0],
            'properties' : properties,
            'rangeSteps' : (get_port_data(port, ns_mod.rangeSteps) or get_port_data(port, ns_pprops.rangeSteps) or [None])[0],
            "scalePoints": scalepoints,
            'shortname'  : psname,
        })
예제 #5
0
 def get_first_port_node(self, subject):
     return lilv.lilv_nodes_get_first(self.port.get_value(subject))
예제 #6
0
 def unit(self, port):
     port_value = port.get_value(self.ns_units.unit.me)
     return lilv.lilv_nodes_get_first(port_value)
예제 #7
0
 def unit(self, port):
     port_value = port.get_value(self.ns_units.unit.me)
     return lilv.lilv_nodes_get_first(port_value)
예제 #8
0
 def get_first_port_node(self, subject):
     return lilv.lilv_nodes_get_first(self.port.get_value(subject))