2025-02-22
I converted the audio sample files in a 2010 sample collection (the AdventureKid waveforms) to work with a 1988 sampler (the Yamaha TX16W with Typhoon OS).
The AdventureKid AKWF sample collection consists of over 4000 audio samples of single cycle waveforms. Most digital samplers are able to loop audio. The original reason for this is to mask how small the underlying audio samples are, but you can also make creative use of the looping facility. If you loop a very small fragment of audio then the sample playback engine becomes a digital oscillator. Because most samplers also have amplitude envelopes, filters, LFO's etc. you can then use your sampler as a synthesizer.
Making single cycle waveforms is finnicky. If you're not careful you get discontinuities (amplitude jumps) in the waveform which sound like unpleasant high-pitched buzzing. This is why it's valuable that AdventureKid made this collection of short samples that loop cleanly. All the samples are in exactly the same format (44.1kHz 16-bit WAV) and have the same length (600 samples).
If you want to see what the samples look like you can check out this visual index.
Image source: Yamaha Black Boxes
The TX16W was the first sampler made by Yamaha. They were late to the market and the TX16W was not a big success, particularly because of its difficult-to-use operating system.
For some reason it was common for samplers of this time to store their operating system on a floppy disk. You would have to boot the sampler from its OS floppy first, and then after that you could swap in other floppies to read your sound data. (Other digital instruments of the time would have their operating system installed on ROM chips.)
In the 1990s a group of Swedish computer programmers took it on themselves to write a better operating system for the TX16W hardware. There was a market for this because the original operating system was unpopular and all their customers had to do to switch was to boot from the Swedish floppy instead of the Japanese one. This alternative operating system was called Typhoon. Typhoon seems to have displaced the original operating system because it is so much better.
All this is pretty cool but it gets even better. One of the Typhoon developers later started a music software company called Sonic Charge. In 2013, Sonic Charge released Cyclone, a free software emulation of the TX16W that runs the orginal binary of the Typhoon OS. This means that the TX16W/Typhoon now has a digital twin that you can run as an audio plugin on your computer.
As you can imagine, all this adds up to a challenge for me to see if I can get the AKWF samples to work in Cyclone (and by extension, the TX16W).
Getting audio files into Cyclone is a retro experience. You need to make a floppy image, open the image in the VST, and then use the original TX16W interface to load data off the floppy (at the original speed!).
When it comes to audio data, the good news is that Typhoon supports AIFF files which are still commonly used today. The bad news is that the original hardware only supports the following, uncommon sample rates: 16.7kHz, 33kHz and 50kHz. That means that if you want to load an existing audio file you will almost always have to do a sample rate conversion first.
$ sox -G sample.wav sample.aiff rate -v 50k
Congratulations, now you have a 50kHz AIFF audio file. If you like drag and drop you can use this online tool from Sonic Charge to create an image file. If like me you dislike drag and drop, you start by downloading an empty image from the online tool. Then you install GNU Mtools and you can copy files onto the floppy image on the command line.
$ cp empty.img helloworld.img
$ mcopy -i helloworld.img sample.aiff ::/
(I have tried making an empty floppy image with mformat
but I could not get it to work so I gave up and used the empty image generated by Sonic Charge's tool as a starting point instead.)
So, now we have a floppy image with our AIFF file and we can use the virtual buttons in the Cyclone VST to load the file from the virtual floppy. If we try to play it we get a short blip. That is expected because the AKWF files are 600 samples long at the original 44.1kHz sample rate, which works out to 13.6ms. So we go into the TX16W wave editor and we enable looping by setting the start and end point of the loop. Now it turns out that you cannot loop from the first sample; the earliest you can start your loop is at sample 64.
OK! We go back to sox
and we add 64 samples of silence at the beginning.
$ sox -G sample.wav sample.aiff rate -v 50k pad 64s
Then copy with mcopy
, load the virtual floppy and do the whole retro dance again. And it works! If you set the loop points to 64 and 744 you get a cleanly looping single cycle waveform. (The length is now 680 samples because we increased the sampe rate to 50kHz.)
The next problem is the pitch of the waveform. It is customary for MIDI instruments to be tuned to the A440 standard. The Typhoon OS has built-in pitch detection but it does not work well on short samples such as those from AKWF, so we have to enter the pitch manually on the TX16W into the sample metadata. This is the same pitch setting for each AKWF sample (D2+2) but you have to set it in the TX16W every time.
Conclusion so far: it works but it is too cumbersome. Let's see if we can do better.
The Typhoon OS can not only read AIFF files but also save them. And rebooting the sampler shows that the loop points and pitch information get stored in the updated AIFF. Let's look at how the files changed.
This is what the header of an AIFF file looked like before I enabled looping and pitch:
00000000 46 4f 52 4d 00 00 06 20 41 49 46 46 43 4f 4d 54 |FORM... AIFFCOMT|
00000010 00 00 00 1a 00 01 e3 dd 47 6c 00 00 00 10 50 72 |........Gl....Pr|
00000020 6f 63 65 73 73 65 64 20 62 79 20 53 6f 58 43 4f |ocessed by SoXCO|
00000030 4d 4d 00 00 00 12 00 01 00 00 02 e8 00 10 40 0e |MM............@.|
00000040 c3 50 00 00 00 00 00 00 53 53 4e 44 00 00 05 d8 |.P......SSND....|
00000050 00 00 00 00 00 00 00 00 ff ff 00 00 ff ff ff ff |................|
00000060 00 00 00 00 ff ff 00 00 00 00 00 01 00 01 00 01 |................|
(... rest of sample data omitted ...)
Then after I added metadata and saved in Typhoon, we get:
00000000 46 4f 52 4d 00 00 06 72 41 49 46 46 41 50 50 4c |FORM...rAIFFAPPL|
00000010 00 00 00 24 73 74 6f 63 07 54 79 70 68 6f 6f 6e |...$stoc.Typhoon|
00000020 56 49 6e 66 00 00 00 10 b4 a8 f8 28 a8 c6 d1 86 |VInf.......(....|
00000030 7e 42 4f cd 3a af d9 c9 43 4f 4d 4d 00 00 00 12 |~BO.:...COMM....|
00000040 00 01 00 00 02 e8 00 10 40 0e c3 50 00 00 00 00 |........@..P....|
00000050 00 00 49 4e 53 54 00 00 00 14 32 02 00 7f 00 7f |..INST....2.....|
00000060 00 00 00 01 00 01 00 02 00 01 00 01 00 02 4d 41 |..............MA|
00000070 52 4b 00 00 00 24 00 02 00 01 00 00 00 40 0a 6c |RK...$.......@.l|
00000080 6f 6f 70 20 73 74 61 72 74 00 00 02 00 00 02 e8 |oop start.......|
00000090 08 6c 6f 6f 70 20 65 6e 64 00 53 53 4e 44 00 00 |.loop end.SSND..|
000000a0 05 d8 00 00 00 00 00 00 00 00 ff f0 00 00 ff f0 |................|
(... rest of sample data omitted ...)
Time to learn more about how AIFF files work. I found this description of the standard online.
The files are organized into chunks with a 4-byte identifier and a 4-byte length prefix. There is a container chunk of type FORM
. Nested inside the FORM container there is the magic string AIFF
followed by a variable number of other chunks. In the first file we see COMT
, COMM
and SSND
chunks. The COMM and SSND chunks are mandatory and contain audio metadata (length, samplerate, channel count) and raw audio data respectively.
If you click through to the standard document above you see that it is from 1988/1989, i.e. it is from the same vintage as the TX16W itself. It actually looks like the AIFF file format was designed for samplers. The standard describes optional metadata chunks for markers (MARK
) and for using the audio data as an instrument (INST
). The INST chunk has fields for base pitch, loop points, loop modes, MIDI key range and MIDI velocity range.
Once we know this we can make some sense of the second hexdump. There is an application specific chunk (APPL
) which contains the string Typhoon
so it must be Typhoon metadata. Then we see both an INST chunk and a MARK chunk. Let's look at the INST chunk.
Source: AIFF standard
This is what it looks like in the file saved by Typhoon:
49 4e 53 54 00 00 00 14 32 02 00 7f 00 7f 00 00
00 01 00 01 00 02 00 01 00 01 00 02
It starts with ASCII INST
followed by the length of the remainder of the chunk: 0x00000014. Then we get the base pitch: MIDI note 0x32 (D2) detuned up by 0x02 semitones. The key and velocity ranges are both from 0x00 to 0x7f, i.e. the full MIDI range. There is 0x0000 gain (i.e. none) applied to the sample. Then we get the descriptions of the sustain loop and the release loop, both of which are 00 01 00 01 00 02
. That means forward looping (0x0001) from marker 0x0001 to marker 0x0002.
I went over the MARK chunk too but I will spare you the details; it defines the loop start and end markers as expected at 64 and 744.
Now my first thought as an enthusiastic programmer was that I could write a program that parses and deconstructs the AIFF files, inserts the INST and MARK chunks, and reconstructs them. But then on second thought I realized that for each of the 4000+ AKWF files the INST and MARK chunks look exactly the same. All the files are exactly the same length and sample rate, the loop points are exactly the same etc. So all I really had to do was:
FORM
containerI wrote a program in my favourite scripting language that does this. You may wonder if I could have simplified it further by hard-coding the FORM container size but I found out after the fact that a few of the samples are stereo and because my program does the sums, it handled that correctly by accident. This is because the markers specify positions in frames, so in the stereo files the loop still runs from frame 64 to frame 744.
/* addloop.c
Adds AIFF loop points to AKWF sample files to be used in the TX16W with Typhoon
OS. This program assumes the samples have been converted to 50kHz sample rate
and have 64 samples padding because Typhoon does not let loops start at 0.
sox -G AKWF_xxxx.wav AKWF_xxx.aiff rate -v 50k pad 64s
./addloop < AKWF_xxx.aiff > AKWF_xxx.aiff.tmp
mv AKWF_xxx.aiff.tmp AKWF_xxx.aiff
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void fail(char *fmt, ...) {
va_list ap;
fflush(stdout);
fputs("error: ", stderr);
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
fputc('\n', stderr);
exit(1);
}
char magic[] = {
0x49, 0x4e, 0x53, 0x54, 0x00, 0x00, 0x00, 0x14, 0x32, 0x02, 0x00, 0x7f,
0x00, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01,
0x00, 0x01, 0x00, 0x02, 0x4d, 0x41, 0x52, 0x4b, 0x00, 0x00, 0x00, 0x24,
0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x0a, 0x6c, 0x6f, 0x6f,
0x70, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x00, 0x02, 0x00, 0x00,
0x02, 0xe8, 0x08, 0x6c, 0x6f, 0x6f, 0x70, 0x20, 0x65, 0x6e, 0x64, 0x00,
};
int main(void) {
unsigned char buf[12];
int size, c;
if (fread(buf, 1, sizeof(buf), stdin) != sizeof(buf))
fail("short read");
if (memcmp(buf, "FORM\x00\x00", 6) || memcmp(buf + 8, "AIFF", 4))
fail("bad header: %12.12s", buf);
size = ((int)buf[6] << 8) + (int)buf[7];
size += sizeof(magic);
fputs("FORM", stdout);
putchar(0);
putchar(0);
putchar(size >> 8);
putchar(size);
fputs("AIFF", stdout);
size -= 4;
fwrite(magic, 1, sizeof(magic), stdout);
size -= sizeof(magic);
while (c = getchar(), c != EOF) {
putchar(c);
size--;
}
if (size)
fail("input file size %d bytes too large", -size);
}
And then I had to do some shell scripting to convert all the files.
(
set -e
(cd AKWF && ls */*.wav) | while read w
do
aiff=AKWF--TX16W-Typhoon-Cyclone/${w%.wav}.aiff
sox -G AKWF/$w $aiff rate -v 50k pad 64s
./addloop < $aiff > ${aiff}.tmp
mv ${aiff}.tmp $aiff
done
)
Here is an example of a file that went through this process.
Note how the audio editor recognizes the loop points. There is digital silence at the start of the file because Typhoon does not want the loop to start at 0.
I have submitted a pull request to the AKWF GitHub repository with the converted sample files.
This was fun, and easier than I expected because the sampler metadata is natively supported by the AIFF file format and Typhoon does the right thing by using AIFF metadata as the standard intended it.
Now I have a new problem, namely that I can only fit 37 files in the root directory of a floppy (some sort of limit on the number of directory entries?) and I have 4000+ files to try out. This will take a while.
Addendum 2025-02-22. That 37 file limit is due to VFAT long filenames eating up directory slots. If I rename the AIFF files to 8.3 format (Typhoon uses .A01
as the extension for AIFF) then I can fit 111 on a floppy. And then Typhoon only sees the first 99 entries so I'm guessing that is the real limit per floppy now.