Dup Ver Goto 📝

ConsolidateSamples

PT2/music/daw/reaper/rpp-hacking does not exist
To
167 lines, 516 words, 4003 chars Page 'ConsolidateSamples' does not exist.

Now the best way to do this reliably is to use Reaper's save as. But I thought to write a simple 'consolidate' script, and in the process a script to list samples used in a project. As written, the consolidate script only works with cygwin, but is straightforward to adapt to mac or Linux (just remove the cygpath step).

Samples Used

This lists all samples used in at least one .rpp

#!/usr/bin/env python
from subprocess import run, PIPE, DEVNULL
import os
import shutil
import re
import sys

samples = set()
def main():
  args = sys.argv[1:]
  if len(args) < 1:
    print(f"{sys.argv[0]} <rpp file> [<rpp file> ...]")
    exit(1)
  for fn in args[1:]:
    if not os.path.exists(fn):
      print(f"{fn} does not exist")
      continue
    show(fn)
  for s in sorted(samples):
    print(s)

def show(fn):
  with open(fn) as f:
    rpp = f.read().splitlines()

  while len(rpp) > 0:
    line = rpp.pop(0)
    if re.match(r"\s*<SOURCE WAVE",line):
      line = rpp.pop(0)
      m = re.match(r"(\s*FILE )(['`\"])(.*)\2",line)
      if m:
        wfn = m.group(3)
        samples.add(wfn)

if __name__ == "__main__":
  main()

This one does multiple files and a little formatting

#!/usr/bin/env python
from subprocess import run, PIPE, DEVNULL
import os
import shutil
import re
import sys

def main():
  args = sys.argv[1:]
  if len(args) < 1:
    print(f"{sys.argv[0]} <rpp file> [<rpp file> ...]")
    exit(1)
  for fn in args[1:]:
    if not os.path.exists(fn):
      print(f"{fn} does not exist")
      continue
    show(fn)

def show(fn):
  samples = set()
  with open(fn) as f:
    rpp = f.read().splitlines()

  while len(rpp) > 0:
    line = rpp.pop(0)
    if re.match(r"\s*<SOURCE WAVE",line):
      line = rpp.pop(0)
      m = re.match(r"(\s*FILE )(['`\"])(.*)\2",line)
      if m:
        wfn = m.group(3)
        samples.add(wfn)

  if len(samples) > 0:
    print(f"{fn}:")
    for s in sorted(samples):
      print(f"  {s}")

if __name__ == "__main__":
  main()```

Consolidate

Note that as written, this only works with cygwin. For mac or linux, just replace the cygpath(x) with a function that returns its argument unchanged. For non-cygwin you need to see if the path is an absolute or relative path by a different method than seeing if it starts with "/". I assume that Reaper will only use a relative pathname when the pathname points to within the project folder (i.e. it won't use '../' anywhere in the path).

#!/usr/bin/env python
from subprocess import run, PIPE, DEVNULL
import os
import shutil
import re
import sys
import platform

args = sys.argv[1:]
if len(args) != 2:
  print(f"{sys.argv[0]} <rpp file> <out rpp file>")
  exit(1)

ps = platform.system()
if "CYGWIN" in ps:
  def cygpath(x):
    m = run(["cygpath",x],stdout=PIPE)
    return m.stdout.decode().rstrip("\r\n")
elif "Windows" in ps:
  print(f"You need to use cygwin on Windows")
  exit(2)
else:
  def cygpath(x):
    return x

with open(args[0]) as f:
  rpp = f.read().splitlines()

outlines = []
while len(rpp) > 0:
  line = rpp.pop(0)
  if re.match(r"\s*<SOURCE WAVE",line):
    outlines.append(line)
    line = rpp.pop(0)
    m = re.match(r"(\s*FILE )(['`\"])(.*)\2",line)
    if not m:
      outlines.append(line)
    else:
      wfn = m.group(3)
      fn = cygpath(wfn)
      if not fn.startswith("/"):
        outlines.append(line)
        continue
      bfn = fn.split("/")[-1]
      xs = bfn.split(".")
      stem = ".".join(xs[:-1])
      ext = xs[-1]
      ofn = "Audio/"+bfn
      if os.path.exists(ofn):
        # find unused filename
        i = 0
        while os.path.exists(ofn):
          ofn = f"Audio/{stem}_{i:04d}.{ext}"
      if not os.path.isdir("Audio"):
        os.makedirs("Audio",exist_ok=True)
      shutil.copy(fn,ofn) 
      f = m.group(1)
      q = m.group(2)
      l = f"{f}{q}{ofn}{q}"
      outlines.append(l)
      print(ofn)
  else:
    outlines.append(line)

outrpp = "\r\n".join(outlines)

with open(args[1],"wt") as f:
  f.write(outrpp)