{ "cells": [ { "cell_type": "markdown", "id": "7a9aa1cb", "metadata": {}, "source": [ "## 미디 파일에 맞는 스타일 벡터 생성을 위한 곳" ] }, { "cell_type": "code", "execution_count": null, "id": "9c131428", "metadata": {}, "outputs": [], "source": [ "from music21 import note, chord\n", "from music21.stream.base import Score\n", "\n", "def score_to_style_vector(score: Score) -> dict:\n", " \"\"\"MIDI 파일(music21 score)을 분석하여 스타일 벡터를 생성하는 함수\"\"\"\n", "\n", " score.show('midi')\n", "\n", " # 1. Key & Mode\n", " key_obj = score.analyze(\"key\")\n", " key = key_obj.tonic.name # type: ignore\n", " mode = key_obj.mode # type: ignore\n", "\n", " # 2. 멜로디 음표 리스트 추출\n", " melody_notes = [n for n in score.flat.notes if isinstance(n, note.Note)]\n", " pitches = [n.pitch.midi for n in melody_notes]\n", " onsets = [n.offset for n in melody_notes]\n", "\n", " # 3. 코드 (화성) 분석\n", " chords = [c for c in score.flat.getElementsByClass(chord.Chord)]\n", " complex_chords = sum([1 for c in chords if len(c.pitches) > 3])\n", " chord_complexity = complex_chords / (len(chords) + 1e-6) # 비율\n", "\n", " # 4. 멜로디 밀도 (단위 박자당 노트 수)\n", " melody_density = len(melody_notes) / (score.highestTime + 1e-6) # type: ignore\n", "\n", " # 5. 싱코페이션 (off-beat 비율: 1/4 박자 단위 기준)\n", " syncopation = sum([1 for o in onsets if (o % 1) != 0]) / (len(onsets) + 1e-6)\n", "\n", " # 6. 피치 범위\n", " pitch_range = max(pitches) - min(pitches) if pitches else 0\n", "\n", " # 7. 사람이 생각하는 곡의 분위기\n", " mood = input(\"분위기 입력 (이 중에서 선택: Happy, Chill, Emotional, Aggressive, Dreamy, Melodic): \")\n", "\n", " # 스타일 벡터 결과\n", " style_vector = {\n", " \"bpm\": 128, # 기본값 설정\n", " \"key\": key,\n", " \"mode\": mode,\n", " \"chord_complexity\": round(chord_complexity, 3),\n", " \"melody_density\": round(melody_density, 3),\n", " \"syncopation\": round(syncopation, 3),\n", " \"pitch_range\": pitch_range,\n", " \"mood\": mood\n", " }\n", "\n", " return style_vector" ] }, { "cell_type": "code", "execution_count": null, "id": "19ba84e1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Skipping non-MIDI file: 0.mid\n", "Skipping non-MIDI file: 1.mid\n", "Skipping non-MIDI file: 10.mid\n", "Skipping non-MIDI file: 11.mid\n", "Skipping non-MIDI file: 12.mid\n", "Skipping non-MIDI file: 13.mid\n", "Skipping non-MIDI file: 14.mid\n", "Skipping non-MIDI file: 15.mid\n", "Skipping non-MIDI file: 16.mid\n", "Skipping non-MIDI file: 17.mid\n", "Skipping non-MIDI file: 18.mid\n", "Skipping non-MIDI file: 19.mid\n", "Skipping non-MIDI file: 2.mid\n", "Skipping non-MIDI file: 20.mid\n", "Skipping non-MIDI file: 21.mid\n", "Skipping non-MIDI file: 22.mid\n", "Skipping non-MIDI file: 23.mid\n", "Skipping non-MIDI file: 24.mid\n", "Skipping non-MIDI file: 25.mid\n", "Skipping non-MIDI file: 26.mid\n", "Skipping non-MIDI file: 27.mid\n", "Skipping non-MIDI file: 28.mid\n", "Skipping non-MIDI file: 29.mid\n", "Skipping non-MIDI file: 3.mid\n", "Skipping non-MIDI file: 30.mid\n", "Skipping non-MIDI file: 31.mid\n", "Skipping non-MIDI file: 32.mid\n", "Skipping non-MIDI file: 33.mid\n", "Skipping non-MIDI file: 4.mid\n", "Skipping non-MIDI file: 5.mid\n", "Skipping non-MIDI file: 6.mid\n", "Skipping non-MIDI file: 7.mid\n", "Skipping non-MIDI file: 8.mid\n", "Skipping non-MIDI file: 9.mid\n" ] } ], "source": [ "from HarmonyMIDIToken import HarmonyMIDIToken as Tokenizer\n", "import os\n", "\n", "#tokenized_data = []\n", "\n", "for filename in os.listdir(\"data\"):\n", " if filename.endswith(\".mid\") and not filename in [i[\"name\"] for i in tokenized_data]:\n", " MIDI = Tokenizer()\n", " print(f\"file name: {filename}\")\n", " MIDI.set_midi(os.path.join(\"data\", filename))\n", " \n", " vector = score_to_style_vector(MIDI.to_midi()) # type: ignore\n", " \n", " tokenized_data.append({\n", " \"name\": filename,\n", " \"vector\":vector,\n", " \"token\":MIDI.token_id\n", " })\n", " else:\n", " print(f\"Skipping non-MIDI or already Done file: {filename}\")\n", " " ] }, { "cell_type": "code", "execution_count": 2, "id": "f79a6edf", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tokenized MIDI data: 34\n" ] } ], "source": [ "print(\"Tokenized MIDI data:\", len(tokenized_data))" ] }, { "cell_type": "code", "execution_count": 3, "id": "21a9ba89", "metadata": {}, "outputs": [], "source": [ "import json # JSON 파일로 토크나이저 미디 데이터 저장\n", "\n", "with open('tokenized_midi_data.json', 'w') as f:\n", " json.dump(tokenized_data, f, indent=4)" ] }, { "cell_type": "code", "execution_count": 1, "id": "dea532d4", "metadata": {}, "outputs": [], "source": [ "import json # JSON으로 저장한 토크나이저 미디 데이터 불러오기\n", "\n", "with open('tokenized_midi_data.json', 'r') as f:\n", " tokenized_data = json.load(f)" ] }, { "cell_type": "markdown", "id": "5a37da0b", "metadata": {}, "source": [ "## 데이터 수정" ] }, { "cell_type": "code", "execution_count": null, "id": "995a6294", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "
\n", " \n", " \n", " " ], "text/plain": [ "