NetComposer / the record

The Composition is the score of the piece; the record is the score of the performance.

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

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

Performances 1–3 predate the walk and use an earlier, smaller set of the same fields.