Why it exists
Each performance carries an exact account of itself: every sound, its contributor, license, source URL and checksum, where it was placed in the piece, every Performer setting and the seed. CC BY requires credit anyway. The record makes credit exact rather than a footnote.
Recorded music has mostly been a sealed artifact. Sample-level credit is rare and usually private. Here credit, provenance and method travel with the music, in public, readable by people and agents.
Peter’s Notarism is about witnessing and recording existence. The record is NetComposer’s act of witness.
What it makes possible
- Reproduction: the inputs (with checksums), every setting and the seed are enough to rebuild a performance exactly.
- Forks: change one setting or swap one Supplier, and the new record shows exactly what changed.
- Supplier view: Suppliers can see where their sounds were used. A usage view built from records is in draft for musicmatter.art.
- Comparison: performances of one Composition can be compared sound by sound and setting by setting.
- The crawl path as artwork: the walk record traces every hop from the seed sound, drawn as a path chart.
- Agents: agents can read, audit and build on any performance from the raw JSON.
- Signed records, later: records are unsigned for now. Signing is open decision #33.
Anatomy, from a real record
Every excerpt below is copied from records/bwv846-walk.json, performance 4 (the crawl walk: 290 sounds from 234 contributors were used, 265 sounds from 209 contributors are heard; the rest lent rhythm only). Long lists are cut where marked …. The format is a draft: record_type is netcomposer.performance_record, and fields may change.
1. Top level
record_type, record_format_version, record_format_note, performance, hacks_chain, sounds_used, summary, derived_inputs, attribution, provenance_files, created_at, signature, record_hash, amendments.
performance holds what was played and how; sounds_used holds every input; summary holds the counts; record_hash, signature and amendments hold integrity.
2. Which Composition
The record names the Composition file the Performer read and pins it by sha256, so a changed text cannot pass as the same input. (The copy published on this site carries the name amendment, so its own checksum differs; netcomposer.json lists it.)
"composition_ref": {
"composition_id": "compositions/bach_bwv846_prelude_progression.md",
"sha256": "f63acadc04937a289a2f51c96386a0ae92de8f7fba00c69a16a038632b9b43d5",
"composer": {
"display_name": "Peter"
},
"music": "Johann Sebastian Bach, Prelude in C major, BWV 846 (1722). Public domain.",
"analysis": {
"credit": "Mark Gotham et al., When in Rome corpus",
"uri": "https://github.com/MarkGotham/When-in-Rome",
"license": "CC-BY-SA-4.0"
},
"not_used": "Bach's written notes. No score, MIDI or kern file is read."
}
3. The Performer’s settings and the seed
Every rule the Performer followed, including the caps that keep any one sound or contributor from dominating, and the seed that makes the random choices repeatable. Full keys: name, seed, walk, selection, caps, rhythm, bass, bed, tempo_map, transforms_enabled, pitch_shift.
"rule_set": {
"name": "crawl walk (BWV 846)",
"seed": 846,
"caps": {
"sound_max_bars": 3,
"contributor_max_bars": 5,
"donor_max_bars": 2
},
"transforms_enabled": [
"trim",
"gain",
"fade",
"time_stretch"
],
"pitch_shift": false
} …
4. The crawl
How many queries ran against which sources, and when. The query list itself is in the record.
"crawl": {
"queries_by_source": {
"freesound": 133,
"internet_archive": 9,
"wikimedia_commons": 11
},
"first_query_at": "2026-10-17T18:56:31-0700",
"last_query_at": "2026-10-17T19:10:15-0700",
"nodes_found": 1022,
"nodes_analyzed": 1021
}
5. One bar
Bar 9 of 35: the chord, how much of the bar’s energy falls on chord tones, which sound lent its rhythm, how the walk expanded from sounds it already had, and the sounds placed there. Keys: bar, chord, chord_pcs, figure_tones_available, chord_tone_energy, has_bass, has_bed, rhythm, expansions, sounds.
{
"bar": 9,
"chord": "Am7",
"chord_pcs": [
"C",
"E",
"G",
"A"
],
"figure_tones_available": [
"C",
"E",
"G",
"A"
],
"chord_tone_energy": 0.632,
"has_bass": false,
"has_bed": true,
"rhythm": {
"donor": "fs:220942",
"onsets": 8,
"time_scale": 1.1345,
"heard": true,
"fallback_even": false
},
"expansions": [
{
"from": "fs:613178",
"from_title": "Music Box (G, 4/4, 60 BPM)",
"hop": "similar",
"new_sounds": 10
},
"… 3 more"
],
"sounds": [
{
"key": "fs:118165",
"title": "What Child is This.wav",
"by": "ZekiFoxx",
"source": "Freesound",
"license": "CC0 1.0",
"url": "https://freesound.org/people/ZekiFoxx/sounds/118165/",
"roles": [
"figure"
],
"events": 2,
"hop": "similar to “Music Box Melody #3”",
"found_at_bar": 8,
"pitch_classes_used": [
"A"
]
},
{
"key": "fs:473638",
"title": "CreepyMusicBox.wav",
"by": "dansayshi",
"source": "Freesound",
"license": "CC0 1.0",
"url": "https://freesound.org/people/dansayshi/sounds/473638/",
"roles": [
"figure"
],
"events": 3,
"hop": "similar to “Music Box (G, 4/4, 60 BPM)”",
"found_at_bar": 9,
"pitch_classes_used": [
"C",
"G"
]
},
"… 7 more"
]
}
6. One sound
One entry of sounds_used: where the file came from, the checksum of the exact bytes used, the license, a credit line ready to paste, how the walk found it (hop, parent, distance from the seed), and every span where it sounds, down to the source offset and gain. Keys: key, source, title, source_url, audio_used, supplier, license, credit_line, found, roles, uses, bars, time_stretch_ratios, pitch_shift, spans; span keys: layer, bar, at_s, len_s, source_offset_s, pitch_class, midi_est, cents, gain_db, time_stretch, donor_onset_src_s, pitch_classes, fit.
{
"key": "wc:File:Helen Keller - The Story of My Life (Recording A) Part 13.mp3",
"source": "Wikimedia Commons",
"title": "Helen Keller - The Story of My Life (Recording A) Part 13.mp3",
"source_url": "https://commons.wikimedia.org/wiki/File:Helen_Keller_-_The_Story_of_My_Life_(Recording_A)_Part_13.mp3",
"audio_used": {
"url": "https://upload.wikimedia.org/wikipedia/commons/7/73/Helen_Keller_-_The_Story_of_My_Life_%28Recording_A%29_Part_13.mp3?utm_source=commons.wikimedia.org&utm_campaign=imageinfo&utm_content=original",
"what": "original file",
"sha256": "d4d50ae3611413f7b19dd06a92c3ba9808c3c731798e08e8cb27f796f691eb9d",
"size_bytes": 4369472
},
"supplier": {
"display_name": "Helen Keller",
"primary_link": "https://commons.wikimedia.org/wiki/File:Helen_Keller_-_The_Story_of_My_Life_(Recording_A)_Part_13.mp3"
},
"license": {
"name": "CC0 1.0",
"uri": "http://creativecommons.org/publicdomain/zero/1.0/deed.en"
},
"credit_line": "“Helen Keller - The Story of My Life (Recording A) Part 13.mp3” by Helen Keller (https://commons.wikimedia.org/wiki/File:Helen_Keller_-_The_Story_of_My_Life_(Recording_A)_Part_13.mp3), CC0 1.0",
"found": {
"at_bar": 9,
"hop": "Wikimedia Commons search “story” (from “Music Box (G, 4/4, 60 BPM)”)",
"parent": "fs:613178",
"parent_title": "Music Box (G, 4/4, 60 BPM)",
"path_length_from_seed": 9
},
"roles": [
"figure"
],
"uses": 1,
"bars": [
9
],
"time_stretch_ratios": [
1.0
],
"pitch_shift": false,
"spans": [
{
"layer": "figure",
"bar": 9,
"at_s": 27.8261,
"len_s": 0.3,
"source_offset_s": 6.664,
"pitch_class": "G",
"midi_est": 55,
"cents": 10.0,
"gain_db": -3.14,
"time_stretch": 1.0,
"donor_onset_src_s": 0.046
}
]
}
7. Summary
Counts for the whole performance (first keys shown).
"summary": {
"distinct_sounds_heard": 265,
"rhythm_donors": 35,
"distinct_sounds_total": 290,
"contributors": 234,
"sources": {
"Freesound": 255,
"Wikimedia Commons": 21,
"Internet Archive": 14
},
"licenses": {
"CC0 1.0": 165,
"CC BY 3.0": 36,
"CC BY 4.0": 72,
"CC BY-SA 4.0": 8,
"CC BY-SA 3.0": 1,
"Public domain": 7,
"CC BY-SA 2.0": 1
},
"total_events": 619,
"top_contributors_by_events": [
{
"name": "Antti Luode",
"events": 18,
"share": 0.029
},
{
"name": "sgossner",
"events": 16,
"share": 0.026
},
{
"name": "klankbeeld",
"events": 12,
"share": 0.019
}
],
"max_bars_per_sound": 3,
"chord_tone_energy_mean": 0.576
} …
8. Integrity
record_hash is the sha256 of the record in canonical JSON (sorted keys, no whitespace) without record_hash and signature. Anyone can recompute it. Records are unsigned for now (open decision #33). When a record changes after the fact, an amendment says what changed and keeps the previous hash.
"record_hash": {
"algorithm": "sha256",
"over": "canonical JSON (sorted keys, no whitespace) of the record without record_hash and signature",
"value": "ede74c6751c4da03c64f62df2067d7b564971a3cb68eca48188bd670a4d57bfb"
},
"signature": {
"status": "UNSIGNED",
"signed_by": null,
"algorithm": null,
"key_id": null,
"value": null,
"note": "Placeholder. Open decision #33 (signed usage records) is not decided."
},
"amendments": [
{
"at": "2026-10-17T19:29:52-07:00",
"what": "Contributor display name changed from 'Petrus' to 'Peter' (Peter Semmelhack) for netcomposer.art, at his request. No audio, input, setting or other field changed.",
"previous_record_hash": "4ae478e5aadd378528565518aa3ed5c25c53685f474481e2edac08a65dd14a99",
"original_record": "unchanged in the NetComposer working files"
}
]
To check: python3 -c "import json,hashlib;r=json.load(open('bwv846-walk.json'));[r.pop(k) for k in ('record_hash','signature')];print(hashlib.sha256(json.dumps(r,sort_keys=True,separators=(',',':'),ensure_ascii=False).encode()).hexdigest())"
All records
- The C major Prelude, harmony only (after Bach, BWV 846): take 5, forward/reverse echo: read · json
- The C major Prelude, harmony only (after Bach, BWV 846): take 6 arps, 1/4 delay, hall 25%, LP 1 kHz: read · json
- The C major Prelude, harmony only (after Bach, BWV 846): search-driven take: read · json
- The C major Prelude, harmony only (after Bach, BWV 846): crawl walk: read · json
Performances 1–3 predate the walk and use an earlier, smaller set of the same fields.