cfc54d780901d56343b13fc9644e76a885eda66e
[software/elephly-net.git] / posts / 2013-08-11-hacking-the-wavedrum.markdown
1 ---
2 title: Hacking the Wavedrum
3 tags: DIY,electronics,music,hacking
4 ---
5
6 The Wavedrum Oriental is a wonderful electronic instrument. Unlike an
7 electronic drum set or drum machines with touch sensitive pads, this
8 drum synthesizer's sensors don't merely trigger samples. The sensors
9 rather behave like microphones or the pickup in an electric guitar;
10 the signals of the four sensors---one sensor for the drum head, one
11 sensor on the left and another on the right of the metal rim, and a
12 pressure sensor in the centre of the drum---are used to control drum
13 synthesizer algorithms whose output can be mixed with PCM samples. As
14 a result, the instrument feels a lot like a real drum, a feat that
15 cannot easily be achieved with devices that use simple
16 velocity-sensitive sample triggers.
17
18 For all its magic, the Wavedrum also has a number of flaws. Most
19 prominently, all editing is done through five buttons and an endless
20 rotary encoder. What parameters can be selected by the buttons and
21 thus manipulated by the encoder depends entirely on context; one
22 button is used to jump to the next parameter page; simultaneously
23 pressing a pair of buttons switches between the two edit modes (why
24 two?), "global" mode and "live" mode; as one navigates through this
25 confusing environment, a three-character seven-segment display
26 conjures up magic strings that occasionally resemble abbreviations of
27 what appear to be parameter names. Without a copy of the manual lying
28 next to the device, any attempt at deciphering the cryptic
29 three-character hints is doomed to fail.
30
31 Another painful flaw is the lack of connectivity. There is no way to
32 export these precious custom programmes that were edited with so much
33 difficulty. There is no way to back up the programmes, nor can one
34 share programmes with another Wavedrum. When the device dies, all
35 custom patches go down with it. Or so it seemed.
36
37
38 # A look inside the Wavedrum
39
40 Not really knowing what to look for I opened up the Wavedrum in the
41 hopes of finding *something* that would allow me to extend the feature
42 set of the instrument. I first took off the control panel. Only
43 three screws have to be loosened to lift the front panel and look
44 underneath. The PCB, however, does not offer much of interest.
45
46 Much more interesting is the main board which is located right
47 underneath the drum head. Removing the rim and the drum head
48 apparently is a permitted activity which does not void the
49 warranty---the manual includes instructions on how to change the drum
50 head.
51
52 <img class="full stretch" src="/images/posts/2013/wavedrum-opened.jpg" alt="After removing the rim and the drum head" />
53
54 Once the rim and drum head are out of the way, one can already
55 see much of the main board, but access is denied by a transparent
56 plastic disk. In my instrument the plastic disk was only screwed to
57 two posts although there are holes for seven screws. The heads of the
58 two screws are covered with adhesive pads that can easily be removed
59 to undo the screws. (Don't worry, the glue on the pads is strong
60 enough to put them back on when you're done.)
61
62 <warning>
63 **Warning:** if you are following these instructions, at this point, I
64 believe, you might be voiding your warranty. If you're careful and
65 you don't tell anyone, nobody should ever notice. Note that I
66 cannot be made responsible for any damage to your device that may
67 result from following these instructions.
68 </warning>
69
70 With this warning out of the way, let's move on.
71
72 The main board is very tidy making it easy to understand what's going
73 on. The densely packed section on the right appears to be power
74 supply and rim sensor amplification logic. On the left you can see
75 two medium-sized chips, a bulky capacitor and something covered with a
76 black, textured tape. The two chips are RAM (ESMT) and flash memory
77 (cFeon), respectively. The big capacitor buffers the power for the
78 two memory chips and the massive DSP on the back of the board. The
79 back side of the board is rather boring as it really only holds the
80 DSP chip (ADSP-21375 by Analog Devices). The board has a somewhat
81 unusually great number of test pads (most of which are connected to
82 ground, used for automated testing) and quite a few connector pads,
83 possibly allowing a hardware debugger to be connected to debug the
84 DSP's firmware *in situ*.
85
86 <img class="full stretch" src="/images/posts/2013/wavedrum-mainboard.jpg" alt="The mainboard of the Wavedrum Oriental" />
87
88
89 # The treasure trove
90
91 What is underneath that black tape on the front, though? This is
92 where things get really interesting (well, to people like me, at
93 least). As I carefully removed the tape I was pleasently surprised to
94 see a micro SD card reader underneath. The card is locked to the
95 reading interface to make sure it stays in place during operation.
96 Unlock it by shifting the metal brace to the right whereupon it can be
97 lifted.
98
99 ![The taped-over SD card](/images/posts/2013/wavedrum-card-tape.jpg)
100
101 The 2GB micro SD card is a standard card formatted with a FAT32
102 filesystem, making it possible to read it out with a standard card
103 reader. My netbook has a built-in SD card reader only, so I first
104 needed to buy an adapter to connect the micro SD card. This reader is
105 a little weird. It seems that the adapter must be in the reader slot
106 on boot or the micro SD card won't be recognised. (If you're unsure
107 whether the card is recognised by your system check the output of
108 `dmesg`.) Eventually, the card was recognised as `/dev/sdb1`.
109 (`/dev/sdb` is the SD card reader device itself.) As this is my only
110 Wavedrum and I intend to use it for years to come I decided to be
111 especially careful this time and only operate on a *copy* of the card.
112 To create a block level copy of the card I *did not* mount the
113 filesystem and simply executed the following command:
114
115 dd if=/dev/sdb1 of=wavedrum.img
116
117 This instructs `dd` to copy all blocks from the input device file
118 (`if`, i.e. `/dev/sdb1`) to the output file (`of`) of the name
119 `wavedrum.img`. Dependent on the number of disks on your system, the
120 input device file may have a different name. Check the output of
121 `dmesg | tail` as you connect the card reader to see which device node
122 is created for the micro SD card. Note that this blindly copies
123 *everything* on the micro SD card, not just files that are available
124 through the FAT32 filesystem. Hence, the size of the image is quite a
125 bit larger than the sum of all files on the mounted image (502,145,536
126 bytes vs 234,479,878 bytes).
127
128 Before continuing, please put the micro SD card back into the
129 Wavedrum's card reader and lock it to prevent it from being damaged
130 (things can get messy, you know). Going forward, we only need to
131 mount the image to access the data stored on the card. Run the following as
132 root to mount the card image as a read-only filesystem:
133
134 mkdir wavedrum
135 mount -o loop,ro wavedrum.img wavedrum/
136
137 Let's take a look at the files on the card:
138
139 <ul class="tree">
140 <li><b class="NORM">/</b></li>
141 <li>├── [&nbsp;&nbsp;16]&nbsp;&nbsp;<b class="EXEC">CALIB.BOR</b></li>
142 <li>├── [&nbsp;16K]&nbsp;&nbsp;<b class="DIR">Factory</b></li>
143 <li>│   ├── [192K]&nbsp;&nbsp;<b class="EXEC">F_INFO.BOR</b></li>
144 <li>│   ├── [&nbsp;57K]&nbsp;&nbsp;<b class="EXEC">F_INST_H.BOR</b></li>
145 <li>│   ├── [&nbsp;57K]&nbsp;&nbsp;<b class="EXEC">F_INST_R.BOR</b></li>
146 <li>│   ├── [&nbsp;16K]&nbsp;&nbsp;<b class="EXEC">F_PROG.BOR</b></li>
147 <li>│   └── [&nbsp;&nbsp;88]&nbsp;&nbsp;<b class="EXEC">F_USER.BOR</b></li>
148 <li>├── [&nbsp;57K]&nbsp;&nbsp;<b class="EXEC">INST_H.BOR</b></li>
149 <li>├── [&nbsp;57K]&nbsp;&nbsp;<b class="EXEC">INST_R.BOR</b></li>
150 <li>├── [&nbsp;16K]&nbsp;&nbsp;<b class="DIR">LOOP</b></li>
151 <li>│   ├── [744K]&nbsp;&nbsp;<b class="EXEC">LOOP0001.BIN</b></li>
152 <li>│   ├── [402K]&nbsp;&nbsp;<b class="EXEC">LOOP0002.BIN</b></li>
153 <li>│   ├── [750K]&nbsp;&nbsp;<b class="EXEC">LOOP0003.BIN</b></li>
154 <li>&#x22ee;</li>
155 <li>│   ├── [173K]&nbsp;&nbsp;<b class="EXEC">LOOP0138.BIN</b></li>
156 <li>│   ├── [173K]&nbsp;&nbsp;<b class="EXEC">LOOP0139.BIN</b></li>
157 <li>│   └── [234K]&nbsp;&nbsp;<b class="EXEC">LOOP0140.BIN</b></li>
158 <li>├── [&nbsp;16K]&nbsp;&nbsp;<b class="EXEC">PRE_PROG.BOR</b></li>
159 <li>├── [&nbsp;16K]&nbsp;&nbsp;<b class="DIR">SYSTEM</b></li>
160 <li>│   ├── [&nbsp;&nbsp;16]&nbsp;&nbsp;<b class="EXEC">VERSION.INF</b></li>
161 <li>│   ├── [1.0M]&nbsp;&nbsp;<b class="EXEC">WDORM202.BIN</b></li>
162 <li>│   └── [8.0K]&nbsp;&nbsp;<b class="EXEC">WDORS110.BIN</b></li>
163 <li>├── [&nbsp;&nbsp;88]&nbsp;&nbsp;<b class="EXEC">USER.BOR</b></li>
164 <li>├── [157M]&nbsp;&nbsp;<b class="EXEC">WD2_DATA.BOR</b></li>
165 <li>├── [192K]&nbsp;&nbsp;<b class="EXEC">WD2_INFO.BOR</b></li>
166 <li>└── [&nbsp;16K]&nbsp;&nbsp;<b class="EXEC">WD2_PROG.BOR</b></li>
167 </ul>
168
169 The files in the `Factory` directory contain initialisation data.
170 When a factory reset is performed, the customised versions of these
171 files in the root directory are overwritten with the versions
172 contained in the `Factory` directory. All initial programmes that
173 come with the Wavedrum are stored in `Factory/F_PROG.BOR`; once
174 programmes have been edited `PROG.BOR` in the root directory will
175 differ from `Factory/F_PROG.BOR`. (More about the nature of these
176 differences later.) `PRE_PROG.BOR` is the same as
177 `Factory/F_PROG.BOR` and is probably used to make the original factory
178 presets available in addition to custom programmes, starting at
179 position `P.00`, the programme slot after `149`.
180
181 The initial mapping of presets to any of the 12 slots (3 banks with 4
182 slots each) is stored in `Factory/F_USER.BOR`. Initially, `USER.BOR`
183 in the root directory will be identical to this file. The format of
184 this file is rather simple:
185
186 00000000 | 00 00 00 64 00 00 00 67 00 00 00 7b 00 00 00 6c
187 00000010 | 00 00 00 65 00 00 00 68 00 00 00 71 00 00 00 7a
188 00000020 | 00 00 00 84 00 00 00 8c 00 00 00 8b 00 00 00 95
189 00000030 | 00 00 00 00 00 00 00 00 00 00 00 75 00 00 00 26
190 00000040 | 00 00 00 07 00 00 00 14 00 00 00 07 00 00 00 14
191 00000050 | 00 00 00 05 00 00 00 64
192
193 Every 8 digit block (4 byte) is used for one slot. We can see that
194 the first slot in bank A is set to programme 100 (0x64 hex), the
195 second to programme 103 (0x67 hex) and so on. As the Wavedrum only
196 allows for 12 slots to store programme identifiers, only the first 48
197 bytes are used for programmes. The remaining 40 bytes (starting at
198 0x30) are used for global parameters that can be adjusted in "global"
199 editing mode. The global parameters are stored in this order:
200
201 - delay pan
202 - aux input level
203 - loop phrase select
204 - loop play mode (off=38)
205 - head sensor threshold
206 - head sensor sensitivity
207 - rim sensor threshold
208 - rim sensor sensitivity
209 - pressure sensor threshold
210 - pressure maximum
211
212 I don't know yet what purpose `F_INST_H.BOR` and `F_INST_R.BOR`
213 fulfil, but it is clear that the former relates to settings for the
214 drum head while the latter contains similar settings for the rim.
215 Even after editing a few programmes, `INST_H.BOR` and `INST_R.BOR` in
216 the root directory were still identical to their counterparts in the
217 `Factory` directory.
218
219 The `CALIB.BOR` appears to contain calibration information for the
220 head and rim sensors. This is different from the calibration
221 performed by adjusting the four global paramaters for sensor threshold
222 and sensitivity. I have not been able to edit these settings through
223 the Wavedrum so far, so these probably are factory settings.
224
225
226 ## Audio data
227
228 All files in the `LOOP` directory as well as `WD2_DATA.BOR` contain
229 raw audio data. Unfortunately, I haven't quite figured out the format
230 yet, but you can listen to the clearly recognisable loop patterns with
231 `play` (part of the [SoX](http://sox.sourceforge.net) applications):
232
233 find LOOP -name "*.BIN" -print |\
234 xargs -I XXX \
235 play -t raw -r 48k -b 16 -e signed-integer -c 1 XXX
236
237 Obviously, this isn't quite correct. I'm interpreting every 16 bits
238 as a sample in signed integer format, but the sound is distorted and
239 far from the realistic instrument sound when playing back the loops
240 through the Wavedrum.
241
242 All loops start with this 44 byte long header:
243
244 04 dc 10 d3 UU VV WW 95 01 d4 00 d0 30 f8 22 b5
245 46 95 56 95 57 95 57 95 d6 2e 56 95 56 e2 57 95
246 54 95 46 95 32 f4 22 f4 XX YY ZZ 95
247
248 With a few exceptions (namely 0009, 0025, 0027, 0030, 0033, 0036,
249 0049, 0054, 0064, 0082, 0091, 0103, 0104, 0107, 0108, 0127, 0128,
250 0129, 0130, 0131, 0132, 0135), VV equals YY and WW equals ZZ in most
251 loops. Where there is a difference between the pairs VVYY and WWZZ
252 the difference is only in VV/YY. It seems that loops with the same
253 number of bytes have the exact same numbers for UU, VV, WW, XX, YY and
254 ZZ. This is especially apparent in the loops 0127 to 0132
255 (inclusive), which are all 192,010 bytes long and all have the values
256 54:7b:54 for UU:VV:WW and 88:78:54 for XX:YY:ZZ.
257
258 Clearly, more work is required to figure out the complete format of
259 these loop files. Once this is understood we could use custom loops
260 with the Wavedrum.
261
262 The raw audio data in `WD2_DATA.BOR` suffers from the same problems.
263 Although the data can be interpreted as raw audio, the sound is
264 distorted and playback is unnaturally fast.
265
266
267 ## System files
268
269 I don't know what `SYSTEM/WDORS110.BIN` is used for. The only useful
270 string contained in the file is "BOOTABLE". Your guess is as good as
271 mine as to what it does.
272
273 `SYSTEM/VERSION.INF` is only 16 bytes short and pretty boring as it
274 contains just what the name implies: version numbers.
275
276 02 02 01 10 02 02 00 00 57 44 4f 52 00 00 00 00
277
278 This string of numbers is interpreted as follows: firmware version
279 2.02, sub-version 1.10, data version 2.02 (followed by two empty
280 bytes); 57 44 4f 52 (hex for "WDOR") stands for "Wavedrum Oriental"
281 (followed by four empty bytes). You can have the Wavedrum display all
282 its version numbers by pressing the button labelled "Global" when
283 powering on the device. Note that the file name `WDORS110.BIN`
284 references the version number 1.10, while `WDORM202.BIN` references
285 the firmware version number 2.02.
286
287 `SYSTEM/WDORM202.BIN` contains the firmware of the Wavedrum Oriental.
288 There are many interesting strings and binary patterns in the file,
289 but I'm still a long way from *understanding* how it works. To view
290 the strings with the `strings` command, you have to specify the
291 encoding as 32-bit little endian:
292
293 strings --encoding L SYSTEM/WDORM202.BIN
294
295 Some of the strings embedded in the firmware are file names, some of
296 which are not available on the micro SD card. This includes the
297 following files: SYS00000.BIN, SYS00100.BIN, SYSTEM/WDORS100.BIN,
298 SYSTEM/WDX_M100.BIN, SYSTEM/WDX_S100.BIN, and SUBXXXXX.BIN (a
299 pattern?).
300
301
302 # The programme format
303
304 Looking at the hexdump of the file `PROG.BOR` which holds all custom
305 presets, I couldn't find any obvious patterns in the file, so I
306 resorted to editing a single programme, setting particular consecutive
307 parameters to easily recognisable sequences of values (such as 100,
308 99, 98, and 97 for hd1, hd2, hd3, and hd4) and locating the changes in
309 the hexdump.
310
311 <img class="full stretch" src="/images/posts/2013/wavedrum-diff.png" alt="Analysing the programme format by changing values and looking at the differences" />
312
313 This procedure has allowed me to figure out in what order the
314 parameters are stored in the file. Each programme is exactly 54
315 16-bit words long; each parameter takes up exactly 16 bits. Negative
316 values are stored in [two's
317 complement](https://en.wikipedia.org/wiki/Two%27s_complement) format
318 (e.g. negative six is stored as 0xFFFA). The file is exactly 16200
319 bytes long which is just enough to hold 150 custom programmes, each
320 taking up 108 bytes.
321
322 I'm currently writing a Haskell library to parse / build progammes and
323 parameters. The code is available for
324 [free](https://www.fsf.org/about/what-is-free-software) [on
325 gitorious](https://gitorious.org/wavedrum/wavedrum-lib) under the [GNU
326 GPLv3](https://gnu.org/licenses/gpl.html).
327
328 The parameters are stored in this order:
329
330 |identifier | mode | target | name |
331 |----------:|--------|:--------------------|:-----------------------------|
332 |07.1 | Edit 1 | head algorithm | Pressure curve |
333 |type | Edit 2 | -- | Pre EQ |
334 |01.1 | Edit 1 | head algorithm | Tune |
335 |02.1 | Edit 1 | head algorithm | Decay |
336 |03.1 | Edit 1 | head algorithm | Level |
337 |04.1 | Edit 1 | head algorithm | Pan |
338 |05.1 | Edit 1 | head algorithm | Algorithm select |
339 |hd.1 | Edit 2 | head algorithm | Algorithm parameter 1 |
340 |hd.2 | Edit 2 | head algorithm | Algorithm parameter 2 |
341 |hd.3 | Edit 2 | head algorithm | Algorithm parameter 3 |
342 |hd.4 | Edit 2 | head algorithm | Algorithm parameter 4 |
343 |hd.5 | Edit 2 | head algorithm | Algorithm parameter 5 |
344 |hd.6 | Edit 2 | head algorithm | Algorithm parameter 6 |
345 |hd.7 | Edit 2 | head algorithm | Algorithm parameter 7 |
346 |hd.8 | Edit 2 | head algorithm | Algorithm parameter 8 |
347 |01.3 | Edit 1 | rim algorithm | Tune |
348 |02.3 | Edit 1 | rim algorithm | Decay |
349 |03.3 | Edit 1 | rim algorithm | Level |
350 |04.3 | Edit 1 | rim algorithm | Pan |
351 |05.3 | Edit 1 | rim algorithm | Algorithm select |
352 |rm.1 | Edit 2 | rim algorithm | Algorithm parameter 1 |
353 |rm.2 | Edit 2 | rim algorithm | Algorithm parameter 2 |
354 |rm.3 | Edit 2 | rim algorithm | Algorithm parameter 3 |
355 |rm.4 | Edit 2 | rim algorithm | Algorithm parameter 4 |
356 |rm.5 | Edit 2 | rim algorithm | Algorithm parameter 5 |
357 |rm.6 | Edit 2 | rim algorithm | Algorithm parameter 6 |
358 |rm.7 | Edit 2 | rim algorithm | Algorithm parameter 7 |
359 |rm.8 | Edit 2 | rim algorithm | Algorithm parameter 8 |
360 |01.2 | Edit 1 | head PCM instrument | Tune |
361 |02.2 | Edit 1 | head PCM instrument | Decay |
362 |03.2 | Edit 1 | head PCM instrument | Level |
363 |04.2 | Edit 1 | head PCM instrument | Pan |
364 |05.2 | Edit 1 | head PCM instrument | PCM instrument select |
365 |06.2 | Edit 1 | head PCM instrument | Velocity curve |
366 |07.2 | Edit 1 | head PCM instrument | Pressure curve |
367 |08.2 | Edit 1 | head PCM instrument | Pressure tune |
368 |09.2 | Edit 1 | head PCM instrument | Pressure decay |
369 |01.4 | Edit 1 | rim PCM instrument | Tune |
370 |02.4 | Edit 1 | rim PCM instrument | Decay |
371 |03.4 | Edit 1 | rim PCM instrument | Level |
372 |04.4 | Edit 1 | rim PCM instrument | Pan |
373 |05.4 | Edit 1 | rim PCM instrument | PCM instrument select |
374 |06.4 | Edit 1 | rim PCM instrument | Velocity curve |
375 |07.4 | Edit 1 | rim PCM instrument | Pressure curve |
376 |08.4 | Edit 1 | rim PCM instrument | Pressure tune |
377 |09.4 | Edit 1 | rim PCM instrument | Pressure decay |
378 |10.1 | Edit 1 | -- | Reverb type |
379 |10.2 | Edit 1 | -- | Reverb effect level |
380 |10.3 | Edit 1 | -- | Reverb decay time |
381 |10.4 | Edit 1 | -- | Reverb frequency damping |
382 |11.3 | Edit 1 | -- | Delay feedback |
383 |11.2 | Edit 1 | -- | Delay effect level |
384 |11.1 | Edit 1 | -- | Delay time |
385 |11.4 | Edit 1 | -- | Delay frequency damping |
386
387
388 # Thanks
389
390 The following tools have proven indispensable in the analysis:
391
392 - [`calc`](http://www.isthe.com/chongo/tech/comp/calc/), a calculator
393 for the command line supporting hexadecimal representations of
394 numbers (both input and output using the `base` and `base2`
395 functions)
396
397 - [`vbindiff`](http://www.cjmweb.net/vbindiff/), a tool to visualise
398 differences between two binary files with a split-screen hexadecimal
399 display
400
401 - [`ghex`](https://wiki.gnome.org/Ghex), a simple hexadecimal editor
402 supporting pattern search and highlighting
403
404
405 # Call for help
406
407 If you own an earlier model of the Wavedrum or the latest Wavedrum
408 Global Edition, I would be *very* happy if you could send me a
409 block-level copy of the SD card (see above for instructions). This
410 would allow me to understand the firmware better and maybe even make
411 it possible to upgrade an older Wavedrum to the latest version (taking
412 into account possible hardware differences, such as differing memory
413 size).
414
415 Please send a link to the micro SD card image to
416 <span class="obfuscated">sflbep,xbwfesvnAfmfqimz/ofu</span>.