Назирокодил утилиту на Kotlin и JavaScript для создания аккордов в любой тональности. JavaScript.. JavaScript. Kotlin.. JavaScript. Kotlin. zerocode.. JavaScript. Kotlin. zerocode. zerocoding.. JavaScript. Kotlin. zerocode. zerocoding. ИИ.. JavaScript. Kotlin. zerocode. zerocoding. ИИ. искуственный интеллект.. JavaScript. Kotlin. zerocode. zerocoding. ИИ. искуственный интеллект. музыкальная теория.. JavaScript. Kotlin. zerocode. zerocoding. ИИ. искуственный интеллект. музыкальная теория. музыкальные сервисы.. JavaScript. Kotlin. zerocode. zerocoding. ИИ. искуственный интеллект. музыкальная теория. музыкальные сервисы. Тестирование IT-систем.. JavaScript. Kotlin. zerocode. zerocoding. ИИ. искуственный интеллект. музыкальная теория. музыкальные сервисы. Тестирование IT-систем. цепочка аккордов.

Пробовали когда-нибудь сочинять свои аккорды на гитаре, укулеле или на клавишных?
Не всякий аккорд подходить к любому другому, так? Например, ре-мажорный аккорд (D) не очень-то ладит с фа-минорным (Fm). То есть просто “слепить” любые аккорды друг с другом в одну последовательность не получится. Тем более, что хочется, чтобы их было больше 2-х. И повторять до бесконечности Am Dm Em не хочется, так?
Для решения этой проблемки написал, используя ИИ, утилиту на JavaScript, доступную по URL:
https://6a1998fa8733707618d3a7e0–gregarious-flan-52fbaf.netlify.app/

Генератор аккордов. Текстовый веб-интерфейс.
Генератор аккордов. Текстовый веб-интерфейс.

Но сначала по незнанию я сделал это на Kotlin :D
Утилиту сможете применить в вашем браузере. Если чешутся руки погенерить аккорды в более хардкорном режиме, мотайте сразу вниз на раздел “Как запустить утилиту Kotlin?”! В три простых действия получите аккорды.

Как я озадачился этим?

Пройдя курсы по муз. гармонии я разобрался, как подбирать сочетаемые аккорды и задумал сделать себе шпаргалку в виде программы. Давно я чаял идею написать утилиту для создания музыки и вот пришло моё время этим заняться.

Также в этой статье я хотел бы показать, как быстра может быть эволюция от идеи до готового кода с небездумным применением искусственного интеллекта (ИИ).

Почему именно ИИ+Kotlin?
Дело в том, что по работе у меня в road map (это, кто пока не в курсе, дорожная карта дел на год):

  • освоение ИИ в целях оптимизации тестирования;

  • написание автотестов в проекте на Kotlin.

Надо бы в этом всём прокачаться. Надо-надо… Надо подкачаться, вот и решил написать код на Kotlin с консультированием в текстовом чате с ИИ.

Причём тут аккорды?

Любая музыка – суть последовательность аккордов. Если глубже, то последовательность функциональных ступеней в разных комбинациях, подчинённых законам муз.гармонии, описанных уже давно Хуго Риманом и уточнённых его последователями, но мы не будем в этот раз слишком глубоко нырять в гармонию).

Нам пока достаточно того, что упрощённо музыка – последовательность аккордов. Стало быть, чтобы создать музыку нужно эту последовательность создать = сгенерировать.

Первый блин.com

Сперва я составил промпт для текстового ИИ-ассистента (Qwen):

Помоги в простом формате написать программу на Kotlin, которая:

  1. Запрашивает и принимает у пользователя набор аккордов (string-слов) через пробел.

    1. Если пользователь не задаёт, по дефолту используем базовую белоклавишную тональность ля-минор/до-мажор (именно в ней те самые “блатные аккорды”):
      Am Bdim С Dm Em F G.

  2. Уточняет сколько аккордов должно быть в последовательности: 2, 3, 4 или больше (по дефолту – 3)

  3. Выдаёт как финальный результат рандомную последовательность из предложенных пользователем аккордов.

  4. Предлагает повторить сценарий.

ИИ сгенерил код:

import kotlin.random.Random

fun main() {
    while (true) {
        // 1. Получаем аккорды от пользователя
        println("Введите аккорды через пробел (или нажмите Enter для использования по умолчанию):")
        val input = readLine()
        val chords = if (input.isNullOrBlank()) {
            listOf("Am", "Bdim", "C", "Dm", "Em", "F", "G")
        } else {
            input.split(" ").filter { it.isNotEmpty() }
        }

        if (chords.isEmpty()) {
            println("Нет аккордов для обработки. Попробуйте снова.")
            continue
        }

        // 2. Получаем количество аккордов в последовательности
        println("Сколько аккордов в последовательности? (2, 3, 4 или больше, по умолчанию 3):")
        val sequenceLength = try {
            val lengthInput = readLine()
            when {
                lengthInput.isNullOrBlank() -> 3
                else -> lengthInput.toIntOrNull() ?: 3
            }
        } catch (e: NumberFormatException) {
            3
        }

        // 3. Генерируем случайную последовательность
        val randomSequence = (1..sequenceLength).map {
            chords[Random.nextInt(chords.size)]
        }

        // 4. Выводим результат
        println("Случайная последовательность аккордов: ${randomSequence.joinToString(" ")}")

        // 5. Спрашиваем о повторении
        println("Хотите повторить? (y/n):")
        val repeat = readLine()?.lowercase()
        if (repeat != "y" && repeat != "yes") {
            break
        }
    }

    println("Спасибо за интерес к созданию музыки! Впереди всегда много интересного.")
}

Поскольку сначала хотелось прогнать код в браузере онлайн, а не в IDE (среде разработки), попробовал исполнить его в https://play.kotlinlang.org/. Взаимодействия через текстовый диалог, как я задумал, со мной не произошло: этот онлайн-компилятор не рассчитан на вводы пользователя. Зато сработал прописанный в коде механизм предварительно заданных (=дефолтных) значений. Выполнена цель генерации рандомных аккордов из “умолчательного” набора тональности ля-минор.

Вывод онлайн-компилятора. Диалога не получилось, но последовательность аккордов есть!

Вывод онлайн-компилятора. Диалога не получилось, но последовательность аккордов есть!

При уточнении в чате с ИИ, стало ясно, что дело в ограниченности исполнения кода в “песочнице” (play.kotlinlang.org/). ИИ предложил в этом онлайн-компиляторе исполнить упрощённый код:

import kotlin.random.Random

fun main() {
    // Используем стандартный набор аккордов
    val defaultChords = listOf("Am", "Bdim", "C", "Dm", "Em", "F", "G")
    val chords = defaultChords
    
    // Задаем длину последовательности
    val sequenceLength = 3
    
    // Генерируем случайную последовательность
    val randomSequence = (1..sequenceLength).map { 
        chords[Random.nextInt(chords.size)] 
    }
    
    // Выводим результат
    println("Случайная последовательность аккордов: ${randomSequence.joinToString(" ")}")
    
    println("Спасибо за неподдельное любопытство в создании музыки!")
}

Таким образом, вручную меняя значения в функции listOf из инициатора для значения defaultChords, можно без проблем получить желаемую случайную последовательность аккордов средствами Kotlin. Число аккордов в последовательности можно регулировать через значение sequenceLength.

Код получился лаконичный и интуитивно понятный, за что и любят язык программирования Kotlin. Однако в целом заставлять вчитываться в код – это не очень-то дружелюбно к пользователю, если он не знаком с программированием или алгоритмами. Не всем своим приятелям-музыкантам я могу дать в пользование такую утилиту. Вместе с ней нужно высылать пояснительные бригады, а их не напасёшься.

Я захотел сделать что-то более универсальное, гибкое и дружелюбное.
И кстати… откуда я взял изначальные аккорды? Почему именно такие? Гитаристы знают, что есть ещё и другие …

Можно масштабировать этот мой первый опыт для всех тональностей.

Утилита для любой тональности

Ах да, тональностей :D Упоминаю в седьмой раз тональность, но не расшифровываю, что ж…

Тональность – это (опять же упрощённо) набор из 7 нот. Наш с вами друг Иоган Себастьян Бах выбирал определённые 7 нот из 12 нот хроматического ряда. Да-да, нот далеко не 7! 😉 В каждой из тональностей он написал лютейшую красоту, разобранную музыкантами-наследниками на цитаты (см. и слушай “Хорошо темперированный клавир”).

7 нот тональности группируются в эдакие комплексы – трезвучия или всем известные аккорды. Мы в этом маленьком исследовании будем строить базовые трезвучия. Базовых трезвучий, ожидаемо для великих комбинаторов, – 7. Строятся они от каждой из нот по терциям (то есть упрощённо через одну белую клавишу на фортепиано). Короче говоря, в каждой тональности по 7 базовых аккордов.

Собственно таблица тональностей, с которой пользователь может легко и удобно взаимодействовать через простой ввод числа и буков, и является самым большим достижением моего диалога с ИИ.

За 2 простых действия выберите любую тональность, известную современной музыке

За 2 простых действия выберите любую тональность, известную современной музыке

Те, кто прошёл музыкальную школу жизни отметят, что таблица упорядочена по родственным тональностям, имеющим одинаковое число знаков при ключе (♯/♭), что достаточно удобненько само по себе.

Как это получилось?

В чате у ИИ я попросил дать возможность пошагово сгенерировать последовательность аккордов:

  1. Составить таблицу тональностей, и словарь их аккордов.

  2. Дать пользователю возможность выбирать тональность и получить набор её базовых аккордов.

  3. Выбрать аккорды и задать число их случайных появлений в последовательности.

  4. Пользователь имеет возможность повторить ключевые шаги программы, то есть пересоздать последовательность аккордов по-другому.

Тут я включу skip и перемотаю мои мытарства в диалоге с юным ИИ (я, кстати, сменил Qwen на Perplexity), не особо грамотным в муз.теории, а также в тестировании и отладке программы. Покажу вам сразу самую мякотку – готовую программу, которую можно успешно запустить, задав все нужные параметры на https://www.codechef.com/kotlin-online-compiler:

fun main() {
  val app = ChordSequenceGenerator()
  app.run()
}

class ChordSequenceGenerator {

  private enum class RepeatMode {
    SAME_CHORDS,
    SAME_KEY_NEW_CHORDS,
    NEW_KEY,
    EXIT
  }

  fun run() {
    println(
      "=== Генератор последовательностей аккордов ===n" +
        "В каждой тональности есть по 7 аккордов, связанных музыкльной гармонией.n" +
        "Давайте сгенерируем случайную последовательность аккордов в любой из тональностей!" +
        "*-dur - мажорные тональности, *-moll - минорныеn"
    )

    while (true) {
      try {
        val key = step1_chooseKey()
        var selectedChords = step2_chooseChords(key)
        var count = step3_askCount()

        while (true) {
          val sequence = generateSequence(selectedChords, count)
          displaySequence(sequence,key)

          when (step4_askRepeatMode()) {
            RepeatMode.SAME_CHORDS -> {
              continue
            }
            RepeatMode.SAME_KEY_NEW_CHORDS -> {
              selectedChords = step2_chooseChords(key)
              count = step3_askCount()
            }
            RepeatMode.NEW_KEY -> {
              break
            }
            RepeatMode.EXIT -> {
              println("Спасибо за использование!")
              return
            }
          }
        }
      } catch (e: Exception) {
        println("Ошибка: ${e.message}")
        if (!step5_askRepeatAfterError()) break
        println()
      }
    }

    println("Спасибо за использование!")
  }

  private fun step1_chooseKey(): String {
    println("Шаг 1: Выбор тональности")
    println()

    println("    № | Мажор (M)       | минор (m)       | Знаки альтерации")
    println("------|-----------------|-----------------|-----------------")

    val majors = mutableListOf<String>()
    val minors = mutableListOf<String>()

    Vocabulary.keyPairs.forEachIndexed { idx, (maj, min) ->
      majors.add(maj)
      minors.add(min)

      val sigMaj = Vocabulary.keySignatures[maj] ?: "?"
      val numMaj = idx + 1

      println(
        "${numMaj.toString().padStart(5)} | ${maj.padEnd(15)} | " +
          "${min.padEnd(15)} | $sigMaj"
      )
    }

    print("nВведите номер строки: ")
    val choice = readLine()?.toIntOrNull()

    if (choice != null && choice in 1..majors.size) {
      val index = choice - 1
      print("Мажор (M) или минор (m): ")
      val type = readLine()?.lowercase()?.trim()

      return if (type == "m" || type == "минор" || type == "moll") {
        minors[index]
      } else {
        majors[index]
      }
    }

    println("Неверный выбор, используется C-dur")
    return "C-dur"
  }

  private fun step2_chooseChords(key: String): List<String> {
    val availableChords = Vocabulary.allChords[key]
      ?: error("Неизвестная тональность: $key")

    println("nШаг 2: Доступные аккорды выбранной тональности: $key")
    availableChords.forEachIndexed { index, chord ->
      println("${index + 1}. $chord")
    }

    print("Введите номера аккордов через пробел (Enter для всех): ")
    val input = readLine()?.trim()

    if (input.isNullOrBlank()) {
      return availableChords
    }

    val selected = mutableListOf<String>()
    input.split("\s+".toRegex())
      .forEach { num ->
      val index = num.toIntOrNull()
      if (index != null && index in 1..availableChords.size) {
        selected.add(availableChords[index - 1])
      }
    }

    return if (selected.isEmpty()) availableChords else selected.distinct()
  }

  private fun step3_askCount(): Int {
    println("nШаг 3: количество аккордов в последовательности")
    print("Сколько аккордов в последовательности? (по умолчанию 4): ")
    val input = readLine()?.trim()
    return input?.toIntOrNull() ?: 4
  }

  private fun generateSequence(chords: List<String>, count: Int): List<String> {
    return (1..count).map { chords.random() }
  }

  private fun displaySequence(sequence: List<String>, key: String) {
    println("n=== Последовательность в $key, которую мы заслужили ===")
    sequence.chunked(4).forEach { chunk ->
      println(chunk.joinToString(" "))
    }
  }

  private fun step4_askRepeatMode(): RepeatMode {
    println("nЕщё?")
    println("1 — сгенерировать ещё раз с теми же аккордами")
    println("2 — выбрать другие аккорды в той же тональности")
    println("3 — выбрать новую тональность")
    println("4 — выйти")
    print("Ваш выбор: ")

    return when (readLine()?.trim()) {
      "1" -> RepeatMode.SAME_CHORDS
      "2" -> RepeatMode.SAME_KEY_NEW_CHORDS
      "3" -> RepeatMode.NEW_KEY
      "4" -> RepeatMode.EXIT
      else -> RepeatMode.EXIT
    }
  }

  private fun step5_askRepeatAfterError(): Boolean {
    println("nХотите попробовать снова? (y/n): ")
    val input = readLine()?.lowercase()?.trim()
    return input == "y" || input == "yes" || input == "д" || input == "да"
  }
}

object Vocabulary {

  val keySignatures = mapOf(
    // мажоры
    "C-dur"     to "0",
    "G-dur"     to "1♯",
    "D-dur"     to "2♯",
    "A-dur"     to "3♯",
    "E-dur"     to "4♯",
    "B-dur"     to "5♯",
    "C♭-dur"    to "7♭",
    "F♯-dur"    to "6♯",
    "G♭-dur"    to "6♭",
    "D♭-dur"    to "5♭",
    "C♯-dur"    to "7♯",
    "A♭-dur"    to "4♭",
    "E♭-dur"    to "3♭",
    "B♭-dur"    to "2♭",
    "F-dur"     to "1♭",

    // миноры
    "A-moll"    to "0",
    "E-moll"    to "1♯",
    "B-moll"    to "2♯",
    "F♯-moll"   to "3♯",
    "C♯-moll"   to "4♯",
    "G♯-moll"   to "5♯",
    "A♭-moll"   to "7♭",
    "E♭-moll"   to "6♭",
    "D♯-moll"   to "6♯",
    "B♭-moll"   to "5♭",
    "A♯-moll"   to "7♯",
    "F-moll"    to "4♭",
    "C-moll"    to "3♭",
    "G-moll"    to "2♭",
    "D-moll"    to "1♭"
  )

  val keyPairs = listOf(
    "C-dur" to "A-moll",
    "G-dur" to "E-moll",
    "D-dur" to "B-moll",
    "A-dur" to "F♯-moll",
    "E-dur" to "C♯-moll",
    "B-dur" to "G♯-moll",
    "C♭-dur" to "A♭-moll",
    "G♭-dur" to "E♭-moll",
    "F♯-dur" to "D♯-moll",
    "C♯-dur" to "A♯-moll",
    "D♭-dur" to "B♭-moll",
    "A♭-dur" to "F-moll",
    "E♭-dur" to "C-moll",
    "B♭-dur" to "G-moll",
    "F-dur" to "D-moll"
  )

  val allChords = mapOf(
    "C-dur" to listOf("C", "Dm", "Em", "F", "G", "Am", "B°"),
    "G-dur" to listOf("G", "Am", "Bm", "C", "D", "Em", "F♯°"),
    "D-dur" to listOf("D", "Em", "F♯m", "G", "A", "Bm", "C♯°"),
    "A-dur" to listOf("A", "Bm", "C♯m", "D", "E", "F♯m", "G♯°"),
    "E-dur" to listOf("E", "F♯m", "G♯m", "A", "B", "C♯m", "D♯°"),
    "B-dur" to listOf("B", "C♯m", "D♯m", "E", "F♯", "G♯m", "A♯°"),
    "F♯-dur" to listOf("F♯", "G♯m", "A♯m", "B", "C♯", "D♯m", "E♯°"),
    "C♯-dur" to listOf("C♯", "D♯m", "E♯m", "F♯", "G♯", "A♯m", "B♯°"),
    "C♭-dur" to listOf("C♭", "D♭m", "E♭m", "F♭", "G♭", "A♭m", "B♭°"),
    "G♭-dur" to listOf("G♭", "A♭m", "B♭m", "C♭", "D♭", "E♭m", "F°"),
    "D♭-dur" to listOf("D♭", "E♭m", "Fm", "G♭", "A♭", "B♭m", "C°"),
    "A♭-dur" to listOf("A♭", "B♭m", "Cm", "D♭", "E♭", "Fm", "G°"),
    "E♭-dur" to listOf("E♭", "Fm", "Gm", "A♭", "B♭", "Cm", "D°"),
    "B♭-dur" to listOf("B♭", "Cm", "Dm", "E♭", "F", "Gm", "A°"),
    "F-dur" to listOf("F", "Gm", "Am", "B♭", "C", "Dm", "E°"),

    "A-moll" to listOf("Am", "B°", "C", "Dm", "Em", "F", "G"),
    "E-moll" to listOf("Em", "F♯°", "G", "Am", "Bm", "C", "D"),
    "B-moll" to listOf("Bm", "C♯°", "D", "Em", "F♯m", "G", "A"),
    "F♯-moll" to listOf("F♯m", "G♯°", "A", "Bm", "C♯m", "D", "E"),
    "C♯-moll" to listOf("C♯m", "D♯°", "E", "F♯m", "G♯m", "A", "B"),
    "G♭-moll" to listOf("G♭m", "A♭°", "B♭", "C♭m", "D♭m", "E♭", "F"),
    "D♭-moll" to listOf("D♭m", "E♭°", "F", "G♭m", "A♭m", "B♭", "C"),
    "A♭-moll" to listOf("A♭m", "B♭°", "C♭", "D♭m", "E♭m", "F", "G"),
    "E♭-moll" to listOf("E♭m", "F°", "G♭", "A♭m", "B♭m", "C", "D"),
    "D♯-moll" to listOf("D♯m", "E♯°", "F♯", "G♯m", "A♯m", "B♭", "C♯"),
    "B♭-moll" to listOf("B♭m", "C°", "D♭", "E♭m", "Fm", "G", "A"),
    "A♯-moll" to listOf("A♯m", "B♯°", "C♯", "D♯m", "E♯m", "F♯", "G♯"),
    "F-moll" to listOf("Fm", "G°", "A♭", "B♭m", "Cm", "D", "E"),
    "C-moll" to listOf("Cm", "D°", "E♭", "Fm", "Gm", "A♭", "B♭"),
    "G-moll" to listOf("Gm", "A°", "B♭", "Cm", "Dm", "E♭", "F"),
    "D-moll" to listOf("Dm", "E°", "F", "Gm", "Am", "B♭", "C")
  )
}

Как запустить утилиту?

Программу выше можно скопировать и вставить в левое поле интерфейса codechef (1), …

Назирокодил утилиту на Kotlin и JavaScript для создания аккордов в любой тональности - 4

Собственно запуск происходит по нажатии на синюю кнопку Run.

Параметры для запуска можно задать в правом окне (2): каждой параметр (13, m и т.д.) на отдельной строке представляют собой ответы на вопросы из программы, где строки пронумерованы по порядку ввода:

Шаг 1: Выбор тональности:

  1. Введите номер строки:
    в примере 13

  2. Мажор (M) или минор (m):
    в примере m
    (если ничего не задать, оставив строку пустой будет Мажор)

    Шаг 2: Доступные аккорды выбранной тональности:

  3. Введите номера аккордов через пробел (Enter для всех):
    в примере 1 2 3 4 5 6 7 (но лучше для минора 2-ую ступень не выбирать ;) )
    (если ничего не задать, оставив строку пустой будут все 7 аккордов)

    Шаг 3: количество аккордов в последовательности

  4. Сколько аккордов в последовательности? (по умолчанию 4):
    в примере ничего не задано, просто по Enter оставил строку пустой.

  5. Дальше блок повторных вводов: там пока имеет смысл вводить только повторные генерации в той же тональности через ввод “1”. Я 3 раза ввёл “1” в своём примере и получил 3 последовательности.

    Входные параметры (Input) для взаимодействия с программой.

    Входные параметры (Input) для взаимодействия с программой.

Результат смотреть в нижней правой части экрана. Там можно промотать.

Итак, последовательности в выбранной мной тональности, которые я заслужил.

=== Последовательность в C-moll, которую мы заслужили ===
E♭ Fm E♭ Cm

Ещё?
1 — сгенерировать ещё раз с теми же аккордами
2 — выбрать другие аккорды в той же тональности
3 — выбрать новую тональность
4 — выйти

...
=== Последовательность в C-moll, которую мы заслужили ===
B♭ Cm Gm E♭

...

=== Последовательность в C-moll, которую мы заслужили ===
E♭ A♭ E♭ Gm

Умудрённые музыканты увидят, что первую из последовательностей утилита даже кононично закончила на тоническом трезвучии (T). Совпадение? В этом случае точно – да!

Попробовал сыграть все три последовательности на гитаре. Всё звучит классно! 🤘 🤘 🤘
Можно развивать последовательности, меняя ритмику, длительности игры аккорда и даже сам аккорд: был Xm – а стал Xm7 или Xm maj7 или Xsus2/4 или Xm9 или Xaug и т.д.).

Диезы и бемоли не пугают прошаренных гитаристов, ведь последние знают, что:

  • аппликатуры гитарного аккорда с бемолем (♭) левее на 1 лад своего “обычного” представления на грифе:
    например, E♭ ← E.

  • аппликатуры с диезом (♯) – правее на 1 лад:
    например, Em → E♯m.

Пути развития утилиты

  1. Чтобы сделать утилиту user-friendly, переписать её с Kotlin на JavaScript ✅
    https://6a1998fa8733707618d3a7e0–gregarious-flan-52fbaf.netlify.app/

  2. Разместить в GitHub ✅
    https://github.com/VedaIsanin/A-kordey/

  3. Добавить строгие ограничения по законам классической муз. гармонии

  4. Можно добавить и табулатуры аккордов, и иные представления аккордов

  5. Хотел подарить вам эту утилиту в виде Telegram-бота
    Научился разворачивать, подтягиваю зависимости либы com.github.kotlintelegrambot% через gradle и даже запустил бота с токеном от @BotFather из Телеграм, но, увы, сейчас Телега движется туго, надо как-то через прокси или не с российским IP разворачивать удалённо на сервере, поэтому реализация через ТГ-бот отложена.
    Бот в Макс только через ЮЛ, у меня только самозанятость оформлена пока.

Как использовать

  1. Индивидуальная практика в музыке. На вашем музыкальном инструменте сыграйте все(!) возможные аккорды – получите опыт и навык и хвастайтесь друзьям ачивкой!

  2. Практика в коллективе. Сыграйте с вашим рок-бэндом, докрутите последовательность, как вам надо – и играйте новые песни с вашими аккордами, ведь мне они не принадлежат, музыка – общее достояние.

  3. Можете “докрутить” сам код утилиты и сделать вашу утилиту, которая, например,

    1. будет генерировать последовательности по строгим законам гармонии (T-S-D) или допускать, как в блюзе нарушения строгости (T-D-S),

    2. будет давать некие отклонения или модуляции из тональности в тональность.

    3. Будет транспонировать цепочку сгенерированных аккордов (=переводить в другую тональность)

    4. … Ещё масса вариантов. Делитесь вашими идеями, и успехов в их реализации!

Желаю интересных генераций,
а также хорошей, неслучайной и – главное – качественной музыки!


Назирокодил утилиту на Kotlin и JavaScript для создания аккордов в любой тональности - 6

Дмитрий Исанин

Тестировщик ПО, сонграйтер и исполнитель, изучаю и применяю ИТ и ИИ для создания песен и музыки, а также озвучки

Про то, как делаю музыку в последние 2 года читайте статьи на Хабре:
https://habr.com/ru/users/Dmitry_Isanin/articles/,-
среди которых “Почему я выбрал Suno AI для создания мемного альбома «Вася Тестировщик»?”

Слушайте на всех популярных площадках мой альбом в духе хип-хопа
Лоскутное одеяло“: https://band.link/penchwork

А также альбом с утяжелённым звучанием гитар
Хлад металлов“: https://band.link/hlad_metallov

Также я публикуюсь и в других местах:
ВК: https://vk.com/dmisanin
Max: https://max.ru/join/eplS_t3xAWUrdsb52ojWxP3_gc1mbE3pE6c-Jv2-eE8
Telegram: https://t.me/shine_sean (Дзен прицепом)
Suno: https://suno.com/@dmisanin3
Sferoom: https://lk.sferoom.space/artists/117182/feed
Boosty: https://boosty.to/dmisanin (тут можно задонатить)
YouTube: https://www.youtube.com/@dmisanin (не забудьте про VPN)

Автор: Dmitry_Isanin

Источник