Relative importance of compositional techniques

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Relative importance of compositional techniques
by on (#160049)
A packaged version of my music engine won a recent poll about my next project. So I'm curious as to what compositional techniques people consider important to support in a music engine:

Cymbal duty
Alternating between long and short period noise produces a metallic sound ideal for certain kinds of cymbals, especially open hi-hats. But FamiTone does not support duty changes during a note.

Triangle drums
Use of triangle and noise channels together to make kick and snare drums, with the triangle part interrupting whatever is already playing on that channel. This effect is tedious to enter in FamiTracker because it supports only one simultaneous note per channel. This means the drum has to be coded on the triangle channel, with the previous note repeated manually. In addition, when you use one triangle pattern with two different drum patterns, you have to make separate copies of the triangle pattern for each.

Pulse duty sweep
Changing the pulse wave's duty cycle is a common effect in SID music for Commodore 64. The NES approximates it by switching among 1/8, 1/4, or 1/2 duty. But FamiTone does not support duty changes during a note.

Decay
Specifying the attack phase of an instrument frame-by-frame is fine. But some instruments decrease in volume gradually, especially things like piano and guitar. It can be easier to specify the rate of decrease than to laboriously fill it in frame by frame. FamiTracker's frame-by-frame approach encourages envelopes that either quickly die away to zero or stick at a constant value.

Drum fills
A fill is a temporary change in the drum pattern in the measure before a change in the bass line. This effect is tedious to enter in FamiTracker because ending a pattern starts the next pattern on all channels, not just the one with the D00 (pattern end) command. This means a copy of the entire noise pattern has to be made with the fill at the end. If triangle drums are used, the triangle pattern must also be modified.

I've made a FamiTracker module demonstrating of each of these compositional techniques:

0:00 Baseline
0:13 Cymbal duty
0:26 Triangle drums
0:39 Pulse duty sweep
0:52 Longer decay
1:05 Drum fills
1:18 All five techniques

Vote for what techniques most enhance a composition, and feel free to share your reasoning.
Re: Relative importance of compositional techniques
by on (#160083)
I have my own engines, and I just add features that I want if I want them, so I'm not really a person to tell you what to prioritize, but if you want my personal opinion on the features you asked about:

1. Duty envelopes are very useful on both pulse and noise channels.
2. Triangle drums easy enough to do without a special feature.
3. Procedural decay not worth it. (Already covered by envelopes; it takes only takes seconds to type out a long envelope.)
4. Drum fills, see below. I think this is too complex to be worthwhile.

I implemented the duty envelopes, and none of the other things you suggested were important features to me. Famitone is in a similar boat, where shiru only implemented the features that were important to him. Apparently he doesn't care for duty envelopes. :P

You can always think of more features to add. Whether it's worth it depends on whether your composer can make good use of it or not. Vibrato and pitch slides, for example, you didn't mention at all, but the composer for Haunted made them essential to its soundtrack by using them everywhere, so this necessitated putting it in as a feature. I have vibrato and pitch slides in my own soundtrack too, but I decided to do them all via pitch envelopes so that I wouldn't have to create more engine features to support it. In professional game development, artist/programmer feature negotiations are a normal part of the process, e.g. often the programmer can think about the request and help the artist do what they wanted (or something close) without having to add new features.


By drum fills, what you're really asking for is alternate endings for patterns, per channel. I think what you really want here is a per-channel repeat/loop commands, or perhaps a "mirror" command that takes data from another pattern/place for several rows. You could have a user annotate the track with hints (e.g. unused Zxx effect?) that you use on export, but it's a bit annoying when you can't preview what you're doing in the tracker. Alternatively you can try to auto-detect these kinds of things; e.g. I think famitone tries to subdivide patterns on export to see if it can save space by reusing half/quarter patterns; this seems like a decent approach (though it complicates the relationship between source material and exported data; harder to debug?).

Startropics had a really good repeat implementation, but it's also a format that seems designed around a text-editor style workflow, doesn't really map well to any existing tracker. It's a very limited format, overall, but nice and compact, very good at keeping the data small.


To save a little bit of runtime, you can combine duty + volume into a single envelope. You can merge them on export from Famitracker (though obviously looping both volume and duty with different lengths at the same time could be a problem, maybe just forbid it?) A lot of commercial era music engines combine duty and volume. I didn't do this in my own engine, I thought keeping them separate was simpler.


If you're actually using Famitracker, "triangle drums" can be implemented more easily in Famitracker by using the "fixed" arpeggio feature (i.e. plays specific notes during the arpeggio envelope, then releases to the note's pitch when the envelope is done). Not really applicable unless you want to support that feature in your engine. Personally I found it easy enough to do triangle drums when I wanted to even without a fixed arp feature. (Maybe it doesn't look "nice" in the tracker, but nobody sees that but me. It sounds right either way, and I didn't let it eat too much data space.)
Re: Relative importance of compositional techniques
by on (#160084)
rainwarrior wrote:
3. Procedural decay not worth it. (Already covered by envelopes; it takes only takes seconds to type out a long envelope.)

I guess it's a code space vs. envelope space tradeoff.

Quote:
In professional game development, artist/programmer feature negotiations are a normal part of the process, e.g. often the programmer can think about the request and help the artist do what they wanted (or something close) without having to add new features.

Is it normal to get a request like "I'm willing to hire you as a composer so long as you don't use your own engine"?

Quote:
By drum fills, what you're really asking for is alternate endings for patterns, per channel. I think what you really want here is a per-channel repeat/loop commands, or perhaps a "mirror" command that takes data from another pattern/place for several rows.

In my engine, it's coded as "Starting X rows after the start of this pattern, replace the current pattern on channel Y with pattern Z."

Quote:
You could have a user annotate the track with hints (e.g. unused Zxx effect?) that you use on export, but it's a bit annoying when you can't preview what you're doing in the tracker.
[...]
Startropics had a really good repeat implementation, but it's also a format that seems designed around a text-editor style workflow, doesn't really map well to any existing tracker. It's a very limited format, overall, but nice and compact, very good at keeping the data small.

Which are attributes that I'm trying to keep, and I plan on making my own tracker for it.

Quote:
If you're actually using Famitracker, "triangle drums" can be implemented more easily in Famitracker by using the "fixed" arpeggio feature (i.e. plays specific notes during the arpeggio envelope, then releases to the note's pitch when the envelope is done).

Somehow I failed to find the "Fixed" feature, thinking Absolute and Relative were the only options in that drop-down.
Code:
tri with kick = fixed 40 36 33 31

Thanks. That's a lot easier, but I'd still need to duplicate the bass pattern if I use it with a different drum pattern.