A 48K Spectrum has one bit of sound hardware -- bit 4 of port $FE, the speaker -- and Knight Lore makes every sound by setting and clearing it with the processor counting in between. Nothing else happens while a sound plays: the tunes and effects are timing loops, and they take the machine. Every effect comes down to toggle_audio_hw, which turns the speaker on for B turns of a 13 T-state loop and off for as long; toggle_audio_hw_xC repeats it C times. A half-wave count of 128 is about 1 kHz.

A tune is a string of note bytes ended by $FF (start_game_tune). The low six bits index freq_tbl, a table of five octaves of semitones from G#1 to G6, 0 being a rest; each row holds two counts that time the half-wave and the number of waves in one unit of length, scaled so a unit lasts about 0.155 s whatever the pitch. The top two bits are the length less one, one to four units. play_audio plays a tune through; play_audio_until_keypress stops at a key.

Every recording here is the game's own code running in SkoolKit's simulator, with each change of the speaker bit logged to the T-state and rendered at 44100 Hz; nothing is synthesised. A sound made by one call was recorded by calling its routine on a machine of its own, with the values it reads set as given. A sound that is a blip a frame from something moving was recorded by running the game itself, with Sabreman put into a room where that thing is the only source of noise, so the gaps between the blips are the game's real frames. The simulator has no memory contention, so all of this runs a little faster, and sounds a little higher, than on a real Spectrum. A quiet frame (room $0B, nothing moving) lasts 145,709 T-states, 42 ms.

Tunes

The start of a game

Played in full by main once a control method has been chosen, before Sabreman first appears.

Recorded: play_audio called with DE = $B20E. 9 notes, 16 units.

2.52 s, 1031 edges.

Game over

Played by await_restart under the game-over screen until a key is pressed: a moving upper note alternating with a held bass.

Recorded: play_audio_until_keypress called with DE = $B218 and no key down, so it plays to the end, as it does for a player who waits. 32 notes, 32 units.

5.03 s, 3783 edges.

The game completed

Played in full by game_complete_msg under the closing message.

Recorded: play_audio called with DE = $B239. 25 notes, 27 units.

4.24 s, 2237 edges.

Effects

Picking up, dropping, an extra life

toggle_audio_hw_x16: 16 waves at a half-wave count of 128. Played when an object is picked up or dropped, when an extra life is collected, and when the menu's choice changes.

Recorded: One call; it sets its own pitch and length.

16 ms, 32 edges, 1026 Hz.

Pause

toggle_audio_hw_x24: 24 waves at a half-wave count of 80, as SPACE pauses the game and again as it lets go.

Recorded: One call; it sets its own pitch and length.

15 ms, 48 edges, 1619 Hz.

Jumping

sound_jump: a rising sweep of 32 single waves, played as Sabreman leaves the ground.

Recorded: One call; it sets its own pitch and length.

30 ms, 64 edges, 534 to 25735 Hz (the top of that is above hearing).

A thud

sound_thud: four low blips of three waves, their pitches the first four bytes of the ROM with the top two bits set. A bouncing ball landing, a flame turning at a wall.

Recorded: One call; it takes its pitches from the ROM, so it is the same every time.

21 ms, 24 edges, 521 to 635 Hz.

Turning on the spot

sound_footstep: one of Sabreman's footsteps, played by itself when he turns without walking.

Recorded: One call with Sabreman's legs (IX) at X $80, Y $80, Z $80 -- the middle of the floor, so 8 waves -- and the frame counter at 0, which picks the fixed pitch (half-wave count $60); on the other frames of the pair it takes its pitch from his height instead. The walking recording below has both.

6 ms, 16 edges, 1358 Hz.

A charm into the cauldron

cycle_colours_with_sound: sixteen passes, each stepping the ink of every attribute cell on by one, making a burst with sound_sparkle and pausing. The colour cycling and noise when the right charm lands in the cauldron.

Recorded: One call with the charm (IX) of type 104, the first of the types a charm takes as it falls in (104-110), so each burst is (NOT 104) AND 31 = 23 blips; a charm of type 110 makes 17. The silences are the attribute passes and the pauses, which are part of the routine.

1.86 s, 1472 edges, 515 to 32407 Hz (the top of that is above hearing).

The finale's tone

sound_pitch_from_a: six waves at a half-wave count from A. During the finale end_of_frame plays it at the end of every frame, pitched by the last spark's height at $5BC5.

Recorded: One call with A = $A4, the height a spark climbs to before homing on Sabreman (half-wave count $6D). In the game it sounds once a frame for the whole finale.

5 ms, 12 edges, 1200 Hz.

Man to werewolf, and back

sound_transform: a warble of 16 to 40 single waves at pitches scrambled from the step count, played by transform_step every fourth frame for the eight steps of the change at sunset and sunrise.

Recorded: Eight calls with the legs (IX) of types 92, 93, 94, 95, 92, 93, 94, 95 -- 16, 24, 32 and 40 waves -- where the game picks each frame at random; four quiet frames apart (four times the frame measured in room $0B, 582,836 T-states).

1.34 s, 448 edges, 797 to 1514 Hz.

A block sinking

sound_pitch_from_z: six waves pitched by the object's height -- higher when higher. A dropping block sinking under Sabreman, a spiked ball falling, a bouncing ball, and Sabreman falling fast.

Recorded: 25 calls with the object's Z falling one a frame from $98 to $80 (the floor), as a dropping block sinks, a quiet frame apart (measured in room $0B, 145,709 T-states).

1.23 s, 300 edges, 526 to 841 Hz.

Sabreman appearing

sound_materialise: a rising sweep, one wave a step. Both of Sabreman's records materialise together, stepping their type from 120 to 127 every other frame (upd_120_to_126), and each plays the sweep for its new type -- so every other frame the sweep sounds twice, and each pair is longer than the last. It starts every life and follows him into every room.

Recorded: The game running in room $0B, which has nothing in it, from the first frame to the last of the effect. The types passed are 121 to 127, so the sweeps are 7, 11, 15 ... 31 steps (the type is stepped before the call, so type 120's 3 steps are never heard).

1.16 s, 532 edges, 15 frames, 478 to 11438 Hz.

Sabreman walking

sound_walk_step: a footstep on every other frame of the walk cycle, alternating a fixed pitch with one from his height -- the tick-tock of two feet -- with fewer waves the further he is to the west or north.

Recorded: The game running in room $0B with A held (walk forward, on the keyboard) from the frame after he has appeared, as he walks from the middle of the room towards the west wall.

926 ms, 134 edges, 20 frames, 1358 to 2035 Hz.

Sabreman dying

sound_sparkle: bursts of short blips pitched by bytes of the ROM from $1234. When Sabreman is killed both his records turn to sparkles (types 112-119, init_death_sparkles) and each plays a burst every frame, one blip shorter each frame. A crumbling block makes the same noise, briefly, as it goes.

Recorded: The game running in room $F7, where he is killed as soon as he has formed, over the eight frames of the sparkle: bursts of 15 down to 8 blips, twice a frame.

940 ms, 736 edges, 8 frames, 221 to 32407 Hz (the top of that is above hearing).

The movable block's buzz

sound_movable_block: four waves, at one of eight pitches (block_blip_pitches) chosen by the frame counter. The type 62 block plays it every frame, so a room with one has a buzz under everything else.

Recorded: The game running in room $A3, where the block is the only thing making a noise, for 24 frames (three turns of the eight pitches).

3.19 s, 192 edges, 24 frames, 593 to 1358 Hz.

A block sliding east and west

sound_pitch_from_x: six waves pitched by X. A sliding block (type 54) plays it every frame as it shuttles one unit a frame, 15 units each way; a flame moving along X uses it too. The half-wave count is four times the bottom six bits of NOT X, so the pitch climbs as X rises and drops back to the bottom every 64 units -- which this block's run crosses at X = $80, where a whine far above hearing becomes the lowest note.

Recorded: The game running in room $2D, whose sliding block is its only noise, for 32 frames: one shuttle there and back.

3.22 s, 384 edges, 32 frames, 526 to 26119 Hz (the top of that is above hearing).

A block sliding north and south

sound_pitch_from_y: the same, pitched by Y. A sliding block of type 55, and flames moving along Y.

Recorded: The game running in room $48, whose sliding block is its only noise, for 32 frames: one shuttle there and back.

2.25 s, 384 edges, 32 frames, 835 to 1331 Hz.

A guard walking

audio_guard_wizard: the guards' and the wizard's footsteps, on every other frame of the walk cycle, their two pitches alternating the opposite way round to Sabreman's.

Recorded: The game running in room $D1, which holds a guard and spikes, for 24 frames of the guard walking round the walls.

2.13 s, 192 edges, 24 frames, 1026 to 2035 Hz.

A portcullis rising and crashing down

sound_pitch_from_xyz while it rises: six waves pitched by X + Y + Z, a frame at a time as it climbs one unit a frame -- the sound charms, tables and chests make when pushed, too. Then sound_portcullis_crash as it lands: sixteen blips of two waves pitched by bytes from a random address in the ROM, so no two crashes are alike.

Recorded: The game running in room $3F, whose portcullis is its only noise, from frame 81 after arriving: its second rise, 32 frames to the top, the fall, and the crash.

3.19 s, 448 edges, 39 frames, 514 to 32407 Hz (the top of that is above hearing).