10个必学的Essentia Python示例:快速上手音乐分析

【免费下载链接】essentia C++ library for audio and music analysis, description and synthesis, including Python bindings 【免费下载链接】essentia 项目地址: https://gitcode.com/gh_mirrors/es/essentia

Essentia是一个强大的C++音频分析库,提供了丰富的Python绑定,让音乐和音频分析变得简单高效。本文将通过10个实用示例,帮助你快速掌握Essentia的核心功能,从基础的音频加载到高级的音乐特征提取,开启你的音频分析之旅。

1. 音频文件加载与基本信息获取 🎵

Essentia提供了简单的音频加载接口,让你轻松读取各种格式的音频文件并获取基本信息。

import essentia.standard as es

# 加载音频文件
audio = es.MonoLoader(filename='input.wav')()
sample_rate = 44100

# 获取音频基本信息
duration = len(audio) / sample_rate
print(f"音频时长: {duration:.2f}秒")
print(f"采样率: {sample_rate}Hz")
print(f"音频数据点数: {len(audio)}")

这段代码使用MonoLoader加载音频文件,并计算了音频的时长、采样率等基本信息。Essentia支持多种音频格式,包括WAV、MP3等。

音频波形可视化

音频波形图

2. 节奏分析:检测音乐BPM 🎶

BPM(每分钟节拍数)是音乐的重要特征,Essentia提供了强大的节奏分析工具。

import essentia.standard as es
import numpy as np

# 加载音频
audio = es.MonoLoader(filename='input.wav')()

# 配置参数
frame_size = 2048
hop_size = 128

# 计算频谱和频率带能量
w = es.Windowing(type='hann')
s = es.Spectrum()
freq_bands = es.FrequencyBands()

bands_energies = []
for frame in es.FrameGenerator(audio, frameSize=frame_size, hopSize=hop_size):
    bands_energies.append(freq_bands(s(w(frame))))

# 计算 novelty curve 和 BPM
novelty = es.NoveltyCurve(frameRate=44100./hop_size)(np.array(bands_energies))
bpm, _, _, _, _, _, _, _ = es.BpmHistogram(frameRate=44100./hop_size)(novelty)

print(f"检测到的BPM: {bpm:.1f}")

这段代码通过分析音频的频谱能量变化,计算出音乐的节拍信息。你可以调整frame_sizehop_size参数来优化检测结果。

3. 频谱特征:提取MFCC 🎧

MFCC(梅尔频率倒谱系数)是音频信号的重要特征,广泛应用于语音识别和音乐信息检索。

import essentia.standard as ess

def extract_mfcc(filename):
    # 配置参数
    frame_size = 1102
    hop_size = 441
    fft_size = 2048
    spectrum_size = fft_size // 2 + 1
    
    # 加载音频
    audio = ess.MonoLoader(filename=filename, sampleRate=44100)()
    
    # 初始化算法
    w = ess.Windowing(type='hamming', size=frame_size, zeroPadding=fft_size - frame_size)
    spectrum = ess.Spectrum(size=fft_size)
    mfcc = ess.MFCC(inputSize=spectrum_size, numberBands=26, numberCoefficients=13, 
                    warpingFormula='htkMel', highFrequencyBound=8000)
    
    # 提取MFCC
    mfccs = []
    for frame in ess.FrameGenerator(audio, frameSize=frame_size, hopSize=hop_size):
        spect = spectrum(w(frame))
        _, mfcc_coeffs = mfcc(spect)
        mfccs.append(mfcc_coeffs)
    
    return ess.array(mfccs).T

这个示例实现了类似HTK风格的MFCC提取,适用于需要与语音识别系统兼容的场景。

4. 音调分析:检测音乐调式 🔑

Essentia可以分析音乐的调性特征,包括调式和调性强度。

import essentia
from essentia.streaming import *

def detect_key(audio_file, output_file):
    # 初始化算法
    loader = MonoLoader(filename=audio_file)
    framecutter = FrameCutter()
    windowing = Windowing(type="blackmanharris62")
    spectrum = Spectrum()
    spectralpeaks = SpectralPeaks(orderBy="magnitude", magnitudeThreshold=1e-05,
                                 minFrequency=40, maxFrequency=5000, maxPeaks=10000)
    hpcp = HPCP()
    key = Key()
    
    # 创建数据池
    pool = essentia.Pool()
    
    # 连接算法网络
    loader.audio >> framecutter.signal
    framecutter.frame >> windowing.frame >> spectrum.frame
    spectrum.spectrum >> spectralpeaks.spectrum
    spectralpeaks.magnitudes >> hpcp.magnitudes
    spectralpeaks.frequencies >> hpcp.frequencies
    hpcp.hpcp >> key.pcp
    key.key >> (pool, 'tonal.key_key')
    key.scale >> (pool, 'tonal.key_scale')
    key.strength >> (pool, 'tonal.key_strength')
    
    # 运行分析
    essentia.run(loader)
    
    # 输出结果
    print(f"音乐调式: {pool['tonal.key_key']} {pool['tonal.key_scale']}")
    print(f"调性强度: {pool['tonal.key_strength']:.3f}")
    
    # 保存结果
    essentia.standard.YamlOutput(filename=output_file, format="json")(pool)

这个示例展示了Essentia的流式处理能力,通过构建算法网络来分析音频的调性特征。

调性提取流程

Essentia调性提取流程图

5. 傅里叶变换:STFT分析与合成 🔄

短时傅里叶变换(STFT)是音频分析的基础工具,Essentia提供了高效的STFT实现。

import essentia
import essentia.streaming as es
from pathlib import Path

def stft_analysis_synthesis(input_file, output_file):
    # 参数配置
    frame_size = 1024
    hop_size = 256
    
    # 初始化算法
    loader = es.MonoLoader(filename=input_file, sampleRate=44100)
    fcut = es.FrameCutter(frameSize=frame_size, hopSize=hop_size)
    w = es.Windowing(type="hann")
    fft = es.FFT(size=frame_size)
    ifft = es.IFFT(size=frame_size)
    overl = es.OverlapAdd(frameSize=frame_size, hopSize=hop_size, gain=1.0/frame_size)
    awrite = es.MonoWriter(filename=output_file, sampleRate=44100)
    
    # 构建处理网络
    loader.audio >> fcut.signal
    fcut.frame >> w.frame
    w.frame >> fft.frame
    fft.fft >> ifft.fft
    ifft.frame >> overl.frame
    overl.signal >> awrite.audio
    
    # 执行处理
    essentia.run(loader)

这段代码实现了一个简单的STFT分析和合成系统,可以用于音频的频谱分析和各种音频效果处理。

6. 正弦模型:音频分析与合成 🎛️

正弦模型是一种强大的音频分析合成技术,可以将音频分解为一系列正弦波分量。

import essentia
import essentia.streaming as es
from pathlib import Path

def sine_model_analysis_synthesis(input_file, output_file):
    # 参数配置
    params = {
        "frameSize": 2048,
        "hopSize": 512,
        "sampleRate": 44100,
        "maxnSines": 100,
        "magnitudeThreshold": -74,
        "freqDevOffset": 10,
        "freqDevSlope": 0.001,
    }
    
    # 初始化算法
    loader = es.MonoLoader(filename=input_file, sampleRate=params["sampleRate"])
    fcut = es.FrameCutter(frameSize=params["frameSize"], hopSize=params["hopSize"])
    w = es.Windowing(type="blackmanharris92")
    fft = es.FFT(size=params["frameSize"])
    smanal = es.SineModelAnal(**params)
    smsyn = es.SineModelSynth(sampleRate=params["sampleRate"], 
                              fftSize=params["frameSize"], 
                              hopSize=params["hopSize"])
    ifft = es.IFFT(size=params["frameSize"])
    overl = es.OverlapAdd(frameSize=params["frameSize"], hopSize=params["hopSize"])
    awrite = es.MonoWriter(filename=output_file, sampleRate=params["sampleRate"])
    
    # 构建处理网络
    loader.audio >> fcut.signal
    fcut.frame >> w.frame >> fft.frame >> smanal.fft
    smanal.magnitudes >> smsyn.magnitudes
    smanal.frequencies >> smsyn.frequencies
    smanal.phases >> smsyn.phases
    smsyn.fft >> ifft.fft >> overl.frame >> awrite.audio
    
    # 执行处理
    essentia.run(loader)

这个示例实现了基于正弦模型的音频分析与合成,可以用于音频分离、声音转换等高级应用。

7. 音频分离:正弦波减法 🎸

通过正弦模型,我们可以分离音频中的正弦分量和残差分量。

import essentia
import essentia.streaming as es
import numpy as np
from pathlib import Path

def sine_subtraction(input_file, output_file):
    # 参数配置
    params = {
        "frameSize": 2048,
        "hopSize": 128,
        "sampleRate": 44100,
        "maxnSines": 100,
        "magnitudeThreshold": -74,
        "freqDevOffset": 10,
        "freqDevSlope": 0.001,
    }
    
    # 初始化算法
    loader = es.MonoLoader(filename=input_file, sampleRate=params["sampleRate"])
    pool = essentia.Pool()
    fcut = es.FrameCutter(frameSize=params["frameSize"], hopSize=params["hopSize"])
    w = es.Windowing(type="blackmanharris92")
    fft = es.FFT(size=params["frameSize"])
    smanal = es.SineModelAnal(**params)
    subtrFFTSize = int(min(params["frameSize"] / 4, 4 * params["hopSize"]))
    smsub = es.SineSubtraction(sampleRate=params["sampleRate"], 
                               fftSize=subtrFFTSize, 
                               hopSize=params["hopSize"])
    
    # 构建分析网络
    loader.audio >> fcut.signal
    fcut.frame >> w.frame >> fft.frame >> smanal.fft
    smanal.magnitudes >> (pool, "magnitudes")
    smanal.frequencies >> (pool, "frequencies")
    smanal.phases >> (pool, "phases")
    fcut.frame >> smsub.frame
    smanal.magnitudes >> smsub.magnitudes
    smanal.frequencies >> smsub.frequencies
    smanal.phases >> smsub.phases
    smsub.frame >> (pool, "frames")
    
    # 执行分析
    essentia.run(loader)
    
    # 保存残差分量
    outaudio = pool["frames"].flatten()
    awrite = es.MonoWriter(filename=output_file, sampleRate=params["sampleRate"])
    outvector = es.VectorInput(outaudio)
    outvector.data >> awrite.audio
    essentia.run(outvector)

这个示例展示了如何使用正弦减法从音频中分离出非正弦分量(残差),这在音乐分离和音频修复中非常有用。

8. 谱图模型:SPR分析与合成 🎹

SPR(Sinusoidal plus Residual)模型是一种更完整的音频分析合成方法。

import essentia
import essentia.streaming as es
from pathlib import Path

def spr_model_analysis_synthesis(input_file, output_file):
    # 参数配置
    params = {
        "frameSize": 2048,
        "hopSize": 128,
        "sampleRate": 44100,
        "maxnSines": 100,
        "magnitudeThreshold": -74,
        "freqDevOffset": 10,
        "freqDevSlope": 0.001,
    }
    
    # 初始化算法
    loader = es.MonoLoader(filename=input_file, sampleRate=params["sampleRate"])
    fcut = es.FrameCutter(frameSize=params["frameSize"], hopSize=params["hopSize"])
    smanal = es.SprModelAnal(**params)
    synFFTSize = int(min(params["frameSize"] / 4, 4 * params["hopSize"]))
    smsyn = es.SprModelSynth(sampleRate=params["sampleRate"], 
                             fftSize=synFFTSize, 
                             hopSize=params["hopSize"])
    
    # 创建数据池
    pool = essentia.Pool()
    
    # 构建处理网络
    loader.audio >> fcut.signal
    fcut.frame >> smanal.frame
    smanal.magnitudes >> (pool, "magnitudes")
    smanal.frequencies >> (pool, "frequencies")
    smanal.phases >> (pool, "phases")
    smanal.magnitudes >> smsyn.magnitudes
    smanal.frequencies >> smsyn.frequencies
    smanal.phases >> smsyn.phases
    smanal.res >> smsyn.res
    smsyn.frame >> (pool, "frames")
    
    # 执行分析
    essentia.run(loader)
    
    # 合成并保存结果
    outaudio = pool["frames"].flatten()
    awrite = es.MonoWriter(filename=output_file, sampleRate=params["sampleRate"])
    outvector = es.VectorInput(outaudio)
    outvector.data >> awrite.audio
    essentia.run(outvector)

SPR模型同时考虑了音频的正弦分量和残差分量,能够更完整地表示音频信号,适用于高质量的音频合成和转换。

9. 音高跟踪:提取主音高 🎤

音高跟踪是音乐分析的重要任务,可以用于旋律提取、歌声分离等应用。

import essentia.standard as es
import numpy as np
import matplotlib.pyplot as plt

def extract_pitch(input_file):
    # 参数配置
    frame_size = 2048
    hop_size = 128
    sample_rate = 44100
    
    # 加载音频
    audio = es.MonoLoader(filename=input_file, sampleRate=sample_rate)()
    
    # 提取主音高
    pitch_extractor = es.PredominantPitchMelodia(frameSize=frame_size, 
                                                hopSize=hop_size, 
                                                sampleRate=sample_rate)
    pitch, pitch_confidence = pitch_extractor(audio)
    
    # 可视化结果
    time = np.arange(len(pitch)) * hop_size / sample_rate
    plt.figure(figsize=(12, 6))
    plt.subplot(2, 1, 1)
    plt.plot(time, pitch, 'b-')
    plt.ylabel('Frequency (Hz)')
    plt.title('Estimated Pitch')
    plt.subplot(2, 1, 2)
    plt.plot(time, pitch_confidence, 'g-')
    plt.xlabel('Time (s)')
    plt.ylabel('Confidence')
    plt.tight_layout()
    plt.show()
    
    return pitch, pitch_confidence

音高跟踪结果

音高跟踪结果图

这个示例使用Melodia算法提取音频中的主音高,适用于歌声和旋律乐器的音高分析。

10. 谐波 masking:音频分离与增强 🔍

谐波masking技术可以用于分离音频中的谐波成分,实现音频增强或分离。

import essentia.standard as es
import numpy as np

def harmonic_mask(input_file, output_file):
    # 参数配置
    frame_size = 2048
    hop_size = 128
    sample_rate = 44100.0
    attenuation_dB = 100
    mask_bin_width = 2
    
    # 加载音频
    audio = es.MonoLoader(filename=input_file, sampleRate=sample_rate)()
    
    # 提取主音高
    pitch_extractor = es.PredominantPitchMelodia(frameSize=frame_size, 
                                                hopSize=hop_size, 
                                                sampleRate=sample_rate)
    pitch, _ = pitch_extractor(audio)
    
    # 初始化算法
    fcut = es.FrameCutter(frameSize=frame_size, hopSize=hop_size)
    w = es.Windowing(type="hann")
    fft = es.FFT(size=frame_size)
    hmask = es.HarmonicMask(sampleRate=sample_rate, 
                           binWidth=mask_bin_width, 
                           attenuation=attenuation_dB)
    ifft = es.IFFT(size=frame_size)
    overl = es.OverlapAdd(frameSize=frame_size, hopSize=hop_size)
    
    # 处理每一帧
    audio_out = np.array(0)
    for idx, frame in enumerate(es.FrameGenerator(audio, frameSize=frame_size, hopSize=hop_size)):
        # STFT分析
        in_fft = fft(w(frame))
        # 应用谐波mask
        out_fft = hmask(in_fft, pitch[idx])
        # STFT合成
        out_frame = overl(ifft(out_fft))
        audio_out = np.append(audio_out, out_frame)
    
    # 保存结果
    es.MonoWriter(filename=output_file, sampleRate=sample_rate)(audio_out.astype(np.float32))

这个示例展示了如何使用谐波masking技术来增强或分离音频中的谐波成分,可应用于语音增强、音乐分离等场景。

总结与进阶学习

通过以上10个示例,你已经掌握了Essentia的核心功能。要深入学习,可以参考以下资源:

Essentia提供了丰富的音频分析功能,从基础的特征提取到高级的音乐分析,都可以通过简洁的Python接口实现。无论是音乐信息检索、音频信号处理还是音乐生成,Essentia都是一个强大而灵活的工具。

要开始使用Essentia,首先需要克隆仓库:

git clone https://gitcode.com/gh_mirrors/es/essentia

然后按照官方文档的指引进行安装和配置。祝你在音频分析的旅程中取得成功!

【免费下载链接】essentia C++ library for audio and music analysis, description and synthesis, including Python bindings 【免费下载链接】essentia 项目地址: https://gitcode.com/gh_mirrors/es/essentia

更多推荐