Re: Structured Audio Rendering Syntax Proposal

From: Eric Scheirer (eds)
Date: Sun Mar 30 1997 - 10:17:04 EST


[list note -- if you want replies to go to the list, not to me, be
sure to change the "to:" address in your reply.]

In message <199703290713.XAA08743@mail.themall.net> Jackee wrote:
>I am posting these suggestions and inviting commentary on them. They are
>currently in the discussion stage. There is no guarantee any of them will
>be included in any standard, but I feel they are needed for high-quality
>rendering.

Thanks for your comments. I'll respond to some of them here; I've
incorporated some of them into a proposed set of MPEG revisions.

>SUGGESTED MODIFICATIONS TO THE STRUCTURED AUDIO STANDARD TO FACILITATE
>RENDERING:
>
>1. I am concerned about the specification that a Note Off event (Sec.
>1.5.5.2) causes all notes in a channel to be turned off.

Note that this is only for MIDI control in very simple circumstances.
Using scores or controllers does not have this restriction. Also,
"turned off" is *always* with respect to the extend syntax -- instruments
written with "extend" never have to turn themselves off until they're
ready, regardless of what the MIDI information coming says.

>Perhaps, "extend", and "allowoverlap". If this is the intended function of
>"extend", the I would hope to see it expressly stated. I am glad that the
>"released" variable allows a programmer to determine when a note was
>released. It also might be useful to allow an instrument to be able to
>access the duration of an event as "dur".

I don't think "allowoverlap" is needed -- you can do it with "extend"
and a global variable. And "dur" is already there, see section 4.5.3.

>2. I am glad that the orchestra language now includes extensive opcodes to
>create and modify tables. Although the authors are probably aware of this
>fact, I would like to reiterate the importance of not loading sample data
>for a voice until it is used. A good GM sample library usually includes
>hundreds of samples, spanning megabytes, only a few of which might be
>used in a particular rendition.

This is what we call in MPEG-world "an implementation issue". Somebody
might build some weird architecture in which it's more efficient to
preload every sample ever downloaded, and we shouldn't prohibit them
in standard from doing so (we let the free market prohibit them from
making silly design decisions).

>3. Would prefer that the "soundfile" table generator definition specify
>that full pathnames, whether system dependent or in some way made
>portable, be allowed.

This is tricky, because in MPEG it depends on multiplexing. I'm sure
if people build standalone implementations, they'll include such
functionality, but I'm sure for now this must be left open.

>4. The basecps parameter of the loscil statement could be made optional as
>well, as WAV files and perhaps other supported formats can encode this
>value. (I like the doscil opcode, by the way!) Suggest a ftbasefreq()
>function.

Yes, these are both good points. I've incorporated them both.

>5. The soundfile spec (Sec. 1.11.1) would then need to specify that base
>frequency is also read in. Also, there is no provision here for reading in
>an unnormalized sample, as with a negative table number in Csound.

All tables are unnormalized. I have always found the Csound way
confusing. If you want to normalize tables, it's simple to write
an iopcode to do it yourself.

>6. If a table contains a sample, the sample can have one or more channels.
>This sample may then be used by the loscil unit, but nothing else can be
>done with it, unless there is a ftchannels() function to identify the
>number of channels, and an optional parameter to the table() function to
>identify the channel to get a value from.

All tables are one-channel right now; you have to specify in the
"soundfile" tablegen which one to read. This is awkward, and I'm
considering syntaxes like yours and some others, but it might end
up this way, where you'd just do:

  table soundl(soundfile,-1,"mysound.aiff",0,1);
  table soundr(soundfile,-1,"mysound.aiff",0,2);

>7. A typical MIDI module has the ability to cause a note to be interrupted
>by another note. The most significant case this occurs in is when an open
>hi-hat is struck, and the close hi-hat is struck, immediately following,
>causing the open hi-hat note to be terminated. This could be implemented
>by a command such as turnoff nn,ii where nn is the number of another note
>which might possibly be playing, and ii is an optional instrument number.

Global variables can do this -- interpret the apparent "pitch" as not
a sound, but instructions to pass a message to the other instantiations
of the current instrument, who then call "turnoff" themselves. It's
easier with scores than with MIDI.

>8. The template multiple instrument declaration is a useful attempt to
>address multiple instruments being implemented by a single declaration.
>For some GM orchestras, there would be over one hundred instruments, and it
>seems pointless to list each number explicitly, especially if many of them
>simply loop a sample. A syntax to deal with this might be to allow a
>declaration such as:
>
> template(instr_num) 32-128 {
> BLOCK
> }

I'll think about this, but adding new syntax (modifying the parser) is
a big step. It's not that big a deal to list them all, IMHO.

>9. Debugging this language will be difficult, especially when the programs
>are complex, and the implementation is not bug-free. I propose a
>"log_msg(<string const>)" statement that can output a string, and a
>"log_num(<expr>)" which can log a real or integer number to a logging
>device, which can be implementation dependent, such as the console, or a
>log file; but may be different from the device used to log syntax errors.

I'd say these are implementation issues -- nothing is preventing you,
as implementor, from adding "extra" non-portable opcodes, and these
obviously only apply to developer-composer oriented implementations. If I
want a playback-only box to run as fast as possible, I want stuff like this
out of it.

>10. Samples which are rendered from midi source have two types of panning
>to deal with. [...]
>I propose an instruction to implement this, producing to panning effects in
>series, and keeping the power output of speakers constant:
>
> audio_left, audio_right dualpan(aud_in_right, aud_in_left, pan1, pan >2);
>
>I see no signal modifier similar to the pan command in Csound.

It's easy to write yourself with a user-defined opcode -- no need to make
it core. Of course, stereo "returns" from an opcode must be
parameters updated by reference, since the "multiple return value"
syntax is gone.

[Philosophy note: User-defined opcodes "should be" nearly as fast as
core opcodes in a good implementation; therefore, we try not to add
core opcodes except when the essential functionality can't be implemented
efficiently in a UDO itself.]

>11. Suggest the expanded specification require at least enough tables be
>allowed to implement at least one sample for every General MIDI instrument.

There are no upper limits on anything in the spec, and it's going to
stay that way as far as I can help it. Everything must be allocated
and numbered dynamically up to the memory limits of the platform.

>12. Suggest a sign(<expr>) function, to return -1, 0, or 1 depending on the
>sign and value of <expr>. Also, an if(<cond>, <true value> [, <false
>value>]) function might help the programmer. The need for these functions
>is not now so acute, as conditionals will be allowed on a-rate variables.

I've added sgn(). The latter is the (a ? b : c) syntax.

>SAMPLE LAYERING
>
>My suggestion for syntax for sample layering at this point at this point is
>still formative. However, I feel that a configuration file such as the
>following would be a good start. Such a configuration of layers could be
>generated by standalone applications without having to rewrite the
>Orchestra code. Instead, this file would be referenced from opcodes in the
>Orchestra code.

No configuration files. I dislike this mechanism intensely. (Sorry,
don't mean to harsh on you). For 'lpc' and 'pvoc' sorts of applications,
make big wavetables or sample files and use them in funny ways.

I'm not inclined to include terribly sophisticated built-in support for
layers, because you *can* do it using what's there (except for the
pitchmap hole). If you want clever layering, you can write it yourself
using calls to instr().

>ODDS AND ENDS (petty language theory goop):
>
>The table() function may be redundant, as tables are arrays, and the
>specification implies that they can be accessed with syntax such as
>"table1[7]". It would not be redundant, if an argument to access an
>individual sample of a channel were allowed, or the syntax "table1[7]" were
>to refer to a single table in an array of tables. It might be less
>confusing with a name different from the table creator function, as in:
>
>t1 table(sampfile, ...);
>a1 = table(t1,7);

I've changed 'table' to 'tableread' on this point. I don't agree that
I think of tables as "arrays" -- they're wavetables. I do agree that
the uses are converging, but as I already wrote, I think of indexing
arrays with asigs as being "like wavetables", not the other way
around.

Can you suggest where the "table1[7]" is implied? I meant to prohibit
that. If anything, it should be an array-of-tables reference, which
isn't in there not, but might be, if I can figure out the initializer
syntax (suggestions?)

Thanks very much for your helpful comments.

 -- Eric

+-------------------+
| Eric Scheirer | A-7b5 D7b9 | G-7 C7 | Cb C-7b5 F7#9 | Bb | B-7 E7 |
| eds@media.mit.edu | < http://sound.media.mit.edu/~eds >
| 617 253 0112 | A A/G# F#-7 F#-/E | Eb-7b5 D7b5 | Db | C7b5 B7b5 | Bb |
+-------------------+



This archive was generated by hypermail 2b29 : Wed May 10 2000 - 12:11:07 EDT