C/C++ は、librosa オーディオ処理ライブラリ melspectrogram および mfcc を実装します。
目次
C/C++ は、librosa オーディオ処理ライブラリ melspectrogram および mfcc を実装します。
3. C++ librosa オーディオ処理ライブラリの実装
5. librosa ライブラリ C++ ソース コードのダウンロード
深層学習の音声処理では音声処理ライブラリ librosa がよく使われますが、librosa は現状 Python 版しかなく、音声認識アルゴリズムの開発ではメルスペクトログラム (Mel-spectrogram) や MFCC ( Mel spectrogram )が) これらの音声情報を処理するため、C/C++ バージョンのメルスペクトログラムと MFCC を実装する必要があります。インターネット上にはすでに多くのバージョンの C/C++ メルスペクトログラムと MFCC が存在しますが、テストの結果、処理に大きな違いがあることがわかりました。 Python の librosa の結果; 後 複数の最適化テストを経て、このプロジェクトは、オーディオ処理ライブラリ librosa の C/C++ バージョンに、load、melspectrogram、および mfcc の関数を実装しました。このプロジェクトは、基本的に、Python オーディオの 3 つの関数と完全に連携しています。処理ライブラリ librosa:
- librosa.load: 音声読み上げを実装する
- librosa.feature.melspectrogram: 計算メルスペクトログラムmelspectrogramを実装します。
- librosa.feature.mfcc:メル周波数ケプストラム係数MFCCの計算を実装します。
[独創性を尊重し、転載する場合は出典を明記してください] https://blog.csdn.net/guyuealian/article/details/132077896
1. プロジェクトの構造
2.環境に応じて
プロジェクトでは、Python および C/C++ 関連の依存関係パッケージをインストールする必要があります
Python はライブラリに依存します。pip install を使用してください。
numpy==1.16.3
matplotlib==3.1.0
Pillow==6.0.0
easydict==1.9
opencv-contrib-python==4.5.2.52
opencv-python==4.5.1.48
pandas==1.1.5
PyYAML==5.3.1
scikit-image==0.17.2
scikit-learn==0.24.0
scipy==1.5.4
seaborn==0.11.2
tqdm==4.55.1
xmltodict==0.12.0
pybaseutils==0.7.6
librosa==0.8.1
pyaudio==0.2.11
pydub==0.23.1
C++依存ライブラリ、主にEigen3とOpenCVを使用
- Eigen3 : 行列計算に使用されます。プロジェクトはすでに Eigen3 をサポートしているため、インストールする必要はありません。
- OpenCV : 画像の表示に使用されます。インストール方法については、opencv と opencv_contrib のインストールについては Ubuntu18.04を参照してください。
3. C++ librosa オーディオ処理ライブラリの実装
音声処理で一般的に使用される固有値:メル スペクトログラム(Mel Spectrogram)とメル周波数ケプストラム係数(MFCC)、参考記事:https: //www.cnblogs.com/Ge-ronimo/p/17281385 .html
(1) 音声ファイルを整列して読み込む
Python の librosa.load を使用してオーディオ ファイルを読み取ることができます
data, sr = librosa.load(path, sr, mono)
Python はオーディオ ファイルの読み取りを実装します。
# -*-coding: utf-8 -*-
import numpy as np
import librosa
def read_audio(audio_file, sr=16000, mono=True):
"""
默认将多声道音频文件转换为单声道,并返回一维数组;
如果你需要处理多声道音频文件,可以使用 mono=False,参数来保留所有声道,并返回二维数组。
:param audio_file:
:param sr: sampling rate
:param mono: 设置为true是单通道,否则是双通道
:return:
"""
audio_data, sr = librosa.load(audio_file, sr=sr, mono=mono)
audio_data = audio_data.T.reshape(-1)
return audio_data, sr
def print_vector(name, data):
np.set_printoptions(precision=7, suppress=False)
print("------------------------%s------------------------\n" % name)
print("{}".format(data.tolist()))
if __name__ == '__main__':
sr = None
audio_file = "data/data_s1.wav"
data, sr = read_audio(audio_file, sr=sr, mono=False)
print("sr = %d, data size=%d" % (sr, len(data)))
print_vector("audio data", data)
C/C++ オーディオ ファイルの読み取り:オーディオ データ形式に従ってデコードする必要があります。「C 言語の wav ファイル形式の解析 」を参照してください。このプロジェクトは、モノラルとデュアルをサポートできるオーディオ データの読み取りの C/C++ バージョンを実現しました。チャンネルオーディオデータ(モノラル)
/**
* 读取音频文件,目前仅支持wav格式文件
* @param filename wav格式文件
* @param out 输出音频数据
* @param sr 输出音频采样率
* @param mono 设置为true是单通道,否则是双通道
* @return
*/
int read_audio(const char *filename, vector<float> &out, int *sr, bool mono = true);
#include <iostream>
#include <vector>
#include <algorithm>
#include "librosa/audio_utils.h"
#include "librosa/librosa.h"
using namespace std;
int main() {
int sr = -1;
string audio_file = "../data/data_s1.wav";
vector<float> data;
int res = read_audio(audio_file.c_str(), data, &sr, false);
if (res < 0) {
printf("read wav file error: %s\n", audio_file.c_str());
return -1;
}
printf("sr = %d, data size=%d\n", sr, data.size());
print_vector("audio data", data);
return 0;
}
オーディオ ファイル データを読み取るために Python と C++ のバージョンをテストして比較します。数回のテストの後、2 つの間で読み取られるオーディオ値の差は非常に小さく、Python librosa ライブラリの librosa.load() 関数は基本的に整列されました。
数値比較 | |
C++バージョン | |
Pythonのバージョン |
(2) メルスペクトログラムの位置合わせ melspectrogram
メルスペクトログラムメル スペクトルの関連原理については、 「メル スペクトルに基づくオーディオ信号の分類と認識 (Pytorch)」を参照してください。
Python の librosa ライブラリは、OpenCV を使用して表示できる 2 次元配列を返す librosa.feature.melspectrogram() 関数を提供します。
def librosa_feature_melspectrogram(y,
sr=16000,
n_mels=128,
n_fft=2048,
hop_length=256,
win_length=None,
window="hann",
center=True,
pad_mode="reflect",
power=2.0,
fmin=0.0,
fmax=None,
**kwargs):
"""
计算音频梅尔频谱图(Mel Spectrogram)
:param y: 音频时间序列
:param sr: 采样率
:param n_mels: number of Mel bands to generate产生的梅尔带数
:param n_fft: length of the FFT window FFT窗口的长度
:param hop_length: number of samples between successive frames 帧移(相邻窗之间的距离)
:param win_length: 窗口的长度为win_length,默认win_length = n_fft
:param window:
:param center: 如果为True,则填充信号y,以使帧 t以y [t * hop_length]为中心。
如果为False,则帧t从y [t * hop_length]开始
:param pad_mode:
:param power: 幅度谱的指数。例如1代表能量,2代表功率,等等
:param fmin: 最低频率(Hz)
:param fmax: 最高频率(以Hz为单位),如果为None,则使用fmax = sr / 2.0
:param kwargs:
:return: 返回Mel频谱shape=(n_mels,n_frames),n_mels是Mel频率的维度(频域),n_frames为时间帧长度(时域)
"""
mel = librosa.feature.melspectrogram(y=y,
sr=sr,
S=None,
n_mels=n_mels,
n_fft=n_fft,
hop_length=hop_length,
win_length=win_length,
window=window,
center=center,
pad_mode=pad_mode,
power=power,
fmin=fmin,
fmax=fmax,
**kwargs)
return mel
librosa.feature.melspectrogram() の Python バージョンに従って、プロジェクトは melspectrogram の C++ バージョンを実装します。
/***
* compute mel spectrogram similar with librosa.feature.melspectrogram
* @param x input audio signal
* @param sr sample rate of 'x'
* @param n_fft length of the FFT size
* @param n_hop number of samples between successive frames
* @param win window function. currently only supports 'hann'
* @param center same as librosa
* @param mode pad mode. support "reflect","symmetric","edge"
* @param power exponent for the magnitude melspectrogram
* @param n_mels number of mel bands
* @param fmin lowest frequency (in Hz)
* @param fmax highest frequency (in Hz)
* @return mel spectrogram matrix
*/
static std::vector <std::vector<float>> melspectrogram(std::vector<float> &x, int sr,
int n_fft, int n_hop, const std::string &win, bool center,
const std::string &mode,
float power, int n_mels, int fmin, int fmax)
メルスペクトログラムの Python バージョンと C++ バージョンをテストして比較すると、2 つの戻り値の違いはすでに非常に小さく、視覚化されたメルスペクトログラムは基本的に同じです。
バージョン | 数値比較 |
C++バージョン | |
Pythonのバージョン |
(3) アライメントされたメル周波数ケプストラム係数MFCC
Python バージョンでは、librosa ライブラリの librosa.feature.mfcc を使用して MFCC (メル周波数ケプストラム係数) を実装できます。
def librosa_feature_mfcc(y,
sr=16000,
n_mfcc=128,
n_mels=128,
n_fft=2048,
hop_length=256,
win_length=None,
window="hann",
center=True,
pad_mode="reflect",
power=2.0,
fmin=0.0,
fmax=None,
dct_type=2,
**kwargs):
"""
计算音频MFCC
:param y: 音频时间序列
:param sr: 采样率
:param n_mfcc: number of MFCCs to return
:param n_mels: number of Mel bands to generate产生的梅尔带数
:param n_fft: length of the FFT window FFT窗口的长度
:param hop_length: number of samples between successive frames 帧移(相邻窗之间的距离)
:param win_length: 窗口的长度为win_length,默认win_length = n_fft
:param window:
:param center: 如果为True,则填充信号y,以使帧 t以y [t * hop_length]为中心。
如果为False,则帧t从y [t * hop_length]开始
:param pad_mode:
:param power: 幅度谱的指数。例如1代表能量,2代表功率,等等
:param fmin: 最低频率(Hz)
:param fmax: 最高频率(以Hz为单位),如果为None,则使用fmax = sr / 2.0
:param kwargs:
:return: 返回MFCC shape=(n_mfcc,n_frames)
"""
# MFCC 梅尔频率倒谱系数
mfcc = librosa.feature.mfcc(y=y,
sr=sr,
S=None,
n_mfcc=n_mfcc,
n_mels=n_mels,
n_fft=n_fft,
hop_length=hop_length,
win_length=win_length,
window=window,
center=center,
pad_mode=pad_mode,
power=power,
fmin=fmin,
fmax=fmax,
dct_type=dct_type,
**kwargs)
return mfcc
librosa.feature.mfcc() の Python バージョンによると、プロジェクトは MFCC の C++ バージョンを実装します。
/***
* compute mfcc similar with librosa.feature.mfcc
* @param x input audio signal
* @param sr sample rate of 'x'
* @param n_fft length of the FFT size
* @param n_hop number of samples between successive frames
* @param win window function. currently only supports 'hann'
* @param center same as librosa
* @param mode pad mode. support "reflect","symmetric","edge"
* @param power exponent for the magnitude melspectrogram
* @param n_mels number of mel bands
* @param fmin lowest frequency (in Hz)
* @param fmax highest frequency (in Hz)
* @param n_mfcc number of mfccs
* @param norm ortho-normal dct basis
* @param type dct type. currently only supports 'type-II'
* @return mfcc matrix
*/
static std::vector<std::vector<float>> mfcc(std::vector<float> &x, int sr,
int n_fft, int n_hop, const std::string &win, bool center, const std::string &mode,
float power, int n_mels, int fmin, int fmax,
int n_mfcc, bool norm, int type)
MFCC の Python バージョンと C++ バージョンをテストして比較すると、2 つの戻り値の違いは非常に小さく、視覚化された MFCC図は基本的に同じです。
バージョン | 数値比較 |
C++バージョン | |
Pythonのバージョン |
4. デモの実行
- C++ バージョンをプロジェクトのルート ディレクトリとターミナルに入力できます: bash build.sh でテスト デモを実行します。
#!/usr/bin/env bash
if [ ! -d "build/" ];then
mkdir "build"
else
echo "exist build"
fi
cd build
cmake ..
make -j4
sleep 1
./main
メイン機能
/****
* @Author : [email protected]
* @E-mail :
* @Date :
* @Brief : C/C++实现Melspectrogram和MFCC
*/
#include <iostream>
#include <vector>
#include <algorithm>
#include "librosa/audio_utils.h"
#include "librosa/librosa.h"
#include "librosa/cv_utils.h"
using namespace std;
int main() {
int sr = -1;
int n_fft = 400;
int hop_length = 160;
int n_mel = 64;
int fmin = 80;
int fmax = 7600;
int n_mfcc = 64;
int dct_type = 2;
float power = 2.f;
bool center = false;
bool norm = true;
string window = "hann";
string pad_mode = "reflect";
//string audio_file = "../data/data_d2.wav";
string audio_file = "../data/data_s1.wav";
vector<float> data;
int res = read_audio(audio_file.c_str(), data, &sr, false);
if (res < 0) {
printf("read wav file error: %s\n", audio_file.c_str());
return -1;
}
printf("n_fft = %d\n", n_fft);
printf("n_mel = %d\n", n_mel);
printf("hop_length = %d\n", hop_length);
printf("fmin, fmax = (%d,%d)\n", fmin, fmax);
printf("sr = %d, data size=%d\n", sr, data.size());
//print_vector("audio data", data);
// compute mel Melspectrogram
vector<vector<float>> mels_feature = librosa::Feature::melspectrogram(data, sr, n_fft, hop_length, window,
center, pad_mode, power, n_mel, fmin, fmax);
int mels_w = (int) mels_feature.size();
int mels_h = (int) mels_feature[0].size();
cv::Mat mels_image = vector2mat<float>(get_vector(mels_feature), 1, mels_h);
print_feature("mels_feature", mels_feature);
printf("mels_feature size(n_frames,n_mels)=(%d,%d)\n", mels_w, mels_h);
image_show("mels_feature(C++)", mels_image, 10);
// compute MFCC
vector<vector<float>> mfcc_feature = librosa::Feature::mfcc(data, sr, n_fft, hop_length, window, center, pad_mode,
power, n_mel, fmin, fmax, n_mfcc, norm, dct_type);
int mfcc_w = (int) mfcc_feature.size();
int mfcc_h = (int) mfcc_feature[0].size();
cv::Mat mfcc_image = vector2mat<float>(get_vector(mfcc_feature), 1, mfcc_h);
print_feature("mfcc_feature", mfcc_feature);
printf("mfcc_feature size(n_frames,n_mfcc)=(%d,%d)\n", mfcc_w, mfcc_h);
image_show("mfcc_feature(C++)", mfcc_image, 10);
cv::waitKey(0);
printf("finish...");
return 0;
}
- Python のバージョンをプロジェクトのルート ディレクトリとターミナルに入力します: python main.py でテスト デモを実行します。
# -*-coding: utf-8 -*-
"""
@Author :
@E-mail :
@Date : 2023-08-01 22:27:56
@Brief :
"""
import cv2
import numpy as np
import librosa
def cv_show_image(title, image, use_rgb=False, delay=0):
"""
调用OpenCV显示图片
:param title: 图像标题
:param image: 输入是否是RGB图像
:param use_rgb: True:输入image是RGB的图像, False:返输入image是BGR格式的图像
:param delay: delay=0表示暂停,delay>0表示延时delay毫米
:return:
"""
img = image.copy()
if img.shape[-1] == 3 and use_rgb:
img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR) # 将BGR转为RGB
# cv2.namedWindow(title, flags=cv2.WINDOW_AUTOSIZE)
cv2.namedWindow(title, flags=cv2.WINDOW_NORMAL)
cv2.imshow(title, img)
cv2.waitKey(delay)
return img
def librosa_feature_melspectrogram(y,
sr=16000,
n_mels=128,
n_fft=2048,
hop_length=256,
win_length=None,
window="hann",
center=True,
pad_mode="reflect",
power=2.0,
fmin=0.0,
fmax=None,
**kwargs):
"""
计算音频梅尔频谱图(Mel Spectrogram)
:param y: 音频时间序列
:param sr: 采样率
:param n_mels: number of Mel bands to generate产生的梅尔带数
:param n_fft: length of the FFT window FFT窗口的长度
:param hop_length: number of samples between successive frames 帧移(相邻窗之间的距离)
:param win_length: 窗口的长度为win_length,默认win_length = n_fft
:param window:
:param center: 如果为True,则填充信号y,以使帧 t以y [t * hop_length]为中心。
如果为False,则帧t从y [t * hop_length]开始
:param pad_mode:
:param power: 幅度谱的指数。例如1代表能量,2代表功率,等等
:param fmin: 最低频率(Hz)
:param fmax: 最高频率(以Hz为单位),如果为None,则使用fmax = sr / 2.0
:param kwargs:
:return: 返回Mel频谱shape=(n_mels,n_frames),n_mels是Mel频率的维度(频域),n_frames为时间帧长度(时域)
"""
mel = librosa.feature.melspectrogram(y=y,
sr=sr,
S=None,
n_mels=n_mels,
n_fft=n_fft,
hop_length=hop_length,
win_length=win_length,
window=window,
center=center,
pad_mode=pad_mode,
power=power,
fmin=fmin,
fmax=fmax,
**kwargs)
return mel
def librosa_feature_mfcc(y,
sr=16000,
n_mfcc=128,
n_mels=128,
n_fft=2048,
hop_length=256,
win_length=None,
window="hann",
center=True,
pad_mode="reflect",
power=2.0,
fmin=0.0,
fmax=None,
dct_type=2,
**kwargs):
"""
计算音频MFCC
:param y: 音频时间序列
:param sr: 采样率
:param n_mfcc: number of MFCCs to return
:param n_mels: number of Mel bands to generate产生的梅尔带数
:param n_fft: length of the FFT window FFT窗口的长度
:param hop_length: number of samples between successive frames 帧移(相邻窗之间的距离)
:param win_length: 窗口的长度为win_length,默认win_length = n_fft
:param window:
:param center: 如果为True,则填充信号y,以使帧 t以y [t * hop_length]为中心。
如果为False,则帧t从y [t * hop_length]开始
:param pad_mode:
:param power: 幅度谱的指数。例如1代表能量,2代表功率,等等
:param fmin: 最低频率(Hz)
:param fmax: 最高频率(以Hz为单位),如果为None,则使用fmax = sr / 2.0
:param kwargs:
:return: 返回MFCC shape=(n_mfcc,n_frames)
"""
# MFCC 梅尔频率倒谱系数
mfcc = librosa.feature.mfcc(y=y,
sr=sr,
S=None,
n_mfcc=n_mfcc,
n_mels=n_mels,
n_fft=n_fft,
hop_length=hop_length,
win_length=win_length,
window=window,
center=center,
pad_mode=pad_mode,
power=power,
fmin=fmin,
fmax=fmax,
dct_type=dct_type,
**kwargs)
return mfcc
def read_audio(audio_file, sr=16000, mono=True):
"""
默认将多声道音频文件转换为单声道,并返回一维数组;
如果你需要处理多声道音频文件,可以使用 mono=False,参数来保留所有声道,并返回二维数组。
:param audio_file:
:param sr: sampling rate
:param mono: 设置为true是单通道,否则是双通道
:return:
"""
audio_data, sr = librosa.load(audio_file, sr=sr, mono=mono)
audio_data = audio_data.T.reshape(-1)
return audio_data, sr
def print_feature(name, feature):
h, w = feature.shape[:2]
np.set_printoptions(precision=7, suppress=True, linewidth=(11 + 3) * w)
print("------------------------{}------------------------".format(name))
for i in range(w):
v = feature[:, i].reshape(-1)
print("data[{:0=3d},:]={}".format(i, v))
def print_vector(name, data):
np.set_printoptions(precision=7, suppress=False)
print("------------------------%s------------------------\n" % name)
print("{}".format(data.tolist()))
if __name__ == '__main__':
sr = None
n_fft = 400
hop_length = 160
n_mel = 64
fmin = 80
fmax = 7600
n_mfcc = 64
dct_type = 2
power = 2.0
center = False
norm = True
window = "hann"
pad_mode = "reflect"
audio_file = "data/data_s1.wav"
data, sr = read_audio(audio_file, sr=sr, mono=False)
print("n_fft = %d" % n_fft)
print("n_mel = %d" % n_mel)
print("hop_length = %d" % hop_length)
print("fmin, fmax = (%d,%d)" % (fmin, fmax))
print("sr = %d, data size=%d" % (sr, len(data)))
# print_vector("audio data", data)
mels_feature = librosa_feature_melspectrogram(y=data,
sr=sr,
n_mels=n_mel,
n_fft=n_fft,
hop_length=hop_length,
win_length=None,
fmin=fmin,
fmax=fmax,
window=window,
center=center,
pad_mode=pad_mode,
power=power)
print_feature("mels_feature", mels_feature)
print("mels_feature size(n_frames,n_mels)=({},{})".format(mels_feature.shape[1], mels_feature.shape[0]))
cv_show_image("mels_feature(Python)", mels_feature, delay=10)
mfcc_feature = librosa_feature_mfcc(y=data,
sr=sr,
n_mfcc=n_mfcc,
n_mels=n_mel,
n_fft=n_fft,
hop_length=hop_length,
win_length=None,
fmin=fmin,
fmax=fmax,
window=window,
center=center,
pad_mode=pad_mode,
power=power,
dct_type=dct_type)
print_feature("mfcc_feature", mfcc_feature)
print("mfcc_feature size(n_frames,n_mfcc)=({},{})".format(mfcc_feature.shape[1], mfcc_feature.shape[0]))
cv_show_image("mfcc_feature(Python)", mfcc_feature, delay=10)
cv2.waitKey(0)
5. librosa ライブラリ C++ ソース コードのダウンロード
C/C++ は librosa オーディオ処理ライブラリ melspectrogram および mfcc を実装します。プロジェクト コードのダウンロード アドレス: C/C++ は librosa オーディオ処理ライブラリ melspectrogram および mfcc を実装します。
プロジェクトのソース コードの内容は次のとおりです。
- オーディオ ファイルを読み取るための C++ バージョンの read_audio() 関数を提供します。現在は wav 形式のファイルのみをサポートし、シングル/デュアル チャネルのオーディオ読み取りをサポートします。
- melspectrogram 関数を実現するために、C++ バージョンの librosa::Feature::melspectrogram() を提供します。
- MFCC 関数を実現するために、C++ バージョンの librosa::Feature::mfcc() を提供します。
- OpenCVマップ表示モードを提供する
- プロジェクトデモにはテストデータが付属しており、ビルド完了後に実行可能です