Notes on programming

The Yamaha DX7 Envelope Generator, part two.

Part one is here

A closer look at an operator envelope.

Let's begin our understanding of the envelope generators by trying to answer the easier question: what kind of shape the envelope segments have.

As already anticipated, we'll have to look at the DX7 output, and in order to have a rational analysis we'll have to control it somehow, to isolate the part we want to study.

Let's do this by creating a simple voice and uploading it to the synthesizer. The voice (ENV TEST#0) will have one operator active, with a simple envelope. The envelope will go from 0 to 99, 99 to 50, 50 to 80, 80 to 0. On a constant, slow rate. Fast enough that can be recorded quickly, slow enough that the curve can be seen.

The rest of the voice should be configured as flat as possible, with no fancy settings to avoid complicating our analysis.

Creating a voice.

In order to create a voice we need to create a MIDI System Exclusive message that contains the voice in the Packed 32 Voice format. It is a format that stores all 32 voices of a DX7 in 4096 bytes.

The structure of the SYSEX message and the bulk voice format can be both found in the DX7s Owner's Manual.

genrom.c is a simple application that write to standard output a packed 32 voices bulk SYSEX message for the Yamaha DX7. The first voice in the set is ENV TEST#0, all others are empty).

The basic characteristic of the voice can be seen in this code excerpt:

v.ops[0].eg_rate[0] = 50;
v.ops[0].eg_rate[1] = 50;
v.ops[0].eg_rate[2] = 50;
v.ops[0].eg_rate[3] = 50;
v.ops[0].eg_level[0] = 99;
v.ops[0].eg_level[1] = 50;
v.ops[0].eg_level[2] = 80;
v.ops[0].eg_level[3] = 0;

Note that we're only setting to non-zero the first operator. All other operators are essentially turned off. The algorithm used (i.e., the connection map of the operators) is 32, i.e., all operators go directly to output, no one modulates any other operator.

After compiling the above program, we can finally create a file to send to the synthesizer:

$ ./genrom > envtest.syx
$ file envtest.syx 
envtest.syx: SysEx File - Yamaha

We now have a file slightly bigger that 4k that contains the set of voices just created. The next step is sending it to the synthesizer.

Uploading a voice.

Uploading the set of voices to the synthesizer is also straightforward.

All we need to do is turn the synthesizer on and setting memory protection to off (the synthesizer manual will explain how to do that). Once this is done, you can send envtest.syx from your computer with the amidi ALSA utility:

$ amidi --send envtest.syx -p <port>

<port> should be substituted with your midi device ALSA port. If you don't know it you can find it with amidi -l. Should be in the form hw:[0-9]+,[0-9]+,[0-9]+.

If this is successful, you should see that the voice names in your DX7 have changed. They'll be all empty except from the first one, which will be ENV TEST#0.

ENV TEST#0 loaded

ENV TEST#0 loaded on a Yamaha TX7, a desktop version of the DX7.

We now have our test voice loaded in the synthesizer. All we need to do is playing a note and recording the sound.

Recording a voice.

This step is also very basic. All that is required now is to connect the output of the DX7 to the microphone input of the computer, and record the output of a single note in raw format:

$ arecord -f FLOAT_LE -t raw -c 1 -r 44100 envtest0.raw

envtest0 contains a sequence of 32-bit floats (on a little-endian machine), one per each sample, -c 1 specifies mono recording.

It can be played back using aplay:

$ aplay -f FLOAT_LE -t raw -c 1 -r 44100 envtest0.raw

Now that we have a recording of the sound, we can finally start analysing it.

Plotting the voice.

Let's write a basic tool that we'll hack as we go: raw2plot.c is a simple C program that takes a raw file and converts it into a format understood by gnuplot.

Once it is compiled, we can generate a gnuplot output and plot it.

$ ./raw2plot < envtest0.raw > envtest0.plt
$ gnuplot
gnuplot> plot 'envtest0.plt' with lines

And you should see a window appear with your wave plotted.

Plot of recording

Plot of the signal

plot of the first two segments

gnuplot output at three different zoom levels: full recording, the signal recording, the first two segments of the envelope.

As you can see, something quite strange is going on at the start of the recording, most likely at the sound card level. After giving it some time for settling, a key is pressed and the sounds is recorded. As expected, the envelope goes to level 99, then to 50, and then to 80, and finally back to zero.

Even with a single plot we can derive the following conclusions:

  1. The envelope is not linear. Appears exponential, and at parity of rate the rising of the envelope is faster than the decay.
  2. Levels are not linear: level 50 is very close to zero, and level 80 is less than half of level 99.

In the next part we'll attempt at characterising this plot.

Source code and samples

All source code and samples used in this post are in the 'part2' branch of this GitHub project.

Part three is here