- matplotlib

ScratchBook 📝🎶

A platform for browsing, composing and visualizing scratches in TTM notation.

This Page is old, please use the New ScratchBook..


Visualizer

Type and visualize your scratch formula...

Loading scratch plot...

Basic Info

Sounds Elements Tears Orbits

Clicks and Curves

FO FC PO PC D A S Q Ex Log

Elements

Babies Ins Outs Dices Flares iFlares oFlares Transformers Ghosts Holds G-Holds

Orbits

Chirps Slices Stabs Flare-Orbits OG-Flares Baby-Orbits Dice-Orbits Off-Stabs

Orbit Types

S-Curved Tazers Phantazms Ex-Tazers Ex-Phantazms


Library and Logic

ScratchBook lets you write TTM-notation just like math. Combine scratches and operators into formulas, such as: autobahn + prizm + (slice / 0.25) * 4

Open the cards to learn more...

Browse scratches and click on their preview to add them to the visualizer. Use the expert mode for more options.

Collections

Core

Elements

Tears

Orbits

Combos

Clicks

Regular

Irregular

Curves

Regular

Irregular

Columns

Clicks

Curves

Scratches

Read how operators can be used to modify and combine scratches.

Operator Purpose Grammar Example
~ "Reverse" or "backwards" scratching (Flip a scratch on the y-axis) ~scratch ~autobahn
- "Mirror" scratching (Flip a scratch on the x-axis) -scratch -autobahn
* Repeat a scratch n times (n must be an integer number) scratch * n chirp * 4
+ Add scratches from left to right scratch + scratch chirp + flob2 + steps
/ Set the length n of a scratch in 1/4 notes (aka beats) scratch / n baby / 2
// Decide how much of the sample is used (n must be between 0 and 1) scratch // n swingflare // 0.2
** Move a scratch or expression up on the Y-axis. Typically used in connection with the "//" Operator". Use brackets wisely! For example, "chirp // 0.5 ** 0.5" is not the same as "(chirp // 0.5) ** 0.5". expression ** n (chirp // 0.5) ** 0.5
% Shift the "phase" of a scratch by rotating its elements from right to left. (n must be an integer number) scratch % n prizm % 0.25
[n] Show the n-ths element of a composed scratch (n must be an integer number. Counting starts at 0 not at 1!) scratch[n] autobahn[3]
[n:m] Show all elements between the n-ths (included) and m-ths (excluded) element of a composed scratch (n and m must be integer numbers. Counting starts at 0 not at 1!) scratch[n:m] autobahn[3:7]
(expression) Use (nested) brackets to logically "shield off" expressions from each other. For example, "chirp / 1/3" is not the same as "chirp / (1/3)". Brackets are essential for many complex expressions. (expression) (chirp // (1/3)) ** (2/3)

ScratchBook's formulas work on two levels.

At the first level, you can combine scratches (i.e. their names) and operators into formulas like autobahn + prizm + (slice / 0.25) * 4. See the two tabs above to learn more.

At the second level, ScratchBook offers formal languages to define elements, tears, and orbits.

Elements are scratches that cannot be broken down into smaller scratches, only into their "subatomic features" (see the Theory section below). Their names obey the grammar [BASE][N]*[CP]*[CRV]*, whereby

  • [BASE] is obligatory and stands for one of the eleven base names: baby, in, out, dice, flare, iflare, oflare, transformer, ghost, hold, ghosthold.
    👻 If you're lazy, like me, simply use abbreviations: b, i, o, d, f, if, of, tr, g, h, gh.
  • [N]* is only possible but then also obligatory after the bases f, if, of, where it stands for the number of flare-clicks, as well as after the base tr, where it stands for the number of transformer sounds. Currently, all numbers between 1 and 9 are permitted.
  • [CP]* is optional and stands for a non-standard click-pattern (D, A, S or Q) after any of the bases f, if, of, tr.
  • [CRV]* is optional and stands for a non-standard curve shape (Ex or Log) after all bases except g, h, gh.

Examples for elements following this grammar are:

  • babyLog (a baby with a logarithmic curve)
  • f8Q (an 8-click flare with a squeezed click-pattern)
  • tr2AEx (a 2-sound transformer with an augmented click-pattern and an exponential curve)

Tears are sequences of upwards or downwards oriented elements, forming cascades. Their names obey the grammar [TBASE]*tear[N][CRV]*[__EL]*, whereby

  • [TBASE] is optional and stands for one of the following tear-bases: i, o, d, f, if, of, tr. The purpose of the tear-base is to specify if and where clicks are added when the record is paused, i.e. during the tearing moments:
    i = click at the start,
    o = click at the end,
    d = click at the start AND click at the end,
    f = clicks at every tearing moment,
    if = click at the start AND clicks at every tearing moment,
    of = clicks at every tearing moment AND click at the end,
    tr = click at the start AND clicks at every tearing moment AND click at the end.
  • tear is obligatory but can be abbreviated as t.
  • [N] is obligatory and stands for the number of pauses or tearing moments, i.e. how often the record is held still during a tear scratch.
  • [CRV]* is optional and stands for a non-standard curve shape (Ex or Log).
  • [__EL]* is optional and stands for a specific element being used during the tear scratch. This function is only useful for tears and transformers, and only their base names are allowed, e.g. __f3 or __tr2, but not __f3D or tr2Log. Note that you must use two underscores to specify the tear element (otherwise you're falsely using the orbit language, see the tab below).

Examples for tears following this grammar are:

  • tear5 (a 5-tear without any clicks)
  • it2 (a 2-tear with a click at the start)
  • oft4 (a 4-tear with clicks at all 4 tearing moments and a click at the end)
  • it4__f1 (a 4-tear with a click at the start whose elements are 1-click flares)

Orbits are scratches that incorporate both a forward and backward movement, or vice versa, of the record in sequence. At the first level, you can always construct orbits like so: [SCRATCH] + ~[SCRATCH], where [SCRATCH] in both cases stands for any element or tear scratch. But if you want to specify a particular length-ratio, things get messier. For example, to get a ratio of "two-to-three", you need to write something like ([SCRATCH] / 2 + ~[SCRATCH] / 3) / 1.

At the second level, a more convenient way to formulate orbits is to use the grammar [SCRATCH]_[SCRATCH][_RATIO]*, whereby

  • [SCRATCH] is obligatory in both cases and stands for any element or tear scratch (the second one automatically being the backward scratch).
  • _ is obligatory and simply stands for "orbit".
  • [_RATIO]* is optional and stands for a specific length-ratio, such as _23, meaning "two-to-three", i.e. that the forward scratch gets 2/5th of the total length while the backward scratch gets 3/5th of the total length. If no length-ratio is specified, a ratio of "one-to-one" is automatically assumed.

Examples for orbits following this grammar are:

  • flare1_flare2 (a "1-click-flare-vs-2-click-flare" orbit aka "rawhippopotamus" with a non-specified "one-to-one" length-ratio.)
  • f1_f2_23 (a "1-click-flare-vs-2-click-flare" orbit aka "hippopotamus" with a specified "two-to-three" length-ratio.)
  • it4_o (a "4-tear-vs-out" orbit)

Please note:

  • You can use both elements and tears as scratches.
  • The grammar allows you to compose unloopable orbits, like b_o, whose start and end connectors do not match, so that the orbit could not be looped in reality.
  • The grammar (currently) does not prohibit you from composing "impossible" orbits, like b_i, whose direct connectors don't match. In the example, a baby-scratch without a click at the end meets an in-scratch with a click at the start.


Theory

ScratchBook builds on two theoretical pillars: A theory of scratch notation and a theory of scratch elements.

Open the cards to learn more...

The turntablist transcription methodology (TTM) was created and published by John Carluccio, Ithan Imboden, and Raymond Pirtle in the late 1990s. It is a system for transcribing any scratch as the graph of a function of time, on the x-axis, against the roation of the record or against the duration of the sample, on the y-axis.[1]

  • When the curve moves up this means that the record moves forward. When the curve moves down the record moves down.
  • The steepness of the curve at any point signifies the speed of the record, which usually corresponds to the pitch of the sample (except when pitch control technologies are used). The faster the sample is played, the steeper the curve and vice versa.
  • When the curve forms a horizontal line, even for a very short period of time, this indicates that the record is held still and makes no sound. This occurs, for example, during a tear scratch and at the turning point of any orbit scratch.
  • Circles on top of the curve signify "clicks", i.e. moments when the cross-fader is closed and re-opened in as little time as possible, causing small breaks in the sound.

According to the original TTM-booklet, TTM is emphatically "an open source effort...Fight it, defend it, tweak it, trash it - all will assist its evolution" (p.10). In this spirit, ScratchBook modifies the original TTM in the following way:

  • The color white generally indicates that the fader is closed.
  • Consequently, white circles (not black ones) are used to represent regular fader clicks.
  • When the cross fader is closed for a longer time period, e.g. when the record is brought back during the second half of a stab scratch, this is indicated by a white curve.
  • No "phantom clicks" are used to indicate moments when the record is held still. However, for the geeks among you, the number of opening and closing "phantom clicks" is reported in the tables.

[1] TTM has been fleshed out more fully in Raymond Pirtle's later work on the "Periodic Matrix of Scratches". There is also an alternative scratch notation system, which resembles the modern staff notation. See Alex Sonnenfeld's S-Notation.

Under the hood, ScratchBook takes a unique atomistic approach to scratch notation. Any scratch curve is generated from a sequence of distinct building blocks, called elements, each of which exhibits a unique combination of "subatomic features".

ScratchBook's elements fall into eleven classes and two groups:

Group 1

Babies

Babies

Ins

Ins

Outs

Outs

Dices

Dices

Flares

Flares

iFlares

iFlares

oFlares

oFlares

dFlares (Transformers)

dFlares (Transformers)

Group 2

Ghost

Ghost

Hold

Hold

Ghost-Hold

Ghost-Hold


Group 1 comprises 8 classes of elements that make a sound. These classes relate to each other in the following ways:

  • Babies and Flares both have no clicks at their start and end points, but they differ in that only the Flares have clicks in between their start and end points (only one such click is shown here, but scratches of all Flare classes can have up to 9 clicks).
  • Ins and iFlares both have a click at their start points and no click at their end points, but they differ in that only the iFlares have clicks in between their start and end points.
  • Outs and oFlares both have a click at their end points and no click at their start points (opposite of Ins/iFlares!), but they differ in that only the iFlares have clicks in between their start and end points.
  • Dices and dFlares both have clicks at their start AND end points, but they differ in that only the dFlares have clicks in between their start and end points.
  • Since dFlares are commonly referred to as Transformers, Scratchbook permits both names, but the grammar is slightly different. The equivalent of df2 is tr3 (not t2), because the numbers refer to different quantities. In all flare scratches, including dFlares, the number refers to the number of clicks while in transformers the number refers to the number of sounds.

Group 2 comprises 3 elements that do not make a sound:

  • The Ghost is used mainly in the stab scratch, where it signifies the silent backward movement of the record after the fader has been closed.
  • The Hold is used whenever the record is held still for a longer time period while the fader remains open. See for example the slicecombo1.
  • The Ghost-Hold is used whenever the record is held still for a longer time period while the fader is closed.

The total number of elements within and across all classes depends on the number of subatomic features and the rules of their combination. ScratchBook considers five classes of features:

  • Curve shapes (horizontal, sine, exponential, logarithmic)
  • Curve colors (black, white)
  • io-Clicks (in/out-clicks), i.e. clicks at the start and/or at the end of a of a scratch (none, start, end, start+end).
  • f-Clicks (flare-clicks), i.e. clicks somewhere in the middle of a scratch (0-9 clicks, but limited to 0-3 clicks in the element collection)
  • Click patterns (normal, diminished, augmented, stretched, squeezed)

Not all of these features should be combined with each other. For example, since white curves always represents silent record movement, they should never have any clicks at all, and, to keep things simple, when they are not horizontal (1 Ghost-Hold), they should always be sine (1 Ghost). Also, click patterns only ever make sense when a scratch has at least one f-click, whereby stretched and squeezed patterns only make sense when at least two f-clicks are given.

The following example of a 3-click flare scratch gives an overview over the five available click patterns:

normal

normal (f3)

Hold

augmented (f3A)

Ghost-Hold

diminished (f3D)

Ghost-Hold

stretched (f3S)

Ghost-Hold

squeezed (f3Q)

The following table shows the distribution of subatomic features over ScratchBook's elements:

classes of elements

In order to keep the size of ScratchBook's elements collection reasonably small, the number of f-clicks is limited to 3 there, resulting in a total of 171 elements, computed by the following rules of combination:

rules for combining elements



import base64 from io import BytesIO import re from js import XMLHttpRequest req = XMLHttpRequest.new() req.open("GET", "https://raw.githubusercontent.com/arnosimons/scratchbook_old/main/scratchbook.py", False) req.send() exec(str(req.response)) req = XMLHttpRequest.new() req.open("GET", "https://raw.githubusercontent.com/arnosimons/scratchbook_old/main/codebook.json", False) req.send() exec(f"codebook = {req.response}") session_info = document.getElementById("session_info") session_svg = document.getElementById("session_svg") session_png = document.getElementById("session_png") info_basic = document.getElementById("info_basic_tbody") info_curves_clicks = document.getElementById("info_curves_clicks_tbody") info_elements = document.getElementById("info_elements_tbody") info_orbits = document.getElementById("info_orbits_tbody") info_orbit_types = document.getElementById("info_orbit_types_tbody") def plot(x=None): session_svg.innerHTML = "" session_png.innerHTML = "" formula = Element("scratch_input").element.value try: myscratch = makeScratch(formula, codebook) info = getInfo(myscratch) fig = Session(myscratch, fontsize=11, w_pad=2).fig tmpfile = BytesIO() fig.savefig(tmpfile, format='svg') encoded = base64.b64encode(tmpfile.getvalue()).decode('utf-8') src = f'data:image/svg+xml;base64, {encoded}' svg = document.createElement('img') svg.setAttribute("src", src) session_svg.appendChild(svg) pyscript.write("session_png", fig) for body, keys in [ [info_basic, ["Sounds", "Elements", "Tears", "Orbits"]], [info_curves_clicks, ["FO", "FC", "PO", "PC", "D", "A", "S", "Q", "Ex", "Log"]], [info_elements, ["Babies", "Ins", "Outs", "Dices", "Flares", "iFlares", "oFlares", "Transformers", "Ghosts", "Holds", "G-Holds"]], [info_orbits, ["Chirps", "Slices", "Stabs", "Flare-Orbits", "OG-Flares", "Baby-Orbits", "Dice-Orbits", "Off-Stabs"]], [info_orbit_types, ["S-Curved", "Tazers", "Phantazms", "Ex-Tazers", "Ex-Phantazms"]], ]: body.innerHTML = "" row = document.createElement('tr') for k in keys: td = document.createElement('td') td.innerHTML = info[k] row.appendChild(td) body.appendChild(row) session_info.style.display = "block" except SyntaxError as e: session_svg.innerHTML = repr(e) except KeyError as e: session_svg.innerHTML = f'{e} is not a valid scratch name' except AttributeError as e: if "object has no attribute 'slices'" in repr(e): session_svg.innerHTML = "You have used an invalid scratch name" else: session_svg.innerHTML = repr(e) except Exception as e: session_svg.innerHTML = repr(e) plot()