Партнерка на США и Канаду по недвижимости, выплаты в крипто
- 30% recurring commission
- Выплаты в USDT
- Вывод каждую неделю
- Комиссия до 5 лет за каждого referral
}
else
{
SetLabelsNameNotesAndRhythm(generatedMelody);
MessageBox. Show("Эта мелодия уже сохранена!"); }}}
private void deleteSavedMelodyButton_Click(object sender, EventArgs e)
{
if (MessageBox. Show("Действительно хотите удалить мелодию\n\"" + savedMelody. Name + "(" + savedMelody. ScaleName. ToString() + ")\"" + "?", "Внимание", MessageBoxButtons. OKCancel) == DialogResult. OK)
{
savedMelodyList. Remove(savedMelody);
Parser. RewriteMelodysFile(savedMelodyList);
int i = savedMelodysComboBox. SelectedIndex;
savedMelodysComboBox. Items. RemoveAt(i);
if (i - 1 >= 0)
savedMelodysComboBox. SelectedIndex = i - 1; }}
private void editGeneratedMelodyButton_Click(object sender, EventArgs e)
{
if (!editGenerated && generatedMelody!= null)
{
editGeneratedMelodyButton. Text = "Применить";
nameTextBox. Text = generatedMelody. Name;
SetLabelsNameNotesAndRhythm(generatedMelody);
nameTextBox. Visible = true;
editGenerated = true;
SetEnable(false, SetEnableMode. Generated);
return;
}
if(editGenerated && generatedMelody!= null)
{
int[] notes = Parser. GetMassive(notesTextBox. Text);
int[] rhythm = Parser. GetMassive(rhythmTextBox. Text);
if (notes == null || rhythm == null)
{
MessageBox. Show("Неверный формат мелодии. Подробности смотрите в описании программы");
notesTextBox. Text = Parser. GetString(generatedMelody. Notes);
rhythmTextBox. Text = Parser. GetString(generatedMelody. Rhythm);
}
else
{
if (MessageBox. Show("Действительно хотите изменить мелодию\n\"" + generatedMelody. Name + "(" + generatedMelody. ScaleName. ToString() + ")\"" + "?", "Внимание", MessageBoxButtons. OKCancel) == DialogResult. OK)
{
RefreshListAndCombobox(generatedMelodyList, generatedMelody, generatedMelodysComboBox, notes, rhythm);
}
else
{
notesTextBox. Text = Parser. GetString(generatedMelody. Notes);
rhythmTextBox. Text = Parser. GetString(generatedMelody. Rhythm);
}
}
editGeneratedMelodyButton. Text = "Изменить";
nameTextBox. Visible = false;
editGenerated = false;
SetEnable(true, SetEnableMode. Generated); }}
private void tabControl_SelectedIndexChanged(object sender, EventArgs e)
{
if (editGenerated)
{
tabControl1.SelectedIndex = 0;
}
if (editSaved)
{
tabControl1.SelectedIndex = 1;
}
}
private void editSavedMelodyButton_Click(object sender, EventArgs e)
{
if (!editSaved && savedMelody!= null)
{
editSavedMelodyButton. Text = "Применить";
SetLabelsNameNotesAndRhythm(savedMelody);
nameTextBox. Text = savedMelody. Name;
nameTextBox. Visible = true;
editSaved = true;
SetEnable(false, SetEnableMode. Saved);
return;
}
if (editSaved && savedMelody!= null)
{
int[] notes = Parser. GetMassive(notesTextBox. Text);
int[] rhythm = Parser. GetMassive(rhythmTextBox. Text);
if (notes == null || rhythm == null)
{
MessageBox. Show("Неверный формат мелодии. Подробности смотрите в описании программы");
notesTextBox. Text = Parser. GetString(savedMelody. Notes);
rhythmTextBox. Text = Parser. GetString(savedMelody. Rhythm);
}
else
{
if (MessageBox. Show("Действительно хотите изменить мелодию\n\"" + savedMelody. Name + "(" + savedMelody. ScaleName. ToString() + ")\"" + "?", "Внимание", MessageBoxButtons. OKCancel) == DialogResult. OK)
{
RefreshListAndCombobox(savedMelodyList, savedMelody, savedMelodysComboBox, notes, rhythm);
Parser. RewriteMelodysFile(savedMelodyList);
}
else
{
notesTextBox. Text = Parser. GetString(savedMelody. Notes);
rhythmTextBox. Text = Parser. GetString(savedMelody. Rhythm);
}
}
editSavedMelodyButton. Text = "Изменить";
nameTextBox. Visible = false;
editSaved = false;
SetEnable(true, SetEnableMode. Saved);
}
}
private void stopButton_Click(object sender, EventArgs e)
{
if(cts!= null)
cts. Cancel();
outputDevice. SilenceAllNotes();
SetEnable(true, SetEnableMode. All);
timer. Stop(); }
private void timer_Tick(object sender, EventArgs e)
{
if (task!= null)
{
if (task. IsCanceled || task. IsCompleted)
{
SetEnable(true, SetEnableMode. All);
timer. Stop();
}
}
}
public void RefreshListAndCombobox(List<Melody> list, Melody melody, ComboBox cmb, int[] notes, int[] rhythm)
{
int i = list. IndexOf(melody);
cmb. Items. RemoveAt(i);
cmb. Items. Insert(i, nameTextBox. Text + "(" + melody. ScaleName. ToString() + ")");
int j = list. IndexOf(melody);
list. RemoveAt(i);
melody = new Melody(nameTextBox. Text, notes, rhythm, melody. ScaleName);
list. Insert(j, melody);
/* Здесь срабатывает событие и меняется значение notesCountTextBox */
cmb. SelectedIndex = i;
nameLabel. Text = melody. Name + "(" + melody. ScaleName. ToString() + ")";
}
}
Заключение
Можно с большой долей уверенности считать, что цель данной дипломной работы была достигнута. В процессе работы было разработано приложение, способное генерировать случайные мелодии с заданными параметрами: количество нот, стиль, темп, тоника. Приложение имеет удобный и интуитивно понятный интерфейс. Также имеется наглядная демонстрация проигрывания мелодий путем подсвечивания проигрываемых нот на гитарном грифе. Приложение работает в двух потоках. Основной поток реагирует на пользовательские действия и постоянно находится в режиме ожидания этих действий. Во втором потоке происходит проигрывание сгенерированных или сохраненных мелодий. В приложении был реализован полный CRUD мелодий. Таким образом мелодию можно не только сгенерировать, но и изменить, сохранить и удалить её.
Безусловно, более важным этапом являлся этап моделирования и формального описания предметной области. На данном уровне предметная область была детально изучена и описана. Были выделены основные сущности и их связи. Был применен достаточный уровень абстракции, позволяющий не потерять смысл всего процесса.
Конечный результат получился достаточно приемлемым для проблемы такого уровня. Мелодии генерируются в необходимой степени благозвучные.
В процессе работы была разработана система машинного представления мелодии, музыкальных ладов, ритма. Были разработаны алгоритмы генерации нот по определенному звукоряду, алгоритмы генерации ритма, алгоритм построения аппликатурной сетки по музыкальному ладу.
Стоит отметить, однако, что мелодии не всегда могут показаться нам приятными для слуха. Попробуем ответить на вопрос: хорошо это или плохо.
Стоит вспомнить рассуждения, касающиеся степени свободы генератора. Первая мысль такова: чем больше правил мы сможем выявить и формализовать, тем лучше. Но было сказано про баланс между количеством правил и степенью свободы, которую мы должны дать нашему генератору мелодий. Таким образом было принято решение взять только определенный набор правил, необходимый для того, чтобы мелодия принадлежала пространству мелодий данного музыкального лада. Но не давалось никаких намёков на более конкретную структуру мелодии для того, чтобы избежать шаблонности.
В процессе разработки мы столкнулись с проблемой блокирования пользовательского интерфейса в связи с тем, что воспроизведение мелодии занимало основной поток своим выполнением. Для решения этой проблемы очевидным стало создание второго потока, в котором выполнялось воспроизведение мелодии. Основной поток приложения стал свободным и использовался теперь для того, чтобы постоянно находиться в режиме ожидания пользовательских действий.
В начале проектирования архитектуры приложения было не совсем понятно, в каком виде хранить мелодию. Для этого был создан класс Melody. Параметрами его конструктора служили название мелодии, ноты, ритм, название лада. Таким образом мелодия состоит из нот и ритма. Ноты берутся из гаммы музыкального лада, который задан. Причем ноты имеют не абсолютное значение, а относительное. Они указываются относительно тоники: нашей точки отсчета. Так достигается гибкость, так как наша мелодия не зависит от тоники, которую мы укажем, и мы можем проигрывать нашу мелодию от любой начальной ноты. Такое решение кажется наиболее гибким.
Также было неясно, как представлять и генерировать ритм. Хотя после того, как решение получено, кажется, что оно очевидное и единственно верное.
Ритм – совокупность нот и пауз. Первая мысль – хранить эти длительности нот и пауз в виде промежутков времени. Но наилучшим вариантом является хранение двоичных векторов, как это и сделано в нашем приложении. Таким образом время всей мелодии делится на равные доли, и каждая доля имеет своё соответствующее значение в двоичном векторе. 1 – играется нота, 0 – пауза. При таком проектировании опять же достигается гибкость, так как темп мелодии никак не будет зависеть от ритма. Получается, что мелодия не зависит ни от тоники, ни от темпа, что и соответствует действительности. В самом деле, мелодия ни коим образом не зависит от выбранной тоники и от темпа. При изменении этих параметров, мелодия остается прежней. Все эти нюансы учитывались при разработке приложения.
Для задания стиля мелодии использовались названия музыкальных ладов, и, следовательно, стиль полностью определяется набором нот из гаммы выбранного звукоряда. Конечно, стиль определяется и другими параметрами, например, ритмом и приемами игры. Но в данной работе эти параметры не учитываются, что, безусловно, дает мотивацию для дальнейших усовершенствований.
Правда, остались нерешенными некоторые интересные задачи, ставшие следствием нашей работы. Открытым остался вопрос гармонизации мелодии. Наша мелодия не зависит от аккомпанемента. Таким образом можно было бы разрабатывать алгоритм генерации мелодии, которая зависит от играющего в аккомпанементе аккорда. Но тогда пришлось быть значительно менять алгоритм генерации. Вместо этого лучше было бы предпочесть другой вариант: предлагать аккомпанемент по уже сгенерированной мелодии.
Приложение является законченным продуктом с достаточным набором функций. Однако оно может быть расширено. Не представляет труда пополнить список музыкальных ладов. В данной работе был реализован только небольшой список, но архитектура приложения позволяет без труда добавить большее количество ладов. Конечно, в перспективе наилучшим вариантом будет возможность добавления ладов самим пользователем. Также существуют варианты для реализации аккомпанемента, о котором было сказано чуть выше. Множество идей может быть реализовано, так как тема генерации мелодий довольно обширна. Мы же рассмотрели эту проблему только с одной стороны: стороны генерации основной мелодии произведения. Также существуют проблемы гармонизации и многие другие проблемы, которые требуют тщательного анализа и изучения.
Список литературы
Гуриков, в программирование на языке Visual C#/.- М.:Инфра-М, 2013. - 448 c
Молотков, импровизация на шестиструнной гитаре /.-Киев.:Музычна Украйина,1989.-150с.
Приемы объектно-ориентированного программирования. Паттерны проектирования /Э. Гамма, Р. Хелм, Р. Джносон и др.-СПб.:Питер,2001.-368с.
Рихтер, Д. CLR via C#. Программирование на платформе Framework 4.5 на языке C# /Д. Рихтер.-СПб.:Питер, 2013. - 896 c.
Русаков, импровизатора /.-М., 2013.-80с.
Стиллмен, Э. Изучаем C# /Э. Стиллмен, Дж. Грин.-СПб.:Питер, 2012.-696с.
Фленов, C# /.-СПб.:Питер, 2011. - 560 c.
Чакон, С. Git для профессионального программиста /С. Чакон, Б. Штрауб.-СПб.:Питер,2016.-496с.
Шилдт, Г. С#: Полное руководство /Г. Шилдт.-М.:Вильямс, 2011.-1056с.
1 екреты импровизатора, 2013, с.19.
2 екреты импровизатора, 2013, с.19.
3 Михаил Русаков «Секреты импроивзатора»
4 C# Полное руководство
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 |


