| Thanks for all the suggestions, everyone. The nonexistant prize goes to
Jens Kilian whose suggestion to use fflush() was exactly what was needed
to get things working the way I wanted.
Here's some sample code that does a (meaningless?) benchmark of realtime
csound output. Watch out for sneaky email line wraps...
Sorry for the length of this message, but I think some of the issues
raised are interesting.
(first the orchestra)
sr = 44100
kr = 4410
ksmps = 10
nchnls = 1
instr 1
;p4 = freq of fundamental (Hz)
;p5 = amp (dB)
iamp = ampdb(p5)
a1 oscil iamp, p4, 1
out a1
endin
instr 2
; same but using oscili
;p4 = freq of fundamental (Hz)
;p5 = amp (dB)
iamp = ampdb(p5)
a1 oscili iamp, p4, 1
out a1
endin
;now the sco
f1 0 32768 10 1 ; great big sinusoid table.
f0 1000 ; dummy line to keep score active for a long time.
e
And here's the C code...
/*******************************
Some code to benchmark realtime csound output.
This version sends only 1 note at a time; each note sticks around for a
long time.
***************************/
#include
#include
#include
#include
#include
#define ORCFILE "/home/pw/Orcs+Scores/osciltest.orc"
#define SCOFILE "/home/pw/Orcs+Scores/osciltest.sco"
#define DUR 2
int i, pitch, volume, initpitch, initnum, initvol, instr, sndbufsize;
FILE *ofp;
char csoundcmd[256];
int main(void)
{ /**** Got tired of typing these over and over...
printf("Give starting pitch in integer hz: ");
scanf("%d", &initpitch);
printf("Give starting volume in integer db: ");
scanf("%d", &initvol);
******/
printf("Give initial number of oscillators: ");
scanf("%d", &initnum);
printf("Use oscil or oscili? [oscil = 1, oscili = 2] ");
scanf("%d", &instr);
printf("Buffer size: ");
scanf("%d", &sndbufsize);
pitch = initpitch = 100;
volume = initvol = 70;
/* Now let's make a pipe to write notes to... */
sprintf(csoundcmd, "csound -m 2 -d -L stdin -b %d -odevaudio %s %s >
/dev/null", sndbufsize, ORCFILE, SCOFILE);
/***** Note that I'm only playing with -b, not -B. I haven't observed
any benefits from changing -B yet, but maybe I'm not looking hard
enough... ******/
ofp = popen(csoundcmd, "w");
sleep(3);
assert(ofp != NULL);
printf("Opened pipe to Csound.\n");
for(i= 1; pitch < 22050 && volume > 0 ; ++i, pitch += initpitch,
volume -=1){
fprintf(ofp, "i%d 0 1000 %d %d\n", instr, pitch, volume);
fflush(ofp );
printf("%d oscillators, oh my...\n", i);
if (i >= initnum) {
/* nicely suspend for 2 seconds after each score event */
sleep(DUR);
}
}
pclose(ofp);
return 0;
}
I was curious if there was a limit to how much I could dump at csound at
once, so I made the following version to play with that; it's the same
up until after the pipe is open, except we also declare
int tones;
...and then after the pipe's open it reads like this:
/*************************
This version also tests dumping a whole lot of notes of duration DUR to
stdin of csound at once. This illustrates that popen() to stdin as
a method of csound control is not very satisfactory; with just a few
score events you can clearly hear them entering at different times, and
eventually (around 23 oscils for me) csound just goes silent!
The problem seems to be with the pipe (I explored this by substituting
printf for fprintf), but I'm not sure if it can be improved, perhaps by
tuning the pipe's buffer size; or if it's just in the nature of pipes...
or maybe there's a limit to how many lines csound can receive from stdin
at once?
******************************/
/***
Start with initnum voices. Each note adds 1 voice. Each voice is the
next overtone in the series, and each voice is 1 db softer than the
previous.
***/
for(tones = initnum; ; ++tones) {
for (i = 0, pitch = initpitch, volume = initvol; i < tones ; ++i) {
fprintf(ofp, "i%d 0 %d %d %d\n", instr, DUR, pitch, volume);
pitch += initpitch;
--volume;
}
fflush(ofp); /* dump this batch of tones all at once */
printf("%d oscillators, oh my...\n", i);
sleep(2); /* wait 2 seconds after each batch of notes. */
}
pclose(ofp);
return 0;
}
Finally, I was noticing latency issues with various buffer sizes, so I
made this version which lets you really feel the latency.
Again, this is the same as the first version up until after the pipe's
open. Oops, up top we need to declare char noteline[reasonable size]....
/********** Some code intended to test the effects of the -b buffersize
on realtime csound output.
It seems to be quite acceptable at values around 256, or even 512, but
conversely this somewhat limits what csound can do... at 1024 the delay
is easy to feel and would probably be annoying to try to "play" in
realtime. At 2048 the delay is probably in the range of 100 ms.
For a realtime interactive csound frontend app to be really
"playable" I would guess the latency should be more in the range of
10 ms. Some testing suggests that csound on my system gives most
reliable output with the buffer around 8192 which gives latency of about
half a second.
Yuck!!!
*************/
printf("Enter S to hear a sound, ctrl-c to exit.\n");
/* Get the note events ready. */
for (i = 0, pitch = initpitch, volume = initvol; i < initnum ; ++i) {
sprintf(nextnote, "i%d 0 %d %d %d\n", instr, DUR, pitch, volume);
strcat(noteline, nextnote);
pitch += (initpitch * 1.1); /*got bored of harmonic stuff */
--volume;
}
/*** Try to send note events as soon as ENTER is pressed. **/
while ((c = getchar())) {
if (c == 's' || c == 'S') {
fprintf(ofp, "%s", noteline);
fflush(ofp); /* dump this batch of tones all
at once */
}
}
pclose(ofp);
return 0;
}
end of blahblah.
regards,
PW
______________________________________________________
Get Your Private, Free Email at http://www.hotmail.com |