示例#1
0
def music_extractor(audio_file,
                    sig_file,
                    profile=None,
                    store_frames=False,
                    format='yaml'):
    if profile:
        extractor = MusicExtractor(profile=profile)
    else:
        extractor = MusicExtractor()

    poolStats, poolFrames = extractor(audio_file)

    folder = os.path.dirname(sig_file)

    if not os.path.exists(folder):
        os.makedirs(folder)
    elif os.path.isfile(folder):
        raise EssentiaError(
            'Cannot create directory {} .There exist a file with the same name. Aborting analysis.'
            .format(folder))

    output = YamlOutput(filename=sig_file + '.sig', format=format)
    output(poolStats)
    if store_frames:
        YamlOutput(filename=sig_file + '.frames.sig',
                   format=format)(poolFrames)
示例#2
0
def doSegmentation(inputFilename, audio, pool, options):

    # options
    segtype = options[namespace]['type']
    minimumLength = options[namespace]['minimumSegmentsLength']
    writeFile = options[namespace]['writeSegmentsAudioFile']
    sampleRate = options['sampleRate']

    if segtype == 'fromFile':
        segments = [
            map(float,
                l.strip().split('\t'))
            for l in open(options[namespace]['segmentsFile'], 'r').readlines()
        ]

    else:
        if segtype == 'maxEnergy':
            onsets = segmentation_max_energy.compute(pool, options)

        elif segtype == 'bic':  # Bayesian Information Criterion (Bic) segmentation
            onsets = segmentation_bic.compute(pool, options)

        else:
            raise EssentiaError('Unknown segmentation type: ' + segtype)

        # creating segment wave file
        if writeFile:
            outputFilename = inputFilename + '.segments.wav'
            print 'Creating segments audio file ' + outputFilename + '...'
            audioOnsetsMarker = essentia.AudioOnsetsMarker(
                filename=outputFilename, sampleRate=sampleRate)
            audioOnsetsMarker(audio, onsets)

        # transforming the onsets into segments = pairs of onsets
        segments = []
        for onset, onsetNext in zip(onsets[:-1], onsets[1:]):
            segments.append([onset, onsetNext])

    if options['verbose']:
        if len(segments) > 0:
            print 'Segments : ',
            for segment in segments:
                print '[',
                print_onset(segment[0])
                print ",",
                print_onset(segment[1])
                print '] ',
        else:
            print 'No segments found!'
        print

    return segments
示例#3
0
    def add(self, name, value, scope = CurrentScope):
        if isinstance(value, tuple):
            raise EssentiaError('error when adding %s: you can\'t add tuples to the pool' % name)

        if scope == self.GlobalScope:
            self.statsBlackList.append((self.__currentNamespace, name))
            scope = self.__globalScope

        elif scope == self.CurrentScope:
            scope = self.__currentScope

        try:
            self.descriptors[self.__currentNamespace][name]['values'].append(value)
            self.descriptors[self.__currentNamespace][name]['scopes'].append(scope)
        except KeyError:
            self.descriptors[self.__currentNamespace][name] = {'values' : [value], 'scopes' : [scope]}
示例#4
0
def batch_music_extractor(audio_dir, output_dir, generate_log=True,
                          audio_types=None, profile=None,
                          store_frames=False, skip_analyzed=False,
                          format='yaml', jobs=0):
    """
        Processes every audio file matching `audio_types` in `audio_dir` with MusicExtractor. The generated
        .sig yaml/json files are stored in `output_dir` matching the folder structure found in `audio_dir`.
    """

    if not audio_types:
        audio_types = ('.WAV', '.AIFF', '.FLAC', '.MP3', '.OGG')
        print("Audio files extensions considered by default: " +
              ' '.join(audio_types))
    else:
        audio_types = tuple(audio_types)
        print("Searching for audio files extensions: " + ' '.join(audio_types))
    print("")

    output_dir = os.path.abspath(output_dir)

    if profile:
        assert os.path.isfile(profile)

    if jobs == 0:
        try:
            jobs = cpu_count()
        except NotImplementedError:
            print("Failed to automatically detect the cpu count, the analysis will try to continue with 4 jobs. For a different behavior change the `job` parameter.")
            jobs = 4

    # find all audio files and prepare folder structure in the output folder
    os.chdir(audio_dir)

    skipped_count = 0
    skipped_files = []
    cmd_lines = []
    for root, dirnames, filenames in os.walk("."):
        for filename in filenames:
            if filename.upper().endswith(audio_types):
                audio_file = os.path.relpath(os.path.join(root, filename))
                audio_file_abs = os.path.join(audio_dir, audio_file)
                sig_file = os.path.join(output_dir, audio_file)

                if skip_analyzed:
                    if os.path.isfile(sig_file + '.sig'):
                        print("Found descriptor file for " +
                              audio_file + ", skipping...")
                        skipped_files.append(audio_file)
                        skipped_count += 1
                        continue
                folder = os.path.dirname(sig_file)
                if not os.path.exists(folder):
                    os.makedirs(folder)

                elif os.path.isfile(folder):
                    raise EssentiaError('Cannot create directory {} .There exist a file with the same name. Aborting analysis.'.format(folder))

                cmd_line = [
                            sys.executable,
                            os.path.join(os.path.dirname(__file__), 'extractors/music_extractor.py'), 
                            audio_file_abs, sig_file,
                            '--format', format
                            ]

                if store_frames:
                    cmd_line += ['--store_frames']

                if profile:
                    cmd_line += ['--profile', profile]

                cmd_lines.append(cmd_line)


    # analyze
    errors, oks = 0, 0
    if len(cmd_lines) > 0:
        p = Pool(jobs)
        outs = p.map(__subprocess__, cmd_lines)

        status, cmd, stderr = zip(*outs)

        oks, errors = 0, 0
        for i in status:
            if i == 0:
                oks += 1
            else:
                errors += 1

    summary = "Analysis done. {} files have been skipped due to errors, {} were processed and {} already existed.".format(
        errors, oks, skipped_count)
    print(summary)

    # generate log
    if generate_log:
        log = [summary]

        if errors > 0:
            log += ['Errors:'] + ['"{}"\n{}\n\n'.format(cmd[idx], stderr[idx])
                                  for idx, i in enumerate(status) if i != 0]

        if oks > 0:
            log += ['Oks:'] + [cmd[idx]
                               for idx, i in enumerate(status) if i == 0]

        if skipped_count > 0:
            log += ['Skipped files:'] + skipped_files

        if not os.path.exists(output_dir):
            os.makedirs(output_dir)

        with open(os.path.join(output_dir, 'log'), 'w') as f:
            f.write('\n'.join(log))
示例#5
0
def _batch_extractor(audio_dir,
                     output_dir,
                     extractor_cmd,
                     output_extension,
                     generate_log=True,
                     audio_types=None,
                     skip_analyzed=False,
                     jobs=0,
                     verbose=True):
    if not audio_types:
        audio_types = ('.wav', '.aiff', '.flac', '.mp3', '.ogg')
        print("Audio files extensions considered by default: " +
              ', '.join(audio_types))
    else:
        if type(audio_types) == str:
            audio_types = [audio_types]

        audio_types = tuple(audio_types)
        audio_types = tuple([i.lower() for i in audio_types])
        print("Searching for audio files extensions: " +
              ', '.join(audio_types))
    print("")

    output_dir = os.path.abspath(output_dir)
    audio_dir = os.path.abspath(audio_dir)

    if jobs == 0:
        try:
            jobs = cpu_count()
        except NotImplementedError:
            print('Failed to automatically detect the cpu count, '
                  'the analysis will try to continue with 4 jobs. '
                  'For a different behavior change the `job` parameter.')
            jobs = 4

    skipped_count = 0
    skipped_files = []
    cmd_lines = []
    for root, _, filenames in os.walk(audio_dir):
        for filename in filenames:
            if filename.lower().endswith(audio_types):
                audio_file = os.path.join(audio_dir, root, filename)
                out_file = os.path.join(output_dir, output_dir, filename)

                if skip_analyzed:
                    if os.path.isfile('{}.{}'.format(out_file,
                                                     output_extension)):
                        print("Found descriptor file for " + audio_file +
                              ", skipping...")
                        skipped_files.append(audio_file)
                        skipped_count += 1
                        continue
                folder = os.path.dirname(out_file)

                if os.path.isfile(folder):
                    raise EssentiaError('Cannot create directory "{}". '
                                        'There is a file with the same name. '
                                        'Aborting analysis.'.format(folder))
                else:
                    os.makedirs(folder, exist_ok=True)

                cmd_lines.append(extractor_cmd + [audio_file, out_file])

    # analyze
    log_lines = []
    total, errors, oks = 0, 0, 0
    if cmd_lines:
        p = Pool(jobs)
        outs = p.map(partial(_subprocess, verbose=verbose), cmd_lines)

        total = len(outs)
        status, cmd, stderr = zip(*outs)

        oks, errors = 0, 0
        for i, cmd_idx, err in zip(status, cmd, stderr):
            if i == 0:
                oks += 1
                log_lines.append('"{}" ok!'.format(cmd_idx))
            else:
                errors += 1
                log_lines.append('"{}" failed'.format(cmd_idx))
                log_lines.append('  "{}"'.format(err))

    summary = (
        "Analysis done for {} files. {} files have been skipped due to errors, "
        "{} were successfully processed and {} already existed.\n").format(
            total, errors, oks, skipped_count)
    print(summary)

    # generate log
    if generate_log:
        log = [summary] + log_lines

        with open(os.path.join(output_dir, 'log'), 'w') as f:
            f.write('\n'.join(log))
示例#6
0
def compute(audio, pool, options):

    INFO('Computing Tonal descriptors...')

    sampleRate = options['sampleRate']
    frameSize = options['frameSize']
    hopSize = options['hopSize']
    zeroPadding = options['zeroPadding']
    windowType = options['windowType']

    frames = essentia.FrameGenerator(audio=audio,
                                     frameSize=frameSize,
                                     hopSize=hopSize)
    window = essentia.Windowing(size=frameSize,
                                zeroPadding=zeroPadding,
                                type=windowType)
    spectrum = essentia.Spectrum(size=(frameSize + zeroPadding) / 2)
    spectral_peaks = essentia.SpectralPeaks(maxPeaks=10000,
                                            magnitudeThreshold=0.00001,
                                            minFrequency=40,
                                            maxFrequency=5000,
                                            orderBy="frequency")
    tuning = essentia.TuningFrequency()

    # computing the tuning frequency
    tuning_frequency = 440.0

    for frame in frames:

        frame_windowed = window(frame)
        frame_spectrum = spectrum(frame_windowed)

        (frame_frequencies, frame_magnitudes) = spectral_peaks(frame_spectrum)

        #if len(frame_frequencies) > 0:
        (tuning_frequency, tuning_cents) = tuning(frame_frequencies,
                                                  frame_magnitudes)

    pool.add(namespace + '.' + 'tuning_frequency',
             tuning_frequency)  #, pool.GlobalScope)

    # computing the HPCPs
    spectral_whitening = essentia.SpectralWhitening()

    hpcp_key_size = 36
    hpcp_chord_size = 36
    hpcp_tuning_size = 120

    hpcp_key = essentia.HPCP(size=hpcp_key_size,
                             referenceFrequency=tuning_frequency,
                             bandPreset=False,
                             minFrequency=40.0,
                             maxFrequency=5000.0,
                             weightType='squaredCosine',
                             nonLinear=False,
                             windowSize=4.0 / 3.0,
                             sampleRate=sampleRate)

    hpcp_chord = essentia.HPCP(size=hpcp_chord_size,
                               referenceFrequency=tuning_frequency,
                               harmonics=8,
                               bandPreset=True,
                               minFrequency=40.0,
                               maxFrequency=5000.0,
                               splitFrequency=500.0,
                               weightType='cosine',
                               nonLinear=True,
                               windowSize=0.5,
                               sampleRate=sampleRate)

    hpcp_tuning = essentia.HPCP(size=hpcp_tuning_size,
                                referenceFrequency=tuning_frequency,
                                harmonics=8,
                                bandPreset=True,
                                minFrequency=40.0,
                                maxFrequency=5000.0,
                                splitFrequency=500.0,
                                weightType='cosine',
                                nonLinear=True,
                                windowSize=0.5,
                                sampleRate=sampleRate)

    # intializing the HPCP arrays
    hpcps_key = []
    hpcps_chord = []
    hpcps_tuning = []

    # computing HPCP loop
    frames = essentia.FrameGenerator(audio=audio,
                                     frameSize=frameSize,
                                     hopSize=hopSize)

    total_frames = frames.num_frames()
    n_frames = 0
    start_of_frame = -frameSize * 0.5

    progress = Progress(total=total_frames)

    for frame in frames:

        #frameScope = [ start_of_frame / sampleRate, (start_of_frame + frameSize) / sampleRate ]
        #pool.setCurrentScope(frameScope)

        if options['skipSilence'] and essentia.isSilent(frame):
            total_frames -= 1
            start_of_frame += hopSize
            continue

        frame_windowed = window(frame)
        frame_spectrum = spectrum(frame_windowed)

        # spectral peaks
        (frame_frequencies, frame_magnitudes) = spectral_peaks(frame_spectrum)

        if (len(frame_frequencies) > 0):
            # spectral_whitening
            frame_magnitudes_white = spectral_whitening(
                frame_spectrum, frame_frequencies, frame_magnitudes)
            frame_hpcp_key = hpcp_key(frame_frequencies,
                                      frame_magnitudes_white)
            frame_hpcp_chord = hpcp_chord(frame_frequencies,
                                          frame_magnitudes_white)
            frame_hpcp_tuning = hpcp_tuning(frame_frequencies,
                                            frame_magnitudes_white)
        else:
            frame_hpcp_key = essentia.array([0] * hpcp_key_size)
            frame_hpcp_chord = essentia.array([0] * hpcp_chord_size)
            frame_hpcp_tuning = essentia.array([0] * hpcp_tuning_size)

        # key HPCP
        hpcps_key.append(frame_hpcp_key)

        # add HPCP to the pool
        pool.add(namespace + '.' + 'hpcp', frame_hpcp_key)

        # chords HPCP
        hpcps_chord.append(frame_hpcp_chord)

        # tuning system HPCP
        hpcps_tuning.append(frame_hpcp_tuning)

        # display of progress report
        progress.update(n_frames)

        n_frames += 1
        start_of_frame += hopSize

    progress.finish()

    # check if silent file
    if len(hpcps_key) == 0:
        raise EssentiaError('This is a silent file!')

    # key detection
    key_detector = essentia.Key(profileType='temperley')
    average_hpcps_key = numpy.average(essentia.array(hpcps_key), axis=0)
    average_hpcps_key = normalize(average_hpcps_key)

    # thpcps
    max_arg = numpy.argmax(average_hpcps_key)
    thpcp = []
    for i in range(max_arg, len(average_hpcps_key)):
        thpcp.append(float(average_hpcps_key[i]))
    for i in range(max_arg):
        thpcp.append(float(average_hpcps_key[i]))
    pool.add(namespace + '.' + 'thpcp', thpcp)  #, pool.GlobalScope  )

    (key, scale, key_strength,
     first_to_second_relative_strength) = key_detector(
         essentia.array(average_hpcps_key))
    pool.add(namespace + '.' + 'key_key', key)  #, pool.GlobalScope)
    pool.add(namespace + '.' + 'key_scale', scale)  #, pool.GlobalScope)
    pool.add(namespace + '.' + 'key_strength',
             key_strength)  #, pool.GlobalScope)

    # chord detection
    chord_detector = essentia.Key(profileType='tonictriad', usePolyphony=False)
    hpcp_frameSize = 2.0  # 2 seconds
    hpcp_number = int(hpcp_frameSize * (sampleRate / hopSize - 1))

    for hpcp_index in range(len(hpcps_chord)):

        hpcp_index_begin = max(0, hpcp_index - hpcp_number)
        hpcp_index_end = min(hpcp_index + hpcp_number, len(hpcps_chord))
        average_hpcps_chord = numpy.average(essentia.array(
            hpcps_chord[hpcp_index_begin:hpcp_index_end]),
                                            axis=0)
        average_hpcps_chord = normalize(average_hpcps_chord)
        (key, scale, strength,
         first_to_second_relative_strength) = chord_detector(
             essentia.array(average_hpcps_chord))

        if scale == 'minor':
            chord = key + 'm'
        else:
            chord = key

        frame_second_scope = [
            hpcp_index_begin * hopSize / sampleRate,
            hpcp_index_end * hopSize / sampleRate
        ]
        pool.add(namespace + '.' + 'chords_progression',
                 chord)  #, frame_second_scope)
        pool.add(namespace + '.' + 'chords_strength',
                 strength)  #, frame_second_scope)

    # tuning system features
    keydetector = essentia.Key(profileType='diatonic')
    average_hpcps_tuning = numpy.average(essentia.array(hpcps_tuning), axis=0)
    average_hpcps_tuning = normalize(average_hpcps_tuning)
    (key, scale, diatonic_strength,
     first_to_second_relative_strength) = keydetector(
         essentia.array(average_hpcps_tuning))

    pool.add(namespace + '.' + 'tuning_diatonic_strength',
             diatonic_strength)  #, pool.GlobalScope)

    (equal_tempered_deviation, nontempered_energy_ratio,
     nontempered_peaks_energy_ratio
     ) = essentia.HighResolutionFeatures()(average_hpcps_tuning)

    pool.add(namespace + '.' + 'tuning_equal_tempered_deviation',
             equal_tempered_deviation)  #, pool.GlobalScope)
    pool.add(namespace + '.' + 'tuning_nontempered_energy_ratio',
             nontempered_energy_ratio)  #, pool.GlobalScope)
    pool.add(namespace + '.' + 'tuning_nontempered_peaks_energy_ratio',
             nontempered_peaks_energy_ratio)  #, pool.GlobalScope)
示例#7
0
    def aggregate_descriptors(self, descriptors_stats={}):
        aggregated = {}
        for namespace in self.descriptors:
            aggregated[namespace] = {}
            descs = self.descriptors[namespace].keys()
            descs.sort()

            stats_default = ['mean', 'var', 'min', 'max']

            for desc in descs:
                values = self.descriptors[namespace][desc]['values']

                if (namespace, desc) in self.statsBlackList:
                    # make sure there is only one value
                    if len(values) != 1:
                        raise EssentiaError(
                            'You declared %s as a global descriptors, but there are more than 1 value: %s'
                            % (desc, values))

                    value = values[0]
                    try:
                        # if value is numeric
                        aggregated[namespace][desc] = {
                            'value': essentia.array(value)
                        }
                    except:
                        # if value is not numeric
                        aggregated[namespace][desc] = {'value': value}

                    continue

                aggregated[namespace][desc] = {}
                aggrDesc = aggregated[namespace][desc]

                stats = list(stats_default)
                if not isinstance(values[0], numpy.ndarray):
                    #stats += [ 'percentile_5', 'percentile_95' ]
                    stats += ['dmean', 'dmean2', 'dvar', 'dvar2']

                if namespace in descriptors_stats and desc in descriptors_stats[
                        namespace]:
                    stats = descriptors_stats[namespace][desc]

                try:

                    if 'mean' in stats:
                        aggrDesc['mean'] = essentia.array(
                            numpy.mean(values, axis=0))

                    if 'var' in stats:
                        aggrDesc['var'] = essentia.array(
                            numpy.var(values, axis=0))

                    if 'min' in stats:
                        aggrDesc['min'] = essentia.array(
                            numpy.min(values, axis=0))

                    if 'max' in stats:
                        aggrDesc['max'] = essentia.array(
                            numpy.max(values, axis=0))

                    derived = None
                    derived2 = None

                    if 'dmean' in stats:
                        if not derived:
                            derived = [
                                a - b for a, b in izip(values[1:], values[:-1])
                            ]
                        aggrDesc['dmean'] = essentia.array(
                            numpy.mean(numpy.abs(derived), axis=0))

                    if 'dvar' in stats:
                        if not derived:
                            derived = [
                                a - b for a, b in izip(values[1:], values[:-1])
                            ]
                        aggrDesc['dvar'] = essentia.array(
                            numpy.var(derived, axis=0))

                    if 'dmean2' in stats:
                        if not derived:
                            derived = [
                                a - b for a, b in izip(values[1:], values[:-1])
                            ]
                        if not derived2:
                            derived2 = [
                                a - b
                                for a, b in izip(derived[1:], derived[:-1])
                            ]
                        if derived2:
                            aggrDesc['dmean2'] = essentia.array(
                                numpy.mean(numpy.abs(derived2), axis=0))
                        else:
                            aggrDesc['dmean2'] = 'undefined'

                    if 'dvar2' in stats:
                        if not derived:
                            derived = [
                                a - b for a, b in izip(values[1:], values[:-1])
                            ]
                        if not derived2:
                            derived2 = [
                                a - b
                                for a, b in izip(derived[1:], derived[:-1])
                            ]
                        if derived2:
                            aggrDesc['dvar2'] = essentia.array(
                                numpy.var(derived2, axis=0))
                        else:
                            aggrDesc['dvar2'] = 'undefined'

                    if 'frames' in stats:
                        aggrDesc['frames'] = essentia.array(values)

                    if 'single_gaussian' in stats:
                        single_gaussian = essentia.SingleGaussian()
                        (m, cov,
                         icov) = single_gaussian(essentia.array(values))
                        aggrDesc['mean'] = m
                        aggrDesc['cov'] = cov
                        aggrDesc['icov'] = icov

                    for stat in stats:
                        if stat.startswith('percentile_'):
                            p = float(stat.split('_')[1])
                            aggrDesc[stat] = essentia.array(
                                percentile(values, p))

                except (TypeError, ValueError):  # values are not numeric

                    if len(values) == 1:
                        aggrDesc['value'] = values[0]
                    else:
                        aggrDesc['value'] = []
                        for value in values:
                            aggrDesc['value'].append(value)

        return aggregated