link to other wavedrum posts
[software/elephly-net.git] / posts / 2013-08-11-hacking-the-wavedrum.markdown
1 ---
2 title: Hacking the Wavedrum
3 tags: DIY,electronics,music,hacking,wavedrum
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 The Wavedrum's card reader is perfectly capable of reading 8GB micro
113 SD HC cards, so if you want to play with the data on the card I
114 recommend mirroring the original card image onto whatever micro SD
115 card you have at your disposal and play with that instead of the
116 original card. To create a block level copy of the card I *did not*
117 mount the filesystem and simply executed the following command:
118
119 dd if=/dev/sdb1 of=wavedrum.img
120
121 This instructs `dd` to copy all blocks from the input device file
122 (`if`, i.e. `/dev/sdb1`) to the output file (`of`) of the name
123 `wavedrum.img`. Dependent on the number of disks on your system, the
124 input device file may have a different name. Check the output of
125 `dmesg | tail` as you connect the card reader to see which device node
126 is created for the micro SD card. Note that this blindly copies
127 *everything* on the micro SD card, not just files that are available
128 through the FAT32 filesystem. Hence, the size of the image is quite a
129 bit larger than the sum of all files on the mounted image (502,145,536
130 bytes vs 234,479,878 bytes).
131
132 Before continuing, please put the micro SD card back into the
133 Wavedrum's card reader and lock it to prevent it from being damaged
134 (things can get messy, you know). Going forward, we only need to
135 mount the image to access the data stored on the card. Run the following as
136 root to mount the card image as a read-only filesystem:
137
138 mkdir wavedrum
139 mount -o loop,ro wavedrum.img wavedrum/
140
141 Let's take a look at the files on the card:
142
143 <ul class="tree">
144 <li><b class="NORM">/</b></li>
145 <li>├── [&nbsp;&nbsp;16]&nbsp;&nbsp;<b class="EXEC">CALIB.BOR</b></li>
146 <li>├── [&nbsp;16K]&nbsp;&nbsp;<b class="DIR">Factory</b></li>
147 <li>│   ├── [192K]&nbsp;&nbsp;<b class="EXEC">F_INFO.BOR</b></li>
148 <li>│   ├── [&nbsp;57K]&nbsp;&nbsp;<b class="EXEC">F_INST_H.BOR</b></li>
149 <li>│   ├── [&nbsp;57K]&nbsp;&nbsp;<b class="EXEC">F_INST_R.BOR</b></li>
150 <li>│   ├── [&nbsp;16K]&nbsp;&nbsp;<b class="EXEC">F_PROG.BOR</b></li>
151 <li>│   └── [&nbsp;&nbsp;88]&nbsp;&nbsp;<b class="EXEC">F_USER.BOR</b></li>
152 <li>├── [&nbsp;57K]&nbsp;&nbsp;<b class="EXEC">INST_H.BOR</b></li>
153 <li>├── [&nbsp;57K]&nbsp;&nbsp;<b class="EXEC">INST_R.BOR</b></li>
154 <li>├── [&nbsp;16K]&nbsp;&nbsp;<b class="DIR">LOOP</b></li>
155 <li>│   ├── [744K]&nbsp;&nbsp;<b class="EXEC">LOOP0001.BIN</b></li>
156 <li>│   ├── [402K]&nbsp;&nbsp;<b class="EXEC">LOOP0002.BIN</b></li>
157 <li>│   ├── [750K]&nbsp;&nbsp;<b class="EXEC">LOOP0003.BIN</b></li>
158 <li>&#x22ee;</li>
159 <li>│   ├── [173K]&nbsp;&nbsp;<b class="EXEC">LOOP0138.BIN</b></li>
160 <li>│   ├── [173K]&nbsp;&nbsp;<b class="EXEC">LOOP0139.BIN</b></li>
161 <li>│   └── [234K]&nbsp;&nbsp;<b class="EXEC">LOOP0140.BIN</b></li>
162 <li>├── [&nbsp;16K]&nbsp;&nbsp;<b class="EXEC">PRE_PROG.BOR</b></li>
163 <li>├── [&nbsp;16K]&nbsp;&nbsp;<b class="DIR">SYSTEM</b></li>
164 <li>│   ├── [&nbsp;&nbsp;16]&nbsp;&nbsp;<b class="EXEC">VERSION.INF</b></li>
165 <li>│   ├── [1.0M]&nbsp;&nbsp;<b class="EXEC">WDORM202.BIN</b></li>
166 <li>│   └── [8.0K]&nbsp;&nbsp;<b class="EXEC">WDORS110.BIN</b></li>
167 <li>├── [&nbsp;&nbsp;88]&nbsp;&nbsp;<b class="EXEC">USER.BOR</b></li>
168 <li>├── [157M]&nbsp;&nbsp;<b class="EXEC">WD2_DATA.BOR</b></li>
169 <li>├── [192K]&nbsp;&nbsp;<b class="EXEC">WD2_INFO.BOR</b></li>
170 <li>└── [&nbsp;16K]&nbsp;&nbsp;<b class="EXEC">WD2_PROG.BOR</b></li>
171 </ul>
172
173 The files in the `Factory` directory contain initialisation data.
174 When a factory reset is performed, the customised versions of these
175 files in the root directory are overwritten with the versions
176 contained in the `Factory` directory. All initial programmes that
177 come with the Wavedrum are stored in `Factory/F_PROG.BOR`; once
178 programmes have been edited `WD2_PROG.BOR` in the root directory will
179 differ from `Factory/F_PROG.BOR`. (More about the nature of these
180 differences later.) `PRE_PROG.BOR` is the same as
181 `Factory/F_PROG.BOR` and is probably used to make the original factory
182 presets available in addition to custom programmes, starting at
183 position `P.00`, the programme slot after `149`.
184
185 The initial mapping of presets to any of the 12 slots (3 banks with 4
186 slots each) is stored in `Factory/F_USER.BOR`. Initially, `USER.BOR`
187 in the root directory will be identical to this file. The format of
188 this file is rather simple:
189
190 00000000 | 00 00 00 64 00 00 00 67 00 00 00 7b 00 00 00 6c
191 00000010 | 00 00 00 65 00 00 00 68 00 00 00 71 00 00 00 7a
192 00000020 | 00 00 00 84 00 00 00 8c 00 00 00 8b 00 00 00 95
193 00000030 | 00 00 00 00 00 00 00 00 00 00 00 75 00 00 00 26
194 00000040 | 00 00 00 07 00 00 00 14 00 00 00 07 00 00 00 14
195 00000050 | 00 00 00 05 00 00 00 64
196
197 Every 8 digit block (4 byte) is used for one slot. We can see that
198 the first slot in bank A is set to programme 100 (0x64 hex), the
199 second to programme 103 (0x67 hex) and so on. As the Wavedrum only
200 allows for 12 slots to store programme identifiers, only the first 48
201 bytes are used for programmes. The remaining 40 bytes (starting at
202 0x30) are used for global parameters that can be adjusted in "global"
203 editing mode. The global parameters are stored in this order:
204
205 - delay pan
206 - aux input level
207 - loop phrase select
208 - loop play mode (off=38)
209 - head sensor threshold
210 - head sensor sensitivity
211 - rim sensor threshold
212 - rim sensor sensitivity
213 - pressure sensor threshold
214 - pressure maximum
215
216 I don't know yet what purpose `F_INST_H.BOR` and `F_INST_R.BOR`
217 fulfil, but it is clear that the former relates to settings for the
218 drum head while the latter contains similar settings for the rim.
219 Even after editing a few programmes, `INST_H.BOR` and `INST_R.BOR` in
220 the root directory were still identical to their counterparts in the
221 `Factory` directory.
222
223 The `CALIB.BOR` appears to contain calibration information for the
224 head and rim sensors. This is different from the calibration
225 performed by adjusting the four global paramaters for sensor threshold
226 and sensitivity. I have not been able to edit these settings through
227 the Wavedrum so far, so these probably are factory settings.
228
229
230 ## Audio data
231
232 All files in the `LOOP` directory as well as `WD2_DATA.BOR` contain
233 raw audio data. Unfortunately, I haven't quite figured out the format
234 yet, but you can listen to the clearly recognisable loop patterns with
235 `play` (part of the [SoX](http://sox.sourceforge.net) applications):
236
237 find LOOP -name "*.BIN" -print |\
238 xargs -I XXX \
239 play -t raw -r 48k -b 16 -e signed-integer -c 1 XXX
240
241 Obviously, this isn't quite correct. I'm interpreting every 16 bits
242 as a sample in signed integer format, but the sound is distorted and
243 far from the realistic instrument sound when playing back the loops
244 through the Wavedrum.
245
246 All loops start with this 44 byte long header:
247
248 04 dc 10 d3 uU vV 5W 95 01 d4 00 d0 30 f8 22 b5
249 46 95 56 95 57 95 57 95 d6 2e 56 95 56 e2 57 95
250 54 95 46 95 32 f4 22 f4 xX yY 5W 95
251
252 With a few exceptions (namely 0009, 0025, 0027, 0030, 0033, 0036,
253 0049, 0054, 0064, 0082, 0091, 0103, 0104, 0107, 0108, 0127, 0128,
254 0129, 0130, 0131, 0132, 0135), vV equals yY in most loops. It seems
255 that loops with the same number of bytes have the exact same numbers
256 for uU, vV, W, xX, and yY. This is especially apparent in the
257 loops 0127 to 0132 (inclusive), which are all 192,010 bytes long and
258 all have the values 54:7b:54 for uU:vV:5W and 88:78:54 for xX:yY:5W.
259
260 Clearly, more work is required to figure out the complete format of
261 these loop files. Once this is understood we could use custom loops
262 with the Wavedrum.
263
264 The raw audio data in `WD2_DATA.BOR` suffers from the same problems.
265 Although the data can be interpreted as raw audio, the sound is
266 distorted and playback is unnaturally fast.
267
268
269 ## System files
270
271 I don't know what `SYSTEM/WDORS110.BIN` is used for. The only useful
272 string contained in the file is "BOOTABLE". Your guess is as good as
273 mine as to what it does.
274
275 `SYSTEM/VERSION.INF` is only 16 bytes short and pretty boring as it
276 contains just what the name implies: version numbers.
277
278 02 02 01 10 02 02 00 00 57 44 4f 52 00 00 00 00
279
280 This string of numbers is interpreted as follows: firmware version
281 2.02, sub-version 1.10, data version 2.02 (followed by two empty
282 bytes); 57 44 4f 52 (hex for "WDOR") stands for "Wavedrum Oriental"
283 (followed by four empty bytes). You can have the Wavedrum display all
284 its version numbers by pressing the button labelled "Global" when
285 powering on the device. Note that the file name `WDORS110.BIN`
286 references the version number 1.10, while `WDORM202.BIN` references
287 the firmware version number 2.02.
288
289 `SYSTEM/WDORM202.BIN` contains the firmware of the Wavedrum Oriental.
290 There are many interesting strings and binary patterns in the file,
291 but I'm still a long way from *understanding* how it works. To view
292 the strings with the `strings` command, you have to specify the
293 encoding as 32-bit little endian:
294
295 strings --encoding L SYSTEM/WDORM202.BIN
296
297 Some of the strings embedded in the firmware are file names, some of
298 which are not available on the micro SD card. This includes the
299 following files: SYS00000.BIN, SYS00100.BIN, SYSTEM/WDORS100.BIN,
300 SYSTEM/WDX_M100.BIN, SYSTEM/WDX_S100.BIN, and SUBXXXXX.BIN (a
301 pattern?).
302
303
304 # The programme format
305
306 Looking at the hexdump of the file `WD2_PROG.BOR` which holds all custom
307 presets, I couldn't find any obvious patterns in the file, so I
308 resorted to editing a single programme, setting particular consecutive
309 parameters to easily recognisable sequences of values (such as 100,
310 99, 98, and 97 for hd1, hd2, hd3, and hd4) and locating the changes in
311 the hexdump.
312
313 <img class="full stretch" src="/images/posts/2013/wavedrum-diff.png" alt="Analysing the programme format by changing values and looking at the differences" />
314
315 This procedure has allowed me to figure out in what order the
316 parameters are stored in the file. Each programme is exactly 54
317 16-bit words long; each parameter takes up exactly 16 bits. Negative
318 values are stored in [two's
319 complement](https://en.wikipedia.org/wiki/Two%27s_complement) format
320 (e.g. negative six is stored as 0xFFFA). The file is exactly 16200
321 bytes long which is just enough to hold 150 custom programmes, each
322 taking up 108 bytes.
323
324 I'm currently writing a Haskell library to parse / build progammes and
325 parameters. The code is available for
326 [free](https://www.fsf.org/about/what-is-free-software) [on
327 gitorious](https://gitorious.org/wavedrum/wavedrum-lib) under the [GNU
328 GPLv3](https://gnu.org/licenses/gpl.html).
329
330 The parameters are stored in this order:
331
332 |identifier | mode | target | name |
333 |----------:|--------|:--------------------|:-----------------------------|
334 |07.1 | Edit 1 | head algorithm | Pressure curve |
335 |type | Edit 2 | -- | Pre EQ |
336 |01.1 | Edit 1 | head algorithm | Tune |
337 |02.1 | Edit 1 | head algorithm | Decay |
338 |03.1 | Edit 1 | head algorithm | Level |
339 |04.1 | Edit 1 | head algorithm | Pan |
340 |05.1 | Edit 1 | head algorithm | Algorithm select |
341 |hd.1 | Edit 2 | head algorithm | Algorithm parameter 1 |
342 |hd.2 | Edit 2 | head algorithm | Algorithm parameter 2 |
343 |hd.3 | Edit 2 | head algorithm | Algorithm parameter 3 |
344 |hd.4 | Edit 2 | head algorithm | Algorithm parameter 4 |
345 |hd.5 | Edit 2 | head algorithm | Algorithm parameter 5 |
346 |hd.6 | Edit 2 | head algorithm | Algorithm parameter 6 |
347 |hd.7 | Edit 2 | head algorithm | Algorithm parameter 7 |
348 |hd.8 | Edit 2 | head algorithm | Algorithm parameter 8 |
349 |01.3 | Edit 1 | rim algorithm | Tune |
350 |02.3 | Edit 1 | rim algorithm | Decay |
351 |03.3 | Edit 1 | rim algorithm | Level |
352 |04.3 | Edit 1 | rim algorithm | Pan |
353 |05.3 | Edit 1 | rim algorithm | Algorithm select |
354 |rm.1 | Edit 2 | rim algorithm | Algorithm parameter 1 |
355 |rm.2 | Edit 2 | rim algorithm | Algorithm parameter 2 |
356 |rm.3 | Edit 2 | rim algorithm | Algorithm parameter 3 |
357 |rm.4 | Edit 2 | rim algorithm | Algorithm parameter 4 |
358 |rm.5 | Edit 2 | rim algorithm | Algorithm parameter 5 |
359 |rm.6 | Edit 2 | rim algorithm | Algorithm parameter 6 |
360 |rm.7 | Edit 2 | rim algorithm | Algorithm parameter 7 |
361 |rm.8 | Edit 2 | rim algorithm | Algorithm parameter 8 |
362 |01.2 | Edit 1 | head PCM instrument | Tune |
363 |02.2 | Edit 1 | head PCM instrument | Decay |
364 |03.2 | Edit 1 | head PCM instrument | Level |
365 |04.2 | Edit 1 | head PCM instrument | Pan |
366 |05.2 | Edit 1 | head PCM instrument | PCM instrument select |
367 |06.2 | Edit 1 | head PCM instrument | Velocity curve |
368 |07.2 | Edit 1 | head PCM instrument | Pressure curve |
369 |08.2 | Edit 1 | head PCM instrument | Pressure tune |
370 |09.2 | Edit 1 | head PCM instrument | Pressure decay |
371 |01.4 | Edit 1 | rim PCM instrument | Tune |
372 |02.4 | Edit 1 | rim PCM instrument | Decay |
373 |03.4 | Edit 1 | rim PCM instrument | Level |
374 |04.4 | Edit 1 | rim PCM instrument | Pan |
375 |05.4 | Edit 1 | rim PCM instrument | PCM instrument select |
376 |06.4 | Edit 1 | rim PCM instrument | Velocity curve |
377 |07.4 | Edit 1 | rim PCM instrument | Pressure curve |
378 |08.4 | Edit 1 | rim PCM instrument | Pressure tune |
379 |09.4 | Edit 1 | rim PCM instrument | Pressure decay |
380 |10.1 | Edit 1 | -- | Reverb type |
381 |10.2 | Edit 1 | -- | Reverb effect level |
382 |10.3 | Edit 1 | -- | Reverb decay time |
383 |10.4 | Edit 1 | -- | Reverb frequency damping |
384 |11.3 | Edit 1 | -- | Delay feedback |
385 |11.2 | Edit 1 | -- | Delay effect level |
386 |11.1 | Edit 1 | -- | Delay time |
387 |11.4 | Edit 1 | -- | Delay frequency damping |
388
389
390 # Thanks
391
392 The following tools have proven indispensable in the analysis:
393
394 - [`calc`](http://www.isthe.com/chongo/tech/comp/calc/), a calculator
395 for the command line supporting hexadecimal representations of
396 numbers (both input and output using the `base` and `base2`
397 functions)
398
399 - [`vbindiff`](http://www.cjmweb.net/vbindiff/), a tool to visualise
400 differences between two binary files with a split-screen hexadecimal
401 display
402
403 - [`ghex`](https://wiki.gnome.org/Ghex), a simple hexadecimal editor
404 supporting pattern search and highlighting
405
406
407 # Call for help
408
409 If you own an earlier model of the Wavedrum or the latest Wavedrum
410 Global Edition, I would be *very* happy if you could send me a
411 block-level copy of the SD card (see above for instructions). This
412 would allow me to understand the firmware better and maybe even make
413 it possible to upgrade an older Wavedrum to the latest version (taking
414 into account possible hardware differences, such as differing memory
415 size).
416
417 Please send a link to the micro SD card image to
418 <span class="obfuscated">sflbep,xbwfesvnAfmfqimz/ofu</span>.
419
420 Read [more posts about the Wavedrum here](http://elephly.net/tags/wavedrum.html).