3.04 Improving Drum
===================
- Split met\_percussion in different functions and improved them. So
they can also be used differently.
- Create print start end\_, drum and meteorological volume functions.
- Weather period from 1.8.2019 to 28.8.2019
.. code:: python3
from pyknon.genmidi import Midi
from pyknon.music import Rest, Note, NoteSeq
from music_generation import*
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as plticker
from datetime import date
Read Meteorological Data
~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: python3
def read_meteo_data(fName):
colNames = ['Stao','time', 'T_Boden_20cm', 'Flash_30km', 'Glob_rad', 'QFE','T_2m','Rain_Sum','H_rel','visibi','V_wind','direction_wind']
df = pd.read_csv(fName,sep=';', skiprows=3, names=colNames, na_values='-')
print(df.head())
return df
fPath = '/mnt/daten/04_Schule/42_Kanti/Matrua/Music_generation/Organisation/MeteoSchweiz/Daten/'
fName = 'order_75330_data.txt'
dM = read_meteo_data(fPath+fName)
NT, MP = dM.shape
.. parsed-literal::
Stao time T_Boden_20cm Flash_30km Glob_rad QFE T_2m \
0 KLO 201908010000 21.5 0 2 969.5 15.3
1 KLO 201908010010 21.5 0 2 969.5 14.9
2 KLO 201908010020 21.5 0 2 969.5 14.6
3 KLO 201908010030 21.5 0 2 969.5 14.6
4 KLO 201908010040 21.4 0 2 969.6 13.7
Rain_Sum H_rel visibi V_wind direction_wind
0 0.0 80.4 20000.0 0.9 117
1 0.0 82.4 20000.0 1.1 98
2 0.0 83.7 20000.0 1.0 121
3 0.0 82.7 20000.0 1.2 119
4 0.0 88.8 20000.0 1.0 173
Chords and scales
~~~~~~~~~~~~~~~~~
.. code:: python3
C = np.array([ 0, 4, 7])
Cm = np.array([ 0, 3, 7])
Cdim = np.array([ 0, 3, 6])
CM7 = np.array([ 0, 4, 7, 11])
C7 = np.array([ 0, 4, 7, 10])
Cm7 = np.array([ 0, 3, 7, 10])
Cdim7 = np.array([ 0, 3, 6, 10])
Cdim6 = np.array([ 0, 3, 6, 9 ])
C6 = np.array([ 0, 4, 7, 9 ]) # inversion of Am7
Cm6 = np.array([ 0, 3, 7, 9 ])
Csus4 = np.array([ 0, 5, 7])
Csus2 = np.array([ 0, 2, 7])
Csus47= np.array([ 0, 5, 7, 10])
P = np.array([ 0,7]) # Power chord (Perfect unison, Perfect fifth)
B = np.array([ 0]) # Bass (Perfect unison)
major = np.array([ 0, 2, 4, 5, 7, 9, 11])
minor = np.array([ 0, 2, 3, 5, 7, 8, 10])
blues = np.array([ 0, 3, 5, 6, 7, 10])
Drum
~~~~
- Together with **on\_off** and **met\_vol** it replaces
**met\_percus** of the previous version.
- Creates a regular drum track by defining a rhythmic, note and volume
pattern.
- the volume can be overwritten be the **met\_vol** function.
.. code:: python3
def drum(rythems,notes,volumes,melody_len):
ryth_rep = int((melody_len/(np.sum(rythems)*4))+1) # calculate repeat factor
rythem = np.tile(rythems,ryth_rep) # tile
rythem = np.delete(rythem, np.argwhere(np.cumsum(rythem)*4 >= melody_len)) # delete not used notes
note_nr = len(rythem)
melody_rep = int(note_nr/len(notes)+1) # calculate repeat factor
melody = np.tile(notes,melody_rep) # tile
melody = melody[:note_nr] # delete not used notes
volume_rep = int(note_nr/len(volumes)+1) # calculate repeat factor
volume = np.tile(volumes,volume_rep) # tile
volume = volume[:note_nr] # delete not used notes
return melody, rythem, volume
Meteorological Volume
~~~~~~~~~~~~~~~~~~~~~
- Generates out of meteorological data a Volume track.
- Uses the rhythm to calculate the position in the meteorological data.
- Volumes can be in or decreased by a value (add).
- Maximum value is 127 as this is the maximum MIDI-Volume.
.. code:: python3
def met_vol(meteo, add, rythem, mpb):
met_resolution = 10
cum_ryth = np.concatenate((np.asarray([0]),np.cumsum(rythem)))[:-1] # add 0 at beginig remove last element
i_data = (cum_ryth * (mpb /met_resolution)).astype(int) # calculate index of the data
volumes = meteo[i_data].astype(int) # fill in meteo data
volumes = volumes + add # add
volumes = np.minimum(volumes, 127) # set values bigger than 127 to 127
return volumes
Print Start and End
~~~~~~~~~~~~~~~~~~~
- Prints the end and starting point of the actual tune.
- Calculates melody\_len and Start
.. code:: python3
def print_dur(bar,bpb,mpb,s_day,s_hour,tune_name):
start = (s_day*24)+ s_hour # start in hours
melody_len = bar * bpb
S_h = start%24
S_d = start//24
dur_h = melody_len *mpb/60
E_h = (start+dur_h)%24
E_d = (start+dur_h)//24
print(tune_name+': Start:',S_d,'day',S_h,'h End:', E_d,'day',E_h,'h')
return melody_len, start
tune 304\_A
-----------
- This tune is similar to the previous one. but the function used where
changed and improved.
- Period from 5.8 to 7.8.2019
.. code:: python3
def tune_304_A():
tune_name = 'tune_304_A'
#np.random.seed(56)
bar, bpb = 15, 4 # bar: Takt , bpb: beat per bar
s_day, s_hour = 4, 18 # Start point in the data
mpb = 60 # minutes per beat
end_dur = 0
melody_len, start = print_dur(bar,bpb,mpb,s_day,s_hour,tune_name)
trans = met_transform(dM,[1,1,1,4,1.3,400,0.2,1,4.5,1,],[6,6,6,6,6,24,6,6,6,2],start)
scales = [[8,'C',major]]
end_scale = [[1,'C',P]]
pattern = pattern_gen(scales, end_scale, melody_len)
# Pressure
range_1 = liniar_range(0,0,0,0)
rythem1, notenr_1 = ran_duration([1/32,1/8, 1/4,1/2], [0,2,3,1], melody_len, end_dur)
melody1 = meteo_melody(trans[3],pattern, 60, range_1, notenr_1, rythem1,mpb)
volumes1 = ran_volume([0,100], [1,8], notenr_1 )
notes1 = NoteSeq( [Note(no,octave=0, dur=du, volume=vo) for no,du,vo in zip(melody1,rythem1,volumes1)] )
# temp
range_2 = liniar_range(0,0,0,0)
rythem2, notenr_2 = ran_duration([1/16,1/8, 1/4,1/2], [0,2,3,2], melody_len, end_dur)
melody2 = meteo_melody(trans[4],pattern, 80, range_2, notenr_2, rythem2,mpb)
volumes2 = ran_volume([0,100], [1,8], notenr_2 )
notes2 = NoteSeq( [Note(no,octave=0, dur=du, volume=vo) for no,du,vo in zip(melody2,rythem2,volumes2)] )
#timpani rain
melody3, rythem3, volumes3 = drum([1/16,1.5/16], [60,63,66],[100,127],melody_len)
volumes3 = met_vol(trans[5],0,rythem3, mpb)
notes3 = NoteSeq( [Note(no,octave=0, dur=du, volume=vo) for no,du,vo in zip(melody3,rythem3,volumes3)] )
instruments = [48,48,47]
notes = [notes1,notes2,notes3]
return notes, instruments,tune_name
.. raw:: html
tune_304_A
tune_304_A
**Instruments:** Available are at lest the 128 General-Midi (GM)
Instruments. Depending on the sound-fonts there is a bigger choice. A
list of the GM instruments can be found here.
https://jazz-soft.net/demo/GeneralMidi.html
Generate Midi and Audio file
----------------------------
.. code:: python3
def gen_midi():
# squezze into a MIDI framework
notes, instruments, tune_name = tune_304_A() # <--- select a tune <<-- <<<<<<<<<--- select a tune -----
nTracks = len(notes)
m = Midi(number_tracks=nTracks, tempo=120, instrument=instruments)
for iTrack in range(nTracks):
m.seq_notes(notes[iTrack], track=iTrack)
#--- write the MIDI file -----
midi_file_name = tune_name +'.mid' # set the name of the file
m.write(midi_file_name)
return midi_file_name
.. code:: python3
######--- Main ---######
midi_file_name = gen_midi()
midi_play(midi_file_name)
midi_audio(midi_file_name)
midi_png(midi_file_name)
.. parsed-literal::
tune_304_A: Start: 4 day 18 h End: 7.0 day 6.0 h
.. image:: output_18_1.png
External **Music\_Generation** library
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This library changes from version to version. New or changed code is
first explained above. This is a copy of music\_generation.py
.. literalinclude:: music_generation.py
:language: python