Now, if you're a Mac user (I'm not sure if the following will work
on Linux; you may have to set up your path), you don't have to do
all this ancient bizarreness. If you double-click on the
CMIX command, it will start up a Terimnal
window and wait for input. The CMIX command
resides in the "bin/" subdirectory of your RTcmix install. In my
"RTcmix-for-me/" example, it would be in my "Desktop/RTcmix-for-me/bin/"
directory. All I need to do is double-click on it to start RTcmix.
[NOTE: you can move the CMIX command
anywhere you'd like from that "bin/" folder for more convenient access
if you want -- just drag it wherever is best for you]
Once the Terminal window for RTcmix is open, simply copy/paste your
script from your scorefile into that window,
and then hit CTRL-D and RETURN to have
RTcmix run the whole score. Any errors will be printed in the Terminal
window. When the score is finished, it will say
[process completed]
and the Terminal window will be dead. You can close it.
RTcmix Instrument: REALLYBASIC
If you double-click on the "REALLYBASIC.cpp" file (or open it in a
text-editor you like), it will bring up the C++ code for the instrument.
I have left the modifications in place that we did in class, basically
a 'printf()' statement in the REALLYBASIC::init() function:
int REALLYBASIC::init(double p[], int n_args)
{
rtsetoutput(p[0], p[1], this);
printf("HEY! I JUST INITTED THIS INSTRUMENT! YAY!!!!!!\n");
return nSamps();
}
and one in the REALLYBASIC::run() function:
int REALLYBASIC::run()
{
printf("running... ");
return framesToRun();
}
Recall that the REALLYBASIC::init() function is invoked when
RTcmix encounters the REALLYBASIC() instrument in a scorefile,
and the REALLYBASIC::run() function gets called repeatedly when samples
are to be generated (each call to the REALLYBASIC::run() function will
generate 1 buffer of samples); it will get called starting at the
starttime (set by rtsetoutput() in the REALLYBASIC::init()
function) and will run as long as the duration (also
set by rtsetoutput() in the REALLYBASIC::init() function).
To compile this instrument so that it will run with RTcmix, you need
to do two things. The first is to edit the file "package.conf" and
change it so that it can find your RTcmix/makefile.conf
file. If you open the file in a text-editor, you will see
something like this:
include /Users/brad/Desktop/RTcmix-for-me/makefile.conf
What you should do is delete everything after the "include"
(i.e. "/Users/brad/Desktop/RTcmix-for-me/makefile.conf") and
instead put your own location in it's place. The easiest way
to do this (Mac users) is to go to your "RTcmix/" folder
and click/drag the file inside it called "makefile.conf" into
the editor. It should then show something like this:
include /Users/WhoYouAre/WhereYouPutRTcmix/makefile.conf
Save this file.
You now need to 'compile' the instrument to create a
dynamically-loadable library for RTcmix to access.
This is very easy -- all you do is click into a Terminal window
and type the "cd" command, followed by a space, and then drag
the "REALLYBASIC/" folder into the Terminal. You should see
something like this:
[woofing:~] cd /Users/brad/Desktop/REALLYBASIC/
Hit RETURN and you will then be "in" the "REALLYBASIC/" folder.
type "make", RETURN, and you should see:
[woofing:~] make
c++ -Wno-deprecated -I. -I/Users/brad/Desktop/RTcmix-for-me/include -g -O2
-Wall -Wno-unused -DMACOSX -m64 -fno-common -I. -Wall -c -o REALLYBASIC.o REALLYBASIC.cpp
c++ -Wno-deprecated -DMACOSX -m64 -fno-common -bundle -flat_namespace -undefined suppress
-o libREALLYBASIC.so REALLYBASIC.o
-dylib_file /usr/lib/librtcmix.dylib:/Users/brad/Desktop/RTcmix-for-me/lib/librtcmix.dylib
-L/Users/brad/Desktop/RTcmix-for-me/lib -lgen -framework CoreAudio
This will create several new files in the "REALLYBASIC/" folder, including
one called "libREALLYBASIC.so" -- this is the dynamic library you want.
The only other modification you will need to make to run this
instrument is to the "test.sco" file. When the archive is unpacked,
it will probably say something like this:
rtsetparams(44100, 2)
load("/Users/brad/Desktop/REALLYBASIC/libREALLYBASIC.so")
REALLYBASIC(4, 7)
You will need to edit this file and change the "load()" scorefile command
to reflect where the "libREALLYBASIC.so" file is on your own system.
Again, you can do this by simply dragging the folder over from your
Finder.
Once you do this, you can copy/paste the scorefile into your "CMIX"
command window (see above) and off you go!
RTcmix Instrument: BASIC
and the destructor:
// Destruct an instance of this instrument, freeing any memory you've allocated.
BASIC::~BASIC()
{
}
We're not really using them here, but we will in the future.
In the BASIC::init() function, we checked to see if
rtsetoutput() did its jobs properly (return DONT_SCHEDULE if it doesn't),
and we also set a variable, "firsttimeflag", to 1:
// Called by the scheduler to initialize the instrument.
int BASIC::init(double p[], int n_args)
{
// Tell scheduler when to start this inst. If rtsetoutput returns -1 to
// indicate an error, then return DONT_SCHEDULE.
if (rtsetoutput(p[0], p[1], this) == -1)
return DONT_SCHEDULE;
firsttimeflag = 1;
return nSamps();
}
Then in the BASIC::run() function, we check the value of this
"firsttimeflag" variable. If it is "1", then we generate a 'click'
(a single spike at full 16-bit (32767) amplitude), and reset the
value of the "firsttimeflag" variable to "0" so it won't run again.
When "firsttimeflag" is "0", we write "0.0" into the out[] array,
which is where we store the left and right channel sample-values
until we write it to the digital-to-analog convertor buffer using
the rtaddout(out) function:
// Called by the scheduler for every time slice in which this instrument
// should run. This is where the real work of the instrument is done.
int BASIC::run()
{
float out[2]; // Space for only 2 output chans!
// framesToRun() gives the number of sample frames
// Each loop iteration outputs one sample frame.
for (int i = 0; i < framesToRun(); i++) {
if (firsttimeflag == 1) {
out[0] = 32767.0;
out[1] = 32767.0;
firsttimeflag = 0;
} else {
out[0] = 0.0;
out[1] = 0.0;
}
// Write this sample frame to the output buffer.
rtaddout(out);
// Increment the count of sample frames this instrument has written.
increment();
}
// Return the number of frames we processed.
return framesToRun();
}
The only other thing we had to add to this instrument is the
declaration of the "firsttimeflag" variable. We did this in the
BASIC.h file, so that it would be accessible throughout the
BASIC instrument (i.e. we can use it in all of the BASIC::*()
functions):
class BASIC : public Instrument {
public:
BASIC();
virtual ~BASIC();
virtual int init(double *, int);
virtual int run();
private:
int firsttimeflag;
};
When this is all set, you can modify the "package.conf" file
(if you haven't already),
do the "make" compilation and modify the "test.sco" file in the
same way we did for the REALLYBASIC instrument.