Python を使って、Just the Two of Us などの任意のコード進行を演奏してみます。
たまには音楽でもどうぞ。
以下の環境で動作確認をしています。
環境:
・ Windows パソコン (Anaconda 設定済み)
・ Python 3、pygame のインストール済み
★ 再生にあたり、pygame と Windows パソコン内の MIDI 音源を使用します。
pygame のインストール方法等については、下記の関連リンクを参照してください。
背景 ~ コード進行を自力で生成&理解する!
YouTube で洋楽やストリートピアノなどをよく聴きます。
また以前に、Python を使ってドレミファソラシドを鳴らすプログラムをまとめたりしています。
たまたまですが最近、音律や音階、コード進行に関する本を読みました。
手元にあるプログラムを改変して、実際に自分でコードを鳴らしたくなってきます。
ということで、音階やコード進行(和音)を再生する Python のスクリプトをまとめておくことにします。
テキストファイルに音符の長さ、音階・コードを書いておくと、そのデータを読み込んで音楽を再生します。
楽器を持っていなくても、パソコン1台さえあれば、各和音、音階で演奏できます。
簡単な作曲もできるのではないかと思います。
なお、私が使っているパソコンがたまたま Windows であり、Windows パソコン内の MIDI の機能を使っています。プログラムは Windows などの環境依存になる可能性がありますが、ご理解ください。
設定手順
① 以下を参考に、パソコン内にフォルダ(例:”desktop_music1″)を作成してください。
例: c:\user\desktop_music1
② ①のフォルダ内に chord_player1.py という名前でテキストを作成し、末尾のサンプルスクリプトをコピー&ペーストして保存してください。
例: c:\user\desktop_music1\chord_player1.py
③ ①のフォルダに、さらに、”chord1″ という名前でフォルダを作成してください。
例: c:\user\desktop_music1\chord1
※ このフォルダの中に音階を記載したテキスト(以下の「再生用のサンプル」を参照)を入れます。
※ 以下の Python のスクリプトから、このフォルダ内にあるテキストファイルを読み取って演奏します。
使い方
④ あらかじめ、音階・コードを記載したテキストファイルを、”chord1″ フォルダ(③)に入れておきます。
例: c:\user\desktop_music1\chord1\01_just_the_two_of_us_chord1.txt
※ 最初は、末尾の再生用のサンプル(5つ)をテキストファイルで保存して、動作確認をしてください。
⑤ コマンドプロンプト(または、Anaconda Prompt)を起動し、②のスクリプトを実行します。
例: python c:\user\desktop_music1\chord_player1.py
→ アプリが起動します。
※ 以後、音が出ますので、事前にパソコンの音量を(小さめに)調整しておきます。
⑥ アプリ上で、ファイル名の部分をクリックします。
→ コード・音楽が再生できたら成功です!
※ [play] ボタンをクリックしても、再生します。
※ メモ帳などでテキストを書き換えた場合は、アプリ上でファイル名の部分を再度クリックすることで、新たにファイルを読み込んで再生できます。簡単に再読み込みができますので、ちょっとした和音の違い、変更の違いを聞き比べることが可能です。
※ もし、④のフォルダにテキストファイルを追加した場合は、アプリを閉じて、再度、起動(⑤)しなおしてください。
音階、コードの書き方
音階の書き方
一例として、フォルダ chord1(②)内にテキストファイルを作って以下を書き込み、プログラムを起動してみてください。1拍ずつの時間間隔で、ドレミファソラシド(C4、D4、E4、F4、G4、A4、B4、C5)を順に鳴らす事例です。
1.00 C4
1.00 D4
1.00 E4
1.00 F4
1.00 G4
1.00 A4
1.00 B4
1.00 C5
※ テキストファイルの1行が、1つの音(音階やコードの長さ)、または、コマンドに対応します。
※ メロディを鳴らす場合は、各行に「音の拍数(音の長さ) + ” ” (半角スペース)+ 音名」の形式で記載していきます。
※ 「音の拍数」は、半角の数値で記載します。音の相対的な長さに対応します。
たとえば、1.00 と記載すると、1拍分の長さになります。2.00 と記載すると、2拍分の長さになります。
2.00、1.00、0.50、0.25 とすると、4/4 拍子での二分音符、四分音符、八分音符、十六分音符に対応する長さで、各音階の音を設定できます。
※ 1拍の絶対的な時間(秒)は、BPM などとして別途定義します(以下)。
※ 「音名」部分は、国際的表記(C4 など)、和音のコード(C4_Mなど)、MIDI のノート番号(60 など)のいずれかで記載します。
※ 「C4」がピアノの中央のド(middle C)に対応します。「A4」が国際標準音のラ(440Hz)に対応します。
※ 国際的表記で記載するとき、「音名」の末尾の1文字はオクターブ番号に対応します。
たとえば、C4 を1オクターブ下げるには C3、1オクターブ上げるには C5 とします。
※ シャープ、フラットとする場合は、「音名」部分の2文字目に、”s”、”f” を入れます。
たとえば、”Cs4″ は、ドのシャープ(C♯4)に対応します。
休符の書き方
休符を入れる場合は、拍数(時間)部分のみを記載します。
1.00
休符を表現できるようにするために、行の冒頭で音符/休符の長さを書くことにしています。
2.00、1.00、0.50、0.25 とすると、二分休符、四分休符、八分休符、十六分休符のように、休符の長さを任意に設定できます。
コメントの入れ方
# comment
1.00 C4
行の冒頭を # とすることで、コメントを入れることができます。
空行も読み飛ばします。
音を再生するときに、空行や # から始まる行は読み飛ばすようにしています。
テンポ/BPMの設定
テンポを設定するには、たとえば以下を記載します。
set_BPM1 60
この場合、この行以降の音を1分間に60拍のテンポで再生します。(BPM = beats per minute)
“set_BPM1 120” とすると、120拍/分のテンポで再生します。
曲の途中でテンポの変更が可能です。
あるいは以下として、1拍の長さを時間(秒)の単位で設定することも可能です。
set_duration1 0.5
この場合、1拍を 0.5秒として設定された音を再生します。
なお、”set_ … ” で始まる行は、コマンド行です。曲の再生途中で設定を変更できるようにしています。
複数の音を鳴らす方法
複数の音名を1行に並べて書くことで、同時に複数の音を鳴らすことができます。
1.00 C4 E4 G4
上記は、同時にド、ミ、ソ(C4, E4, G4 の和音)を鳴らす例です。
この場合、以下の記載も可能です。Cメジャーの意味です。
1.00 C4_M
こうした記載をすることで、四和音、三和音、メジャー、マイナー、不協和音など、よくいわれるコードや音楽の概念を実際に再生し、自分の耳で聴き比べることが可能になります。
コード(和音)の記載方法
コード(和音)を記載する場合は、アンダーバー “_” を途中に入れて記載します。
1.00 C4_M
※ アンダーバー “_” の左側が、基準となる音(ルート)となるようにします。
アンダーバーの右側でコードの種類(3和音、4和音等)を指定します。
※ 3和音のメジャー、マイナーの場合、C4_M、C4_m のように記載します。
プログラムでは、”_” の有無で単音か和音(コード)かを判別しています。
コードの種類
コードは現在のところ、以下の3和音および4和音を定義しています。
各行の左側の記載をすることで、各コードを再生できます。
3和音
C4_M Cメジャー(C)
C4_m Cマイナー (Cm、C-)
4和音
C4_7 Cセブンス(C7)
C4_M7 Cメジャーセブンス (C△7、Cmaj7、CM7)
C4_m7 Cマイナーセブンス(Cm7)
C4_m7f5 Cマイナーセブンスフラットファイブ(Cm7(♭5))
※ 上記で、”C4″ の部分は一例です。他の “D4″、”E4″、… などに書き換えて使用できます。
※ また、コードの表記には、音楽の各分野によって流儀があるようですので、参考のためによく使われる表記をカッコ内に示しておきます。右側の表記、カッコ内の表記はプログラムでは使えません。
よく使われるコード進行
代表的なコード進行の一例についてまとめておくことにします。
下記のようなコード進行が得られたとき、前述の書き方に従ってテキストファイルを作成すると、実際に、そのコード進行を Python のプログラムで演奏することができます。
Just the Two of Us 進行
F△7 | E7 | Am7 | Gm7 C7 | ★1
IV△7 | III7 | VIm7 | Vm7 I7 | ★2
※ 下記の “01_just_the_two_of_us_chord1.txt” が記載例です。
※ このコード進行の派生バージョンもいくつかあります。
一例を “05_just_the_two_of_us_chord_simplified1.txt” に入れてあります。
※ 椎名林檎の「丸の内サディスティック」で有名です。おしゃれコードの定番といわれており、J-POP を席巻しています。
カノン進行
D A | Bm F#m | G D | G A |
I V | VI III | IV I | IV V |
※ ヨハン・パッヘルベルのカノン(ニ長調)
※ 下記の “02_canon_progression_chord1.txt” が記載例です。
Japanese Chord Progression (王道進行)
F | G | Em | Am |
IV | V | IIIm | VIm |
※ 下記の “03_japanese_chord_progression1.txt” が記載例です。
参考:I, II, III, IV, V, VI, VII の数値の当てはめ方
一例として、★2のコード進行で、I ~ VII の7つの数値を音階の C ~ B にそれぞれ対応させると、★1が得られます。これは、C がキー(I)の場合に対応しています。
D をキーとする場合は、I ~ VII の7つの数値を、音階の D ~ C に対応させます。
同様に、E、F、G、…、B をキーとする場合は、I ~ VII を E ~ D、F ~ E、G ~ F、… にそれぞれ対応させます。
これにより、★2のような汎用なコード進行が与えられたとき、任意のキー(音階)/すべてのパターンでコード進行を作ることが可能となります。
余談: 音楽と数学の関係
基本式
音楽には数学的な背景が関わっていますので、まとめておくことにします。
(半音)×12個分が1オクターブ(周波数で2倍)に対応します。式でいえば、以下となります。
$$ (半音) = 2^{1/12} 倍$$
$$ (1オクターブ) = (半音)^{12} = 2 倍$$
・ MIDI 音源で出てくる note number は、1つ値が増えると、半音上がること(周波数で\(2^{1/12}\)倍)に対応しています。
・ 音の本質は空気などの分子の振動ですが、人間が耳で音を聞くと、1オクターブ音が上がったときに同じ種類の音として認識されます。
人が音楽を聴くとき、1個1個の分子が振動する動きを感じているというよりは、多数の分子が振動する際に共通する周波数、周波数応答を耳で検出しているということになります。(1個1個の分子の動きを認識することは難しく、耳(音)や目(色)など、周波数を検出する器官が進化してきたといえます。)
いいかえると、音や音楽は、大学で習うフーリエ変換に対応した周波数成分として認識されているといえます。また、音の周波数や大きさは対数スケールで認識されているといえます。音だけでなく光も同様です。
三和音・四和音の整理
半音、三和音(トライアド)、四和音(セブンス)が出てきますので、整理しておきます。
| 半音数 | 音程名(日本語/英語) | Cを基準とした例 | Cメジャーコードに含まれるか否か | Cマイナーコードに含まれるか否か |
| 0 | 完全1度 / Perfect Unison | C → C | 〇 | 〇 |
| 1 | 短2度 / Minor Second | C → D♭ | – | – |
| 2 | 長2度 / Major Second | C → D | – | – |
| 3 | 短3度 / Minor Third | C → E♭ | – | 〇(第3音) |
| 4 | 長3度 / Major Third | C → E | 〇(第3音) | – |
| 5 | 完全4度 / Perfect Fourth | C → F | – | – |
| 6 | 増4度 / Augmented Fourth 減5度 / Diminished Fifth |
C → F♯ / G♭ | – | – |
| 7 | 完全5度 / Perfect Fifth | C → G | 〇(第5音) | 〇(第5音) |
| 8 | 短6度 / Minor Sixth | C → A♭ | – | – |
| 9 | 長6度 / Major Sixth | C → A | – | – |
| 10 | 短7度 / Minor Seventh | C → B♭ | – | 〇(第7音:Cm7) |
| 11 | 長7度 / Major Seventh | C → B | 〇(第7音:Cmaj7) | – |
| 12 | 完全8度 / Perfect Octave | C → C(上) | 〇 | 〇 |
※ 「半音数」は、半音の何個分に相当するかの数です。12個で1オクターブ(Perfect Octave)に相当しています。
※ 小学校で習う三和音の「ド・ミ・ソ」(Cメジャー)は、半音数の 0、4、7 に対応しています。
※ 表の上から、〇を3個拾うか、4個拾うかで、三和音、四和音が決まります。
※ 四和音なのになぜ「セブンス」というのかについては、三和音(トライアド)を前提とし、オクターブ(オクト=8の意味)の1つ手前の音(セブンス)を加えるため、と理解するとわかりやすいかと思います。
※ メジャーをマイナーに変えるには、三和音の中央を半音下げる。四和音では2、4番目を半音下げると視覚的に把握しておくとわかりやすいかと思います。
マイナーに変えるにあたり、四和音の場合は片方だけ下げるという派生パターンもあるので、計3種類等のマイナーがあります。
※ 上の表では、1オクターブの内訳を8つで数えるのか、12段階にわけるのかといった2つの考え方が混在しています。
4世紀頃からのグレゴリオ聖歌などで、オクターブ、8音の概念が広がった。しかし、転調が難しいなど限界が出てきた。その後、17~18世紀に、数学的に整合性のとれた12段階の平均律が考案されて普及し、バロック音楽、古典派音楽が大きく発展した。このようにとらえると、数学的な背景と音楽用語の双方の理解がしやすいと思います。
※ 下記のサンプルスクリプトは、上記の和音の半音数の関係などをプログラム化したものです。音楽・芸術系の大学を出ていたり、音楽を本格的に極めている人であれば、同様のアイディアやプログラムはすぐにでも思いつくような内容かなと思います。
サンプルスクリプトの説明
・ サンプルスクリプトで、MIDI を使った音源の鳴らし方は、下記リンクの「ドレミファソラシドを鳴らすサンプル」とほぼ同じです。
・ GUI を使うため、tkinter を使っています。
・ 国際式の音階(例:C4, D4, A4)などを MIDI の note number (例:60, 62, 69)に変換するため、関数 notation_to_midi1() を定義しています。
・ 関数 CDEFGAB_to_semitones1() は、国際式でのアルファベットを半音いくつ分のオフセットに相当するかを求める関数です。A4 (440Hz) が音程の基準ですので値 0とし、ドレミファソラシのそれぞれに対し、半音が -9, -7, … 0, +2 個分に対応することを求めています。
・ CDEFGAB_to_midi1() 関数では、”A4″ などの表記を “69” などの MIDI の note number に換算しています。すでに “69” などの数値が入っていた場合は換算せずに出力を求めます。
・ デフォルトでのパラメータを def set_init1() としたところで定義しています。
たとえば、MIDI の楽器の種類は ins1 = 0 (ピアノ)としているところで定義しています。値を変えると、楽器を変更できます。楽器を変更する場合は、下記リンクの「キーボードピアノ【本格49鍵!】」を参照してみてください。
・ 音程を1オクターブ上下する場合は、set_init1() 関数内の oct1 = 0*12 としているところで、oct1 = 1*12、oct1 = -1*12 などに修正してください。(半音)*12 が1オクターブに対応しているため、このような記載としています。
・ 転調させる場合は、oct1 = 1、2、… などに書き換えることで、半音1、2、…個分、強制的に転調させることが可能です。
・ 和音については、基準となる音(ルート)に、半音のいくつ分の音を加えるか、という考え方で、3和音、4和音のデータを生成しています。
・ ルートとなる音(note number)を n1 としたとき、メジャー、マイナーなどのコードの定義とプログラム内での記載を書き出しておきます。この記載を拡張していくことで、自由にコードを追加していくことが可能です。
コードの定義
3和音のメジャーは、ルート(n1)に対し、4×(半音)と、7×(半音)を加えたものです。したがって、プログラム内での和音の表記は、n1, n1+4, n1+7 となります。
3和音のマイナーは、ルート(n1)に対し、3×(半音)と、7×(半音)を加えたものです。したがって、n1, n1+3, n1+7 となります。
「セブンス」(7の数値がついているもの)は、すべて4和音で定義されています。原則、3和音に1音加えたもの、となっています。
メジャーセブンスは、3和音のメジャーに、11×(半音)を加えたものです。したがって、n1, n1+4, n1+7, n1+11 となります。
セブンスは、3和音のメジャーに、10×(半音)を加えたものです。したがって、n1, n1+4, n1+7, n1+10 となります。
マイナーセブンスは、3和音のマイナーに、10×(半音)を加えたものです。したがって、n1, n1+3, n1+7, n1+10 となります。
上の表と対応したものとしています。
まとめ
Python で、任意のコード進行を再生するスクリプトについてまとめました。
パソコン1台さえあれば、コード進行の再生、作曲した音楽の再生などが可能になります。
当初、興味が沸いたので、「Just the Two of Us 」進行(椎名林檎の「丸の内サディスティック」進行)のコードをプログラミングで再生して確認したいと思いました。
プログラムを作ってみると、コード進行のファイルの追加は容易です。数分もかかりません。
そこで、パッヘルベルのカノン、Japanese Chord Progression(王道進行)など、オーソドックスなコード進行も加えました。
自力でコードを書いて再生してみると、和音、不協和音、3和音、4和音を聴き比べることができ、和音やコード進行についてよく理解できます。
楽器が使えなくても、ソフトウェアを使うことで、コード進行が自由自在に扱えるようになりました。
もっと昔からやっておけばよかった。。パソコン1台さえあれば、特殊な機材や高価なソフトウェア不要で、音階やコード進行が自由自在に扱えることになります。ネット検索をする限り、Python などのプログラミング言語を楽器替わりにして、名曲、ヒット曲などのコード進行を分析している人がほとんどいない?ような気がします。
なお、音楽に関連する Python のプログラムについては、以下の関連リンクなどでもまとめています。
興味のある方は参照してみてください。
関連リンク
・ ドレミファソラシドを鳴らすサンプル【Python】
・ キーボードピアノ 【本格49鍵!】
・ ブラウザでメロディーを鳴らす 【JavaScript】
・ ブラウザで電子ドラムを鳴らす 【JavaScript】
・ 指定範囲を繰り返し再生する音楽プレーヤー【Python】
・ 音声データの音量レベルを一括で変換する
・ Anaconda 環境で Pygame をインストールする手順【Python】
・ Pygame をインストールする手順
外部リンク
・ Grover Washington Jr. feat. Bill Withers – Just The Two of Us (YouTube)
再生用のサンプル(テキストで保存)
サンプル1: “01_just_the_two_of_us_chord1.txt” Just the Two of Us のコード進行
set_BPM1 80
1.0 F4_M7
1.0 F4_M7
1.0 E4_7
1.0 E4_7
1.0 A4_m7
1.0 A4_m7
1.0 G4_m7
1.0 C4_7
1.0 F4_M7
1.0 F4_M7
1.0 E4_7
1.0 E4_7
1.0 A4_m7
1.0 A4_m7
1.0 G4_m7
1.0 C4_7
サンプル2: “02_canon_progression_chord1.txt” パッヘルベルのカノンのコード進行
set_BPM1 80
1.0 D4_M
1.0 D4_M
1.0 A4_M
1.0 A4_M
1.0 B4_m
1.0 B4_m
1.0 Fs4_m
1.0 Fs4_m
1.0 G4_M
1.0 G4_M
1.0 D4_M
1.0 D4_M
1.0 G4_M
1.0 G4_M
1.0 A4_M
1.0 A4_M
1.0 D4_M
1.0 D4_M
1.0 A4_M
1.0 A4_M
1.0 B4_m
1.0 B4_m
1.0 Fs4_m
1.0 Fs4_m
1.0 G4_M
1.0 G4_M
1.0 D4_M
1.0 D4_M
1.0 G4_M
1.0 G4_M
1.0 A4_M
1.0 A4_M
サンプル3: “03_japanese_chord_progression1.txt” 王道進行 Japanese Chord Progression のコード進行
set_BPM1 80
1.0 F4_M
1.0 F4_M
1.0 G4_M
1.0 G4_M
1.0 E4_m
1.0 E4_m
1.0 A4_m
1.0 A4_m
1.0 F4_M
1.0 F4_M
1.0 G4_M
1.0 G4_M
1.0 E4_m
1.0 E4_m
1.0 A4_m
1.0 A4_m
サンプル4: “04_sample_CDEFGABC1.txt” ドレミファソラシド等を再生する例
set_duration1 0.5
1.0 C4
1.0 D4
1.0 E4
1.0 F4
1.0 G4
1.0 A4
1.0 B4
1.0 C5
1.0
set_duration1 1.5
1.0 C4 E4 G4
1.0 D4 G4 B4
2.0 C4 E4 G4
set_duration1 0.5
1.0 60
1.0 62
1.0 64
1.0 65
1.0 67
1.0 69
1.0 71
1.0 72
1.0
set_duration1 1.5
1.0 60 64 67
1.0 62 67 71
2.0 60 64 67
サンプル5: “05_just_the_two_of_us_chord_simplified1.txt” Just the Two of Us の簡略化バージョンの例
set_BPM1 80
# original
1.0 F4_M7
1.0 F4_M7
1.0 E4_7
1.0 E4_7
1.0 A4_m7
1.0 A4_m7
1.0 G4_m7
1.0 C4_7
2.0
# simplified 1
1.0 F4_M7
1.0 F4_M7
1.0 E4_7
1.0 E4_7
1.0 A4_m7
1.0 A4_m7
1.0 C4_7
1.0 C4_7
2.0
# simplified 2
1.0 F4_M
1.0 F4_M
1.0 E4_M
1.0 E4_M
1.0 A4_m
1.0 A4_m
1.0 C4_M
1.0 C4_M
サンプルスクリプト chord_player1.py
import os
import glob
import pygame.midi as pm1
import time as tm1
import tkinter as tk1
def read1(file1):
with open( file1, 'r', encoding='utf-8' ) as f1:
str1 = f1.read()
return str1
def get_a1(file1):
a1 = read1(file1).strip().split( "\n" )
a2 = []
for i1 in range(len(a1)):
str1 = a1[i1].strip()
if len(str1) == 0 or str1[0] == "#":
continue
else:
a2.append( str1.split( " " ) )
return a2
def CDEFGAB_to_semitones1(str1):
map1 = {"C":-9, "D":-7, "E":-5, "F":-4, "G":-2, "A":0, "B":2 }
return map1.get(str1.upper(), 0)
def CDEFGAB_to_midi1( str1 ):
str2 = str1.strip()
n1 = 69 + CDEFGAB_to_semitones1(str2[0]) # first character
if len(str2) > 1:
n1 = n1 + (int( str2[-1] )-4)*12 # last character, octave
if str2[1] == "s": # second character
n1 = n1 + 1
elif str2[1] == "#":
n1 = n1 + 1
elif str2[1] == "♯":
n1 = n1 + 1
elif str2[1] == "f":
n1 = n1 - 1
elif str2[1] == "b":
n1 = n1 - 1
elif str2[1] == "♭":
n1 = n1 - 1
return n1
def notation_to_midi1( str1, oct1 ):
str2 = str1.strip()
n1 = -1
a1 = []
if str2.isnumeric(): # MIDI note number, numeric
a1 = [ int( str2 )+oct1 ]
elif "_" in str2: # chord, multiple pitches
a2 = str2.split("_")
n1 = CDEFGAB_to_midi1( a2[0] ) + oct1 # root
if a2[1] == "M":
a1 = [ n1, n1+4, n1+7 ]
elif a2[1] == "m":
a1 = [ n1, n1+3, n1+7 ]
elif a2[1] == "M7":
a1 = [ n1, n1+4, n1+7, n1+11 ]
elif a2[1] == "7":
a1 = [ n1, n1+4, n1+7, n1+10 ]
elif a2[1] == "m7":
a1 = [ n1, n1+3, n1+7, n1+10 ]
elif a2[1] == "m7f5":
a1 = [ n1, n1+3, n1+6, n1+10 ]
else: # single pitch, scientific pitch note
n1 = CDEFGAB_to_midi1( str2 )
if n1 > 0:
n1 = n1 + oct1
a1 = [ n1 ]
return a1
def set_init1():
global len1
global vol1
global oct1
global chn1
global ins1
global busy1
len1 = 1.0
vol1 = 127
oct1 = 0 * 12
chn1 = 0
ins1 = 0 # instruments
busy1 = 0
def set_param1( a1 ):
global len1
if a1[0] == "set_BPM1": # beats per minute
len1 = 60.0 / float( a1[1] )
print( "len1:" + str(len1) )
elif a1[0] == "set_duration1": # sec
len1 = float( a1[1] )
print( "len1:" + str(len1) )
def tone1( a1, vol1 ):
global len1
if "set_" in a1[0]:
set_param1( a1 )
print( " ".join(a1) )
else:
a2 = []
for i1 in range( len(a1)-1 ):
a2 = a2 + notation_to_midi1( a1[i1+1], oct1 )
print( [ " ".join(a1), a2 ] )
for i1 in range( len(a2) ):
op1.note_on( a2[i1], vol1 )
tm1.sleep( float( a1[0])*len1 )
for i1 in range( len(a2) ):
op1.note_off( a2[i1], vol1 )
def play0():
global a0
global busy1
if busy1 < 1:
busy1 = 1
for a1 in a0:
tone1( a1, vol1 )
busy1 = 0
def play1():
frame1.after( 1000, play0 )
def click_list1( self ):
global file1
global list1
global n1
global a0
set_init1()
n1 = listbox1.curselection()[0]
file1 = list1[n1]
a0 = get_a1( file1 )
print( file1 )
frame1.after( 1000, play0 )
path1 = os.path.dirname(__file__) + "/chord1/"
list1 = glob.glob( path1 + "*.txt" )
n1 = 0
file1 = list1[n1]
a0 = get_a1( file1 )
print( a0 )
len1 = 1.0
vol1 = 127
oct1 = 0 * 12
chn1 = 0
ins1 = 0
busy1 = 0
set_init1()
pm1.init()
op1 = pm1.Output(0)
op1.set_instrument(ins1, chn1)
frame1 = tk1.Tk()
frame1.title( 'chord player v0.1' )
frame1.geometry( "350x270+100+100" )
btn1 = tk1.Button( frame1, text="play", command=play1 )
btn1.place( x=10, y=10, width=60 )
listbox1 = tk1.Listbox( frame1, selectmode='single' )
listbox1.place( x=10, y=50, width=305, height=200 )
scrollbar1 = tk1.Scrollbar(frame1, orient='v', command=listbox1.yview)
scrollbar1.place( x=305, y=50, height=200 )
listbox1.configure( yscrollcommand=scrollbar1.set )
for list2 in sorted( list1 ):
list3 = os.path.split( list2 )[1]
listbox1.insert('end', list3 )
listbox1.bind('<<ListboxSelect>>', click_list1 )
frame1.mainloop()
op1.close()
pm1.quit()

