Jacob Vosmaer's blog

Revisiting the ADS disk images, and a review of Syntorial

2024-12-08

The ADS disk image extractor now detects sample rate

In a previous post I wrote about my project to extract WAV files from a collection of disk images for the Dynacord ADS sampler. One of the many things that I never figured out was the sample rate of the WAV files: I just assumed it to be 44.1kHz because that is what the sampler was advertised with. Many of the samples are indeed 44.1 kHz but some sounded too high. At the time I had a hard time finding out where in the original files the sample rate was set.

This made the samples harder to use because it's annoying if you have to make large pitch changes every time you load a sample into a sampler. I forgot about this sample collection for a while. Then forum user Clemens reached out to me on Sequencer.de, the forum where I got the original disk images from, because he wanted to use the samples but he needed to extract more of their metadata to do so. This was very motivating, and helpful, because Clemens has the actual physical machine these disk images are for. Finally I was not alone working on this and I could ask someone who actually knows the machine.

After lots of staring at hexdumps I came up with a criterion that seems to reliably distinguish the 22.05kHz samples from the 44.1kHz ones.

To get started I investigated the perplexing fact that the first sector of each sample file contains data from the first sector of the floppy it sits on. Mind you the first sample does not always start at the same offset into the floppy. Why on earth did they copy the first disk sector there and then overwrite bits of it?

I came up with the following script. It parses output from the toc command in the adsimg repository to find the offset of the first sample on the disk. It then compares the first sector (512 bytes) of the whole disk to the first sector of the first sample (all files on the disk are sector-aligned). I rewrite the offsets produced by hexdump so that I can run the output through diff. If I didn't do that diff would say each line is different because of the file offsets.


#!/bin/sh
set -e

if [ $# != 1 ]; then
  echo 'Usage: compare IMG' 1>&2
  exit 1
fi
img=$1

firstsample=$(./toc < "$img" | grep '^sam ' | sed 1q | sed 's/.*, offset=//' | sed 's/, len=.*//')
transform='sed'
for i in 0 1 2; do
  base=$(echo $firstsample | cut -c 1-6)
  prefix=$(printf %06x $((0x$base + $i)))
  transform="$transform -e $(printf "s/^%s/%06x/\n" $prefix $i)"
done
hexdump -vC -n512 "$img" > c0
hexdump -vC -n512 -s "0x$firstsample" "$img" | $transform > c1
diff c0 c1

This produces output like:


% ./compare '112.001 CHURCH BELLS 1.1.img'
1,3c1,3
< 00000000  30 2e 30 30 20 44 79 6e  61 63 6f 72 64 20 41 64  |0.00 Dynacord Ad|
< 00000010  76 61 6e 63 65 64 20 44  69 67 74 61 6c 20 53 61  |vanced Digtal Sa|
< 00000020  6d 70 6c 65 72 2e 20 44  69 73 6b 20 6f 70 65 72  |mpler. Disk oper|
---
> 00000000  c3 48 2e 42 45 4c 4c 20  4c 4f 3f 3f 2a 3f 26 00  |.H.BELL LO??*?&.|
> 00000010  a0 f1 cc 8a 01 00 a0 f1  6d 7a 02 00 a0 f1 6d 7a  |........mz....mz|
> 00000020  02 02 6d 79 72 2e 20 44  69 73 6b 20 6f 70 65 72  |..myr. Disk oper|
17c17
< 00000100  00 10 00 00 00 00 01 00  42 fc 02 01 43 48 55 52  |........B...CHUR|
---
> 00000100  00 00 00 00 00 0c 6a 00  00 00 01 01 43 48 55 52  |......j.....CHUR|

Each of the two hexdump commands produces 32 lines of output but 28 of those lines are apparently identical. This happens for each disk in the collection. On each disk image in the archive, diff spits out the same two ranges (bytes 0-47 and 256-271). You can also see the string "r. Disk operating system" appearing each time so the ranges that really differ are 0-35 and (for similar reasons) 256-265.

I then used the following ad-hoc header printing script to look at these interesting bits of the first sector of each sample file. I ignore the first 10 bytes of the first range because that is the name of the sample. The second range wasn't helpful so I commented it out after a while.


#!/bin/sh
set -e

if [ $# != 1 ]; then
  echo 'Usage: header IMG' 1>&2
  exit 1
fi
img=$1

IFS='
'
./toc < "$img" | grep '^sam ' | while read line; do
  #printf '%s ' $(echo "$line" | cut -c -14)
  offset=$(echo "$line" | sed 's/.*, offset=//' | sed 's/, len=.*//')
  hexdump -vC -n16 -s$((0x$offset + 10)) "$img" | grep '\|' | sed 's/\|.*//'
  #hexdump -vC -n10 -s$((0x$offset + 0x100)) "$img" | grep '\|' | sed 's/\|.*//'
done

Output:


% ./header '112.001 CHURCH BELLS 1.1.img'
0000620a  3f 3f 2a 3f 26 00 a0 f1  cc 8a 01 00 a0 f1 6d 7a  
0003fe0a  3f 3f 1f 3f 30 02 6d 7b  f7 fc 02 02 6d 7b 65 76  
0009f00a  3f 3f 1f 3f 30 05 65 77  f5 a8 02 05 65 77 5b 1e  
000fde0a  3f 3f 1f 3f 30 08 5b 1f  ec ac 02 08 5b 1f 47 ca  
0015ba0a  3f 3f 2a bf 2b 0b 47 cb  be 6d 01 0b 47 cb 06 37  

By listening I can tell that the first and last sample are 22.05kHz, the rest is 44.1kHz. After a lot of staring I eventually concluded that if the high nibble of the fifth byte in this print-out (i.e. byte 14 of the sample file) is "3" then that means the sample is 44.1kHz. You'd also think that "2" means 22.05kHz but sometimes that nibble is "a". This threw me off for a long time.

Syntorial is awesome

I saw someone recommend Syntorial in a forum discussion about sound design. I never heard of this app before even though it has been around for 11 years now. I had my doubts about spending time and money on it but it turns out to be really really good which is why I am writing about it now.

I make music using synthesizers and part of the process is to configure my own sounds on those machines. This a skill all of itself that I mostly learned through trial and error over the years. Syntorial is an educational app that teaches you to become better at this skill. It uses a simple but effective idea: you do challenges where you are presented with a synthesizer sound made on the built-in software synthesizer in the application. You can play the challenge sound with a MIDI keyboard but you can't see how it was made. The goal is to recreate the sound using the built-in synth. Doing this trains your ears to better hear what is going on in a sound.

The brilliant thing is that instead of presenting you with all 40-odd knobs and sliders of the built-in synth, the challenge uses only a limited number of settings. The settings of the individual knobs are also restricted to a small number of values instead of their usual continuous range. The course material very gently ramps up the number of settings you must manipulate to recreate the sound in each challenge.

This is really helpful because if you have 40 knobs in front of you it requires a lot of discipline to say to yourself you will only use 3 of them. Syntorial provides that discipline and takes you on a guided path where you learn to use more and more of the knobs.

I am not a beginner synthesizer user and I thought I might be frustrated doing a course that starts with baby steps from zero. The reason I'm so enthusiastic is that the course is set up so well that in spite of my previous experience, I am learning new things every step of the way so far.

It seems like every hour I spend in Syntorial my ear for sonic details improves and I immediately get to use that in my own music. I am now 8 chapters into the course material and there are 33 chapters in total. I don't know yet if I will be as enthusiastic about the later chapters but even if I end up liking them less, I have already learned so much.

If you are interested in getting better at synthesizer sound design and you have a computer, a pair of headphones and a MIDI keyboard than I can highly recommend Syntorial.

Tags: music dynacord-ads syntorial

IndexContact