reaper/insert-envelope [ Functions ]

[ Top ] [ Functions ]

AUTHOR

 Leon Focker: leon@leonfocker.de

DATE

 April 30th 2023.

DESCRIPTION

 get the string of a reaper file and rewrite it, so that a given envelope is
 inserted into the project in a given place.

ARGUMENTS

 - the string of the project file you want to edit
 - the reaper-envelope object that you want to insert into the reaper project
 - the number of the track, on which to insert the envelope (master is 0)

RETURN VALUE

 the edited string of the entire reaper file

EXAMPLE

;;; insert the angle-env value of a sndfile as an envelope on track 1 of 
;;; project.rpp and give it the duration of the sndfile.
(let ((snd (make-sndfile "/E/sound.wav" :angle-env '(0 0 1 1 2 .5))))
  (insert-envelope (read-file-as-string "/E/project.rpp")
                   (make-reaper-envelope (angle-env snd)
                                         :env-type 'parmenv
                                         :parameter-slot 6)
                   1 0 (duration snd)))

SYNOPSIS

#+cl-ppcre
(defun insert-envelope (string reaper-envelope track-nr)

reaper/insert-plugin [ Functions ]

[ Top ] [ Functions ]

AUTHOR

 Leon Focker: leon@leonfocker.de

DATE

 April 30th 2023.

DESCRIPTION

 get the string of a reaper file and rewrite it, so that a given plugin is
 inserted into the project in a given place.

ARGUMENTS

 - the string of the project file you want to edit
 - the binary string of the plugin you want to insert. The easiest way of
 obtaining this is probably by copying it from a reaper file that you created
 manually (create a reaper project file and load the plugin, the open the
 file with a text editor and find and copy the string <VST ..... >.
 See "slippery-chicken/src/txt/iem-stereo-encoder.txt" for an example).
 To use that plugin in write-spatial-reaper-file (of possibly others), add
 it to the 'plugins' slot in the definition of the reaper-file class.
 - the number of the track, on which to insert the plugin (master is 0)

OPTIONAL ARGUMENTS

 - if the plugin is to be inserted before all others (t) or after all other
 plugins already on the track (nil)

RETURN VALUE

 the edited string of the entire reaper file

EXAMPLE

;;; insert the blue ripple binaural ambisonics decoder on the master track of 
;;; project.rpp
(insert-plugin (read-file-as-string "/E/project.rpp") *blue-ripple-decoder* 0 t)

SYNOPSIS

#+cl-ppcre
(defun insert-plugin (string plugin-binary-string track-nr &optional (pre nil))

reaper/reaper-layer-sounds [ Functions ]

[ Top ] [ Functions ]

DATE

 October 1st 2022

DESCRIPTION

 Given a list of paths to sound files, create a reaper file that layers/mixes
 these together. We create as many mixes as possible given the number of
 tracks required, e.g. if there are 20 sound files and <num-tracks> is 4,
 then five mixes will be created, one after the other, with a gap of 10
 seconds by default. So the files are mixed together in the order of the
 first argument, with the longest file in the mix determining the overall
 duration and the shorter files beginning after a wait of <indent> multiplied
 by the difference between the longest and shorter files'
 durations. E.g. with a longest file duration of 60 seconds and a shorter
 file of 30 seconds, given :indent 0.5 the shorter file's start time would be
 15 seconds; if its duration was 20 seconds, the start time would be 20.

 In case sound files are passed in alphabetical order, e.g. by
 (get-sndfiles...), and assuming that it is undesireable that similarly-named
 sound files are placed one after the other, by default the function will
 shuffle the order of the mixes (i.e. the groups of 4 or whatever sound files
 per mix). NB the 4-groups are shuffled, not the files in the groups.

ARGUMENTS

 - a list of sound file paths (strings)
 - the number of tracks that should be layered/mixed

OPTIONAL ARGUMENTS

 keyword arguments:
 :tempo. The BPM value that should be written to the reaper project, if
 desired. Default = 60.
 :max-fade. The maximum length in seconds of a fade-in or fade-out. If this
 is too long for any given sound file, the :mid-fade multiplied by the sound
 file duration will be used. Default = 15 seconds.
 :min-fade. The proportion of a sound file's duration that should be used if
 :max-fade can't be used for both fade-in and fade-out. This should generally
 be < 0.5 but is not enforced. Default = 0.5.
 :reaper-file. The path of the reaper-file to be written. If this is NIL then
 no file is written and the reaper-file object is returned instead, with all
 mixes present. This could be used to add more tracks before writing the
 reaper file (see example below). Default = "/tmp/reaper-layer-sounds.rpp"
 :min-channels. The minimum number of a channels a reaper track should
 have. Usually this will be set to be the maximum number of channels any of
 the files on a single track have. But if you have a bunch of stereo files
 you want to place on, say, a track which should become 5th order ambisonics,
 you can set this to 36. Note that all reaper tracks should have an even
 number of channels so however the channel number is achieved it will be
 rouned up to the nearest even number if necessary. Default = 2.
 :max-channels. This can be set to override the number of channels of any
 given sound file, should it have more channels than you want, for some
 reason. Default = 4.
 :gap. The gap in seconds between the end of the previous mix and the start
 of the next. Default = 10 seconds.
 :shuffle. Whether to shuffle the mixes before writing. See above for
 details. Default = T.
 :indent. How far in to start the shorter sounds, as a function of their
 duration difference to the longest file (see above). 0.5 would have them
 centered bang in the middle. By default the golden mean, 0.618034 (what
 else?) i.e. (/ (- (sqrt 5) 1) 2).

RETURN VALUE

 If :reaper-file is given, then the path will be returned after writing,
 otherwise a reaper-file object is returned.

EXAMPLE

(let ((overlaps (reaper-overlap-sounds
                 (get-sndfiles "/Volumes/slim500/snd/samples/ambience/rain") 
                 :reaper-file nil))
      (layers (reaper-layer-sounds (get-sndfiles "~/ic/projects/mete/clm") 4
                                   :reaper-file nil)))
  (add (get-first (tracks overlaps)) (tracks layers))
  (write-reaper-file layers :min-channels 36
                     :file "~/ic/projects/mete/reaper/mete-clm-with-rain.rpp"))

SYNOPSIS

(defun reaper-layer-sounds (sndfiles num-tracks
                            &key (tempo 60)
                              (max-fade 15) ; seconds
                              (min-fade .4) ; proportion of duration
                              (reaper-file "/tmp/reaper-layer-sounds.rpp")
                              ;; e.g. if you want all tracks to be 26 channels
                              ;; despite the number of channels in the sound
                              ;; files set this here
                              (min-channels 2)
                              (max-channels 4)
                              ;; gap in seconds between groups
                              (gap 10)
                              ;; shuffle (fixed-seed) the subgroups so that the
                              ;; sound files are not simply processed by
                              ;; directory order?
                              (shuffle t)
                              (indent 0.618034))

reaper/reaper-overlap-sounds [ Functions ]

[ Top ] [ Functions ]

DATE

 October 1st 2022.

DESCRIPTION

 Create a reaper file with one track that overlaps/cross-fades all the given
 sound files.

ARGUMENTS

 - a list of sound files paths (strings) to overlap

OPTIONAL ARGUMENTS

 keyword arguments:
 
 :overlap. The proportion by which to overlap the sound files. Given that
 sound files can have any duration and be overlapped in any order, this
 proportion is applied to the shortest of any two sound files to be
 cross-faded. default = 0.5.
 :reaper-file. The path of the reaper-file to be written. If this is NIL then
 no file is written and the reaper-file object is returned instead, with all
 mixes present. This could be used to add more tracks before writing the
 reaper file (see example in reaper-layer-sounds). Default =
 "/tmp/reaper-layer-sounds.rpp"
 :min-channels. See reaper-layer-sounds. Default = 2.
 :max-channels. See reaper-layer-sounds. Default = 4.
 :track-name. The string used to name the track in reaper. Default =
 "overlaps"
 :tempo. The BPM value that should be written to the reaper project, if
 desired. Default = 60.

RETURN VALUE

 If :reaper-file is given, then the path will be returned after writing,
 otherwise a reaper-file object is returned. See reaper-layer-sounds for an
 example.

SYNOPSIS

(defun reaper-overlap-sounds (sndfiles &key (tempo 60) (min-channels 2)
                                         (max-channels 4) (overlap .5)
                                         (track-name "overlaps")
                                         (reaper-file
                                          "/tmp/reaper-layer-sounds.rpp"))

reaper/write-reaper-ambisonics-file [ Functions ]

[ Top ] [ Functions ]

AUTHOR

 Leon Focker: leon@leonfocker.de

DATE

 April 30th 2023.

DESCRIPTION

 Create a reaper file that contains all the data to spatialize sndfiles using
 the ambisonics method. For more information on the spatialization data, see
 #'make-sndfile

ARGUMENTS

 - a list of sndfile objects: their angle-env and elevation-env arguments
 will be used for spatialization.

OPTIONAL ARGUMENTS

 keyword arguments:

 :file. The path to the file that shall be generated.
 :start-times. A list of start times for each soundfile on each track in
 seconds. If the list is shorter than the number of sndfiles, it is looped.
 Default = '(0) - this means all files start at 0.
 :sample-rate. The sample-rate that should be written to the reaper project.
 Default = 48000.
 :ambi-order. Should be an integer between 1 and 8, this determines the
 number of channel for each track.
 :tempo. The BPM value that should be written to the reaper project, if
 desired. Default = 60.
 :init-volume. Volume multipliers for all faders.
 -0dB would be 1, Default = -12dB.
 :encoder. The key to find the binary data for the plugin that will be
 inserted into all tracks except the master track in the 'plugins' slot
 of the reaper-file class.
 Default: :iem-stereo-encoder
 :decoder. The key to find the binary data for the plugin that will be
 inserted on the master track in the 'plugins' slot of the reaper-file class.
 Default: :blue-ripple-decoder
 :angle-parameter-slot. The automation slot that the angle-env will controll.
 This should be changed when other plugins are used than the defaults.
 Default = 6, because the IEM stereo encoders 6th automation slot is the
 angle-argument. If this is a list of numbers, the first element will be used
 for the first angle-env of the sndfile and the second for the second env
 etc. (when more than one is given for each sndfile).
 :elevation-parameter-slot. The automation slot that the elevation-env will
 controll. This should be changed when other plugins are used than the
 defaults. Default = 7, because the IEM stereo encoders 7th automation slot
 is the elevation-argument. If this is a list of numbers, the first element
 will be used for the first elevation-env of the sndfile and the second for
 the second env etc. (when more than one is given for each sndfile).
 :angle-offset. An offset for the rotation of the scene, where 1 = 360°.
 Default is 0.5, so that the angle 0 is the front for the iem plugins.
 :envs-use-start-times. If nil, all envelopes start at the minimal
 start-time. If t, the envelopes use the start time of the respective
 sndfile.
 :envs-use-end-times. If nil, all envelopes end when every sndfile hast
 stopped. If t, end when the respective sndfile stopps.
 :envs-duration. If nil, the behavior of envs-use-end-times applies.
 If a number, every automation envelope gets this duration -
 envs-use-end-times will be ignored in this case.
 envs-only. If t, don't write a file or insert any plugins, just re-write the
 envelopes. This is usefull if you generate a file with this function and 
 edited the project file by adding more tracks etc. (These should be added
 after the already existing ones). Then you could edit the envelopes of the
 sndfiles and set envs-only to t. This way, the file will stay the same
 except for the envelopes.
 :envs-visible. t or nil, wheter all envelopes will be visible (opened) in the
 reaper-file.

RETURN VALUE

 path to the reaper file that was generated.

EXAMPLE

;;; make three soundfiles into sndfile objects and spatialize them, while 
;;; returning their paths in windows format.
(set-sc-config 'reaper-files-for-windows t)
(write-reaper-ambisonics-file
 `(,(make-sndfile "/E/pads.wav"
                          :angle-env '(0 0  .5 .5  .8 4  1 3.5)
                          :elevation-env '(0 0  .6 .25  2 .5))
    ,(make-sndfile "/E/synths.wav"
                          :angle-env '(0 0  .5 .5  .8 8  1 3.25)
                          :elevation-env '(0 0.5  1 .25))
    ,(make-sndfile "/E/drums.wav"
                          :angle-env '(0 .5  .5 1  .8 8.5  1 3.75)
                          :elevation-env '(0 0.5  1 .25)))
 :file "/E/spatial.rpp"
 :ambi-order 3
 :envs-use-start-times t
 :envs-use-end-times t)


;;; spatialize one sndfile with two channels, that are opposite and circling
;;; each other:
(write-reaper-ambisonics-file 
 `(,(make-sndfile "/E/code/feedback/intro.wav"
                  :angle-env '((0 0  .5 .5  .8 4  1 3.5)
                               (0 .5  .5 1  .8 4.5  1 4))
                  :elevation-env '(0 0  .6 .25  2 .5)))
 :file "/E/code/test.rpp"
 :encoder :iem-multi-encoder
 :angle-parameter-slot '(7 12)
 :elevation-parameter-slot '(8 13))

SYNOPSIS

#+cl-ppcre
(defun write-reaper-ambisonics-file (list-of-sndfiles
                                     &key file
                                       (start-times '(0))
                                       (sample-rate 48000)
                                       (ambi-order 3)
                                       (tempo 60)
                                       (init-volume .2511)
                                       (encoder :iem-stereo-encoder)
                                       (decoder :blue-ripple-decoder)
                                       (angle-parameter-slot 6)
                                       (elevation-parameter-slot 7)
                                       (angle-offset 0.5)
                                       (envs-use-start-times t)
                                       (envs-use-end-times t)
                                       envs-duration
                                       envs-only
                                       (envs-visible t))

reaper/write-reaper-file [ Methods ]

[ Top ] [ Methods ]

DESCRIPTION

 Write a reaper file from the reaper-items in the data slot.

ARGUMENTS

 - a reaper-file object

OPTIONAL ARGUMENTS

 keyword arguments: 
 - :file. The path of the reaper file to write. Default will be the id slot
   of the reaper-file object + .rpp, placed in the default-directory of
   slippery-chicken (itself /tmp by default).
 - :markers. These are either a simple list of times (in seconds) or a
   mixture containing sublists such as (marker-number time-in-secs
   label-string colour), or just the first two or three of those. See the
   write-reaper-marker method for details. Default = NIL.
 - :min-channels (default 2) and :max-channels (default 4). These are the
   minimum and maximum channel counts of the reaper-tracks which are usually
   dependent upon or influence the number of channels reflected in the sound
   files' playback. A sound file could have any number of channels of course
   and usually we'd use the maximum number of channels a track's sound files
   have to set the channels slot, but here we can limit these to something
   reasonable (or e.g. force 4-channel tracks even though all sound files are
   stereo).

RETURN VALUE

 The patch to the generated reaper file.

EXAMPLE

;;; one simple way of algorithmically generating a reaper file:
(let* ((tempo 240)
       (items
         (make-reaper-items1
          (get-sndfiles
           (concatenate 'string
                        cl-user::+slippery-chicken-home-dir+
                        "tests/test-sndfiles-dir-2"))
          '(e (w) (q) q (h) (e) e. (q.) q (w) e (w) e.)
           tempo
          :input-start '(0 .1 .2)
          :play-rate '(1 1.02 1 .98 1.01 1 1.02)
          :preserve-pitch t))
       ;; NB the tempo of the reaper file is independent of the items
       (rf (make-reaper-file 'reaper-test items :tempo tempo)))
  (write-reaper-file rf))

;;; or to write a reaper file with markers only, at times given in seconds
(write-reaper-file (make-reaper-file 'test nil) :markers '(1 2 3.5 7))

;;; mixed marker data starting with simple times
(write-reaper-file (make-reaper-file 'test nil)
  :markers '(1 2 3.5 7 (49 8.021 "nice label") ; number 49, time 8.021, named 
             (562 9.1 "better label" blue))) ; sim. but with a recognised colour

SYNOPSIS

(defmethod write-reaper-file ((rf reaper-file)
                              &key file markers
                              (min-channels 2) (max-channels 4))

reaper/write-reaper-sad-file [ Functions ]

[ Top ] [ Functions ]

AUTHOR

 Leon Focker: leon@leonfocker.de

DATE

 May 22nd 2023.

DESCRIPTION

 Create a reaper file that contains all the data to spatialize sndfiles using
 the spatial audio designer plugins. For this, the angle and elevation
 arguments of the sndfiles wil be converted to the cartesian coordinate
 system.

ARGUMENTS

 - a list of sndfile objects: their angle-env and elevation-env arguments
 will be used for spatialization.

OPTIONAL ARGUMENTS

 keyword arguments:

 :file. The path to the file that shall be generated.
 :start-times. A list of start times for each soundfile on each track in
 seconds. If the list is shorter than the number of sndfiles, it is looped.
 Default = '(0) - this means all files start at 0.
 :sample-rate. The sample-rate that should be written to the reaper project.
 Default = 48000.
 :nr-of-master-channels. = How many channels the master bus will have. The
 number of channels for each track is determined by the number of channels
 the soundfiles on each track has, but is at least 2 and not more than 8.
 :tempo. The BPM value that should be written to the reaper project, if
 desired. Default = 60.
 :init-volume. Volume multpiliers for all faders.
 -0dB would be 1, Default = -12dB.
 :angle-offset. An offset for the rotation of the scene, where 1 = 360°.
 Default is 0, so that the angle 0 is the front.
 :env-conversion-srate. This number is the minimum amount of times per second
 that an additional point is calculated and converted from polar to cartesian
 coordinates. Default = 4, which means that at least every .25 seconds there
 will be a breakpoint. If this number is too low (< 1), the conversion from
 polar to cartesian won't represent the original envelope very well.
 :envs-use-start-times. If nil, all envelopes start at the minimal
 start-time. If t, the envelopes use the start time of the respective
 sndfile.
 :envs-use-end-times. If nil, all envelopes end when every sndfile hast
 stopped. If t, end when the respective sndfile stopps.
 :envs-duration. If nil, the behavior of envs-use-end-times applies.
 If a number, every automation envelope gets this duration -
 envs-use-end-times will be ignored in this case.
 envs-only. If t, don't write a file or insert any plugins, just re-write the
 envelopes. This is usefull if you generate a file with this function and 
 edited the project file by adding more tracks etc. (These should be added
 after the already existing ones). Then you could edit the envelopes of the
 sndfiles and set envs-only to t. This way, the file will stay the same
 except for the envelopes.
 :envs-visible. t or nil, wheter all envelopes will be visible (opened) in the
 reaper-file.

RETURN VALUE

 path to the reaper file that was generated.

EXAMPLE

;;; make three soundfiles into sndfile objects and spatialize them, while 
;;; returning their paths in windows format.
(set-sc-config 'reaper-files-for-windows t)
(write-reaper-sad-file
 `(,(make-sndfile "/E/pads.wav"
                          :angle-env '(0 0  .5 .5  .8 4  1 3.5)
                          :elevation-env '(0 0  .6 .25  2 .5))
    ,(make-sndfile "/E/synths.wav"
                          :angle-env '(0 0  .5 .5  .8 8  1 3.25)
                          :elevation-env '(0 0.5  1 .25))
    ,(make-sndfile "/E/drums.wav"
                          :angle-env '(0 .5  .5 1  .8 8.5  1 3.75)
                          :elevation-env '(0 0.5  1 .25)))
 :file "/E/spatial.rpp"
 :envs-use-start-times t
 :envs-use-end-times t)

;;; spatialize one sndfile with two channels, that are opposite and circling
;;; each other:
(write-reaper-sad-file 
 `(,(make-sndfile "/E/code/feedback/intro.wav"
                  :angle-env '((0 0  .5 .5  .8 4  1 3.5)
                               (0 .5  .5 1  .8 4.5  1 4))
                  :elevation-env '(0 0  .6 .25  2 .5)))
 :file "/E/code/test.rpp")

SYNOPSIS

#+cl-ppcre
(defun write-reaper-sad-file (list-of-sndfiles
                              &key file
                                (start-times '(0))
                                (sample-rate 48000)
                                (nr-of-master-channels 2)
                                (tempo 60)
                                (init-volume .2511)
                                (angle-offset 0)
                                (env-conversion-srate 4)
                                (envs-use-start-times t)
                                (envs-use-end-times t)
                                envs-duration
                                envs-only
                                (envs-visible t))

sclist/reaper-file [ Classes ]

[ Top ] [ sclist ] [ Classes ]

sclist/reaper-track [ Classes ]

[ Top ] [ sclist ] [ Classes ]

sndfile/reaper-item [ Classes ]

[ Top ] [ sndfile ] [ Classes ]

NAME

 reaper

 File:             reaper.lsp            

 Class Hierarchy:  named-object -> linked-named-object -> sndfile ->
                   reaper-item
 Class Hierarchy:  named-object -> linked-named-object -> sclist ->
                   reaper-track
 Class Hierarchy:  named-object -> linked-named-object -> sclist ->
                   reaper-file

 Version:          1.0.12

 Project:          slippery chicken (algorithmic composition)

 Purpose:          Class and routine definition for the generation of partial
                   and/or complete reaper files from rhythms, soundfiles.

 Author:           Michael Edwards: m@michael-edwards.org

 Creation date:    January 21st 2021

 $$ Last modified:  11:14:51 Fri Feb  2 2024 CET

 SVN ID: $Id: sclist.lsp 963 2010-04-08 20:58:32Z medward2 $

utilities/make-reaper-envelope [ Functions ]

[ Top ] [ utilities ] [ Functions ]

AUTHOR

 Leon Focker: leon@leonfocker.de

DATE

 April 30th 2023.

DESCRIPTION

 make a reaper-envelope object.

ARGUMENTS

 - a list which represents an envelope, meaning it consists of x and y values
 For example: '(0 0  50 1  100 .5)
 Usually the first x value would be 0, all following x values should be
 ascending numbers. The length of the envelope (meaning the value of the last
 x value isn't important here)
 Note that if you use generate-auotmation-data on the resulting
 reaper-envelope object, y values will range from 0 to 1. The env list can
 obviously have y values greater than that, but those will be reduced
 modulo 1 (see env-mod). An envelope like '(0 0 1 3) would then result in
 something like this:
 '(0 0 1/3 .9999999 (+ 1/3 .001) 0 2/3 .9999999 (+ 2/3 .001) 0 1.0 .9999999)
 :parameter-min and :parameter-max are applied after that operation.

OPTIONAL ARGUMENTS

 keyword arguments:
 :env-type. A symbol. Wheter this envelope controls a plugin ('parmenv) or
 another parameter of a track. Valid options are:
 volume volume-pre-fx trim-volume pan pan-pre-fx width width-pre-fx mute tempo
 aux-volume aux-pan aux-mute parmenv...
 Any symbol that isn't recognized will create a 'parmenv.
 :start-time. the time in seconds at which the first point of the envelope
 will be
 :end-time. the time in seconds at which the last point of the envelope will
 be
 :parameter-slot. A positive integer. When env-type is 'parmenv, this
 determines which parameter of the plugin the envelope controls. Open reaper
 and the plugin and then count the automatable parameters to find out which
 one you want. For example, the angle-parameter for the iem stereo encoder is
 the 6th.
 :parameter-min. The minimm value the envelope will have in reaper. Usually
 it is 0 but for example for panorama it could be -1. This is less important.
 :parameter-max. The maximum value the envelope will have in reaper. Usually
 it is 1 but for example for volume it could be 2. This is less important.
 :is-visible. t or nil, wheter the envelope will be visible (opened) in the
 reaper-file.

RETURN VALUE

 the envelope-object

SYNOPSIS

(defun make-reaper-envelope (env &key (env-type 'parmenv)
                                   start-time
                                   end-time
                                   parameter-slot
                                   parameter-min
                                   parameter-max
                                   (is-visible t))

utilities/make-reaper-items4 [ Functions ]

[ Top ] [ utilities ] [ Functions ]

AUTHOR

 Leon Focker: leon@leonfocker.de

DATE

 April 30th 2023.

DESCRIPTION

 make-reaper-items but every sndfile gets its own track and start-times are
 given individually. 

ARGUMENTS

 - a list of sndfiles
 - a list of start-times for the sndfiles within the reaper project. If this
 list is shorter than sndfiles it is looped.

RETURN VALUE

 a list of reaper-items

SYNOPSIS

(defun make-reaper-items4 (sndfiles &optional (start-times '(0)))

utilities/pdivide-reaper-markers [ Functions ]

[ Top ] [ utilities ] [ Functions ]

DESCRIPTION

 Write to standard out (terminal/interpreter) marker data for a reaper file
 generated from calls to the pdivide function.

ARGUMENTS

 Takes the same arguments as the pdivide function

RETURN VALUE

 T

SYNOPSIS

(defun pdivide-reaper-markers (&rest args)

utilities/pexpand-reaper-markers [ Functions ]

[ Top ] [ utilities ] [ Functions ]

DATE

 September 4th 2015, Edinburgh

DESCRIPTION

 Using the pexpand function, we write marker information in a format which
 can be read by the Reaper (version 4/5+) DAW software. Though we can think
 of the outputs of pexpand to be in beats, seconds, bars, or any arbitrary
 scale, the timings of Reaper markers are in seconds, hence the need here
 for an initial tempo. In other words, we treat the output of pexpand to be
 beat counts; if you would prefer to interpret these as bars, simply divide
 the tempo by the number of beats per bar. If there are to be tempo changes
 in the mix/piece Reaper itself will update the markers' positions when the
 new tempo is inserted in the project window--this is fine when you are
 thinking in beats/bars but beware of changing tempo in Reaper if you are
 thinking of markers with fixed timings (seconds).

 Copy the output of this into the Reaper file verbatim (no enclosing < >
 marks) before the <PROJBAY tag.

ARGUMENTS

 - the tempo in BPM
 - the number of generations: see the pexpand function
 - (&rest) the proportions: see the pexpand function

RETURN VALUE

 Always T

EXAMPLE

(pexpand-reaper-markers 144 2 6 3 5 4)
->
  MARKER 1 7.5 "level 4" 0 0 1
  MARKER 2 15.0 "level 4" 0 0 1
  MARKER 3 22.5 "level 4" 0 0 1
  MARKER 4 30.0 "level 4" 0 0 1
  MARKER 5 37.5 "level 4" 0 0 1
...
  MARKER 108 810.0 "level 1" 0 0 1
  MARKER 109 817.5 "level 4" 0 0 1
  MARKER 110 825.0 "level 4" 0 0 1
  MARKER 111 832.5 "level 4" 0 0 1
  MARKER 112 840.0 "level 4" 0 0 1
  MARKER 113 847.5 "level 4" 0 0 1
  MARKER 114 855.0 "level 3" 0 0 1
...
  MARKER 319 2392.5 "level 4" 0 0 1
  MARKER 320 2400.0 "level 3" 0 0 1
  MARKER 321 2407.5 "level 4" 0 0 1
  MARKER 322 2415.0 "level 4" 0 0 1
  MARKER 323 2422.5 "level 4" 0 0 1


Here's where I pasted the data into the .RPP Reaper file:

  <TEMPOENVEX
    ACT 0
    VIS 1 0 1
    LANEHEIGHT 0 0
    ARM 0
    DEFSHAPE 1 -1 -1
  >
  MARKER 1 7.5 "level 4" 0 0 1
  MARKER 2 15 "level 4" 0 0 1
  MARKER 3 22.5 "level 4" 0 0 1
  MARKER 4 30 "level 4" 0 0 1
...
  MARKER 320 2400 "level 3" 0 0 1
  MARKER 321 2407.5 "level 4" 0 0 1
  MARKER 322 2415 "level 4" 0 0 1
  MARKER 323 2422.5 "level 4" 0 0 1
  <PROJBAY
  >
  <TRACK {EBF9837F-BE25-9542-B720-A1862C0DF380}

SYNOPSIS

(defun pexpand-reaper-markers (tempo generations &rest proportions)