new post: hacking the wavedrum
authorrekado <rekado@elephly.net>
Wed, 14 Aug 2013 10:53:47 +0000 (18:53 +0800)
committerrekado <rekado@elephly.net>
Wed, 14 Aug 2013 10:53:47 +0000 (18:53 +0800)
images/posts/2013/wavedrum-card-tape.jpg [new file with mode: 0644]
images/posts/2013/wavedrum-diff.png [new file with mode: 0644]
images/posts/2013/wavedrum-mainboard.jpg [new file with mode: 0644]
images/posts/2013/wavedrum-opened.jpg [new file with mode: 0644]
posts/2013-08-11-hacking-the-wavedrum.markdown [new file with mode: 0644]

diff --git a/images/posts/2013/wavedrum-card-tape.jpg b/images/posts/2013/wavedrum-card-tape.jpg
new file mode 100644 (file)
index 0000000..39bacbd
Binary files /dev/null and b/images/posts/2013/wavedrum-card-tape.jpg differ
diff --git a/images/posts/2013/wavedrum-diff.png b/images/posts/2013/wavedrum-diff.png
new file mode 100644 (file)
index 0000000..e0eb9f7
Binary files /dev/null and b/images/posts/2013/wavedrum-diff.png differ
diff --git a/images/posts/2013/wavedrum-mainboard.jpg b/images/posts/2013/wavedrum-mainboard.jpg
new file mode 100644 (file)
index 0000000..6f1aab1
Binary files /dev/null and b/images/posts/2013/wavedrum-mainboard.jpg differ
diff --git a/images/posts/2013/wavedrum-opened.jpg b/images/posts/2013/wavedrum-opened.jpg
new file mode 100644 (file)
index 0000000..9b0e7b6
Binary files /dev/null and b/images/posts/2013/wavedrum-opened.jpg differ
diff --git a/posts/2013-08-11-hacking-the-wavedrum.markdown b/posts/2013-08-11-hacking-the-wavedrum.markdown
new file mode 100644 (file)
index 0000000..aafd1a6
--- /dev/null
@@ -0,0 +1,400 @@
+---
+title: Hacking the Wavedrum
+tags: DIY,electronics,music,hacking
+---
+
+The Wavedrum Oriental is a wonderful electronic instrument.  Unlike an
+electronic drum set or drum machines with touch sensitive pads, this
+drum synthesizer's sensors don't merely trigger samples.  The sensors
+rather behave like microphones or the pickup in an electric guitar;
+the signals of the four sensors---one sensor for the drum head, one
+sensor on the left and another on the right of the metal rim, and a
+pressure sensor in the centre of the drum---are used to control drum
+synthesizer algorithms whose output can be mixed with PCM samples.  As
+a result, the instrument feels a lot like a real drum, a feat that
+cannot easily be achieved with devices that use simple
+velocity-sensitive sample triggers.
+
+For all its magic, the Wavedrum also has a number of flaws.  Most
+prominently, all editing is done through five buttons and an endless
+rotary encoder.  What parameters can be selected by the buttons and
+thus manipulated by the encoder depends entirely on context; one
+button is used to jump to the next parameter page; simultaneously
+pressing a pair of buttons switches between the two edit modes (why
+two?), "global" mode and "live" mode; as one navigates through this
+confusing environment, a three-character seven-segment display
+conjures up magic strings that occasionally resemble abbreviations of
+what appear to be parameter names.  Without a copy of the manual lying
+next to the device, any attempt at deciphering the cryptic
+three-character hints is doomed to fail.
+
+Another painful flaw is the lack of connectivity.  There is no way to
+export these precious custom programmes that were edited with so much
+difficulty.  There is no way to back up the programmes, nor can one
+share programmes with another Wavedrum.  When the device dies, all
+custom patches go down with it.  Or so it seemed.
+
+
+# A look inside the Wavedrum
+
+Not really knowing what to look for I opened up the Wavedrum in the
+hopes of finding *something* that would allow me to extend the feature
+set of the instrument.  I first took off the control panel.  Only
+three screws have to be loosened to lift the front panel and look
+underneath.  The PCB, however, does not offer much of interest.
+
+Much more interesting is the main board which is located right
+underneath the drum head.  Removing the rim and the drum head
+apparently is a permitted activity which does not void the
+warranty---the manual includes instructions on how to change the drum
+head.
+
+<img class="full stretch" src="/images/posts/2013/wavedrum-opened.jpg" alt="After removing the rim and the drum head" />
+
+Once the rim and drum head are out of the way, one can already
+see much of the main board, but access is denied by a transparent
+plastic disk.  In my instrument the plastic disk was only screwed to
+two posts although there are holes for seven screws.  The heads of the
+two screws are covered with adhesive pads that can easily be removed
+to undo the screws.  (Don't worry, the glue on the pads is strong
+enough to put them back on when you're done.)
+
+<warning>
+**Warning:** if you are following these instructions, at this point, I
+  believe, you might be voiding your warranty.  If you're careful and
+  you don't tell anyone, nobody should ever notice.  Note that I
+  cannot be made responsible for any damage to your device that may
+  result from following these instructions.
+</warning>
+
+With this warning out of the way, let's move on.
+
+The main board is very tidy making it easy to understand what's going
+on.  The densely packed section on the right appears to be power
+supply and rim sensor amplification logic.  On the left you can see
+two medium-sized chips, a bulky capacitor and something covered with a
+black, textured tape.  The two chips are RAM (ESMT) and flash memory
+(cFeon), respectively.  The big capacitor buffers the power for the
+two memory chips and the massive DSP on the back of the board.  The
+back side of the board is rather boring as it really only holds the
+DSP chip (ADSP-21375 by Analog Devices).  The board has a somewhat
+unusually great number of test pads (most of which are connected to
+ground, used for automated testing) and quite a few connector pads,
+possibly allowing a hardware debugger to be connected to debug the
+DSP's firmware *in situ*.
+
+<img class="full stretch" src="/images/posts/2013/wavedrum-mainboard.jpg" alt="The mainboard of the Wavedrum Oriental" />
+
+
+# The treasure trove
+
+What is underneath that black tape on the front, though?  This is
+where things get really interesting (well, to people like me, at
+least).  As I carefully removed the tape I was pleasently surprised to
+see a micro SD card reader underneath.  The card is locked to the
+reading interface to make sure it stays in place during operation.
+Unlock it by shifting the metal brace to the right whereupon it can be
+lifted.
+
+![The taped-over SD card](/images/posts/2013/wavedrum-card-tape.jpg)
+
+The 2GB micro SD card is a standard card formatted with a FAT32
+filesystem, making it possible to read it out with a standard card
+reader.  My netbook has a built-in SD card reader only, so I first
+needed to buy an adapter to connect the micro SD card.  This reader is
+a little weird.  It seems that the adapter must be in the reader slot
+on boot or the micro SD card won't be recognised.  (If you're unsure
+whether the card is recognised by your system check the output of
+`dmesg`.)  Eventually, the card was recognised as `/dev/sdb1`.
+(`/dev/sdb` is the SD card reader device itself.)  As this is my only
+Wavedrum and I intend to use it for years to come I decided to be
+especially careful this time and only operate on a *copy* of the card.
+To create a block level copy of the card I *did not* mount the
+filesystem and simply executed the following command:
+
+    dd if=/dev/sdb1 of=wavedrum.img
+
+This instructs `dd` to copy all blocks from the input device file
+(`if`, i.e. `/dev/sdb1`) to the output file (`of`) of the name
+`wavedrum.img`.  Dependent on the number of disks on your system, the
+input device file may have a different name.  Check the output of
+`dmesg | tail` as you connect the card reader to see which device node
+is created for the micro SD card. Note that this blindly copies
+*everything* on the micro SD card, not just files that are available
+through the FAT32 filesystem.  Hence, the size of the image is quite a
+bit larger than the sum of all files on the mounted image (502,145,536
+bytes vs 234,479,878 bytes).
+
+Before continuing, please put the micro SD card back into the
+Wavedrum's card reader and lock it to prevent it from being damaged
+(things can get messy, you know).  Going forward, we only need to
+mount the image to access the data stored on the card.  Run the following as
+root to mount the card image as a read-only filesystem:
+
+    mkdir wavedrum
+    mount -o loop,ro wavedrum.img wavedrum/
+
+Let's take a look at the files on the card:
+
+<ul class="tree">
+<li><b class="NORM">/</b></li>
+<li>├── [&nbsp;&nbsp;16]&nbsp;&nbsp;<b class="EXEC">CALIB.BOR</b></li>
+<li>├── [&nbsp;16K]&nbsp;&nbsp;<b class="DIR">Factory</b></li>
+<li>│   ├── [192K]&nbsp;&nbsp;<b class="EXEC">F_INFO.BOR</b></li>
+<li>│   ├── [&nbsp;57K]&nbsp;&nbsp;<b class="EXEC">F_INST_H.BOR</b></li>
+<li>│   ├── [&nbsp;57K]&nbsp;&nbsp;<b class="EXEC">F_INST_R.BOR</b></li>
+<li>│   ├── [&nbsp;16K]&nbsp;&nbsp;<b class="EXEC">F_PROG.BOR</b></li>
+<li>│   └── [&nbsp;&nbsp;88]&nbsp;&nbsp;<b class="EXEC">F_USER.BOR</b></li>
+<li>├── [&nbsp;57K]&nbsp;&nbsp;<b class="EXEC">INST_H.BOR</b></li>
+<li>├── [&nbsp;57K]&nbsp;&nbsp;<b class="EXEC">INST_R.BOR</b></li>
+<li>├── [&nbsp;16K]&nbsp;&nbsp;<b class="DIR">LOOP</b></li>
+<li>│   ├── [744K]&nbsp;&nbsp;<b class="EXEC">LOOP0001.BIN</b></li>
+<li>│   ├── [402K]&nbsp;&nbsp;<b class="EXEC">LOOP0002.BIN</b></li>
+<li>│   ├── [750K]&nbsp;&nbsp;<b class="EXEC">LOOP0003.BIN</b></li>
+<li>&#x22ee;</li>
+<li>│   ├── [173K]&nbsp;&nbsp;<b class="EXEC">LOOP0138.BIN</b></li>
+<li>│   ├── [173K]&nbsp;&nbsp;<b class="EXEC">LOOP0139.BIN</b></li>
+<li>│   └── [234K]&nbsp;&nbsp;<b class="EXEC">LOOP0140.BIN</b></li>
+<li>├── [&nbsp;16K]&nbsp;&nbsp;<b class="EXEC">PRE_PROG.BOR</b></li>
+<li>├── [&nbsp;16K]&nbsp;&nbsp;<b class="DIR">SYSTEM</b></li>
+<li>│   ├── [&nbsp;&nbsp;16]&nbsp;&nbsp;<b class="EXEC">VERSION.INF</b></li>
+<li>│   ├── [1.0M]&nbsp;&nbsp;<b class="EXEC">WDORM202.BIN</b></li>
+<li>│   └── [8.0K]&nbsp;&nbsp;<b class="EXEC">WDORS110.BIN</b></li>
+<li>├── [&nbsp;&nbsp;88]&nbsp;&nbsp;<b class="EXEC">USER.BOR</b></li>
+<li>├── [157M]&nbsp;&nbsp;<b class="EXEC">WD2_DATA.BOR</b></li>
+<li>├── [192K]&nbsp;&nbsp;<b class="EXEC">WD2_INFO.BOR</b></li>
+<li>└── [&nbsp;16K]&nbsp;&nbsp;<b class="EXEC">WD2_PROG.BOR</b></li>
+</ul>
+
+The files in the `Factory` directory contain initialisation data.
+When a factory reset is performed, the customised versions of these
+files in the root directory are overwritten with the versions
+contained in the `Factory` directory.  All initial programmes that
+come with the Wavedrum are stored in `Factory/F_PROG.BOR`; once
+programmes have been edited `PROG.BOR` in the root directory will
+differ from `Factory/F_PROG.BOR`.  (More about the nature of these
+differences later.)  `PRE_PROG.BOR` is the same as
+`Factory/F_PROG.BOR` and is probably used to make the original factory
+presets available in addition to custom programmes, starting at
+position `P.00`, the programme slot after `149`.
+
+The initial mapping of presets to any of the 12 slots (3 banks with 4
+slots each) is stored in `Factory/F_USER.BOR`.  Initially, `USER.BOR`
+in the root directory will be identical to this file.  The format of
+this file is rather simple:
+
+    00000000 |  00 00 00 64 00 00 00 67  00 00 00 7b 00 00 00 6c
+    00000010 |  00 00 00 65 00 00 00 68  00 00 00 71 00 00 00 7a
+    00000020 |  00 00 00 84 00 00 00 8c  00 00 00 8b 00 00 00 95
+    00000030 |  00 00 00 00 00 00 00 00  00 00 00 75 00 00 00 26
+    00000040 |  00 00 00 07 00 00 00 14  00 00 00 07 00 00 00 14
+    00000050 |  00 00 00 05 00 00 00 64
+
+Every 8 digit block (4 byte) is used for one slot.  We can see that
+the first slot in bank A is set to programme 100 (0x64 hex), the
+second to programme 103 (0x67 hex) and so on.  As the Wavedrum only
+allows for 12 slots to store programme identifiers, only the first 48
+bytes are used for programmes.  The remaining 40 bytes (starting at
+0x30) are used for global parameters that can be adjusted in "global"
+editing mode.  The global parameters are stored in this order:
+
+  - delay pan
+  - aux input level
+  - loop phrase select
+  - loop play mode (off=38)
+  - head sensor threshold
+  - head sensor sensitivity
+  - rim sensor threshold
+  - rim sensor sensitivity
+  - pressure sensor threshold
+  - pressure maximum
+
+I don't know yet what purpose `F_INST_H.BOR` and `F_INST_R.BOR`
+fulfil, but it is clear that the former relates to settings for the
+drum head while the latter contains similar settings for the rim.
+Even after editing a few programmes, `INST_H.BOR` and `INST_R.BOR` in
+the root directory were still identical to their counterparts in the
+`Factory` directory.
+
+The `CALIB.BOR` appears to contain calibration information for the
+head and rim sensors.  This is different from the calibration
+performed by adjusting the four global paramaters for sensor threshold
+and sensitivity.  I have not been able to edit these settings through
+the Wavedrum so far, so these probably are factory settings.
+
+
+## Audio data
+
+All files in the `LOOP` directory as well as `WD2_DATA.BOR` contain
+raw audio data.  Unfortunately, I haven't quite figured out the format
+yet, but you can listen to the clearly recognisable loop patterns with
+`play` (part of the [SoX](http://sox.sourceforge.net) applications):
+
+    find LOOP -name "*.BIN" -print |\
+      xargs -I XXX \
+      play -t raw -r 48k -b 32 -e unsigned-integer -c 2 XXX speed 0.3
+
+Obviously, this isn't quite correct.  I'm interpreting every 32 bits
+as a sample in unsigned integer format, but assuming a sample rate of
+48kHz and two channel output results in extremely fast playback which
+I then artificially slow down again.  This really is the same effect
+as playing back the data at a lower sample rate.  Even at the correct
+speed, the sound is distorted and far from the realistic instrument
+sound when playing back the loops through the Wavedrum.  Clearly, more
+work is required to figure out the correct format.  Once this is
+understood we could use custom loops with the Wavedrum.
+
+The raw audio data in `WD2_DATA.BOR` suffers from the same problems.
+Although the data can be interpreted as raw audio, the sound is
+distorted and playback is unnaturally fast.
+
+
+## System files
+
+I don't know what `SYSTEM/WDORS110.BIN` is used for.  The only useful
+string contained in the file is "BOOTABLE".  Your guess is as good as
+mine as to what it does.
+
+`SYSTEM/VERSION.INF` is only 16 bytes short and pretty boring as it
+contains just what the name implies: version numbers.
+
+    02 02 01 10 02 02 00 00  57 44 4f 52 00 00 00 00
+
+This string of numbers is interpreted as follows: firmware version
+2.02, sub-version 1.10, data version 2.02 (followed by two empty
+bytes); 57 44 4f 52 (hex for "WDOR") stands for "Wavedrum Oriental"
+(followed by four empty bytes).  You can have the Wavedrum display all
+its version numbers by pressing the button labelled "Global" when
+powering on the device. Note that the file name `WDORS110.BIN`
+references the version number 1.10, while `WDORM202.BIN` references
+the firmware version number 2.02.
+
+`SYSTEM/WDORM202.BIN` contains the firmware of the Wavedrum Oriental.
+There are many interesting strings and binary patterns in the file,
+but I'm still a long way from *understanding* how it works.  To view
+the strings with the `strings` command, you have to specify the
+encoding as 32-bit little endian:
+
+    strings --encoding L SYSTEM/WDORM202.BIN
+
+Some of the strings embedded in the firmware are file names, some of
+which are not available on the micro SD card.  This includes the
+following files: SYS00000.BIN, SYS00100.BIN, SYSTEM/WDORS100.BIN,
+SYSTEM/WDX_M100.BIN, SYSTEM/WDX_S100.BIN, and SUBXXXXX.BIN (a
+pattern?).
+
+
+# The programme format
+
+Looking at the hexdump of the file `PROG.BOR` which holds all custom
+presets, I couldn't find any obvious patterns in the file, so I
+resorted to editing a single programme, setting particular consecutive
+parameters to easily recognisable sequences of values (such as 100,
+99, 98, and 97 for hd1, hd2, hd3, and hd4) and locating the changes in
+the hexdump.
+
+<img class="full stretch" src="/images/posts/2013/wavedrum-diff.png" alt="Analysing the programme format by changing values and looking at the differences" />
+
+This procedure has allowed me to figure out in what order the
+parameters are stored in the file.  Each programme is exactly 54
+16-bit words long; each parameter takes up exactly 16 bits.  Negative
+values are stored in [two's
+complement](https://en.wikipedia.org/wiki/Two%27s_complement) format
+(e.g. negative six is stored as 0xFFFA).  The file is exactly 16200
+bytes long which is just enough to hold 150 custom programmes, each
+taking up 108 bytes.
+
+The parameters are stored in this order:
+
+    identifier |  mode  | target              | name
+    -----------+--------+---------------------+------------------------------
+    07.1       | Edit 1 | head algorithm      | Pressure curve
+    type       | Edit 2 | --                  | Pre EQ
+    -----------+--------+---------------------+------------------------------
+    01.1       | Edit 1 | head algorithm      | Tune
+    02.1       | Edit 1 | head algorithm      | Decay
+    03.1       | Edit 1 | head algorithm      | Level
+    04.1       | Edit 1 | head algorithm      | Pan
+    05.1       | Edit 1 | head algorithm      | Algorithm select
+    hd.1       | Edit 2 | head algorithm      | Algorithm parameter 1
+    hd.2       | Edit 2 | head algorithm      | Algorithm parameter 2
+    hd.3       | Edit 2 | head algorithm      | Algorithm parameter 3
+    hd.4       | Edit 2 | head algorithm      | Algorithm parameter 4
+    hd.5       | Edit 2 | head algorithm      | Algorithm parameter 5
+    hd.6       | Edit 2 | head algorithm      | Algorithm parameter 6
+    hd.7       | Edit 2 | head algorithm      | Algorithm parameter 7
+    hd.8       | Edit 2 | head algorithm      | Algorithm parameter 8
+    -----------+--------+---------------------+------------------------------
+    01.3       | Edit 1 | rim algorithm       | Tune
+    02.3       | Edit 1 | rim algorithm       | Decay
+    03.3       | Edit 1 | rim algorithm       | Level
+    04.3       | Edit 1 | rim algorithm       | Pan
+    05.3       | Edit 1 | rim algorithm       | Algorithm select
+    rm.1       | Edit 2 | rim algorithm       | Algorithm parameter 1
+    rm.2       | Edit 2 | rim algorithm       | Algorithm parameter 2
+    rm.3       | Edit 2 | rim algorithm       | Algorithm parameter 3
+    rm.4       | Edit 2 | rim algorithm       | Algorithm parameter 4
+    rm.5       | Edit 2 | rim algorithm       | Algorithm parameter 5
+    rm.6       | Edit 2 | rim algorithm       | Algorithm parameter 6
+    rm.7       | Edit 2 | rim algorithm       | Algorithm parameter 7
+    rm.8       | Edit 2 | rim algorithm       | Algorithm parameter 8
+    -----------+--------+---------------------+------------------------------
+    01.2       | Edit 1 | head PCM instrument | Tune
+    02.2       | Edit 1 | head PCM instrument | Decay
+    03.2       | Edit 1 | head PCM instrument | Level
+    04.2       | Edit 1 | head PCM instrument | Pan
+    05.2       | Edit 1 | head PCM instrument | PCM instrument select
+    06.2       | Edit 1 | head PCM instrument | Velocity curve
+    07.2       | Edit 1 | head PCM instrument | Pressure curve
+    08.2       | Edit 1 | head PCM instrument | Pressure tune
+    09.2       | Edit 1 | head PCM instrument | Pressure decay
+    -----------+--------+---------------------+------------------------------
+    01.4       | Edit 1 | rim PCM instrument  | Tune
+    02.4       | Edit 1 | rim PCM instrument  | Decay
+    03.4       | Edit 1 | rim PCM instrument  | Level
+    04.4       | Edit 1 | rim PCM instrument  | Pan
+    05.4       | Edit 1 | rim PCM instrument  | PCM instrument select
+    06.4       | Edit 1 | rim PCM instrument  | Velocity curve
+    07.4       | Edit 1 | rim PCM instrument  | Pressure curve
+    08.4       | Edit 1 | rim PCM instrument  | Pressure tune
+    09.4       | Edit 1 | rim PCM instrument  | Pressure decay
+    -----------+--------+---------------------+------------------------------
+    10.1       | Edit 1 | --                  | Reverb type
+    10.2       | Edit 1 | --                  | Reverb effect level
+    10.3       | Edit 1 | --                  | Reverb decay time
+    10.4       | Edit 1 | --                  | Reverb frequency damping
+    11.3       | Edit 1 | --                  | Delay feedback
+    11.2       | Edit 1 | --                  | Delay effect level
+    11.1       | Edit 1 | --                  | Delay time
+    11.4       | Edit 1 | --                  | Delay frequency damping
+
+
+# Thanks
+
+The following tools have proven indispensable in the analysis:
+
+- [`calc`](http://www.isthe.com/chongo/tech/comp/calc/), a calculator
+  for the command line supporting hexadecimal representations of
+  numbers (both input and output using the `base` and `base2`
+  functions)
+
+- [`vbindiff`](http://www.cjmweb.net/vbindiff/), a tool to visualise
+  differences between two binary files with a split-screen hexadecimal
+  display
+
+- [`ghex`](https://wiki.gnome.org/Ghex), a simple hexadecimal editor
+  supporting pattern search and highlighting
+
+
+# Call for help
+
+If you own an earlier model of the Wavedrum or the latest Wavedrum
+Global Edition, I would be *very* happy if you could send me a
+block-level copy of the SD card (see above for instructions).  This
+would allow me to understand the firmware better and maybe even make
+it possible to upgrade an older Wavedrum to the latest version (taking
+into account possible hardware differences, such as differing memory
+size).
+
+Please send a link to the micro SD card image to
+<span class="obfuscated">sflbep,xbwfesvnAfmfqimz/ofu</span>.