Quick Start Guide
Get up and running with BeatBlocks in minutes
Time to Make Some Music! 🎵
First things first, let's get the BeatBlocks script in your project. Add this to your HTML:
<script src="https://ordinals.com/content/808fd704c81a98e5c776dcea26e846abf40d9a514de94feea489f8a6215bc808i0"></script>
window.BeatBlock
ready to create some epic tunes! 🎧Overview
This guide will help you quickly set up and use BeatBlocks to create and play generative music on the Bitcoin blockchain. We'll cover the basic steps to create a BeatBlock, initialize it, and play it back.
Prerequisites
- Basic understanding of JavaScript and Web Audio API
- Audio files prepared as stems (MP3 or OGG format recommended)
- A modern web browser with Web Audio API support
Step 1: Create a BeatBlock Instance
First, create an audio context and initialize a new BeatBlock instance:
// Create an audio context
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
// Initialize BeatBlock
const beatblock = new BeatBlock(audioContext);
// Make it globally accessible if needed
window.beatblock = beatblock;
This creates a new BeatBlock instance with a master processing chain that includes compression and limiting.
Step 2: Prepare Your Song Data
The song data includes a template array that defines the structure and progression of your composition. Each template section specifies the length, number of layers, and which types of layers should be included or excluded:
const songData = {
"details": {
"title": "Cosmic Rhythms",
"author": "RareScrilla, Bunzy, Hathbanger, ShowerShoes",
"bpm": 125,
"imgId": "<INSCRIPTION_ID>"
},
"generationConfig": {
"seed": "custom-upload",
"groups": ["v1", "v2", "v3", "v4"],
"mutexes": ["drums"]
},
"layers": [
{
"id": "ambient_pad",
"name": "Ambient Pad",
"loopLength": 1,
"path": "/content/<INSCRIPTION_ID>",
"volume": 1,
"loop": true,
"alignment": "end",
"groups": [],
"mutex": ["pads"]
},
{
"id": "crash_cymbal",
"name": "Crash Cymbal",
"loopLength": 1,
"path": "/content/<INSCRIPTION_ID>",
"volume": 1,
"loop": false,
"alignment": "start",
"groups": [],
"mutex": ["splash"]
},
{
"id": "rising_fx",
"name": "Rising FX",
"loopLength": 2,
"path": "/content/<INSCRIPTION_ID>",
"volume": 1,
"loop": false,
"alignment": "end",
"groups": [],
"mutex": ["rise"]
},
{
"id": "main_beat",
"name": "Main Beat",
"loopLength": 4,
"path": "/content/<INSCRIPTION_ID>",
"volume": 1,
"loop": true,
"alignment": "end",
"groups": ["v1"],
"mutex": ["drums"]
},
{
"id": "bass_line",
"name": "Bass Line",
"loopLength": 4,
"path": "/content/<INSCRIPTION_ID>",
"volume": 1,
"loop": true,
"alignment": "end",
"groups": ["v2"],
"mutex": ["bass"]
},
{
"id": "melody_synth",
"name": "Melody Synth",
"loopLength": 8,
"path": "/content/<INSCRIPTION_ID>",
"volume": 0.8,
"loop": true,
"alignment": "start",
"groups": ["v3"],
"mutex": ["melody"]
}
],
"template": [
{
"length": 8,
"layerCount": 4,
"inclusions": ["melody", "riser"],
"exclusions": ["drums", "bass", "vox"]
},
{
"length": 8,
"layerCount": 5,
"inclusions": ["drums", "perc", "riser", "melody"],
"exclusions": ["bass"]
},
{
"length": 16,
"layerCount": 6,
"inclusions": ["melody", "drums", "riser", "bass"],
"exclusions": []
}
]
};
This JSON structure defines the metadata for your BeatBlock, including details about the composition, generation configuration, and individual audio layers with their properties.
Step 3: Initialize and Load
Initialize the BeatBlock with your song data and load the audio files:
// Initialize with song data
beatblock.initialize(songData).then(() => {
console.log('All audio loaded and ready to play');
}).catch(error => {
console.error('Error loading audio:', error);
});
The loadAllAudio()
method returns a Promise that resolves when all audio files are loaded.
Step 4: Playback Controls
Implement basic playback controls:
// Play the BeatBlock
beatblock.play();
// Pause playback
beatblock.pause();
// Stop playback and reset to beginning
beatblock.stop();
// Adjust master volume (0.0 to 1.0)
beatblock.setVolume(0.8);
Step 5: Event Handling
Listen for events to update your UI or trigger actions:
// Loading progress and info events
beatblock.on('info', (message) => {
console.log(`Info: ${message}`);
});
beatblock.on('error', (errorMessage) => {
console.error(`Error: ${errorMessage}`);
});
// Playback state changes
beatblock.on('end', (message) => {
console.log('Playback ended:', message);
document.getElementById('play-button').classList.remove('active');
});
// You can also listen for other events
beatblock.on('beat', (beatNumber) => {
console.log(`Current beat: ${beatNumber}`);
// Flash beat indicator
document.getElementById('beat-indicator').classList.add('flash');
setTimeout(() => {
document.getElementById('beat-indicator').classList.remove('flash');
}, 100);
});
beatblock.on('bar', (barNumber) => {
console.log(`Current bar: ${barNumber}`);
document.getElementById('bar-counter').textContent = barNumber;
});
Step 6: Inscribing to Bitcoin
To inscribe your BeatBlock to the Bitcoin blockchain:
Export your BeatBlock JSON
// Get the complete BeatBlock JSON const beatblockJson = beatblock.getBeatBlockData(); // Save to file or copy to clipboard const jsonString = JSON.stringify(beatblockJson, null, 2);
Use an Ordinals wallet to inscribe
# Using the ord CLI tool ord wallet inscribe beatblock.json \ --fee-rate 10 \ --content-type application/json
Once inscribed, your BeatBlock will have a unique inscription ID that can be used to retrieve and play it.
Complete Example
Here's a complete example that puts everything together:
// Initialize audio context and BeatBlock
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const beatblock = new BeatBlock(audioContext);
// Define song data
const songData = {
"details": {
"title": "Cosmic Rhythms",
"author": "RareScrilla, Bunzy, Hathbanger, ShowerShoes",
"bpm": 125,
"imgId": "<INSCRIPTION_ID>"
},
"generationConfig": {
"seed": "custom-upload",
"groups": ["v1", "v2", "v3", "v4"],
"mutexes": ["drums"]
},
"layers": [
{
"id": "ambient_pad",
"name": "Ambient Pad",
"loopLength": 1,
"path": "/content/<INSCRIPTION_ID>",
"volume": 1,
"loop": true,
"alignment": "end",
"groups": [],
"mutex": ["pads"]
},
{
"id": "main_beat",
"name": "Main Beat",
"loopLength": 4,
"path": "/content/<INSCRIPTION_ID>",
"volume": 1,
"loop": true,
"alignment": "end",
"groups": ["v1"],
"mutex": ["drums"]
},
{
"id": "bass_line",
"name": "Bass Line",
"loopLength": 4,
"path": "/content/<INSCRIPTION_ID>",
"volume": 1,
"loop": true,
"alignment": "end",
"groups": ["v2"],
"mutex": ["bass"]
}
],
"template": [
{
"length": 8,
"layerCount": 3,
"inclusions": ["drums", "bass"],
"exclusions": ["melody", "vox"]
},
{
"length": 16,
"layerCount": 4,
"inclusions": ["drums", "bass", "melody"],
"exclusions": ["vox"]
}
]
};
// Set up UI event listeners
document.getElementById('play-button').addEventListener('click', () => beatblock.play());
document.getElementById('pause-button').addEventListener('click', () => beatblock.stop());
document.getElementById('stop-button').addEventListener('click', () => beatblock.stop());
// Initialize and load
async function init() {
try {
// Show loading indicator
document.getElementById('loading').style.display = 'block';
// Initialize with song data and listen for events
beatblock.on('info', (message) => {
console.log(`Info: ${message}`);
});
beatblock.on('error', (errorMessage) => {
console.error(`Error: ${errorMessage}`);
document.getElementById('error').textContent = errorMessage;
document.getElementById('error').style.display = 'block';
});
beatblock.on('end', (message) => {
console.log('Playback ended:', message);
document.getElementById('play-button').classList.remove('active');
});
// Initialize the BeatBlock with song data
await beatblock.initialize(songData);
// Hide loading indicator
document.getElementById('loading').style.display = 'none';
document.getElementById('controls').style.display = 'block';
// Listen for beat and bar events
beatblock.on('beat', (beatNumber) => {
document.getElementById('beat-indicator').classList.add('flash');
setTimeout(() => {
document.getElementById('beat-indicator').classList.remove('flash');
}, 100);
});
beatblock.on('bar', (barNumber) => {
document.getElementById('bar-counter').textContent = barNumber;
});
console.log('BeatBlock initialized and ready to play!');
} catch (error) {
console.error('Error initializing BeatBlock:', error);
document.getElementById('error').textContent = error.message;
document.getElementById('error').style.display = 'block';
}
}
// Start initialization
init();