-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathFeatureExtractor.py
executable file
·173 lines (120 loc) · 7.15 KB
/
FeatureExtractor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
'''
Created on May 27, 2015
@author: joro
'''
import os
import sys
import numpy as np
import logging
import htkmfc
import subprocess
import essentia.standard
import math
import json
### include src folder
import os
import sys
projDir = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__) ), os.path.pardir, os.pardir))
if projDir not in sys.path:
sys.path.append(projDir)
import tempfile
parentDir = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(sys.argv[0]) ), os.path.pardir, os.path.pardir))
pathSMS = os.path.join(parentDir, 'sms-tools')
from predominantmelodymakam.predominantmelodymakam import PredominantMelodyMakam
# print '\n sys.path:' + sys.path + '\n'
# if pathSMS not in sys.path:
# sys.path.append(pathSMS)
from src.smstools.workspace.harmonicModel_function import extractHarmSpec, resynthesize
# from harmonicModel_function import extractHarmSpec, resynthesize
from src.utilsLyrics.Utilz import readListOfListTextFile_gen, writeCsv
import src.utilsLyrics.UtilzNumpy
projDir = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)) , os.path.pardir ))
parentParentDir = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__) ), os.path.pardir))
from ParametersAlgo import ParametersAlgo
class FeatureExtractor(object):
def __init__(self, path_to_hcopy, sectionLink):
self.path_to_hcopy = path_to_hcopy
self.featureVectors = []
def loadMFCCs(self, URI_recording_noExt, extractedPitchList, sectionLink):
'''
for now lead extracted with HTK, read in matlab and seriqlized to txt file
'''
URI_recording = URI_recording_noExt + '.wav'
URIRecordingChunkResynthesized = sectionLink.URIRecordingChunk + '.wav'
logging.info("working on sectionLink: {}".format(URIRecordingChunkResynthesized))
# resynthesize audio chunk:
if ParametersAlgo.POLYPHONIC:
if not os.path.isfile(URIRecordingChunkResynthesized): # only if resynth file does not exist
logging.info("doing harmonic models and resynthesis for segment: {} ...".format(URIRecordingChunkResynthesized))
if extractedPitchList == None:
extractedPitchList= extractPredominantPitch( URI_recording_noExt, 2048, 128, jointAnalysis=True, )
hfreq, hmag, hphase, fs, hopSizeMelodia, inputAudioFromTsToTs = extractHarmSpec(URI_recording, extractedPitchList, sectionLink.beginTs, sectionLink.endTs, ParametersAlgo.THRESHOLD_PEAKS)
resynthesize(hfreq, hmag, hphase, fs, hopSizeMelodia, URIRecordingChunkResynthesized)
else:
sampleRate = 44100
loader = essentia.standard.MonoLoader(filename = URI_recording, sampleRate = sampleRate)
audio = loader()
audioChunk = audio[sectionLink.beginTs*sampleRate : sectionLink.endTs*sampleRate]
monoWriter = essentia.standard.MonoWriter(filename=URIRecordingChunkResynthesized)
monoWriter(audioChunk)
# call htk to extract features
URImfcFile = self._extractMFCCs( URIRecordingChunkResynthesized)
# read features form binary htk file
logging.debug("reading MFCCs from {} ...".format(URImfcFile))
HTKFeat_reader = htkmfc.open(URImfcFile, 'rb')
mfccsFeatrues = HTKFeat_reader.getall()
if ParametersAlgo.FOR_MAKAM and ParametersAlgo.OBS_MODEL == 'GMM': # makam mdoels are trained with 25-dim features (no energy, no deltadeltas )
mfccs_no_energy = mfccsFeatrues[:,0:12]
mfccDeltas = mfccsFeatrues[:,13:26]
mfccsFeatrues = np.hstack((mfccs_no_energy, mfccDeltas))
return mfccsFeatrues
def _extractMFCCs( self, URIRecordingChunk):
baseNameAudioFile = os.path.splitext(os.path.basename(URIRecordingChunk))[0]
dir_ = os.path.dirname(URIRecordingChunk)
# dir_ = tempfile.mkdtemp()
mfcFileName = os.path.join(dir_, baseNameAudioFile ) + '.mfc'
if ParametersAlgo.OBS_MODEL == 'MLP' or ParametersAlgo.OBS_MODEL == 'MLP_fuzzy': # only one type of features trained
PATH_TO_CONFIG_FEATURES = projDir + '/models_makam/input_files/wav_config_default'
elif ParametersAlgo.OBS_MODEL == 'GMM':
if ParametersAlgo.FOR_JINGJU:
PATH_TO_CONFIG_FEATURES = projDir + '/models_makam/input_files/wav_config_singing_yile' # no singal amplitude normalization
elif ParametersAlgo.FOR_MAKAM:
PATH_TO_CONFIG_FEATURES = projDir + '/models_makam/input_files/wav_config_singing_makam'
HCopyCommand = [self.path_to_hcopy, '-A', '-D', '-T', '1', '-C', PATH_TO_CONFIG_FEATURES, URIRecordingChunk, mfcFileName]
if not os.path.isfile(mfcFileName):
logging.info(" Extract mfcc with htk command: {}".format( subprocess.list2cmdline(HCopyCommand) ) )
pipe= subprocess.Popen(HCopyCommand)
pipe.wait()
return mfcFileName
def extractPredominantPitch( URI_recording_noExt, frameSize=None, hopSize=None, jointAnalysis=False, musicbrainzid=None, preload=False):
'''
extract pitch using local version of pycompmusic and save as csv as input
used as inpu to note segmentation algo
preploaded joint analysis has hopsize=256
'''
logging.debug( 'extracting pitch for {}...'.format(URI_recording_noExt))
extractedPitchList = []
####### melodia format
URI_recording = URI_recording_noExt + '.wav'
if preload and musicbrainzid != None: ############# load from extractor output on server
try:
if jointAnalysis:
pitch_data = dunya.docserver.get_document_as_json(musicbrainzid, "jointanalysis", "pitch", 1, version="0.1")
else:
pitch_data = dunya.docserver.get_document_as_json(musicbrainzid, "audioanalysis", "pitch_filtered", 1, version="0.1")
extractedPitchList = pitch_data['pitch']
except:
logging.error("no initialmakampitch series could be downloaded. for rec ID {}".format(musicbrainzid))
elif not os.path.exists(URI_recording):
logging.error('The file {} does not exist, nor is Music Brainz ID provided. No pitch extracted '.format(URI_recording))
else:
########## EXTRACT NOW. dont know how to extract with joint analysis
logging.warning('extracting predominat pitch contour with audio analysis...')
if hopSize != None and frameSize!= None:
extractor = PredominantMelodyMakam(hop_size=hopSize, frame_size=frameSize)
else:
extractor = PredominantMelodyMakam()
results = extractor.run(URI_recording)
extractedPitchList = results['pitch']
extractedPitchList = np.array(extractedPitchList)
return extractedPitchList