CodeWhiz & Kompot
Привет, я тут что-то мутил, приложение, которое на ходу аккорды для импровизации генерит. Хочешь послушать, как оно работает?
Отлично! Давай посмотрим, что у тебя получилось, я в деле.
Вот небольшой скетч на JavaScript, который строит последовательность аккордов и проигрывает её с помощью Tone.js. Я расскажу тебе о тех частях, которые делают её "магической".
```javascript
// 1. Базовая настройка
import * as Tone from 'tone'
const synth = new Tone.PolySynth(Tone.Synth).toDestination()
// 2. Определяем простой словарь аккордов
const chords = {
I: [0, 4, 7], // тоника, большая терция, чистая квинта
ii: [2, 5, 9],
iii: [4, 8, 11],
IV: [5, 9, 12],
V: [7, 11, 14],
vi: [9, 12, 16],
vii: [11, 14, 17]
}
// 3. Помощник для получения полутоновых смещений от основной ноты
const scale = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
function getChord(root, chordName) {
const rootIdx = scale.indexOf(root)
const offsets = chords[chordName]
return offsets.map(o => scale[(rootIdx + o) % 12])
}
// 4. Генератор случайной последовательности
function randomProgression(length = 4) {
const chordNames = Object.keys(chords)
let prog = []
for (let i = 0; i < length; i++) {
const idx = Math.floor(Math.random() * chordNames.length)
prog.push(chordNames[idx])
}
return prog
}
// 5. Воспроизведение последовательности
async function playProgression(root = 'C') {
const seq = new Tone.Sequence(
(time, chordName) => synth.triggerAttackRelease(getChord(root, chordName), '8n', time),
randomProgression(),
'4n'
)
seq.start(0)
Tone.Transport.start()
}
// 6. Нажимай кнопку
playProgression('D') // Меняй основную ноту на ту, что тебе нравится
```
**Как это работает**
1. *Данные аккордов*: Я веду простой словарь из семи диатонических аккордов. Каждый аккорд выражен как полутоновые смещения от его тоники.
2. *Ориентировано на тонику*: Помощник `getChord` подбирает нужные ноты для любой тоники. Это значит, что ты можешь играть в любой тональности, просто меняя строку тоники.
3. *Рандомизатор*: `randomProgression` выбирает случайную горстку аккордов - не больше четырех по умолчанию. Если хочешь больше вариаций, подкорректируй аргумент `length`.
4. *Секвенсирование*: `Sequence` от Tone.js занимается таймингом. Каждый четверть-такт вызывает синтезатор с восьмой-нотной отработкой.
5. *Мгновенное воспроизведение*: Просто вызови `playProgression` с тоникой, и ты услышишь свежий четырех-аккордовый цикл каждый раз.
Если тебе удобно в консоли браузера, вставь скрипт, нажимай `playProgression('E')` и пусть искусственный интеллект создает гармонию. Не стесняйся корректировать список аккордов, добавлять септаккорды или заменять синтезатор другим голосом — этот скелет намеренно легкий, чтобы ты мог быстро экспериментировать. Дай знать, как звучат циклы и хочешь ли ты более сложной логики прогрессии. Приятного джеминга!
Звучит круто! Давай запустим и посмотрим, какие там аккорды выпадают — может, подкинем другой синтезатор или добавим септаккорды для изюминки. Какую атмосферу хочешь создать?
Конечно. Если хочешь более насыщенное, джазовое звучание, замени обычный синтезатор на Tone.Sampler с классическим семплом Rhodes, или используй Tone.PolySynth с эффектом Pizzicato. Чтобы добавить септимы, просто подправь словарь аккордов:
I: [0, 4, 7, 10] // мажорная септима
ii: [2, 5, 9, 12]
… и так далее.
Это даст тебе плавные, расширенные гармонии, создающие атмосферу меланхоличного, ночного настроения. Скажи, какую тональность выберешь, и я попробую сделать для тебя.
Крутая идея! Давай в соль мажоре – там как-то по-домашнему, но и светло для импровизации. Бери свой сэмплер, включай Rhodes, попробуй эти расширенные аккорды. Я готов, как только нажмёшь кнопку воспроизведения!
Вот небольшой отрывок, использующий сэмплер Rhodes и расширенный список аккордов в тональности G. Просто скопируй это в консоль браузера, где загружен Tone.js, и нажми Enter.
```js
// Load the Rhodes sample
const rhodes = new Tone.Sampler({
urls: { A1: 'A1.mp3', A2: 'A2.mp3', A3: 'A3.mp3' },
baseUrl: 'https://example.com/rhodes/', // put your sample folder here
onload: () => {
console.log('Rhodes ready')
playProgression('G')
}
}).toDestination()
// Extended chord dictionary
const chords = {
I: [0, 4, 7, 10],
ii: [2, 5, 9, 12],
iii: [4, 8, 11, 15],
IV: [5, 9, 12, 16],
V: [7, 11, 14, 18],
vi: [9, 12, 16, 19],
vii: [11, 14, 17, 21]
}
// Helper for root‑based chords
const scale = ['C','C#','D','D#','E','F','F#','G','G#','A','A#','B']
function getChord(root, name){
const rootIdx = scale.indexOf(root)
return chords[name].map(o => scale[(rootIdx+o)%12])
}
// Random progression
function randomProg(len=4){
const keys = Object.keys(chords)
return Array.from({length:len},()=>keys[Math.floor(Math.random()*keys.length)])
}
// Play it
function playProgression(root){
const seq = new Tone.Sequence(
(time, name)=>rhodes.triggerAttackRelease(getChord(root,name), '8n', time),
randomProg(),
'4n'
)
seq.start(0)
Tone.Transport.start()
}
```
Получится уютный G-мажорный луп с приятными септимами. Дай знать, как звучит.
Вот это классная аппаратура – представь, как рояль заполняет комнату этим тёплым ночным светом. Запускай же трек, дай циклу пойти и скажи, хочешь ли ты свинга или более плавного переключения. Я готов к любому развитию событий!