def recordAll(score, args, splitRecord = [], counter = 1): #score needs to be flat
   #splitRecord is used to split the original score into pieces
   #because it is possible that the splitRecord is generated by structural 
   #analysis in the future, so we seperate the score splitting code after all 
   #recording are finished
   #record perfs and generate split file
   if len(score) == 0:
      #splitRecFilename= args.outputDir
      #splitRecFilename+= settings.getScoreName(args.scoreFilename)+'.split.json'
      splitRecFilename = settings.getSplitRecFilename(args.scoreFilename, 
                                                      args.outputDir)
      with open(splitRecFilename, 'w') as f:
         simplejson.dump(splitRecord, f, indent = 3)

      print('[INFO] splitting record saved to ' + splitRecFilename)
      return
   else:
      try:
         print("[INFO] Now playing score."),
         print("You can start to record anytime by pressing Ctrl+c")
         record.playStream(score); #provide stop button
      except KeyboardInterrupt:
         pass
      print("[INFO] =====Now recording phrase no." + str(counter) + "=====")
      #recLogFilename = settings.getRecLogFilename(args.scoreFilename +'.'+ str(counter))
      #recLogFilename = args.outputDir + settings.getScoreName(args.scoreFilename)
      #recLogFilename += '.'+ str(counter) + '.log'
      recLogFilename = settings.getRecLogFilename(counter, 
                                                  args.scoreFilename, 
                                                  args.outputDir)
      settings.printDebug(recLogFilename)
      record.record(score, recLogFilename)
      perf = musicGenerator.generatePerf(score, recLogFilename)
      #outFilename= args.outputDir + settings.getScoreName(args.scoreFilename)
      #outFilename+= '.'+ str(counter) + '.perf' + settings.defaultOutputFormat
      outFilename = settings.getOutFilename(counter, 
                                            args.scoreFilename,
                                            args.outputDir)
      musicGenerator.savePerf2File(perf, outFilename)
      scoreHead= score[:len(perf)]
      #if settings.DEBUG:
      #   settings.printDebug('')
      #   scoreHead.show('text')

      scoreTail= score[len(perf):]
      #if settings.DEBUG:
         #settings.printDebug('')
         #scoreTail.show('text')
      scoreHeadOffsets = [n.offset for n in scoreHead]
      splitRecord.append(scoreHeadOffsets)
      settings.printDebug(splitRecord)
      #splitRecord.extend(scoreHead)
      #capture mouse
      #pos = pygame.mouse.get_pos()
      #print("mouse position: "+pos)
      recordAll(scoreTail, args, splitRecord, counter+1)
Example #2
0
def record(recLogFilename):
   period = 1; # in ms
   cmd = ['synclient',  '-m' , str(period)];
   settings.printDebug(cmd)
   key = 'r';
   while (key != ''):
      with open(recLogFilename, 'w') as outfile:
         p = subprocess.Popen(cmd, stdout = outfile);
      key = raw_input('Press ENTER to continue, "r"-Enter to restart.');
      settings.printDebug(key)
      p.kill();
Example #3
0
def split(splitRecFilename, origScoreFilename, outputDir):
   with open(splitRecFilename, 'r') as f:
      splitRec = simplejson.load(f)
   origScore = music21.converter.parse(origScoreFilename)

   timeSigList = computeTimeSigList(origScore)
   settings.printDebug(timeSigList)   

   #scoreElemsAll is all notational elements for each segments
   #e.g. [[timeSig1, key1], [timeSig2, key2]...]
   scoreElemsAll= zip(timeSigList) #may have key etc 

   #for offsetSegment, scoreElems in zip(splitRec, scoreElemsAll):
   writeSegments(splitRec, scoreElemsAll, origScore, outputDir, origScoreFilename)
def savePerf2File(perf, outFilename):
   tempo = music21.tempo.MetronomeMark(number=120)
   onsetDuraObjs= [tempo.secondsToDuration(n['onset']) for n in perf]
   #for d in onsetDuraObjs:
   #   settings.printDebug(d) 
   onsets = [d.quarterLength for d in onsetDuraObjs ]
   
   durations= [tempo.secondsToDuration(n['duration']) for n in perf]
   velocities= [n['velocity'] for n in perf]
   pitches = [n['pitch'] for n in perf]
   outStream = music21.stream.Stream()
   for onset, duration, vel, pitch in zip(onsets, durations, velocities, pitches):
      note = music21.note.Note()
      note.duration = duration
      note.volume.velocity = vel
      note.pitch = pitch
      settings.printDebug(onset)
      settings.printDebug(note)
      outStream.insert(onset, note)
   settings.printDebug('')
   if settings.DEBUG: outStream.show('text')
   midifile = music21.midi.translate.streamToMidiFile(outStream)
   midifile.open(outFilename, 'wb')
   midifile.write()
   midifile.close()
   print('[INFO] Expressive performance wrote to ' + outFilename)
def record(score, recLogFilename):
   period = 1; # in ms
   print("[INFO] Remember to turn on SHMConfig for the touchpad. See README for detail.")
   cmd = ['synclient',  '-m' , str(period)]
   settings.printDebug(cmd)
   p = subprocess.Popen(cmd, stdout = subprocess.PIPE)
   print('[INFO] Press Ctrl+c to cut off the current phrase.')
   noteIter = iter(score)
   recLogLines = ['time\t y\t z\t f\t w\t l\t r\t u\t d\t m\t multi\n']
   prevFingerCount= 0
   while True:
      try:
         line  = p.stdout.readline()
         settings.printDebug(line),
         sys.stdout.flush()

         if len(line.split()) != 12:
            settings.printDebug('Not a data line format. Skipped.'),
            continue;

         (time, x, y, z, f, w, l, r, u, d, m, multi) = line.split();
         fingerCount = int(f)

         if fingerCount > prevFingerCount:
            #Note on event
            settings.printDebug("Note ON")
            try:
               note = noteIter.next()
            except StopIteration:
               print('[ERROR]: Your recording is longer than the score. Force cut.')
               break
               #raise Exception('[ERROR]: Your recording is longer than the score. Stopped')
            t = threading.Thread(target=playNote, args=(note,))
            t.start()
            #playNote(note)

         recLogLines.append(line)
         prevFingerCount = fingerCount

      except KeyboardInterrupt:
         print('[INFO] Current phrase is cut by user')
         break 

   p.kill()
   with open(recLogFilename, 'w') as f:
      f.writelines(recLogLines)
def parseRecLog(filename):
   recLog = []
   settings.printDebug(filename)
   with open(filename, 'r') as recLogFile:
      for line in recLogFile: 
         #settings.printDebug(line.split())
         #if len(line.split()) == 17: 
         #   (time, x, y, z, f, w, l, r, u, d, m, multi, gl, gm, gr, gdx, gdy) = line.split(); 
         if len(line.split()) == 12:
            (time, x, y, z, f, w, l, r, u, d, m, multi) = line.split();
            try: 
               recLog.append({'time': float(time), 'pressure': int(z), 'fingerCount': int(f)})
            except ValueError:
               settings.printDebug('Title line, skipped')
               pass
         else:
            settings.printDebug('Not a data line format in ' + filename + ". Skipped.");
            continue;
   return recLog
def generatePerf(score, recLogFilename):
   recLog = parseRecLog(recLogFilename)
   queue = deque() #enqueue from right, dequeue from left
   perf = []
   noteIter = iter(score)
   for prevLine, thisLine in zip(recLog, recLog[1:]):
      if thisLine['fingerCount'] > prevLine['fingerCount']:
         try:
            note = noteIter.next()
         except StopIteration:
            raise Exception('[ERROR]: Your recording is longer than the score. Stopped')
         queue.append({'onset':thisLine['time'], 
                       'velocity': thisLine['pressure'],
                       'pitch': note.pitch,
                       'duration': None
                       })
         settings.printDebug(queue)
      elif thisLine['fingerCount'] < prevLine['fingerCount']:
         note = queue.popleft()
         settings.printDebug(queue)
         note['duration'] = thisLine['time'] - note['onset'] 
         perf.append(note)
   settings.printDebug(perf)
   return perf
Example #8
0
def writeSegments(splitRec, scoreElemsAll, origScore, 
                  outputDir, scoreFilename, counter = 1): #score needs to be flat
   #see split for def of scoreElemsAll
   if len(splitRec) == 0:
      return 

   splitRecHead = splitRec[0]
   splitRecTail = splitRec[1:]
   scoreElemsAllHead = scoreElemsAll[0]
   scoreElemsAllTail = scoreElemsAll[1:]

   minOffset = min(splitRecHead)
   maxOffset = max(splitRecHead)
   settings.printDebug(origScore)
   scoreSegment = (origScore.flat.getElementsByOffset(minOffset, maxOffset))
   if settings.DEBUG:
      settings.printDebug('')
      scoreSegment.show('text')

   settings.printDebug(scoreSegment[0].offset)
   for scoreElem in scoreElemsAllHead:
      scoreSegment.insert(scoreSegment[0].offset, scoreElem)

   if settings.DEBUG:
      settings.printDebug('')
      scoreSegment.show('text')
   #settings.printDebug(scoreSegment.notes[0])
   #settings.printDebug(scoreSegment.notes[0].beat)

   scoreSegment.shiftElements(-(scoreSegment.lowestOffset)) 
   # segment no >2 need shift, or will have heading rests

   # If not start at first beat, insert rests
   # However, the "beat" is right but "offset" is not. 
   # Inserting rest will increase readability. But may screw up beat
   startBeat = scoreSegment.notes[0].beat 
   if startBeat > 1: # If not start at first beat, insert rests
      r = music21.note.Rest(quarterLength=(startBeat-1))
      settings.printDebug(r.quarterLength)
      scoreSegment.insertAndShift(scoreSegment.notes[0].offset, r)

   if settings.DEBUG:
      settings.printDebug('')
      scoreSegment.show('text')
      


   scoreMeasures = scoreSegment.makeMeasures()

   #splittedScoreFilename = outputDir + scoreName 
   #splittedScoreFilename += '.'+ str(counter) + '.score.xml'
   splittedScoreFilename = settings.getSplittedScoreFilename(counter, 
                                                             scoreFilename, 
                                                             outputDir)
   scoreMeasures.write(settings.defaultScoreFormatName, splittedScoreFilename)
   print('[INFO] Splitted score saved to ' + splittedScoreFilename)

   writeSegments(splitRecTail, scoreElemsAllTail, origScore, 
                 outputDir, scoreFilename, counter+1)
   return 
      for elem in sop.flat:
         if elem.isChord:
            tmpElem = elem[0]
         else:
            tmpElem = elem
         output.append(tmpElem)
      #settings.printDebug(os.path.dirname(scoreName))
      #settings.printDebug(os.path.basename(scoreName))
      #settings.printDebug(os.path.splitext(scoreName))
      #settings.printDebug(os.path.split(scoreName))
      #pathElems = os.path.split(scoreName)[:-1]
      if useCorpus:
         pieceName = scoreName
      else:
         pieceName = os.path.basename(scoreName)
      settings.printDebug(pieceName)
      pathWOtitle= os.path.splitext(pieceName)[0]
      workTitle = '.'.join(pathWOtitle.split('/'))
      #workTitle = os.path.splitext(os.path.basename(scoreName))[0]
      
      outFilename = outputDir + workTitle+ '.score.xml'
      output.write('musicxml', outFilename)
      print('[INFO] '+ outFilename + ' created.')

      #outFilename = outputDir + workTitle+ '.score.mid'
      #sop.write('midi', outFilename)
      #print('[INFO] '+ outFilename + ' created.')
   except (ValueError, AttributeError):
      print('[ERROR] '+ scoreName+ ' conversion FAILED.')
      pass