๐Ÿ› ๏ธBuild on Arpeggi

What is the Audio Relationship Protocol (ARP)?

The Audio Relationship Protocol (ARP) is a composable on-chain registry for music primitives. ARP is a decentralized, transparent and trustless registry for the building blocks of music, allowing musicians to permissionlessly use each other's work thereby unlocking musicโ€™s full composability as an artistic form.

What has been built on top of ARP so far?

Arpeggiโ€™s creation ecosystem at https://arpeggi.io is the first dApp built on top of ARP, allowing for the registration, exploration, consumption, and creation of protocol music primitives.

Arpeggi is in active development with a number of web3 projects and web3 artists to integrate existing catalogs with ARP for use in Arpeggi.

Why build on ARP?

Building ARP into your dApp provides access to this rich ecosystem of music. Registering media (songs, loops, or samples) to ARP makes them:

  • Trackable

    • Media can be tracked as it is used in derivatives in new media

  • Attributable

    • Registering the artist of this work to the permanent blockchain ledger makes it known and traceable to the original artist

  • Useable and remixable

    • Once media is registered, it becomes immediately available in Arpeggi Studio and other music dApps built on ARP can now use this media effectively

  • Composable utility

    • If your media has a token (NFT) representing it, you can link that token in the ARP registry to add composable utility to the token

      • Splits contracts built on top of ARP can funnel value back to not only the artist, but the owner of the token anytime the media is used or remixed. This enables artists to retroactively add financial utility to their tokens, rewarding their token holders and collectors.

License: Creative Commons

Note that for now, all media registered to ARP must already be released under a CC0 License.

How to Use ARP

Full ARP contract code can be found in the Github repo.

ARP Contract Addresses

BlockchainAddress

Polygon - 137

0xb5028d5fc996ae03cf93c90ca469e77da0e3cd57

Mumbai - 80001

0x73e10C4949d91673B33bc271Ea111d14374239fC

Reading Media

Each piece of media in ARP has a unique index and can be read using that index:

/// @notice Fetches ARP Media by ID
/// @param index ARP Media ID of the requested media
/// @return The ARP Media, if exists
function getMedia(uint256 index) external view returns (Media memory);

If a piece of media registered to ARP also has an ERC-721 token representing it, it can be queried using the chainID, token contract address and ID:

/// @notice Fetches media by origin token details
/// @param tokenId The ID of the origin token on the origin contract
/// @param contractAddress The address of the origin contract
/// @return The ARP media, if any exists
function getMediaByOrigin(
    uint256 chainId,
    address contractAddress,
    uint256 tokenId
) external view returns (Media memory);

The Media struct returned by ARP has the following schema:

/// @notice Schema for ARP Media stored within ARP
/// @param mediaId the ARP ID of the registered media
/// @param version the schema version of the registered media 
/// @param artistAddress address of the artist who created this media
/// @param dataUri URL of the actual data
/// @param metadataUri JSON string describing the metadata (or, URL of the JSON string), following the ARP metadata schema
/// @param subcomponents array of ARP IDs of subcomponents used in this media (e.g. list of samples used in a stem)
/// @param originToken optional reference to any ERC-721 compliant token on any EVM-compatible chain representing this media
struct Media {
    uint256 mediaId;
    uint256 version;
    address artistAddress;
    string dataUri;
    string metadataUri;
    uint256[] subcomponents;
    OriginToken originToken;
}

/// @notice A reference to any ERC-721 compliant token on any EVM-compatible chain.
/// @param tokenId token ID
/// @param chainId chain ID of the contract this token is on. See https://chainlist.org/
/// @param contractAddress contract address for this token
/// @param originType the OriginType of this item. Usually PRIMARY, unless registering multiple media elements with the same OriginToken.
struct OriginToken {
    uint256 tokenId;
    uint256 chainId;
    address contractAddress;
    OriginType originType;
}

/// @notice Indicates whether this is the primary media that corresponds to
///    a referenced token, so that when a user calls `getMediaByOrigin()`, ARP will
///    only return the PRIMARY media and ignore the SECNODARY.
///    There can only be one PRIMARY media registered in ARP for each ERC-721 token.
enum OriginType {
    PRIMARY,
    SECONDARY
}

Registering Media

Registering your media is as simple as calling the registerMedia function on the ARP contract.

/**
 * @notice Registers media to the ARP protocol.
 * 
 * @param artistAddress address of the artist who created this media
 * @param dataUri URL of the actual data
 * @param metadataUri JSON string describing the metadata (or, URL of the JSON string), following the ARP metadata schema
 * @param subcomponents array of ARP IDs of subcomponents used in this media (e.g. list of samples used in a stem)
 * @param tokenId token ID
 * @param chainId chain ID of the contract this token is on. See https://chainlist.org/
 * @param contractAddress contract address for this token
 * @param originType the OriginType of this item. Usually PRIMARY registering multiple 
 *        media elements with the same OriginToken. 
 *
 * @return the ARP ID of the newly registered media
 */
function registerMedia(
    address artistAddress,
    string calldata dataUri,
    string calldata metadataUri,
    uint[] calldata subcomponents,
    address originContractAddress,
    uint256 originTokenId,
    uint256 originChainId,
    uint8 originType
): return uint64

Notes:

  • Only one artist can currently be registered as the author of media.

    • In the future, expand this to an array of artists

    • Royalty splits/percentages

    • Migrate artist from v1 ARP to be [artist] in v2 ARP

  • dataUri and metadataUri have four ways to be represented:

    • string json object

    • URL pointing to a json object

    • Arweave URI or IPFS URI

  • subcomponents must only include ARP IDs of media that are already registered in ARP. One-shot samples usually donโ€™t have subcomponents. Stems usually have samples as subcomponents. Songs usually have stems as subcomponents.

    • Thereโ€™s no need to include subcomponents that are already subcomponents of your subcomponents. E.g. if Sample A is registered as a subcomponent of Stem B, and Song C uses Stem B, when registering Song C its subcomponents should just be [Stem B]

  • originToken allows you to link the media in the protocol to an existing ERC-721 token that represents it. This is optional โ€” not all media in ARP needs to be tokenized.

    • If an OriginToken is specified on the same chain that ARP is on, ARP will validate that a valid token exists by using the OwnerOf(address) . The token must have a valid owner (e.g. not be burned or unminted) for this to succeed.

Metadata schema:

We've defined a basic metadata schema to make it easier for music creation tools to use the composable media registered to ARP. The goal is to be as simple as possible, while still remaining flexible. We expect this to grow and evolve over time as new use cases for ARP develop.

Example Metadata object:

 "metadata": {
   "bpm": 0,
   "genres": ["Electronic"],
   "key": 1, // See schema below for how to represent keys.
   "mediaType": "one-shot",
   "tags": [
    "Synth Bass"
   ],
   "title": "Your Bass Wave 2"
 },

Full metadata schema:

{	
	"title": {
	  "description": "Title of the media",
  	  "type": "string"
  },
	"mediaType": {
	  "description": "Type of media. currently supported media types are song, stem and one-shot. This is a required property",
     	  "type": "string"
  },
	"tags": {
	    "description": "Tags for searching and filtering. For one-shot samples, this can be intrument type (e.g. Kick)",
	    "type": "array",
	    "items": {
	      "type": "string"
	    }
  },
	"genres": {
	    "description": "Genre labels for the media.",
	    "type": "array",
	    "items": {
	      "type": "string"
	    }
  }
	"key": {
	  "description": "Key of the media.
	    We use the following schema for int key values:
		- [0]: None
		- [1,12] : C through B (natural)
 		- [13, 24]: C Minor through B Minor
		- [25, 36]: C Major through B Major"
	  "type": "integer"
  },
	"bpm": {
	  "description": "Tempo of this media in BPM. 0 is 'none'.",
	  "type": "integer"
  	}
},

If youโ€™re interested in building on top of or contributing to ARP, reach out to us at support@arpeggi.io! We'd love to hear what you're building.

Last updated