🛠️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
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
andmetadataUri
have four ways to be represented:string json object
URL pointing to a json object
Arweave URI or IPFS URI
the same schema as OpenSea’s Metadata standards for supporting decentralized file store solutions like IPFS and Arweave:

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 theOwnerOf(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
Was this helpful?