Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

97 lines
2.6KB

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. import math
  4. import lilv
  5. import sys
  6. import wave
  7. import numpy
  8. # Read command line arguments
  9. if len(sys.argv) != 4:
  10. print 'USAGE: lv2_apply.py PLUGIN_URI INPUT_WAV OUTPUT_WAV'
  11. sys.exit(1)
  12. # Initialise Lilv
  13. world = lilv.World()
  14. world.load_all()
  15. plugin_uri = world.new_uri(sys.argv[1])
  16. wav_in_path = sys.argv[2]
  17. wav_out_path = sys.argv[3]
  18. # Find plugin
  19. plugin = world.get_all_plugins().get_by_uri(plugin_uri)
  20. if not plugin:
  21. print "Unknown plugin `%s'\n" % plugin_uri
  22. sys.exit(1)
  23. lv2_InputPort = world.new_uri(lilv.LILV_URI_INPUT_PORT)
  24. lv2_OutputPort = world.new_uri(lilv.LILV_URI_OUTPUT_PORT)
  25. lv2_AudioPort = world.new_uri(lilv.LILV_URI_AUDIO_PORT)
  26. n_audio_in = plugin.get_num_ports_of_class(lv2_InputPort, lv2_AudioPort)
  27. n_audio_out = plugin.get_num_ports_of_class(lv2_OutputPort, lv2_AudioPort)
  28. if n_audio_out == 0:
  29. print "Plugin has no audio outputs\n"
  30. sys.exit(1)
  31. # Open input file
  32. wav_in = wave.open(wav_in_path, 'r')
  33. if not wav_in:
  34. print "Failed to open input `%s'\n" % wav_in_path
  35. sys.exit(1)
  36. if wav_in.getnchannels() != n_audio_in:
  37. print "Input has %d channels, but plugin has %d audio inputs\n" % (
  38. wav_in.getnchannels(), n_audio_in)
  39. sys.exit(1)
  40. # Open output file
  41. wav_out = wave.open(wav_out_path, 'w')
  42. if not wav_out:
  43. print "Failed to open output `%s'\n" % wav_out_path
  44. sys.exit(1)
  45. # Set output file to same format as input (except possibly nchannels)
  46. wav_out.setparams(wav_in.getparams())
  47. wav_out.setnchannels(n_audio_out)
  48. rate = wav_in.getframerate()
  49. nframes = wav_in.getnframes()
  50. # Instantiate plugin
  51. instance = lilv.Instance(plugin, rate)
  52. def read_float(wf, nframes):
  53. wav = wf.readframes(nframes)
  54. if wf.getsampwidth() == 4:
  55. wav = wave.struct.unpack("<%ul" % (len(wav) / 4), wav)
  56. wav = [ i / float(math.pow(2, 32)) for i in wav ]
  57. elif wf.getsampwidth() == 2:
  58. wav = wave.struct.unpack("<%uh" % (len(wav) / 2), wav)
  59. wav = [ i / float(math.pow(2, 16)) for i in wav ]
  60. else:
  61. wav = wave.struct.unpack("%uB" % (len(wav)), wav)
  62. wav = [ s - 128 for s in wav ]
  63. wav = [ i / float(math.pow(2, 8)) for i in wav ]
  64. n_channels = wf.getnchannels()
  65. wavs = []
  66. if n_channels > 1:
  67. for i in xrange(n_channels):
  68. wavs.append([ wav[j] for j in xrange(0, len(wav), n_channels) ])
  69. else:
  70. wavs = [ wav ]
  71. return wavs
  72. in_buf = read_float(wav_in, nframes)
  73. # TODO: buffer marshaling
  74. #instance.connect_port(3, in_buf)
  75. print '%s => %s => %s @ %d Hz' % (wav_in_path, plugin.get_name(), wav_out_path, rate)
  76. instance.connect_port(3, in_buf)