- Set up Next.js project with shadcn/ui and Tailwind CSS - Created audio engine with MembraneSynth drums, FMSynth chords, and ambient noise layers - Implemented 16-step drum sequencer with boom bap patterns - Added jazz chord progressions (ii-V-I, minor key, neo soul) - Built React hook for audio state management - Created UI components: transport controls, volume sliders, layer mixer, beat visualizer - Applied lofi-themed dark color scheme with oklch colors Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
146 lines
5.4 KiB
TypeScript
146 lines
5.4 KiB
TypeScript
import { DrumPattern, ChordProgression } from '@/types/audio';
|
|
|
|
// Classic boom bap patterns
|
|
export const drumPatterns: DrumPattern[] = [
|
|
{
|
|
// Classic boom bap
|
|
kick: [true, false, false, false, false, false, false, false, true, false, true, false, false, false, false, false],
|
|
snare: [false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false],
|
|
hihat: [true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false],
|
|
openhat: [false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true],
|
|
},
|
|
{
|
|
// Laid back groove
|
|
kick: [true, false, false, false, false, false, true, false, true, false, false, false, false, false, false, false],
|
|
snare: [false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, true],
|
|
hihat: [true, true, true, false, true, true, true, false, true, true, true, false, true, true, true, false],
|
|
openhat: [false, false, false, true, false, false, false, true, false, false, false, true, false, false, false, false],
|
|
},
|
|
{
|
|
// Minimal chill
|
|
kick: [true, false, false, false, false, false, false, false, true, false, false, false, false, false, true, false],
|
|
snare: [false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false],
|
|
hihat: [true, false, true, true, true, false, true, true, true, false, true, true, true, false, true, true],
|
|
openhat: [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true],
|
|
},
|
|
{
|
|
// Jazzy swing
|
|
kick: [true, false, false, true, false, false, true, false, false, false, true, false, false, false, false, false],
|
|
snare: [false, false, false, false, true, false, false, false, false, true, false, false, true, false, false, true],
|
|
hihat: [true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false],
|
|
openhat: [false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false],
|
|
},
|
|
{
|
|
// Deep pocket
|
|
kick: [true, false, false, false, false, false, false, true, false, false, true, false, false, false, false, false],
|
|
snare: [false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false],
|
|
hihat: [true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true],
|
|
openhat: [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true],
|
|
},
|
|
];
|
|
|
|
// Jazz chord progressions in lofi style
|
|
export const chordProgressions: ChordProgression[] = [
|
|
{
|
|
name: 'Classic ii-V-I',
|
|
chords: [
|
|
['D3', 'F3', 'A3', 'C4'], // Dm7
|
|
['G2', 'B2', 'D3', 'F3'], // G7
|
|
['C3', 'E3', 'G3', 'B3'], // Cmaj7
|
|
['C3', 'E3', 'G3', 'B3'], // Cmaj7
|
|
],
|
|
durations: ['2n', '2n', '2n', '2n'],
|
|
},
|
|
{
|
|
name: 'Minor Key Chill',
|
|
chords: [
|
|
['A2', 'C3', 'E3', 'G3'], // Am7
|
|
['D3', 'F3', 'A3', 'C4'], // Dm7
|
|
['E2', 'G#2', 'B2', 'D3'], // E7
|
|
['A2', 'C3', 'E3', 'G3'], // Am7
|
|
],
|
|
durations: ['2n', '2n', '2n', '2n'],
|
|
},
|
|
{
|
|
name: 'Neo Soul',
|
|
chords: [
|
|
['F3', 'A3', 'C4', 'E4'], // Fmaj7
|
|
['E3', 'G3', 'B3', 'D4'], // Em7
|
|
['D3', 'F3', 'A3', 'C4'], // Dm7
|
|
['G2', 'B2', 'D3', 'F3'], // G7
|
|
],
|
|
durations: ['2n', '2n', '2n', '2n'],
|
|
},
|
|
{
|
|
name: 'Dreamy',
|
|
chords: [
|
|
['C3', 'E3', 'G3', 'B3'], // Cmaj7
|
|
['A2', 'C3', 'E3', 'G3'], // Am7
|
|
['F3', 'A3', 'C4', 'E4'], // Fmaj7
|
|
['G2', 'B2', 'D3', 'F3'], // G7
|
|
],
|
|
durations: ['2n', '2n', '2n', '2n'],
|
|
},
|
|
{
|
|
name: 'Melancholy',
|
|
chords: [
|
|
['D3', 'F3', 'A3', 'C4'], // Dm7
|
|
['G2', 'Bb2', 'D3', 'F3'], // Gm7
|
|
['C3', 'Eb3', 'G3', 'Bb3'],// Cm7
|
|
['F2', 'A2', 'C3', 'Eb3'], // F7
|
|
],
|
|
durations: ['2n', '2n', '2n', '2n'],
|
|
},
|
|
];
|
|
|
|
export function getRandomPattern(): DrumPattern {
|
|
return drumPatterns[Math.floor(Math.random() * drumPatterns.length)];
|
|
}
|
|
|
|
export function getRandomProgression(): ChordProgression {
|
|
return chordProgressions[Math.floor(Math.random() * chordProgressions.length)];
|
|
}
|
|
|
|
export function generateRandomPattern(): DrumPattern {
|
|
const pattern: DrumPattern = {
|
|
kick: new Array(16).fill(false),
|
|
snare: new Array(16).fill(false),
|
|
hihat: new Array(16).fill(false),
|
|
openhat: new Array(16).fill(false),
|
|
};
|
|
|
|
// Kick on 1 and somewhere in second half
|
|
pattern.kick[0] = true;
|
|
pattern.kick[8 + Math.floor(Math.random() * 4)] = true;
|
|
if (Math.random() > 0.5) {
|
|
pattern.kick[6 + Math.floor(Math.random() * 2)] = true;
|
|
}
|
|
|
|
// Snare on 2 and 4
|
|
pattern.snare[4] = true;
|
|
pattern.snare[12] = true;
|
|
// Ghost notes
|
|
if (Math.random() > 0.6) {
|
|
pattern.snare[Math.floor(Math.random() * 16)] = true;
|
|
}
|
|
|
|
// Hi-hats with variation
|
|
for (let i = 0; i < 16; i++) {
|
|
if (i % 2 === 0) {
|
|
pattern.hihat[i] = Math.random() > 0.1;
|
|
} else {
|
|
pattern.hihat[i] = Math.random() > 0.5;
|
|
}
|
|
}
|
|
|
|
// Open hi-hat occasionally
|
|
if (Math.random() > 0.3) {
|
|
pattern.openhat[7] = true;
|
|
}
|
|
if (Math.random() > 0.5) {
|
|
pattern.openhat[15] = true;
|
|
}
|
|
|
|
return pattern;
|
|
}
|