From 57f96c261c98948be52e6a98732bce0fd504767b Mon Sep 17 00:00:00 2001 From: mallang7 <52442878+mallang7@users.noreply.github.com> Date: Fri, 11 Dec 2020 14:32:30 +0900 Subject: [PATCH 1/2] Add files via upload --- MarkovMusic-master/README.md | 15 + MarkovMusic-master/main.ipynb | 259 +++++++++++++++++ .../midi/Debussy_Reverie_945834_1.mid | Bin 0 -> 2711 bytes MarkovMusic-master/midi/random_debussy.mid | Bin 0 -> 897 bytes MarkovMusic-master/midi/random_mix.mid | Bin 0 -> 3746 bytes MarkovMusic-master/midi/random_mix_good.mid | Bin 0 -> 3754 bytes MarkovMusic-master/midi/random_rowboat.mid | Bin 0 -> 796 bytes MarkovMusic-master/midi/random_synth_solo.mid | Bin 0 -> 447 bytes MarkovMusic-master/midi/random_undertail.mid | Bin 0 -> 751 bytes MarkovMusic-master/midi/synth_solo_73708.mid | Bin 0 -> 2360 bytes MarkovMusic-master/midi/undertail_155475.mid | Bin 0 -> 614 bytes MarkovMusic-master/readmidi.py | 262 ++++++++++++++++++ MarkovMusic-master/src/MarkovBuilder.py | 49 ++++ MarkovMusic-master/src/MarkovMusic.py | 109 ++++++++ .../__pycache__/MarkovBuilder.cpython-35.pyc | Bin 0 -> 2341 bytes .../__pycache__/MarkovMusic.cpython-35.pyc | Bin 0 -> 2925 bytes 16 files changed, 694 insertions(+) create mode 100644 MarkovMusic-master/README.md create mode 100644 MarkovMusic-master/main.ipynb create mode 100644 MarkovMusic-master/midi/Debussy_Reverie_945834_1.mid create mode 100644 MarkovMusic-master/midi/random_debussy.mid create mode 100644 MarkovMusic-master/midi/random_mix.mid create mode 100644 MarkovMusic-master/midi/random_mix_good.mid create mode 100644 MarkovMusic-master/midi/random_rowboat.mid create mode 100644 MarkovMusic-master/midi/random_synth_solo.mid create mode 100644 MarkovMusic-master/midi/random_undertail.mid create mode 100644 MarkovMusic-master/midi/synth_solo_73708.mid create mode 100644 MarkovMusic-master/midi/undertail_155475.mid create mode 100644 MarkovMusic-master/readmidi.py create mode 100644 MarkovMusic-master/src/MarkovBuilder.py create mode 100644 MarkovMusic-master/src/MarkovMusic.py create mode 100644 MarkovMusic-master/src/__pycache__/MarkovBuilder.cpython-35.pyc create mode 100644 MarkovMusic-master/src/__pycache__/MarkovMusic.cpython-35.pyc diff --git a/MarkovMusic-master/README.md b/MarkovMusic-master/README.md new file mode 100644 index 0000000..3fac956 --- /dev/null +++ b/MarkovMusic-master/README.md @@ -0,0 +1,15 @@ +# Markov Music + +A markov chain based VERY simplistic procedural music generator. +**Click link to watch [demo video](https://youtu.be/qjFFPDLDLEo)!** + +## Improvements + +- Python 3 compatible +- Auto generate adjacency list (Markov matrix) + +## Dependencies +- Python +- numpy +- pyknon https://github.com/kroger/pyknon +- pysynth https://github.com/mdoege/PySynth diff --git a/MarkovMusic-master/main.ipynb b/MarkovMusic-master/main.ipynb new file mode 100644 index 0000000..b0fe566 --- /dev/null +++ b/MarkovMusic-master/main.ipynb @@ -0,0 +1,259 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "##import pysynth as ps\n", + "from pyknon.genmidi import Midi\n", + "from pyknon.music import NoteSeq, Note, Rest\n", + "from src.MarkovMusic import MusicMatrix\n", + "from pprint import pprint" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "def make_midi(midi_path, notes, bpm=120):\n", + " note_names = 'c c# d d# e f f# g g# a a# b'.split()\n", + "\n", + " result = NoteSeq()\n", + " for n in notes:\n", + " duration = 1. / n[1]\n", + "\n", + " if n[0].lower() == 'r':\n", + " result.append(Rest(dur=duration))\n", + " else:\n", + " pitch = n[0][:-1]\n", + " octave = int(n[0][-1]) + 1\n", + " pitch_number = note_names.index(pitch.lower())\n", + " \n", + " result.append(Note(pitch_number, octave=octave, dur=duration))\n", + " \n", + " midi = Midi(number_tracks=1, tempo=bpm)\n", + " midi.seq_notes(result, track=0)\n", + " midi.write(midi_path)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Row Row Row Your Boat" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "song = [['c4', 4], ['c4', 4], ['c4', 4], ['d4', 8], ['e4', 4], ['e4', 4], ['d4', 8], ['e4', 4], ['f4', 8], ['g4', 2], ['c4', 8], ['c4', 8], ['c4', 8], ['g4', 8], ['g4', 8], ['g4', 8], ['e4', 8], ['e4', 8], ['e4', 8], ['c4', 8], ['c4', 8], ['c4', 8], ['g4', 4], ['f4', 8], ['e4', 4], ['d4', 8], ['c4', 2]]\n", + "\n", + "#ps.make_wav(song, fn='examples/test.wav')" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "matrix = MusicMatrix(song)\n", + "\n", + "start_note = ['c4', 4]\n", + "\n", + "random_song = []\n", + "for i in range(0, 100):\n", + " start_note = matrix.next_note(start_note)\n", + " random_song.append(start_note)\n", + "\n", + "# ps.make_wav(random_song, fn='examples/random.wav')\n", + "make_midi(midi_path='midi/random_rowboat.mid', notes=random_song)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Undertail" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "song = [('g#3', 16.0), ('e4', 16.0), ('d#4', 16.0), ('d4', 16.0), ('d#4', 16.0), ('r', 16.0), ('c#4', 16.0), ('b3', 16.0), ('a#3', 16.0), ('r', 16.0), ('g#3', 16.0), ('g3', 16.0), ('g#3', 16.0), ('r', 16.0), ('d#3', 16.0), ('e3', 16.0), ('d#3', 16.0), ('e3', 16.0), ('d#3', 16.0), ('d3', 16.0), ('d#3', 16.0), ('g3', 16.0), ('b3', 16.0), ('a#3', 16.0), ('g#3', 16.0), ('r', 16.0), ('g#3', 16.0), ('a#3', 16.0), ('b3', 16.0), ('r', 16.0), ('a#3', 16.0), ('b3', 16.0), ('c#4', 16.0), ('r', 16.0), ('b3', 16.0), ('a#3', 16.0), ('g3', 16.0), ('r', 16.0), ('g3', 16.0), ('a#3', 16.0), ('b3', 16.0), ('r', 16.0), ('a#3', 16.0), ('g#3', 16.0), ('d#3', 16.0), ('r', 16.0), ('d#3', 16.0), ('e3', 16.0), ('d#3', 16.0), ('e3', 16.0), ('d#3', 16.0), ('d3', 16.0), ('d#3', 16.0), ('g3', 16.0), ('b3', 16.0), ('a#3', 16.0), ('g#3', 16.0), ('r', 16.0), ('g#3', 16.0), ('g3', 16.0), ('g#3', 16.0), ('r', 16.0), ('g#4', 16.0)]\n", + "\n", + "# ps.make_wav(song, fn='examples/undertail.wav')\n", + "\n", + "matrix = MusicMatrix(song)\n", + "\n", + "start_note = ['d4', 16]\n", + "\n", + "random_song = []\n", + "for i in range(0, 100):\n", + " start_note = matrix.next_note(start_note)\n", + " random_song.append(start_note)\n", + "\n", + "# ps.make_wav(random_song, fn='examples/random_undertail.wav')\n", + "\n", + "make_midi(midi_path='midi/random_undertail.mid', notes=random_song)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Debussy - Reverie" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "song = [('g5', 2.0), ('d5', 1.3333333333333333), ('e5', 8.0), ('f5', 8.0), ('g5', 4.0), ('e5', 8.0), ('d5', 8.0), ('e5', 5.333333333333333), ('c5', 5.314878892780648), ('e5', 5.314878892710022), ('d5', 1.0), ('a#4', 4.0), ('d5', 4.0), ('e5', 4.0), ('f5', 4.0), ('c5', 1.0), ('g4', 2.0), ('a4', 0.4999999999999998), ('a5', 2.0), ('e5', 1.3333333333333333), ('c5', 8.0), ('e5', 8.0), ('d5', 4.0), ('a#4', 8.0), ('g4', 8.0), ('a5', 2.0), ('e5', 1.3333333333333333), ('c5', 8.0), ('e5', 8.0), ('d5', 4.0), ('a#4', 8.0), ('g4', 8.0), ('g5', 2.0), ('d5', 1.3333333333333333), ('a#4', 8.0), ('d5', 8.0), ('c5', 4.0), ('a4', 8.0), ('g4', 8.0), ('a4', 4.0), ('e4', 8.0), ('a4', 8.0), ('f4', 4.0), ('d4', 8.0), ('f4', 8.0), ('d4', 2.0), ('c4', 2.000000000000007), ('c6', 2.0), ('g5', 1.3333333333333333), ('a5', 8.0), ('a#5', 8.0), ('c6', 4.0), ('a5', 8.0), ('g5', 8.0), ('a5', 5.333333333333333), ('f5', 5.314878892498194), ('a5', 5.314878892498194), ('g5', 1.0), ('d#5', 4.0), ('g5', 4.0), ('a5', 4.0), ('a#5', 4.0), ('f5', 1.0), ('a5', 4.0), ('a#5', 4.0), ('c6', 4.0), ('d6', 4.0), ('a5', 1.0), ('a#5', 4.0), ('d6', 4.0), ('f6', 2.0), ('c#6', 2.0000000003000054), ('r', 8.084210527894808), ('d5', 8.0), ('e5', 8.0), ('r', 4.0), ('f5', 8.0), ('a5', 8.0), ('f6', 2.0), ('c#6', 2.0), ('r', 4.0), ('d5', 8.0), ('e5', 8.0), ('r', 4.0), ('f5', 8.0), ('a5', 8.0), ('f5', 4.0), ('d4', 8.0), ('e4', 8.0), ('f5', 0.3333333333333333), ('f4', 8.0), ('a4', 8.0), ('f4', 2.0), ('f4', 1.0), ('d4', 4.0), ('c4', 4.0), ('d4', 1.0), ('c5', 4.0), ('a#4', 8.0), ('a4', 8.0), ('g4', 1.3333333333333333), ('a4', 8.0), ('a#4', 8.0), ('c5', 4.0), ('c5', 8.0), ('d#5', 8.0), ('d5', 0.5), ('c5', 4.0), ('a#4', 8.0), ('a4', 8.0), ('g4', 1.3333333333333333), ('a4', 8.0), ('a#4', 8.0), ('c5', 8.0), ('d#5', 8.0), ('e5', 0.6666666666666666), ('d#5', 4.0), ('e5', 4.0), ('g5', 4.0), ('f5', 8.0), ('e5', 8.0), ('d5', 2.0), ('d5', 2.0), ('e5', 4.0), ('c5', 0.08888888888888886), ('f5', 4.0), ('e5', 8.0), ('d5', 8.0), ('c5', 1.0), ('d5', 4.0), ('f5', 0.5), ('e5', 4.0), ('d5', 8.0), ('c5', 8.0), ('a#4', 2.0), ('a#5', 2.0), ('a5', 4.0), ('g5', 4.0), ('e5', 0.4444444444444444), ('f5', 0.6666666666666666), ('f4', 4.0), ('f5', 0.23529411764705882), ('e4', 4.0), ('f4', 16.0), ('a4', 16.0), ('f4', 16.0), ('e4', 4.0), ('d4', 4.0), ('c4', 2.0), ('e4', 4.0), ('c#4', 4.0), ('c#4', 4.0), ('e4', 4.0), ('f#4', 4.0), ('g#4', 4.0), ('e4', 2.0), ('f#5', 4.0), ('g#5', 4.0), ('e5', 4.0), ('c#6', 4.0), ('f#5', 4.0), ('g#5', 16.0), ('f#5', 16.0), ('g#5', 16.0), ('e5', 4.0), ('b4', 4.0), ('g#4', 4.0), ('b4', 4.0), ('g#4', 4.0), ('e4', 4.0), ('f#4', 2.0), ('c#5', 2.0), ('f#5', 4.0), ('g#5', 4.0), ('e5', 4.0), ('c#6', 4.0), ('f#5', 4.0), ('g#5', 16.0), ('f#5', 16.0), ('g#5', 16.0), ('e5', 4.0), ('b5', 4.0), ('c#6', 4.0), ('e6', 4.0), ('d#6', 4.0), ('b5', 4.0), ('c#6', 4.0), ('e6', 4.0), ('f#6', 4.0), ('b5', 4.000000000000114), ('c#6', 4.0), ('e6', 4.0), ('d#6', 4.0), ('b5', 4.0), ('c#6', 4.0), ('e6', 4.0), ('f#6', 4.0), ('b5', 4.0), ('g6', 1.3333333333333333), ('a5', 4.0), ('g5', 2.6666666666666665), ('a4', 8.0), ('g4', 2.6666666666666665), ('a4', 8.0), ('d4', 4.0), ('e4', 4.0), ('c4', 4.0), ('a4', 4.0), ('d4', 4.0), ('e4', 16.0), ('d4', 16.0), ('e4', 16.0), ('c4', 2.0), ('d5', 4.0), ('e5', 16.0), ('d5', 16.0), ('e5', 16.0), ('c5', 2.0), ('g5', 2.0), ('d5', 1.3333333333333333), ('e5', 8.0), ('f5', 8.0), ('g5', 4.0), ('e5', 8.0), ('d5', 8.0), ('e5', 5.333333333333333), ('c5', 5.31487889037946), ('e5', 5.31487889037946), ('d5', 1.0), ('a#4', 4.0), ('d5', 4.0), ('e5', 4.0), ('f5', 4.0), ('c5', 1.0), ('g4', 2.0), ('a4', 0.5), ('a5', 2.0), ('e5', 1.3333333333333333), ('c5', 8.0), ('e5', 8.0), ('d5', 4.0), ('a#4', 8.0), ('g4', 8.0), ('a5', 2.0), ('e5', 1.3333333333333333), ('c5', 8.0), ('e5', 8.0), ('d5', 4.0), ('a#4', 8.0), ('g4', 8.0), ('g5', 2.0), ('d5', 1.3333333333333333), ('a#4', 8.0), ('d5', 8.0), ('c5', 4.0), ('a4', 8.0), ('f4', 8.0), ('g5', 2.0), ('d5', 1.3333333333333333), ('a#4', 8.0), ('d5', 8.0), ('c5', 4.0), ('d5', 4.0), ('a#4', 4.0), ('e4', 0.02580385041830461), ('a4', 4.0), ('a4', 2.0), ('a#4', 4.0), ('a4', 4.0), ('a4', 2.0), ('a#4', 4.0), ('a#4', 0.6666666666666666), ('a4', 4.0), ('a#4', 16.0), ('d5', 16.0), ('a#4', 16.0), ('a4', 4.0), ('g4', 4.0), ('f4', 2.0), ('a#5', 4.0), ('a4', 0.49983729252717796), ('a5', 4.0), ('a5', 2.0), ('a#5', 4.0), ('a#5', 2.0), ('a5', 2.0), ('a#5', 4.0), ('a5', 4.0), ('a#5', 16.0), ('d6', 16.0), ('a#5', 16.0), ('a5', 2.0), ('g5', 2.0), ('a5', 0.36355029584697357), ('a6', 1.0)]\n", + "\n", + "# ps.make_wav(song[:100], fn='examples/Debussy_Reverie.wav')\n", + "\n", + "matrix = MusicMatrix(song)\n", + "\n", + "start_note = ['g5', 2]\n", + "\n", + "random_song = []\n", + "for i in range(0, 100):\n", + " start_note = matrix.next_note(start_note)\n", + " random_song.append(start_note)\n", + "\n", + "# ps.make_wav(random_song, fn='examples/random_debussy.wav')\n", + "make_midi(midi_path='midi/random_debussy.mid', notes=random_song)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Synth Solo" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "song = [('d3', 16.0), ('r', 16.0), ('g3', 16.0), ('r', 16.0), ('a3', 16.0), ('r', 16.0), ('d3', 16.0), ('r', 16.0), ('g3', 16.0), ('r', 16.0), ('a3', 16.0), ('r', 16.0), ('d3', 16.0), ('r', 16.0), ('d4', 16.0), ('r', 16.0), ('b3', 16.0), ('r', 16.0), ('d3', 16.0), ('r', 16.0), ('a3', 16.0), ('r', 16.0), ('g3', 16.0), ('r', 16.0), ('d3', 16.0), ('r', 16.0), ('a3', 16.0), ('r', 16.0), ('g3', 16.0), ('r', 16.0), ('d3', 16.0), ('r', 16.0), ('r', 5.333333333333333), ('f#3', 16.0), ('g3', 16.0), ('r', 16.0), ('d3', 16.0), ('r', 16.0), ('g3', 16.0), ('r', 16.0), ('a3', 16.0), ('r', 16.0), ('d3', 16.0), ('r', 8.0), ('f#3', 16.0), ('r', 16.0), ('f#3', 16.0), ('g3', 16.0), ('r', 16.0), ('a3', 16.0), ('r', 16.0), ('d3', 16.0), ('r', 16.0), ('b3', 16.0), ('r', 16.0), ('a3', 16.0), ('r', 16.0), ('g3', 16.0), ('r', 16.0), ('d3', 16.0), ('r', 16.0), ('f#3', 16.0), ('r', 16.0), ('g3', 16.0), ('r', 16.0), ('e3', 16.0), ('r', 16.0), ('g3', 16.0), ('r', 16.0), ('d4', 16.0), ('r', 16.0), ('f#3', 16.0), ('r', 16.0), ('g3', 16.0), ('r', 16.0), ('a3', 16.0), ('r', 16.0), ('f#3', 16.0), ('r', 16.0), ('g3', 16.0), ('r', 16.0), ('f#3', 16.0), ('r', 16.0), ('a3', 16.0), ('r', 16.0), ('g3', 16.0), ('r', 16.0), ('f#4', 16.0), ('r', 16.0), ('g4', 16.0), ('r', 16.0), ('g3', 16.0), ('r', 16.0), ('b3', 16.0), ('r', 16.0), ('d4', 16.0)]\n", + "\n", + "# ps.make_wav(song[:100], fn='examples/synth_solo.wav')\n", + "\n", + "matrix = MusicMatrix(song)\n", + "\n", + "start_note = ['d4', 16]\n", + "\n", + "random_song = []\n", + "for i in range(0, 100):\n", + " start_note = matrix.next_note(start_note)\n", + " random_song.append(start_note)\n", + "\n", + "# ps.make_wav(random_song, fn='examples/random_synth_solo.wav')\n", + "make_midi(midi_path='midi/random_synth_solo.mid', notes=random_song)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Mix Songs" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 1],\n", + " [4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],\n", + " [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],\n", + " [0, 0, 0, 13, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 4, 0],\n", + " [0, 0, 0, 0, 0, 0, 2, 0, 4, 0, 0, 0, 0, 2, 0, 1],\n", + " [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1],\n", + " [0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 2, 0, 1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 2, 0, 1, 0, 4, 0, 6, 2, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0],\n", + " [1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 4],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1],\n", + " [0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 4, 0],\n", + " [2, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 3, 1, 1, 0, 0]]\n", + "[[62, 0, 0, 0], [1, 0, 1, 2], [0, 0, 6, 10], [0, 4, 8, 22]]\n" + ] + } + ], + "source": [ + "song1 = [['c4', 4], ['c4', 4], ['c4', 4], ['d4', 8], ['e4', 4], ['e4', 4], ['d4', 8], ['e4', 4], ['f4', 8], ['g4', 2], ['c4', 8], ['c4', 8], ['c4', 8], ['g4', 8], ['g4', 8], ['g4', 8], ['e4', 8], ['e4', 8], ['e4', 8], ['c4', 8], ['c4', 8], ['c4', 8], ['g4', 4], ['f4', 8], ['e4', 4], ['d4', 8], ['c4', 2]]\n", + "\n", + "song2 = [('g#3', 16.0), ('e4', 16.0), ('d#4', 16.0), ('d4', 16.0), ('d#4', 16.0), ('r', 16.0), ('c#4', 16.0), ('b3', 16.0), ('a#3', 16.0), ('r', 16.0), ('g#3', 16.0), ('g3', 16.0), ('g#3', 16.0), ('r', 16.0), ('d#3', 16.0), ('e3', 16.0), ('d#3', 16.0), ('e3', 16.0), ('d#3', 16.0), ('d3', 16.0), ('d#3', 16.0), ('g3', 16.0), ('b3', 16.0), ('a#3', 16.0), ('g#3', 16.0), ('r', 16.0), ('g#3', 16.0), ('a#3', 16.0), ('b3', 16.0), ('r', 16.0), ('a#3', 16.0), ('b3', 16.0), ('c#4', 16.0), ('r', 16.0), ('b3', 16.0), ('a#3', 16.0), ('g3', 16.0), ('r', 16.0), ('g3', 16.0), ('a#3', 16.0), ('b3', 16.0), ('r', 16.0), ('a#3', 16.0), ('g#3', 16.0), ('d#3', 16.0), ('r', 16.0), ('d#3', 16.0), ('e3', 16.0), ('d#3', 16.0), ('e3', 16.0), ('d#3', 16.0), ('d3', 16.0), ('d#3', 16.0), ('g3', 16.0), ('b3', 16.0), ('a#3', 16.0), ('g#3', 16.0), ('r', 16.0), ('g#3', 16.0), ('g3', 16.0), ('g#3', 16.0), ('r', 16.0), ('g#4', 16.0)]\n", + "\n", + "song = list(song1 * 2) + list(song2)\n", + "\n", + "matrix = MusicMatrix(song)\n", + "\n", + "pprint(matrix._markov._matrix)\n", + "pprint(matrix._timings._matrix)\n", + "\n", + "start_note = ['e3', 8]\n", + "\n", + "random_song = []\n", + "for i in range(0, 500):\n", + " start_note = matrix.next_note(start_note)\n", + " random_song.append(start_note)\n", + "\n", + "# ps.make_wav(random_song, fn='examples/random_mix.wav')\n", + "make_midi(midi_path='midi/random_mix.mid', notes=random_song)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/MarkovMusic-master/midi/Debussy_Reverie_945834_1.mid b/MarkovMusic-master/midi/Debussy_Reverie_945834_1.mid new file mode 100644 index 0000000000000000000000000000000000000000..d32de64ad11029d69f5d3c4d3c7c1563567e1ec1 GIT binary patch literal 2711 zcmbW3%W4!+5QdM5hy-_TT+Tdz2(wOxo=keunM*oz$;F7!3z2|mK(cW+Q4vC1Gy%cK z@o9XG@&Bs2k7E)=-6Vh4z3Q)X&WvU!FG2|S!kw^kXFi&}eWkC5VR3Z#?#iS4VKH7^ z`~EmAo&;B|y$p-h2h-Q5r)MXP>AN>)C*j*(DD&2*Q1)A4o`;K24h8z*JSj&4LqIMt z3LjjRBf;2IZu~x!S*wAhkb85U0s1DnEEFu1y_VeZ>eX@j08b&1S&Gl0>@e}ra^L1yj+nA5U@{$H{I#o z+~a(rjklu|1f(4cm{J(oQ?h#(ikvJ<5>y?NNYxhT)RH#9C8~K{sy4l^tHPORn$HAs z4Z->{E+(=W<24hQ1O=q!84`*&6_PxNrjbaIq>xQhoC@S7xh%?o*~lHQK^-RtcnSgd zngr2AKwF7gB{3Ch2vm5$FtItnxVDkFs_?0))Zo6rQySbSPoLRc+rKKSYE7!F0{D+1 z_5b|kOD`&RB+w=+{MhWFC7~FA(E^8&A2#tPKM>W%*ojg=h{{@5zGWFI_QjTzIJT0$ z9pVs4m&UNMePNY2BDPBGxPbu`vTg$oM7?hR6j@R6R6V#`JrHhyi4THmMlz&kmk6*6 zCV_cdH&jLj^$eko^WA4R0Yg&6V-1Km$CB51Qgxy2AdU^niLbJgv^tm3SipxV3fQS0 zT(D)f^}g(K_fn{pbav2~~nnmcp|h%_gmkhCE_3enJ%sedQ9z_D2_9Y%#S-A1LG zZ>aT+I>81BHfy&nfz3MQ7A5c2sy%^SRJ6V)U>)xh2OB#RZc|9zkg$+_v)t2vzHQjs zvNVcFv`sW5TSVJdRa=Utuc~0LN;T}rX0tA42d^8&*x|Csbumhg-5-jX*2Qozr-VHc zutp9Aj*wt;NO@C5vu2~s@v_Y^#(xp#rj7E1@|ebt1*XjNnIccQ{n?jiMD~68=y$ZO zwx7#NV&@X>Q;hw35MT*x8&ZLFRM%_@sT&d&x)_@B^Y8WgiN&QlD1~TiX#ER)H^rrY zXPl%ge4#+`#Oe6wXSqtC`~LUOvK=LRgh_GxvuxL6*81bKY`go*yK0i#pJls+x~=m> z*B(@;L0127-R)hqD-`m0mNgq@q#p(TE8{$|iJ48jC!xyf@h4X{xOdq8INlqtx&^cg zGhR?`BgzSA69d?O_ysN%Agb&pPgP+`r_ttj?u9%XD#;h3r~iDXtgo-8R)@KDSdosv z1Xa8M0b@2YzPEt*iy#7fIBOf}2~ovaaxbK5=*2GdhBp<`zl}0KIqK-S;^(~Zfae1G H!>`RBFFNBh literal 0 HcmV?d00001 diff --git a/MarkovMusic-master/midi/random_debussy.mid b/MarkovMusic-master/midi/random_debussy.mid new file mode 100644 index 0000000000000000000000000000000000000000..22a4eae1433807b456407b2fd6a3d7fe158aca3d GIT binary patch literal 897 zcmaJG!@2}! zzzmoIQ{d7fVF{9xd1Y1*H67<<8n)jFO;q9hxW->%?3+roNflxhNf+( zabKFUR7ZgrN6DzlnjOV*miU~3%BomM^n~hxrb1>o! zm_SVf#u?J7SBTS7UCqEcNU&{05;+MFdKe=$2CjfB;QvLC$W^^YCtjk0&ZZoc_RMjy zIdBS`0ux};i~Gdh2~bKy=hR^BhGYY>C)tBkBwXe|asb(J2{j!NbsdDZ7t9$%y2BjX zjANV7{fDX7F6W=yjcIRel){}q&$r}g`V#dxoqyf?TQFgPC1xZu5P#>GkrPrG5QQ5>B0J8|HvlD(5+%kS%h_gubcUsrZYNud^Vs2R9WE_D&F@WqZ|e_+4~7xH zv-LweuAe9MuWer$xf{b9!`E_;H``?9-C#!bApdB6NqkerhfA+txbEHq4%nfyj>cu+xpvsk_r*^3?h+ee+^jz0Gwa!zV zx@a9V4*YsuIVW}QqrSKH>m0XsIB#`s@Xs8=L9HX4I>JG%C!D-E@8r?OUC%3Woja{x z6t~JXJ~(-RU$1j{yW9Ixx%N@}hCX`Ak^gUGo_mdZTaPo+Fq_6Qt9Q)W| zZrb}QkH6F6bMEK3zBhUgC~wbweUGAhO!q54ZI5>o`)U6>Dbm+>Mf;>&`!ZE$*3}Mj z#kLQ}?;`QG_p#<%?{oT0+;HM)`(N!)FZ{uI7ul@wfe${sQ@i BdvO2& literal 0 HcmV?d00001 diff --git a/MarkovMusic-master/midi/random_mix_good.mid b/MarkovMusic-master/midi/random_mix_good.mid new file mode 100644 index 0000000000000000000000000000000000000000..5bd758bb6c5556810a9ec1096ed1ba66d00c95aa GIT binary patch literal 3754 zcmbuBO-{ow5QUA9V8;qmJA@#)2%xi9CMY3()-hsU43THBw^ zq<(kniTyFHF;rV_j%oeonx%P`7IAK9zs;geS(ssNhPmOwa6f-@UBJ?0dJ-xbc~GkM zG(&SH6uYggx2-ZgEZgR+<6Tps`}cUjnRPqs9XRstz^<9qejDJs5&f4>OfU4@>Uld{ z(48BG@%e6i*wgs&{b+uu6YHv9&sXwme2J@`^0E0EuX-u>wh8TgeRFAe+3m5nJ;vTH zpWiNLu){-MyXNV0f}2LCLp+@4sC|-0yy~a+*k5IJD(f4(F@Ey{C+^DPt}O1t@S=ye z#&3HZKk?*))FTfp`OyW*Q&fF8`t)^eecNwyXLx7*VfK1uK2@cmWt>%Gx<jl>(eK8IC|_6T>aP;$>SVw;;5&{o)M?@ z&_Nd@9?a$82hoF*r*qrykMC#R3!(q~z0f@^aouC|*<(fKw?8j_$LO~d$Gr*Pv*CHu z_oSEa=^+<~?icqo7e`(WRZn%%AB*VZkh=6$;$!O*ul2F#aO@n3 b&*}ZujxO_2jvamca1cB3AoG^_Y);)bM{{|a literal 0 HcmV?d00001 diff --git a/MarkovMusic-master/midi/random_rowboat.mid b/MarkovMusic-master/midi/random_rowboat.mid new file mode 100644 index 0000000000000000000000000000000000000000..80377d48ac5a535b25a279d6fe41669734bf47cf GIT binary patch literal 796 zcma)&QEr1U5JWdZO0MA>veLkK-7LD|9jAaFx^-)0-vX;m#XC2eFb9y zLNUoSzD}J77!JVtf^1q#bV_IittPdiQW{eXG9EGM}N*S{sis`{Frxmk{i`h_CWvu literal 0 HcmV?d00001 diff --git a/MarkovMusic-master/midi/random_synth_solo.mid b/MarkovMusic-master/midi/random_synth_solo.mid new file mode 100644 index 0000000000000000000000000000000000000000..8946a60f82807b617d8ac6b9944953c661af5dbf GIT binary patch literal 447 zcmZ`!K?;LF5Q_-)8~cMwDT)+|=-ESIKTx`df;V5_6ZQ)|_80xxHXs?XMV1hoJM- literal 0 HcmV?d00001 diff --git a/MarkovMusic-master/midi/random_undertail.mid b/MarkovMusic-master/midi/random_undertail.mid new file mode 100644 index 0000000000000000000000000000000000000000..a4e410f46bdf53cc5bf1cfe688839d973f24b994 GIT binary patch literal 751 zcmb7C!3}~y5F90uHnsx|kU${9hc6Ek8Zh3&gdY`9!nI&0wqZ3m@v<=oq8LIZyF0tL zGj~mUH2`+l@Ee-8?||(CV-U9e`O?V&cfeK#<0%MlB12`wW=4k0z{bRwm=Kdc;)wic zkuUbhI)7UeYx1W2l=+nTf>;o9Voub(G}gMCH|J|z`8wClk=6SAzUe-19jZr>UcUVN zyr0bU`TPE=FX>f(=XLc@^{6lYxv*NF=Cxn@GAt55WZBg4&AzRC@4slEQN;{L~zhJ!2-b@QH{TkzFx3N|u#^K&;p*I147xZX*hiMhqO zo1eSsdB&6a$UWBAI#v6@w~YsV;ACEvSLRddV^8RB>jxb4k%Oo6qJ07fagmiM^EdlkR@QbP{mZ&HI literal 0 HcmV?d00001 diff --git a/MarkovMusic-master/readmidi.py b/MarkovMusic-master/readmidi.py new file mode 100644 index 0000000..988107a --- /dev/null +++ b/MarkovMusic-master/readmidi.py @@ -0,0 +1,262 @@ +#!/usr/bin/env python + +# Read MIDI file track and synthesize with PySynth A + +# Usage: + +# python readmidi.py file.mid [tracknum] [file.wav] [--syn_b/--syn_c/--syn_d/--syn_e/--syn_p/--syn_s/--syn_samp] + +# Based on code from https://github.com/osakared/midifile.py +# which appears to be based on +# https://github.com/gasman/jasmid/blob/master/midifile.js + +# Original license: + +""" +Copyright (c) 2014, Thomas J. Webb +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +import struct + +class Note(object): + "Represents a single MIDI note" + + note_names = ['A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#'] + + def __init__(self, channel, pitch, velocity, start, duration = 0): + self.channel = channel + self.pitch = pitch + self.velocity = velocity + self.start = start + self.duration = duration + + def __str__(self): + s = Note.note_names[(self.pitch - 9) % 12] + s += str(self.pitch // 12 - 1) + s += " " + str(self.velocity) + s += " " + str(self.start) + " " + str(self.start + self.duration) + " " + return s + + def get_end(self): + return self.start + self.duration + +class MidiFile(object): + "Represents the notes in a MIDI file" + + def read_byte(self, file): + return struct.unpack('B', file.read(1))[0] + + def read_variable_length(self, file, counter): + counter -= 1 + num = self.read_byte(file) + + if num & 0x80: + num = num & 0x7F + while True: + counter -= 1 + c = self.read_byte(file) + num = (num << 7) + (c & 0x7F) + if not (c & 0x80): + break + + return (num, counter) + + def __init__(self, file_name): + self.tempo = 120 + try: + file = open(file_name, 'rb') + if file.read(4) != b'MThd': raise Exception('Not a MIDI file') + self.file_name = file_name + size = struct.unpack('>i', file.read(4))[0] + if size != 6: raise Exception('Unusual MIDI file with non-6 sized header') + self.format = struct.unpack('>h', file.read(2))[0] + self.track_count = struct.unpack('>h', file.read(2))[0] + self.time_division = struct.unpack('>h', file.read(2))[0] + + # Now to fill out the arrays with the notes + self.tracks = [] + for i in range(0, self.track_count): + self.tracks.append([]) + + for nn, track in enumerate(self.tracks): + abs_time = 0. + + if file.read(4) != b'MTrk': raise Exception('Not a valid track') + size = struct.unpack('>i', file.read(4))[0] + + # To keep track of running status + last_flag = None + while size > 0: + delta, size = self.read_variable_length(file, size) + delta /= float(self.time_division) + abs_time += delta + + size -= 1 + flag = self.read_byte(file) + # Sysex messages + if flag == 0xF0 or flag == 0xF7: + # print "Sysex" + while True: + size -= 1 + if self.read_byte(file) == 0xF7: break + # Meta messages + elif flag == 0xFF: + size -= 1 + type = self.read_byte(file) + if type == 0x2F: # end of track event + self.read_byte(file) + size -= 1 + break + print("Meta: " + str(type)) + length, size = self.read_variable_length(file, size) + message = file.read(length) + # if type not in [0x0, 0x7, 0x20, 0x2F, 0x51, 0x54, 0x58, 0x59, 0x7F]: + print(length, message) + if type == 0x51: # qpm/bpm + # http://www.recordingblogs.com/sa/Wiki?topic=MIDI+Set+Tempo+meta+message + self.tempo = 6e7 / struct.unpack('>i', b'\x00' + message)[0] + print("tempo =", self.tempo, "bpm") + # MIDI messages + else: + if flag & 0x80: + type_and_channel = flag + size -= 1 + param1 = self.read_byte(file) + last_flag = flag + else: + type_and_channel = last_flag + param1 = flag + type = ((type_and_channel & 0xF0) >> 4) + channel = type_and_channel & 0xF + if type == 0xC: # detect MIDI program change + print("program change, channel", channel, "=", param1) + continue + size -= 1 + param2 = self.read_byte(file) + + # detect MIDI ons and MIDI offs + if type == 0x9: + track.append(Note(channel, param1, param2, abs_time)) + elif type == 0x8: + for note in reversed(track): + if note.channel == channel and note.pitch == param1: + note.duration = abs_time - note.start + break + + except Exception as e: + print("Cannot parse MIDI file: " + str(e)) + finally: + file.close() + + def __str__(self): + s = "" + for i, track in enumerate(self.tracks): + s += "Track " + str(i+1) + "\n" + for note in track: + s += str(note) + "\n" + return s + +def getdur(a, b): + "Calculate note length for PySynth" + return 4 / (b - a) + +if __name__ == "__main__": + import sys + m = MidiFile(sys.argv[1]) + if len(sys.argv) > 2: + tracknum = int(sys.argv[2]) + else: + tracknum = 1 + if len(sys.argv) > 3: + filename = sys.argv[3] + else: + filename = "midi.wav" + print() + print("Track first notes") + for t, n in enumerate(m.tracks): + if len(n) > 0: + print(t, n[0], len(n)) + song = [] + notes = {} + + def getnote(q): + for x in q.keys(): + if q[x] >= 0: + return x + return None + + def gettotal(): + t = 0 + for x, y in song: + t += 4 / y + return t + + for n in m.tracks[tracknum]: + print(n) + nn = str(n).split() + start, stop = float(nn[2]), float(nn[3]) + + if start != stop: # note ends because of NOTE OFF event + if start - gettotal() > 0: + song.append(('r', getdur(gettotal(), start))) + print("r1") + song.append((nn[0].lower(), getdur(start, stop))) + elif float(nn[1]) == 0 and notes.get(nn[0].lower(), -1) >= 0: # note ends because of NOTE ON with velocity = 0 + if notes[nn[0].lower()] - gettotal() > 0: + song.append(('r', getdur(gettotal(), notes[nn[0].lower()]))) + print("r2") + song.append((nn[0].lower(), getdur(notes[nn[0].lower()], start))) + notes[nn[0].lower()] = -1 + elif float(nn[1]) > 0 and notes.get(nn[0].lower(), -1) == -1: # note ends because of new note + old = getnote(notes) + if old != None: + if notes[old] != start: + song.append((old, getdur(notes[old], start))) + notes[old] = -1 + elif start - gettotal() > 0: + song.append(('r', getdur(gettotal(), start))) + print("r3") + notes[nn[0].lower()] = start + print() + print("Song") + print(song) + # if "--syn_b" in sys.argv: + # import pysynth_b as pysynth + # elif "--syn_s" in sys.argv: + # import pysynth_s as pysynth + # elif "--syn_e" in sys.argv: + # import pysynth_e as pysynth + # elif "--syn_c" in sys.argv: + # import pysynth_c as pysynth + # elif "--syn_d" in sys.argv: + # import pysynth_d as pysynth + # elif "--syn_p" in sys.argv: + # import pysynth_p as pysynth + # elif "--syn_samp" in sys.argv: + # import pysynth_samp as pysynth + # else: + # import pysynth + # pysynth.make_wav(song, fn = filename, bpm = m.tempo) + diff --git a/MarkovMusic-master/src/MarkovBuilder.py b/MarkovMusic-master/src/MarkovBuilder.py new file mode 100644 index 0000000..f3d6ed2 --- /dev/null +++ b/MarkovMusic-master/src/MarkovBuilder.py @@ -0,0 +1,49 @@ +''' +Created on May 14, 2009 + +@author: darkxanthos +https://www.autoitscript.com/forum/topic/150415-generate-music-algorithmically/ + +''' +import random + +class MarkovBuilder: + def __init__(self, value_list): + self._values_added = 0 + self._reverse_value_lookup = value_list + self._value_lookup = {} + for i in range(0, len(value_list)): + self._value_lookup[value_list[i]] = i + #Initialize our adjacency matrix with the initial + #probabilities for note transitions. + self._matrix=[[0 for x in range(0,len(value_list))] for i in range(0,len(value_list))] + + def add(self, from_value, to_value): + """Add a path from a note to another note. Re-adding a path between notes will increase the associated weight.""" + value = self._value_lookup + self._matrix[value[from_value]][value[to_value]] += 1 + self._values_added = self._values_added + 1 + + def next_value(self, from_value): + value = self._value_lookup[from_value] + value_counts = self._matrix[value] + value_index = self.randomly_choose(value_counts) + if(value_index < 0): + raise RuntimeError("Non-existent value selected.") + else: + return self._reverse_value_lookup[value_index] + + def randomly_choose(self, choice_counts): + """Given an array of counts, returns the index that was randomly chosen""" + counted_sum = 0 + count_sum = sum(choice_counts) + + if count_sum == 0: + return random.randint(0, len(choice_counts)-1) + else: + selected_count = random.randrange(1, count_sum + 1) + for index in range(0, len(choice_counts)): + counted_sum += choice_counts[index] + if(counted_sum >= selected_count): + return index + raise RuntimeError("Impossible value selection made. BAD!") \ No newline at end of file diff --git a/MarkovMusic-master/src/MarkovMusic.py b/MarkovMusic-master/src/MarkovMusic.py new file mode 100644 index 0000000..82aa370 --- /dev/null +++ b/MarkovMusic-master/src/MarkovMusic.py @@ -0,0 +1,109 @@ +''' +Created on May 12, 2009 + +@author: Justin Bozonier +''' +#import pysynth +import numpy as np +from .MarkovBuilder import MarkovBuilder + +class MusicMatrix: + def __init__(self, song=None): + self._previous_note = None + + if song is not None: + notes = np.array(song, dtype=str)[:, 0] + durations = np.array(song, dtype=str)[:, 1] + + for i, d in enumerate(durations): + durations[i] = self.float2str(durations[i]) + + self._markov = MarkovBuilder(np.unique(notes).tolist()) + self._timings = MarkovBuilder(np.unique(durations).tolist()) + + for note in song: + self.add(note) + else: + self._markov = MarkovBuilder(["a", "a#", "b", "c", "c#", "d", "d#", "e", "f", "f#", "g", "g#"]) + self._timings = MarkovBuilder([1, 2, 4, 8, 16]) + + # print(self._markov._value_lookup) + # print(self._timings._value_lookup) + + def float2str(self, d): + if float(d) >= 1: + return '%d' % int(float(d)) + else: + return '%.2f' % float(d) + + def add(self, to_note): + """Add a path from a note to another note. Re-adding a path between notes will increase the associated weight.""" + + to_note = list(to_note) + to_note[1] = self.float2str(to_note[1]) + + if(self._previous_note is None): + self._previous_note = to_note + return + from_note = self._previous_note + self._markov.add(from_note[0], to_note[0]) + self._timings.add(from_note[1], to_note[1]) + self._previous_note = to_note + + def next_note(self, from_note): + from_note = list(from_note) + from_note[1] = self.float2str(from_note[1]) + + return [self._markov.next_value(from_note[0]), float(self._timings.next_value(from_note[1]))] + +if __name__ == "__main__": + # Playing it comes next :) + #test = [['c',4], ['e',4], ['g',4], ['c5',1]] + #pysynth.make_wav(test, fn = "test.wav") + + musicLearner = MusicMatrix() + + # Input the melody of Row, Row, Row Your Boat + # The MusicMatrix will automatically use this to + # model our own song after it. + musicLearner.add(["c", 4]) + musicLearner.add(["c", 4]) + musicLearner.add(["c", 4]) + musicLearner.add(["d", 8]) + musicLearner.add(["e", 4]) + musicLearner.add(["e", 4]) + musicLearner.add(["d", 8]) + musicLearner.add(["e", 4]) + musicLearner.add(["f", 8]) + musicLearner.add(["g", 2]) + + musicLearner.add(["c", 8]) + musicLearner.add(["c", 8]) + musicLearner.add(["c", 8]) + + musicLearner.add(["g", 8]) + musicLearner.add(["g", 8]) + musicLearner.add(["g", 8]) + + musicLearner.add(["e", 8]) + musicLearner.add(["e", 8]) + musicLearner.add(["e", 8]) + + musicLearner.add(["c", 8]) + musicLearner.add(["c", 8]) + musicLearner.add(["c", 8]) + + musicLearner.add(["g", 4]) + musicLearner.add(["f", 8]) + musicLearner.add(["e", 4]) + musicLearner.add(["d", 8]) + musicLearner.add(["c", 2]) + + random_score = [] + current_note = ["c", 4] + for i in range(0,100): + print(current_note[0] + ", " + str(current_note[1])) + current_note = musicLearner.next_note(current_note) + random_score.append(current_note) + + pysynth.make_wav(random_score, fn = "first_score.wav") \ No newline at end of file diff --git a/MarkovMusic-master/src/__pycache__/MarkovBuilder.cpython-35.pyc b/MarkovMusic-master/src/__pycache__/MarkovBuilder.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b3927b405bba0482e6115a4db2ea39415f9ba784 GIT binary patch literal 2341 zcma)7OK;mo5S}F^*=_m$fY=;6lWLA9fN+rq9syU5LJQ<<-}8Y|(%#h}Xbrhm1Jm6U_eQ z(0&6p-E-DB+-Jm?REEwI6s0P^4 za()H_uhA_C5>5NNDXzMcYZv<+u^oOG2X0T%^g09=Ceg8L6%-s4K}$>gMy1x5P(}~j zjjDX1FLFgrxxt<6J&t2P^oOAt_`9mepy!2=zA5|=%0MdH@A@y~GN4KF{%rMYX~t6K zc3S)6Bu)J!k3cjUy9d$_wJxH>(#}{W{ekJe=fdCWxauIoj@G3n%zrwpW zZ;DDQ>ozZ^HL5IzE_}I)O`3b;G{r43xpE#jtT>?orT{Jriy2>#3NyxuFE;=LZUAcv zB8FVP|Hn0Y1LhI52Uj=k1$TJ-H$nL&yUi|G+K%~pyVdoc+}tYiWqF9|l)3S(`#x$y zMquD>r+ylJxqt$Xi!40~qCrt;S+-t`a+7582c-(7+He%>863s8N_`H|YgN@B6<*!3%*?)XZYk;=8L zO$!&a(D>s}`?ECoNQ0KST?bPF|<-TqYBINwYAPUH{4B%`dk)bET_C zS=p#8m2><~a#N8*lY3}=Suw^UEO#0mHno)u8Fu&iH{ zaK)^D8%=Yekkb$?rzLJU*ThY685y4!lUwIAUb%Zxe;fzcDGxIl1f>@QSrLy?)>}ca zKMK=oMqPn*#n(?=XTiswxu7n0xo{L;Ip#pkMA;H8uhnQZ?I?J1E(qcx3IcUww)7$! R<@`qF#6#wH&9%s3{SS$%A~65} literal 0 HcmV?d00001 diff --git a/MarkovMusic-master/src/__pycache__/MarkovMusic.cpython-35.pyc b/MarkovMusic-master/src/__pycache__/MarkovMusic.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..19506532d799dcb1edef926baf2d82ce647c2124 GIT binary patch literal 2925 zcmb7G&2Ah;5U%doe~-QX!^Q+f6O2JC5-V{O38Dx>9E60hC9tAMmZQ;Rr*}Q;-I;aI ztbbPaDdEJE@C3X82OfY!Upe^(S5AD@V=wk5AhSDN+g;UNRbBN}%`Q$()^0uf+5gie z`kgL)N|-;!NPm??A<;Idpioj*(6*$|p|C(*hk6ceJ0!jiixigVHFlNgm89(gDR9cP zCrSSzRe@eXM~PI4I%Ntg6jrG%>6IYyzgRU2C&muCZ|Zsr>v{(#-&8+EVSUUZydQVs zdMxM~KX^SBE;N4ddaUdD^_E@mYdk}53C{Hb4fUfCwgCgI@mTfSRXW-th3o)a(~O*_ zFP_l$1SywPmAOmd3@xfjyK-m=h*`Wq%@i}SfD%=qPW^l-_IvWVnx@VSv%^^m=deo% zfOo4gKfGUC*DA)^2-ickg~yt33_|*>0jAdfyDvEQ-A+$uNl{rE6zg z8JlMUv?0voMxghSgC~Qi8!Fvo*~Q1f;e z7!(T6Q86|!JO@+2- zWw30-OCy>?*~Bay$`C)wh}KZHFl!HGd-;rapB0!?m`sB-Tr=hOwK|BBLF&gzri_gH zrWj})92+Oiw5h6i&{GbCH3P|%2641MP^Oe6-6+jW+3#88nTnr9y(n&{ z#tFi(Q8tBCbz7iG+%`ovlbUKcfYK<5QzIf>Wqk#f{6zW#EdF}1{&446s&u-uHHZ(B zWG6?pMcbWTkY-Bnq`G;Tz1ly9X+Mgi%=agtBz+fzL{++CMXbmraYNn|H|3<5m-oeR z{t|LmFOH26%+catSpIEO$Iff)hG=2z6?Vz@cKcv>$P;!!<@73Wr-JHva7URuX^9BJHQS=bg}!T$_|x^tvK}# zqi)xW;wE}!iqpHw3(_=cMz(Vvs;Ir2t=h0}+EQthOo1_KBdTW*7QMve29x(d8jj6^ zDQ8Ju2UYgYPREnNXFkSAXFswiOGz;{@`oFLp`lp2Oq5n~-A-2%CGY7lsi zDHFoTQl z9|W4JJ-{h?0Kqv9`N~&uINF6`M+wG3Px-#7`F<}62VI`KzP~>Ry17Ju$W|ELc?Lci z8NF&=Gm>i Date: Fri, 11 Dec 2020 14:34:52 +0900 Subject: [PATCH 2/2] Add files via upload Magenta --- .gitignore | 11 ++ .isort.cfg | 7 + .pylintrc | 453 ++++++++++++++++++++++++++++++++++++++++++++ AUTHORS | 7 + LICENSE | 203 ++++++++++++++++++++ README.md | 193 +++++++++++++------ magenta-logo-bg.png | Bin 0 -> 69114 bytes setup.cfg | 2 + setup.py | 162 ++++++++++++++++ 9 files changed, 980 insertions(+), 58 deletions(-) create mode 100644 .gitignore create mode 100644 .isort.cfg create mode 100644 .pylintrc create mode 100644 AUTHORS create mode 100644 LICENSE create mode 100644 magenta-logo-bg.png create mode 100644 setup.cfg create mode 100644 setup.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..162db52 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +*.pyc +*.egg +.eggs/ +.ipynb_checkpoints/ +*.swp +*.egg-info/ +.cache/ +build/ +*.DS_Store +.vscode +.idea/ diff --git a/.isort.cfg b/.isort.cfg new file mode 100644 index 0000000..0f4d103 --- /dev/null +++ b/.isort.cfg @@ -0,0 +1,7 @@ +[settings] +line_length=1000 +force_single_line=True +force_sort_within_sections=True +default_section=THIRDPARTY +sections=FUTURE,STDLIB,LOCALFOLDER,THIRDPARTY +no_lines_before=THIRDPARTY diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..b223df6 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,453 @@ +# This Pylint rcfile contains a best-effort configuration to uphold the +# best-practices and style described in the Google Python style guide: +# https://google.github.io/styleguide/pyguide.html +# +# Its canonical open-source location is: +# https://google.github.io/styleguide/pylintrc + +[MASTER] + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=third_party + +# Add files or directories matching the regex patterns to the blacklist. The +# regex matches against base names, not paths. +ignore-patterns= + +# Pickle collected data for later comparisons. +persistent=no + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + +# Use multiple processes to speed up Pylint. +jobs=4 + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code +extension-pkg-whitelist= + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence= + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). See also the "--disable" option for examples. +#enable= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +disable=abstract-method, + apply-builtin, + arguments-differ, + attribute-defined-outside-init, + backtick, + bad-option-value, + buffer-builtin, + c-extension-no-member, + consider-using-enumerate, + cmp-builtin, + cmp-method, + coerce-builtin, + coerce-method, + delslice-method, + div-method, + duplicate-code, + eq-without-hash, + execfile-builtin, + file-builtin, + filter-builtin-not-iterating, + fixme, + getslice-method, + global-statement, + hex-method, + idiv-method, + implicit-str-concat-in-sequence, + import-error, + import-self, + import-star-module-level, + inconsistent-return-statements, + input-builtin, + intern-builtin, + invalid-str-codec, + locally-disabled, + long-builtin, + long-suffix, + map-builtin-not-iterating, + misplaced-comparison-constant, + missing-function-docstring, + metaclass-assignment, + next-method-called, + next-method-defined, + no-absolute-import, + no-else-break, + no-else-continue, + no-else-raise, + no-else-return, + no-init, + no-member, + no-name-in-module, + no-self-use, + nonzero-method, + not-context-manager, # added + oct-method, + old-division, + old-ne-operator, + old-octal-literal, + old-raise-syntax, + parameter-unpacking, + print-statement, + raise-missing-from, + raising-string, + range-builtin-not-iterating, + raw_input-builtin, + rdiv-method, + reduce-builtin, + relative-import, + reload-builtin, + round-builtin, + setslice-method, + signature-differs, + standarderror-builtin, + super-with-arguments, + suppressed-message, + sys-max-int, + too-few-public-methods, + too-many-ancestors, + too-many-arguments, + too-many-boolean-expressions, + too-many-branches, + too-many-instance-attributes, + too-many-locals, + too-many-nested-blocks, + too-many-public-methods, + too-many-return-statements, + too-many-statements, + trailing-newlines, + unbalanced-tuple-unpacking, # added + unichr-builtin, + unicode-builtin, + unnecessary-pass, + unpacking-in-except, + unsubscriptable-object, # added + useless-else-on-loop, + useless-object-inheritance, + useless-suppression, + using-cmp-argument, + wrong-import-order, + xrange-builtin, + zip-builtin-not-iterating, + + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html. You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Put messages in a separate file for each module / package specified on the +# command line instead of printing them on stdout. Reports (if any) will be +# written in a file name "pylint_global.[txt|html]". This option is deprecated +# and it will be removed in Pylint 2.0. +files-output=no + +# Tells whether to display a full report or only the messages +reports=no + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= + + +[BASIC] + +# Good variable names which should always be accepted, separated by a comma +good-names=main,_ + +# Bad variable names which should always be refused, separated by a comma +bad-names= + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. +property-classes=abc.abstractproperty,cached_property.cached_property,cached_property.threaded_cached_property,cached_property.cached_property_with_ttl,cached_property.threaded_cached_property_with_ttl + +# Regular expression matching correct function names +function-rgx=^(?:(?PsetUp|tearDown|setUpModule|tearDownModule)|(?P_?[A-Z][a-zA-Z0-9]*)|(?P_?[a-z][a-z0-9_]*))$ + +# Regular expression matching correct variable names +variable-rgx=^[a-z][a-z0-9_]*$ + +# Regular expression matching correct constant names +const-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$ + +# Regular expression matching correct attribute names +attr-rgx=^_{0,2}[a-z][a-z0-9_]*$ + +# Regular expression matching correct argument names +argument-rgx=^[a-z][a-z0-9_]*$ + +# Regular expression matching correct class attribute names +class-attribute-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$ + +# Regular expression matching correct inline iteration names +inlinevar-rgx=^[a-z][a-z0-9_]*$ + +# Regular expression matching correct class names +class-rgx=^_?[A-Z][a-zA-Z0-9]*$ + +# Regular expression matching correct module names +module-rgx=^(_?[a-z][a-z0-9_]*|__init__)$ + +# Regular expression matching correct method names +method-rgx=(?x)^(?:(?P_[a-z0-9_]+__|runTest|setUp|tearDown|setUpTestCase|tearDownTestCase|setupSelf|tearDownClass|setUpClass|(test|assert)_*[A-Z0-9][a-zA-Z0-9_]*|next)|(?P_{0,2}[A-Z][a-zA-Z0-9_]*)|(?P_{0,2}[a-z][a-z0-9_]*))$ + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=(__.*__|main|test.*|.*test|.*Test)$ + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=10 + + +[TYPECHECK] + +# List of decorators that produce context managers, such as +# contextlib.contextmanager. Add to this list to register other decorators that +# produce valid context managers. +contextmanager-decorators=contextlib.contextmanager,contextlib2.contextmanager + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis. It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules= + +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes=optparse.Values,thread._local,_thread._local + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members= + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=80 + +# TODO(https://github.com/PyCQA/pylint/issues/3352): Direct pylint to exempt +# lines made too long by directives to pytype. + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=(?x)( + ^\s*(\#\ )??$| + ^\s*(from\s+\S+\s+)?import\s+.+$) + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=yes + +# List of optional constructs for which whitespace checking is disabled. `dict- +# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. +# `trailing-comma` allows a space between comma and closing bracket: (a, ). +# `empty-line` allows space-only lines. +no-space-check= + +# Maximum number of lines in a module +max-module-lines=99999 + +# String used as indentation unit. The internal Google style guide mandates 2 +# spaces. Google's externaly-published style guide says 4, consistent with +# PEP 8. Here, we use 2 spaces, for conformity with many open-sourced Google +# projects (like TensorFlow). +indent-string=' ' + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=TODO + + +[STRING] + +# This flag controls whether inconsistent-quotes generates a warning when the +# character used as a quote delimiter is used inconsistently within a module. +check-quote-consistency=yes + + +[VARIABLES] + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=^\*{0,2}(_$|unused_|dummy_) + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_,_cb + +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules=six,six.moves,past.builtins,future.builtins,functools + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging, + absl.logging, + tensorflow.io.logging # added + + +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + + +[SPELLING] + +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub, + TERMIOS, + Bastion, + rexec, + sets + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + +# Force import order to recognize a module as part of the standard +# compatibility libraries. +known-standard-library= + +# Force import order to recognize a module as part of a third party library. +known-third-party=enchant, absl + +# Analyse import fallback blocks. This can be used to support both Python 2 and +# 3 compatible code, which means that the block might have code that exists +# only in one or another interpreter, leading to false positives when analysed. +analyse-fallback-blocks=no + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__, + __new__, + setUp + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict, + _fields, + _replace, + _source, + _make + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls, + class_ + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=StandardError, + Exception, + BaseException diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..465a024 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,7 @@ +# This is the list of Magenta authors for copyright purposes. +# +# This does not necessarily list everyone who has contributed code, since in +# some cases, their employer may be the copyright holder. To see the full list +# of contributors, see the revision history in source control. +Google LLC +Szymon Sidor \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e3db600 --- /dev/null +++ b/LICENSE @@ -0,0 +1,203 @@ +Copyright 2016 The Magenta Team. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2015, The TensorFlow Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 79b391b..0821430 100644 --- a/README.md +++ b/README.md @@ -1,58 +1,135 @@ -## AIrang 프로젝트
-![image](https://user-images.githubusercontent.com/52441697/100899294-03375a80-3505-11eb-898a-5dc2a67c9ecd.png) - -#### :pencil2: 프로젝트 소개 -모두를 위한 동요 창작 AI, AIRANG -인공지능을 통해 보다 많은 동요를 누구나 손쉽고 빠르게 작사 작곡 -#### :tv: AIrang 시연영상 링크 : https://www.youtube.com/watch?v=_yRwkHZCLmI -#### :space_invader: 팀원 기술블로그 주소 -* 김선우 - - 작곡 알고리즘, 프론트엔드 - - https://sunwoo-725.tistory.com/
-* 김채윤 - - 작곡 알고리즘, 백엔드 - - https://yunyuno3o.tistory.com/
-* 민은영 - - 작사 알고리즘, 프론트엔드 - - https://blog.naver.com/bear0369
-* 정혜민 - - 작사 알고리즘, 백엔드 - - https://codeinleonis.tistory.com/
-#### :book: 참고 -* 음성 데이터셋 -https://github.com/danbom/emotiontts_open_db -* 자연어 처리 -https://github.com/danbom/soynlp -* 키워드 추출을 위한 KRWordRank -https://github.com/lovit/KR-WordRank -* 마르코프 체인 작곡 -https://github.com/danbom/MarkovMusic -* 마젠타 작곡(RNN) -https://github.com/magenta/magenta -* 작사 알고리즘 참고 -https://github.com/danbom/hiphop - -### 2020 졸업프로젝트 진행 과정
-#### 📅 10.16 프로토타입 만들기 시작
-* Adobe XD 활용해 구현
- - 1018
https://xd.adobe.com/view/c1ddf3a1-8039-43de-966e-4c6cf48756b6-948e/ -#### 📅 10.22 작곡소프트웨어 발표
-* 작곡소프트웨어.pdf -#### 📅 10.23 1차 멘토링 및 사업계획서 작성, 프로토타입 장면 연결 시작
-#### 📅 10.24 프로토타입 1차 완성
-* Adobe XD 활용해 구현
- - 1024
https://xd.adobe.com/view/6d4ea879-0b66-4ed4-bbe9-1455d4917689-381d/?fullscreen&hints=off -#### 📅 10.30 사업계획서 제출 및 중간발표 자료(+ 창업경진대회 본선진출)
-#### 📅 11.03 중간발표
-* -#### 📅 11.06 창업 경진 대회 발표
-* 장려상 수상 -#### 📅 11.13 추가 데이터셋, 알고리즘 회의
-* 작사 데이터셋(은영,혜민) : https://docs.google.com/spreadsheets/d/1ot7RgS7kaz1GI-OhT3EXO5I805EZs1rsqfFV1MLsa60/edit?usp=sharing -* 작곡 데이터셋(선우,채윤) : https://docs.google.com/document/d/1D_6VYXj-haVLZm-3O4KSS6XG96-zDQht/edit -* 알고리즘 : https://docs.google.com/spreadsheets/d/1LDNTvfOhnJw_W6Rfeia6OdszMlUh3J3pT3UqdmKehQ0/edit?usp=sharing -#### 📅 11.20 작사, 작곡 회의
-* https://docs.google.com/spreadsheets/d/1LDNTvfOhnJw_W6Rfeia6OdszMlUh3J3pT3UqdmKehQ0/edit#gid=1287511031 -#### 📅 11.27 2차 멘토링
-#### 📅 12.03 AIrang 깃허브 리모델링
-#### 📅 12.08 AIrang 기말발표
+ + + +[![Build Status](https://github.com/magenta/magenta/workflows/build/badge.svg)](https://github.com/magenta/magenta/actions?query=workflow%3Abuild) + [![PyPI version](https://badge.fury.io/py/magenta.svg)](https://badge.fury.io/py/magenta) + +**Magenta** is a research project exploring the role of machine learning +in the process of creating art and music. Primarily this +involves developing new deep learning and reinforcement learning +algorithms for generating songs, images, drawings, and other materials. But it's also +an exploration in building smart tools and interfaces that allow +artists and musicians to extend (not replace!) their processes using +these models. Magenta was started by some researchers and engineers +from the [Google Brain team](https://research.google.com/teams/brain/), +but many others have contributed significantly to the project. We use +[TensorFlow](https://www.tensorflow.org) and release our models and +tools in open source on this GitHub. If you’d like to learn more +about Magenta, check out our [blog](https://magenta.tensorflow.org), +where we post technical details. You can also join our [discussion +group](https://groups.google.com/a/tensorflow.org/forum/#!forum/magenta-discuss). + +This is the home for our Python TensorFlow library. To use our models in the browser with [TensorFlow.js](https://js.tensorflow.org/), head to the [Magenta.js](https://github.com/tensorflow/magenta-js) repository. + +## Getting Started + +Take a look at our [colab notebooks](https://magenta.tensorflow.org/demos/colab/) for various models, including one on [getting started](https://colab.research.google.com/notebooks/magenta/hello_magenta/hello_magenta.ipynb). +[Magenta.js](https://github.com/tensorflow/magenta-js) is a also a good resource for models and [demos](https://magenta.tensorflow.org/demos/web/) that run in the browser. +This and more, including [blog posts](https://magenta.tensorflow.org/blog) and [Ableton Live plugins](https://magenta.tensorflow.org/demos/native/), can be found at [https://magenta.tensorflow.org](https://magenta.tensorflow.org). + +## Magenta Repo + +* [Installation](#installation) +* [Using Magenta](#using-magenta) +* [Development Environment (Advanced)](#development-environment) + +## Installation + +Magenta maintains a [pip package](https://pypi.python.org/pypi/magenta) for easy +installation. We recommend using Anaconda to install it, but it can work in any +standard Python environment. We support Python 3 (>= 3.5). These instructions +will assume you are using Anaconda. + +### Automated Install (w/ Anaconda) + +If you are running Mac OS X or Ubuntu, you can try using our automated +installation script. Just paste the following command into your terminal. + +```bash +curl https://raw.githubusercontent.com/tensorflow/magenta/master/magenta/tools/magenta-install.sh > /tmp/magenta-install.sh +bash /tmp/magenta-install.sh +``` + +After the script completes, open a new terminal window so the environment +variable changes take effect. + +The Magenta libraries are now available for use within Python programs and +Jupyter notebooks, and the Magenta scripts are installed in your path! + +Note that you will need to run `source activate magenta` to use Magenta every +time you open a new terminal window. + +### Manual Install (w/o Anaconda) + +If the automated script fails for any reason, or you'd prefer to install by +hand, do the following steps. + +Install the Magenta pip package: + +```bash +pip install magenta +``` + +**NOTE**: In order to install the `rtmidi` package that we depend on, you may need to install headers for some sound libraries. On Ubuntu Linux, this command should install the necessary packages: + +```bash +sudo apt-get install build-essential libasound2-dev libjack-dev portaudio19-dev +``` +On Fedora Linux, use +```bash +sudo dnf group install "C Development Tools and Libraries" +sudo dnf install SAASound-devel jack-audio-connection-kit-devel portaudio-devel +``` + + +The Magenta libraries are now available for use within Python programs and +Jupyter notebooks, and the Magenta scripts are installed in your path! + +## Using Magenta + +You can now train our various models and use them to generate music, audio, and images. You can +find instructions for each of the models by exploring the [models directory](magenta/models). + +## Development Environment +If you want to develop on Magenta, you'll need to set up the full Development Environment. + +First, clone this repository: + +```bash +git clone https://github.com/tensorflow/magenta.git +``` + +Next, install the dependencies by changing to the base directory and executing the setup command: + +```bash +pip install -e . +``` + +You can now edit the files and run scripts by calling Python as usual. For example, this is how you would run the `melody_rnn_generate` script from the base directory: + +```bash +python magenta/models/melody_rnn/melody_rnn_generate --config=... +``` + +You can also install the (potentially modified) package with: + +```bash +pip install . +``` + +Before creating a pull request, please also test your changes with: + +```bash +pip install pytest-pylint +pytest +``` + +## PIP Release + +To build a new version for pip, bump the version and then run: + +```bash +python setup.py test +python setup.py bdist_wheel --universal +twine upload dist/magenta-N.N.N-py2.py3-none-any.whl +``` diff --git a/magenta-logo-bg.png b/magenta-logo-bg.png new file mode 100644 index 0000000000000000000000000000000000000000..f5557de9438c25c5d9a49fb93cb9d71b73efb9ca GIT binary patch literal 69114 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 literal 0 HcmV?d00001 diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..9af7e6f --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[aliases] +test=pytest \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..c00e65d --- /dev/null +++ b/setup.py @@ -0,0 +1,162 @@ +# Copyright 2020 The Magenta Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""A setuptools based setup module for magenta.""" + +from setuptools import find_packages +from setuptools import setup + +# Bit of a hack to parse the version string stored in version.py without +# executing __init__.py, which will end up requiring a bunch of dependencies to +# execute (e.g., tensorflow, pretty_midi, etc.). +# Makes the __version__ variable available. +with open('magenta/version.py') as in_file: + exec(in_file.read()) # pylint: disable=exec-used + +REQUIRED_PACKAGES = [ + 'absl-py', + 'dm-sonnet', + # tensor2tensor has a dependency on dopamine-rl, which we don't use. + # pin to a version that doesn't require pygame installation because that + # has too many external non-python dependencies. + 'dopamine-rl <= 3.0.1', + 'imageio', + 'librosa >= 0.6.2, < 0.8.0', + 'matplotlib >= 1.5.3', + 'mido == 1.2.6', + 'mir_eval >= 0.4', + 'note-seq', + 'numba < 0.50', # temporary fix for librosa import + 'numpy', + 'Pillow >= 3.4.2', + 'pretty_midi >= 0.2.6', + 'pygtrie >= 2.3', + 'python-rtmidi >= 1.1, < 1.2', # 1.2 breaks us + 'scikit-image', + 'scipy >= 0.18.1', + 'six >= 1.12.0', + 'sk-video', + 'sox >= 1.3.7', + 'tensor2tensor', + 'tensorflow', + 'tensorflow-datasets', + 'tensorflow-probability', + 'tf_slim', + 'wheel', +] + +EXTRAS_REQUIRE = { + 'beam': [ + 'apache-beam[gcp] >= 2.14.0', + ], + 'onsets_frames_realtime': [ + 'pyaudio', + 'colorama', + 'tflite', + ], + 'test': [ + 'pylint', + 'pytest', + ] +} + +# pylint:disable=line-too-long +CONSOLE_SCRIPTS = [ + 'magenta.interfaces.midi.magenta_midi', + 'magenta.interfaces.midi.midi_clock', + 'magenta.models.arbitrary_image_stylization.arbitrary_image_stylization_evaluate', + 'magenta.models.arbitrary_image_stylization.arbitrary_image_stylization_train', + 'magenta.models.arbitrary_image_stylization.arbitrary_image_stylization_with_weights', + 'magenta.models.arbitrary_image_stylization.arbitrary_image_stylization_distill_mobilenet', + 'magenta.models.drums_rnn.drums_rnn_create_dataset', + 'magenta.models.drums_rnn.drums_rnn_generate', + 'magenta.models.drums_rnn.drums_rnn_train', + 'magenta.models.image_stylization.image_stylization_create_dataset', + 'magenta.models.image_stylization.image_stylization_evaluate', + 'magenta.models.image_stylization.image_stylization_finetune', + 'magenta.models.image_stylization.image_stylization_train', + 'magenta.models.image_stylization.image_stylization_transform', + 'magenta.models.improv_rnn.improv_rnn_create_dataset', + 'magenta.models.improv_rnn.improv_rnn_generate', + 'magenta.models.improv_rnn.improv_rnn_train', + 'magenta.models.gansynth.gansynth_train', + 'magenta.models.gansynth.gansynth_generate', + 'magenta.models.melody_rnn.melody_rnn_create_dataset', + 'magenta.models.melody_rnn.melody_rnn_generate', + 'magenta.models.melody_rnn.melody_rnn_train', + 'magenta.models.music_vae.music_vae_generate', + 'magenta.models.music_vae.music_vae_train', + 'magenta.models.nsynth.wavenet.nsynth_generate', + 'magenta.models.nsynth.wavenet.nsynth_save_embeddings', + 'magenta.models.onsets_frames_transcription.onsets_frames_transcription_create_dataset', + 'magenta.models.onsets_frames_transcription.onsets_frames_transcription_create_dataset_maps', + 'magenta.models.onsets_frames_transcription.onsets_frames_transcription_create_tfrecords', + 'magenta.models.onsets_frames_transcription.onsets_frames_transcription_infer', + 'magenta.models.onsets_frames_transcription.onsets_frames_transcription_train', + 'magenta.models.onsets_frames_transcription.onsets_frames_transcription_transcribe', + 'magenta.models.onsets_frames_transcription.realtime.onsets_frames_transcription_realtime', + 'magenta.models.performance_rnn.performance_rnn_create_dataset', + 'magenta.models.performance_rnn.performance_rnn_generate', + 'magenta.models.performance_rnn.performance_rnn_train', + 'magenta.models.pianoroll_rnn_nade.pianoroll_rnn_nade_create_dataset', + 'magenta.models.pianoroll_rnn_nade.pianoroll_rnn_nade_generate', + 'magenta.models.pianoroll_rnn_nade.pianoroll_rnn_nade_train', + 'magenta.models.polyphony_rnn.polyphony_rnn_create_dataset', + 'magenta.models.polyphony_rnn.polyphony_rnn_generate', + 'magenta.models.polyphony_rnn.polyphony_rnn_train', + 'magenta.models.rl_tuner.rl_tuner_train', + 'magenta.models.sketch_rnn.sketch_rnn_train', + 'magenta.scripts.convert_dir_to_note_sequences', + 'magenta.tensor2tensor.t2t_datagen', + 'magenta.tensor2tensor.t2t_decoder', + 'magenta.tensor2tensor.t2t_trainer', +] +# pylint:enable=line-too-long + +setup( + name='magenta', + version=__version__, # pylint: disable=undefined-variable + description='Use machine learning to create art and music', + long_description='', + url='https://magenta.tensorflow.org/', + author='Google Inc.', + author_email='magenta-discuss@gmail.com', + license='Apache 2', + # PyPI package information. + classifiers=[ + 'Development Status :: 4 - Beta', + 'Intended Audience :: Developers', + 'Intended Audience :: Education', + 'Intended Audience :: Science/Research', + 'License :: OSI Approved :: Apache Software License', + 'Programming Language :: Python :: 3', + 'Topic :: Scientific/Engineering :: Mathematics', + 'Topic :: Software Development :: Libraries :: Python Modules', + 'Topic :: Software Development :: Libraries', + ], + keywords='tensorflow machine learning magenta music art', + + packages=find_packages(), + install_requires=REQUIRED_PACKAGES, + extras_require=EXTRAS_REQUIRE, + entry_points={ + 'console_scripts': ['%s = %s:console_entry_point' % (n, p) for n, p in + ((s.split('.')[-1], s) for s in CONSOLE_SCRIPTS)], + }, + + include_package_data=True, + package_data={ + 'magenta': ['models/image_stylization/evaluation_images/*.jpg'], + }, +)