3.03 Chord pattern and Timpani ============================== - Using Chord pattern like in the versions 2.08 and 2.09 - Adding a easy drum function controlled by the volume. - The range and the acceptance functions are not in use. .. 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 Transform Meteorological data ----------------------------- .. code:: python3 def scale(a): return (a-a.min())/(a.max()-a.min()) def read_meteo_data(fName): colNames = ['Stao','time', 'T_Boden_20cm', 'V_Windböe', 'T_Chill', 'Flash_30km', 'Glob_rad', 'QFE','T_2m','Flash_3km','Rain_Sum','Rain_intens','H_rel','visibi','V_wind','stabw_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_74947_data.txt' dM = read_meteo_data(fPath+fName) #---- Parameter bestimmen ----------- NT, MP = dM.shape print('-----------------') print('NT, MP', NT, MP) .. parsed-literal:: Stao time T_Boden_20cm V_Windböe T_Chill Flash_30km Glob_rad \ 0 KLO 201908270000 20.4 1.2 14.2 0 2 1 KLO 201908270010 20.4 0.9 14.4 0 2 2 KLO 201908270020 20.4 1.1 14.4 0 1 3 KLO 201908270030 20.4 0.8 13.8 0 2 4 KLO 201908270040 20.4 0.5 14.2 0 2 QFE T_2m Flash_3km Rain_Sum Rain_intens H_rel visibi V_wind \ 0 968.2 14.2 0 0.0 0.0 99.6 6626.0 0.7 1 968.2 14.4 0 0.0 0.0 98.5 1277.0 0.5 2 968.2 14.4 0 0.0 0.0 98.6 4900.0 0.5 3 968.3 13.8 0 0.0 0.0 99.0 7417.0 0.6 4 968.2 14.2 0 0.0 0.0 99.7 981.0 0.4 stabw_V_wind direction_wind 0 9 110 1 40 198 2 28 333 3 4 326 4 30 256 ----------------- NT, MP 2160 17 **Chords and scales** .. code:: python3 major = np.array([ 0, 2, 4, 5, 7, 9, 11]) minor = np.array([ 0, 2, 3, 5, 7, 8, 10]) C7 = np.array([ 0, 4, 7, 10]) CM7 = np.array([ 0, 4, 7, 11]) Cm7 = np.array([ 0, 3, 7, 10]) Cm = np.array([ 0, 3, 7]) Cdim = np.array([ 0, 3, 6]) C = np.array([ 0, 4, 7]) power= np.array([ 0, 7]) B= np.array([ 0]) **met\_transform** - the **rolling mean** is to remove noise on the data. - the **factors** are used to scale the melody, such that it plays in a certain range - **start** defines the staring point of the melodies by removing the begin of the data Tune\_W ------- - This tune uses the temperature and humidity - With bassoon and clarinet - Chord pattern Cm Ab Fm Ddim G7 Cm Fm G7 .. code:: python3 def tune_W(): tune_name = 'tune_W' np.random.seed(39) #56 bar, bpb = 15, 4 # bar: Takt , bpb: beat per bar melody_len = bar * bpb mpb = 120 #minutes per beat. start =10 # start in hours # met_transform: [Factor for each data serie] ,[numbers of value for the rolling mean] trans = met_transform(dM,[1,1,1,1,0.5,1,0.38,1,1,1,0.1,1,4.5,1,1,],[6,6,6,6,6,6,6,6,6,6,6,6,6,6,2],start) scales = [[1,Cm],[1,C+8],[1,Cm+5],[1,Cdim+2],[1,C7+7],[1,Cm],[1,Cm+5],[1,C7+7]] end_scale = [[1,Cm],[1,power]] pattern = pattern_gen(scales, end_scale, melody_len) # humidity range_1 = liniar_range(0,0,0,0) # not in use rythem1, notenr_1 = ran_duration([1/16,1/8, 1/4,1/2], [0,2,3,1], melody_len) melody1 = meteo_melody(trans[10],pattern, 60, range_1, notenr_1, rythem1,mpb) volumes1 = ran_volume([0,120], [1,8], notenr_1 ) notes1 = NoteSeq( [Note(no,octave=0, dur=du, volume=vo) for no,du,vo in zip(melody1,rythem1,volumes1)] ) # temperature 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) melody2 = meteo_melody(trans[6],pattern, 66, range_2, notenr_2, rythem2,mpb) volumes2 = ran_volume([0,120], [1,8], notenr_2 ) notes2 = NoteSeq( [Note(no,octave=0, dur=du, volume=vo) for no,du,vo in zip(melody2,rythem2,volumes2)] ) instruments = [70,71] notes = [notes1,notes2] return notes, instruments,tune_name .. raw:: html
tune_W
tune_W


Tune\_X ------- - Major-scale - it is the rain of the 8.09.2019. See 3.03.1 Display meteorological data - Air-pressure and temperature as melody. - Air-pressure and temperature are during this rain sequence relatively constant. So the melody does often play the same note - The volume of the timpani is controlled by the amount of rain. The data is magnified by a large factor. The peaks are then cut of. Otherwise the drum would only be heard for a short moment. Met\_percus ~~~~~~~~~~~ - met\_percus is an function to create an easy drum - the played note can be a single note or an list of several notes which is repeated .. code:: python3 def met_percus(meteo, note,frequ,volume, melody_len, mpb): note_nr = int(melody_len/(frequ*4)) #print(melody_len,mpb,note_nr) rythem = np.repeat(frequ,note_nr) melody = np.repeat(note,note_nr/len(note)) volume = np.zeros(note_nr, dtype=int) for npn in range(note_nr): #npn: note per note (index) met_resolution = 10 beat_nr = npn*frequ*4 #find beat nr i_met = np.round((beat_nr*mpb)/met_resolution).astype(int) # calulate index of the data array vol = meteo[i_met] # take the diffrence of the data vol = np.round(vol).astype(int) # round to an int volume[npn]= vol volume = np.where(volume > 127, 127, volume) return melody, rythem, volume .. code:: python3 def tune_X(): tune_name = 'tune_X' #np.random.seed(56) bar, bpb = 13, 4 # bar: Takt , bpb: beat per bar melody_len = bar * bpb mpb = 60 #minutes per beat. start =276 # start in hours trans = met_transform(dM,[1,1,1,1,1,4,0.8,1,500,1,0.2,1,4.5,4,1,],[6,6,6,6,6,6,6,6,6,6,6,6,6,6,2],start) scales = [[8,major]] end_scale = [[3,power]] 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) melody1 = meteo_melody(trans[5],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) melody2 = meteo_melody(trans[6],pattern, 65, 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 # met_percus( meteo-data, ) melody3, rythem3, volumes3 = met_percus(trans[8], [72,73,74], 1/16, [30,120], melody_len, mpb) notes3 = NoteSeq( [Note(no,octave=0, dur=du, volume=vo) for no,du,vo in zip(melody3,rythem3,volumes3)] ) instruments = [70,61,47] notes = [notes1,notes2,notes3] return notes, instruments,tune_name .. raw:: html
tune_X
tune_X


**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_W() # <--- 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) .. image:: output_17_0.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