На рис.8. слева представлены поля, где отображаются сгенерированные ноты и ритм. В обычном режиме эти поля недоступны для изменения. Но, если нажать на кнопку «Изменить» во вкладке «Сгенерированные», то включается режим редактирования, при котором блокируются некоторые элементы формы для корректного ввода данных. Окно в режиме редактирования показано на рис.9. При  этом  открываются  поля  с  нотами  и  ритмом. Теперь  мы  можем 

        Рис.9. Режим редактирования сгенерированной мелодии

редактировать эти поля. Но возникает вопрос: что означают цифры в этих полях?

Давайте разберемся с числами в поле «Ноты». Числами закодированы ноты, но не абсолютные их значения, а относительные: относительно тоники. 1 – это сама тоника. Далее числа означают порядковый номер полутона. Например, цифра 7 означает, что эта нота стоит на седьмом полутоне от тоники. Таким образом это увеличенная кварта от тоники. В блюзовой гамме это и есть тот самый блюзовый тон, который придает блюзу его характерное звучание. При выбранной тонике все ноты принимают конкретные значения. Теперь мы без труда сможем подправить нашу мелодию.

       Теперь рассмотрим поле «Ритм». Кодирование ритма было подробно рассмотрено в параграфе 2.5. Используя эти знания, мы можем смело отредактировать ритм мелодии по нашему усмотрению.

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

НЕ нашли? Не то? Что вы ищете?

Теперь пользователь может нажать на кнопку «Применить», которая появилась вместо кнопки «Изменить». Выскакивает диалоговое окно, где вам предлагается выбор: применить изменения или отменить их. При нажатии на кнопку «Отмена» все изменения, сделанные пользователем, отклоняются. Данный процесс представлен на рис.10.

                Рис.10. Подтверждение изменений

       После всех этих процедур пользователь может нажать на большую иконку дискеты для сохранения данной мелодии. После этого сохраненная мелодия помещается во вкладку «Сохраненные» и теперь пользователю доступны операции CRUD для этой категории.

3.3. Сохранение мелодии. Формат



       Мелодии сохраняются в текстовый файл. Выбор текстового файла обусловлен факторами:

Весь необходимый функционал доступен; Простота в использовании; Мелодию очень легко хранить в одной символьной строке, легко делать преобразования данных из нескольких массивов в одну символьную строку и наоборот; Текстовый файл занимает меньше памяти, чем база данных.

Конечно есть и минусы. После каждого изменения сохраненной мелодии происходит полная перезапись текстового файла. Но такой недостаток облегчается тем, что хранение мелодии требует небольшого объема памяти. И даже при большом количестве мелодий скорость остается высокой.

       Для хранения мелодий в программе предусмотрен текстовый файл Melodys. txt. Мелодия хранится в следующем формате:

название мелодии;гамма;ноты;ритм;

       Как мы видим, разделителем является «;». Вот пример хранения мелодии в текстовом файле:

2-ая мелодия;Minor;-1 11 8 4 3 4 -9 -8 ;1 1 1 1 1 0 0 1 1 0 1 ;

       В программе данные о мелодии хранятся в числовых массивах. За преобразование данных из программных объектов в текстовый формат отвечает класс Parser. Его реализация находится в одноименном файле. Вот пример самого простого метода в этом классе. Метод принимает на входе массив чисел, а на выходе дает строку чисел, разделенных пробелом.

public static string GetString(int[] massive)

  {

  string s = "";

  for (int i = 0; i < massive. Length; i++)

  {

  s += massive[i].ToString() + " ";

  }

  return s;

  }

       Приведем оставшиеся методы в виде сигнатур:

int[] GetMassive(string text) – преобразует строку в массив чисел.

List<Melody> GetAllMelodys() – считывает все мелодии из файла и возвращает список этих мелодий.

void SaveMelodyToFile(Melody melody) – сохраняет мелодию в файл.

void RewriteMelodysFile(List<Melody> list) – переписывает файл, беря за основу список list мелодий. Вызывается после редактирования сохраненных мелодий.

                               

Глава 4. Дополнения

                        4.1. Модульная арифметика



       Во многих местах, где имеется работа с массивом и какой-либо циклической структурой, мы можем наблюдать применение модульной арифметики. Суть её в том, что мы совершаем не обычное сложение. После сложения мы берем остаток от деления на модуль. Например, в машинном представлении данные хранятся в двоичном виде и иногда происходит побитовое сложение по модулю 2. Так называемый XOR. В данной работе имеется необходимость в применении модульной арифметики. Пример: алгоритм отображения сетки. Код программы:

for (int k = j; k < 16; k += scaleIntervals[index % scaleIntervals. Length]){…}

Индекс index массива scaleIntervals не может выходить за его пределы. Но нам нужно, чтобы после того, как значение индекса превысило допустимое значение, наш индекс начал свое движение заново. Для этого мы и используем взятие значения по модулю. Везде, где встречается свойство цикличности, приходится прибегать к такому способу.

4.2. Многопоточность



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

       В языке С# предусмотрено удобное средство для работы с дополнительными потоками. Вот пример создания дополнительного потока перед вызовом метода PlayMelody().

task = Task. Run(() =>

  {

  Accompaniment. PlayAccord(tonica, generatedMelody. ScaleName, Direction. Down, outputDevice);

  Thread. Sleep(800);

  MelodyPlayer. PlayMelody(sd, generatedMelody, tonica, duration, grifNotes, buttons, cts. Token);

  if (!cts. Token. IsCancellationRequested)

  {

  Thread. Sleep(400);

  Accompaniment. PlayAccord(tonica, generatedMelody. ScaleName, Direction. Down, outputDevice);

  }

  }, cts. Token); 

       Параметром метода Task. Run() является анонимный метод, который вызывает методы проигрывания аккорда и метод PlayMelody(). Весь код внутри фигурных скобок анонимного метода выполняется параллельно с основным потоком, который находится в ожидании пользовательских действий.

       Метод PlayMelody() принимает на вход параметр cts. Token. Объект cts имеет тип CancellationTokenSource. Этот объект отправляет токену CancellationToken сигнал отмены. Таким образом мы можем послать потоку сигнал отмены, после которого поток может принять решение об окончании выполнения. Вот так в основном потоке мы посылаем сигнал второму потоку

if(cts!= null)

  cts. Cancel();

а в методе PlayMelody() мы можем перехватить этот сигнал и принять решение об окончании выполнения второстепенного потока.

static void PlayMelody(…)

{        …

       if (ct. IsCancellationRequested)

  return;

       …

}

       Здесь мы просто выходим из метода с помощью оператора безусловного перехода, но это и означает прекращение потока, так как поток выполняет только один метод.

       При создании дополнительного потока возникает известная проблема синхронизации. Элементы формы не могут изменяться в потоке, в котором они не были созданы. Для решения этой проблемы используются делегаты и метод Invoke(), который выполняет указанный делегат в том потоке, которому принадлежит базовый дескриптор окна элемента управления. Вот пример кода внутри метода PlayMelody(), в котором показана реализация выполнения изменений над элементами формы из дочернего потока.

if (Form1.ActiveForm. InvokeRequired)

  {

  Form1.ActiveForm. Invoke(new Action(() =>

  {

  if (!visible)

  button. Visible = false;

  if (Form1.ActiveForm!= null )

  Form1.ActiveForm. Refresh();

  }));

  }

       Вот таким образом осуществляется реализация многопоточности в данном приложении.

4.3. Анализ аналогов и сравнение



       В сети имеется большое количество проектов, посвященных генерации мелодий. В некоторых из них реализуется очень широкий функционал, позволяющий сгенерировать не просто основную мелодию, но даже сымитировать результат работы целого оркестра из всевозможных музыкальных инструментов. Такие генераторы могут по заказу пользователя сгенерировать мелодию по настроению: грустную, веселую, таинственную и так далее. В некоторых из них можно увидеть расширенные настройки, позволяющие сильнее взять под контроль процесс создания мелодии.

       Вот примеры некоторых проектов по генерированию мелодий

Автокомпозитор мелодий Muzz

Рис.11. Настройки в авоткомпозиторе Muzz



Онлайн генератор мелодий на сайте http://.

Это очень просто генератор. Очень простой генератор мелодий. Мелодия проигрывается в случайном порядке. Это простая музыкальная игра, которая понравится вам и вашим детям. Если вы искали игру с незатейливой и неповторяющейся мелодией, то эта флеш игра как раз предназначена для этого. Программа позволяет проигрывать звуки в случайном порядке. Некоторые мелодии веселые, а некоторые грустные. Генератор имеет оригинальный интерфейс в виде трехмерного куба. Когда шары внутри куба касаются его стенок, издается звук мелодии.

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11