Finitions et ajout du tempo.
[minwii.git] / src / songs / Song.py
1 '''
2 Created on 2 oct. 2009
3
4 @author: samsam
5 '''
6 import pickle
7 import os.path
8 try :
9 from MidiToSong import MidiToSong
10 from mxmMidi.MidiInFile import MidiInFile
11 except ImportError :
12 # loadSongFromMidi KO dans ce cas.
13 pass
14
15 class Song:
16 '''
17 classdocs
18 '''
19
20
21 def __init__(self,scale,notesInExtendedScale=[], requiresExtendedScale = False,midiNoteNumbers = None, alterationIndexes = None, alterations = None, modulationIndexes = None, modulationScales = None, lyrics =None, noteLengths = None, quarterNoteLength = 750, name = "unknownSong"):
22 '''
23 Constructor
24 '''
25 self.name = name
26 self.scale = scale
27 self.notes = notesInExtendedScale
28 self.lyrics = lyrics
29 self.noteLengths = noteLengths
30 self.quarterNoteLength = quarterNoteLength
31 if midiNoteNumbers == None :
32 self.midiNoteNumbers = [self.scale[note] for note in self.notes]
33 else:
34 self.midiNoteNumbers = midiNoteNumbers
35 if self.notes == [] :
36 self.assignNotesFromMidiNoteNumbers()
37 self.requiresExtendedScale = requiresExtendedScale
38 if alterationIndexes != None and alterations != None :
39 self.alterNotes(alterationIndexes, alterations)
40 if modulationIndexes != None and modulationScales != None :
41 self.modulate(modulationIndexes, modulationScales)
42
43 def getSongIterator(self):
44 while True:
45 for i in range(len(self.notes)):
46 if self.lyrics :
47 lyrics = self.lyrics[i]
48 else :
49 lyrics = None
50
51 if self.noteLengths :
52 noteLength = self.noteLengths[i]
53 else :
54 noteLength = 1
55
56 yield [self.notes[i],self.midiNoteNumbers[i],lyrics,noteLength]
57
58 def alterNotes(self,noteIndexes,alterations):
59 for i in range(len(noteIndexes)) :
60 self.midiNoteNumbers[noteIndexes[i]] = self.midiNoteNumbers[noteIndexes[i]] + alterations[i]
61
62 def modulate(self,modulationIndexes,scales):
63 for i in range(len(scales)):
64 if i < len(scales)-1 :
65 bound = modulationIndexes[i+1]
66 else :
67 bound = len(self.notes)
68 for j in range(modulationIndexes[i],bound):
69 self.midiNoteNumbers[j]=scales[i][self.notes[j]]
70
71 def assignNotesFromMidiNoteNumbers(self):
72 for i in range(len(self.midiNoteNumbers)):
73 noteInExtendedScale = 0
74 while self.midiNoteNumbers[i] > self.scale[noteInExtendedScale] and noteInExtendedScale < len(self.scale)-1:
75 noteInExtendedScale += 1
76 if self.midiNoteNumbers[i]<self.scale[noteInExtendedScale]:
77 noteInExtendedScale -= 1
78 self.notes.append(noteInExtendedScale)
79
80 def save(self,path = None):
81 if path == None :
82 path = "".join(os.path.join("smwis",self.name),".swmi")
83 f = file(path, 'w')
84 pickler = pickle.Pickler(f)
85 pickler.dump(self)
86 f.close()
87
88 def loadSongFromMidi(filePath,scale):
89 # get data
90 test_file = '../songs/midis/test.mid'
91 f = open(test_file, 'rb')
92
93 # do parsing
94 mts = MidiToSong()
95 midiIn = MidiInFile(mts, f)
96 midiIn.read()
97 f.close()
98
99 s = Song(scale,midiNoteNumbers = mts.midiNoteNumbers,quarterNoteLength = mts.quarterNoteLength,noteLengths = mts.noteLengths)
100 for nn in s.notes :
101 if nn < 3 :
102 s.requiresExtendedScale = True
103 return(s)
104
105 def loadSong(filePath):
106 f = file(filePath, 'r')
107 unpickler = pickle.Unpickler(f)
108 s = unpickler.load()
109 f.close()
110 return(s)
111
112 if __name__ == '__main__':
113
114 # get data
115 test_file = '../songs/midis/boheme.mid'
116 f = open(test_file, 'rb')
117
118 # do parsing
119 from mxmMidi.MidiInFile import MidiInFile
120 mts = MidiToSong()
121 midiIn = MidiInFile(mts, f)
122 midiIn.read()
123 f.close()
124
125 majorScale = [55, 57, 59, 60, 62, 64, 65, 67, 69, 71, 72]
126
127 s = Song(majorScale,requiresExtendedScale = True, midiNoteNumbers = mts.midiNoteNumbers,quarterNoteLength = mts.quarterNoteLength,noteLengths = mts.noteLengths)
128 for i in range(len(s.midiNoteNumbers)):
129 print "note number :" + str(s.midiNoteNumbers[i]) + ", assigned note :" + str(s.notes[i]) + ", duration :" + str(s.noteLengths[i])
130
131 s.lyrics = ["je","vous","par-","-le","d'un","temps","que","les","moins","de","vingt","ans","ne","peu-","-vent","pas","con-","-nai-","-tre","Mont-","-martre","en","ce","temps","la","ac-","-cro-","-chait","ses","li-","-las","jus-","-que","sous","nos","fe-","-netres","et","si","l'hum-","-ble","gar-","-ni","qui","nous","ser-","-vait","de","nid","ne","pay-","-yait","pas","de","mi-","-ne","c'est","la","qu'on","s'est","con-","-nus","moi","qui","cri-","-ait","fa-","-mine","et","toi","qui","po-","-sait","nue","la","bo-","-he-","-me","la","bo-","-he-","-me","ca","vou-","-lait","dire","on","est","heu-","-reux","la","bo-","-he-","-me","la","bo-","-he-","-me","nous","ne","man-","-gions","qu'un","jour","sur","deux"]
132
133 #s.lyrics = ["quand","nous","chan-","-te-","-rons","le","temps","des","ce-","-rises","et","gai","ros-","-si-","-gnol","et","mer-","-le","mo-","-queur","se-","-ront","tous","en","fe-","-e-","-te","les","bel-","-les","au-","-ront","la","fo-","-lie","en","te","te","et","les","a-","-mou-","-reux","du","so-","-leil","au","coeur","quand","vous","chan-","-te-","-rez","le","temps","des","ce-","-rises","sif-","-fle-","-ra","bien","mieux","le","mer-","-le","mo-","-queur"]
134
135 #s.lyrics=["il","pleut","il","pleut","ber-","-ge-","-re","ren-","-tre","tes","blancs","mou-","-tons","al-","-lons","a","ma","chau-","-mie-","-re","ber-","-ge-","-re","vite","al-","-lons","j'en-","-tends","sur","le","feu-","-illa-","-ge","l'eau","qui","tombe","a","grand","bruit","voi-","-ci","ve-","-nir","l'o-","-ra-","-a-","-ge","voi-","-ci","l'e-","-clair","qui","luit"]
136
137 #s.lyrics = ["c'est","une","chan-","-son","qui","nous","res-","-sem-","-ble","toi","tu","m'ai-","-mais","et","je","t'ai-","-mais","nous","e-","-tions","tout","les","deux","en-","-sem-","-ble","toi","qui","m'ai-","-mais","moi","qui","t'ai-","-mais","mais","la","vie","se-","-pare","ceux","qui","s'aiment","tout","dou-","-ce-","-ment","sans","faire","de","bruit","et","la","mer","ef-","-fa-","-ce","sur","le","sa-","-ble","les","pas","des","a-","-mants","de-","-su-","-nis"]
138
139 # s.lyrics = ["quand","il","me","prend","dans","ses","bras","qu'il","me","par-","-le","tout","bas","je","vois","la","vie","en","ro-","-se","il","me","dit","des","mots","d'a-","-mour","des","mots","de","tous","les","jours","et","ca","m'fait","quel-","-que","cho-","-se","il","est","en-","-tre","dans","mon","coeur","u-","-ne","part","de","bon-","-heur","dont","je","con-","-nais","la","cau-","-se","c'est","lmui","pour","moi","moi","pour","lui","dans","la","vie","il","m'a","pro-","-mis","m'a","ju-","-re","pour","la","vie","et","des","que","je","l'a-","-per-","-cois","a-","-lors","je","sens","en","moi","mon","coeur","qui","bat"]
140
141 s.save("smwis/boheme.smwi")