audio_wm/embed.cpp
2025-03-19 19:50:20 +08:00

887 lines
25 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>
#include <filesystem>
#include <sndfile.h>
#include <fmt/core.h>
#include <windows.h>
#include <fstream>
#include <cmath>
#include <numeric>
#include <sstream>
#include <cstring>
#include <Eigen/Dense>
#include "global.h"
#include "dr_wav.h"
#include "embed.h"
#include "util.h"
#include "wavelet.h"
//#include "miniaudio.h"
#include "dr_mp3.h"
using namespace std;
using namespace cv;
namespace fs = std::filesystem;
using namespace Eigen;
const int k1 = 5;
const double PI = 3.1416;
int G_L = 0;
const int G_NMAX_32 = 40;
const int G_SIZE_32 = 2 * G_NMAX_32 + 1;
const int G_TOTAL_ELEMENTS_32 = G_SIZE_32 * G_SIZE_32;
vector<vector<int>> G_ZMLIST_32(G_TOTAL_ELEMENTS_32, vector<int>(2, 0));
vector<complex<double>> G_A_NM_32(G_TOTAL_ELEMENTS_32, (0, 0));
vector<vector<int>> G_ZMLIST_SELECTED_32(G_TOTAL_ELEMENTS_32, vector<int>(2, 0));
const int G_NMAX_10 = 20;
const int G_SIZE_10 = 2 * G_NMAX_10 + 1;
const int G_TOTAL_ELEMENTS_10 = G_SIZE_10 * G_SIZE_10;
vector<vector<int>> G_ZMLIST_10(G_TOTAL_ELEMENTS_10, vector<int>(2, 0));
vector<complex<double>> G_A_NM_10(G_TOTAL_ELEMENTS_10, (0, 0));
vector<vector<int>> G_ZMLIST_SELECTED_10(G_TOTAL_ELEMENTS_10, vector<int>(2, 0));
vector<complex<double>> G_A_NM_SELECTED;
vector<complex<double>> G_A_NM_MODIFIED;
vector<vector<complex<double>>> G_GP_REC_BEFOREMODIFY;
vector<vector<complex<double>>> G_GP_REC;
int wm_embed(const wchar_t* path, const wchar_t* save_path, const int* wm, const int wm_size, const double start_time, const double end_time) {
if (!canFormSquareMatrix(wm_size)) return 2;
int is_mp3 = 0;
int Fs = 0;
int wavelength = 0;
//double D = 0.8; // init 0.2
double DD = 0.0012; // init DD 0.0012
double EE = 0.00002; // init EE 0.00002
int begin = 4095;
int block_length = 0;
vector<int> syn = {1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0};
const int Lsyn = syn.size();
fs::path fname = path;
fs::path s_path = save_path;
int channels;
//int bitrate;
vector<double> yo;
vector<double> yo_origin;
int start = 0;
string audio_name = ConvertUTF16ToMBCS(path);
string save_name = ConvertUTF16ToMBCS(save_path);
cout << "\n read file:" << audio_name << endl;
if (isMp3File(fname, audio_name))
{
// is mp3
is_mp3 = 1;
long Fs_long = 0;
yo_origin = mp3ToDoubleVector(audio_name.c_str(), channels, Fs_long, wavelength);
Fs = (int)Fs_long;
}
else {
drwav wav;
if (!drwav_init_file(&wav, audio_name.c_str(), nullptr)) {
std::cerr << "Error opening WAV file." << std::endl;
return 1;
}
yo_origin = readWav(wav, wavelength, channels, Fs);
}
// stage 1 end
if ((end_time - start_time) < 25.0)
// The difference between start_time and end_time is not less than 25 seconds
return 4;
//int r = static_cast<double>(wavelength) / Fs;
//double embed_range = ceil(r * 0.58);
//if ((end_time - start_time) < embed_range) {
// cout << "[embed error] Please increase the embedding range to " << embed_range << " seconds or more." << endl;
// return 6;
//}
if (Fs < 44100) {
wstring resample_path = AddSuffixToPath(path, L"_resample");
vector<double> out;
convert_wav(yo_origin, Fs, channels, resample_path.c_str());
}
int max_wavelength = Fs * static_cast<int>(end_time - start_time) * channels;
// stage 1 start
//const int frame_size = max_wavelength; // 每帧大小
//const int hop_size = Fs; // 帧移
//size_t num_frames = (yo_origin.size() - frame_size) / hop_size + 1;
//std::vector<double> energy(num_frames);
//// Calculate short-term energy
//for (size_t i = 0; i < num_frames; ++i) {
// double frame_energy = 0.0;
// for (int j = 0; j < frame_size; ++j) {
// frame_energy += yo_origin[i * hop_size + j] * yo_origin[i * hop_size + j];
// }
// energy[i] = frame_energy;
//}
//// Calculate the mean and standard deviation of energy
//double mean_energy = std::accumulate(energy.begin(), energy.end(), 0.0) / num_frames;
//double sq_sum = std::inner_product(energy.begin(), energy.end(), energy.begin(), 0.0);
//double stddev_energy = std::sqrt(sq_sum / num_frames - mean_energy * mean_energy);
//// Set a threshold, such as adding twice the standard deviation to the mean
//double threshold = mean_energy + 2 * stddev_energy;
//// Detect noisy areas
//for (size_t i = 0; i < num_frames; ++i) {
// if (energy[i] > threshold) {
// start = i * hop_size;
// std::cout << "Noisy frame detected at frame index: " << i << ", yo_origin[" << i * hop_size << "], sec: " << static_cast<double>(i * hop_size) / (Fs * 2) << "s,Energy: " << energy[i] << std::endl;
// // 将噪杂的帧添加到yo中
// for (int j = 0; j < max_wavelength; ++j) {
// yo.push_back(yo_origin[start + j]);
// }
// wavelength = max_wavelength / channels;
// break;
// }
//}
bool split = yo_origin.size() > max_wavelength;
if (yo.empty()) {
// 如果音频长度大于25s 则根据start_time, end_time 来确定要嵌入水印的范围
// getAudio20sFront(split, max_wavelength, Fs, channels, wavelength, yo_origin, yo);
if (split) {
start = static_cast<int>(start_time) * Fs * channels;
cout << "start: " << start << endl;
splitAudioByTime(max_wavelength, Fs, channels, wavelength, yo_origin, yo, start_time, end_time, start);
}
else {
yo = yo_origin;
}
}
vector<vector<double>> audio_data(yo.size() / channels, vector<double>(channels, 0.0));
cout << "yo.size():" << yo.size() << endl;
cout << "audio_data.size():" << audio_data.size() << endl;
if (channels == 2)
{
for (int i = 0; i < yo.size(); i++)
{
if (i % 2 == 0) {
audio_data[i / 2][0] = yo[i];
}
if (i % 2 == 1) {
audio_data[i / 2][1] = yo[i];
}
}
}
else
{
for (int i = 0; i < yo.size(); i++)
{
audio_data[i][0] = yo[i];
}
}
std::vector<int> wm_vector(wm, wm + wm_size);
//vector<vector<int>> ww_matrix = matToVector(ww, rows, cols);
int row = static_cast<int>(std::sqrt(wm_size));
vector<vector<int>> ww_matrix = int_ott(wm_vector, row);
int rows = ww_matrix.size();
int cols = ww_matrix[0].size();
cout << "ww_rows:" << ww_matrix.size() << "\t ww_cols:" << ww_matrix[0].size() << endl;
// 图像置乱
vector<vector<int>> w = general(ww_matrix, rows, cols, 5, 6);
// 降维
vector<int> w1 = int_tto(w, rows);
//block_length = rows * cols * 8 * 8;
block_length = 65536;
int i = 1;
//int left = i * (Lsyn * k1 + block_length);
int right = wavelength - (Lsyn * k1 + block_length) * 2;
vector<int> t0;
while (i * (Lsyn * k1 + block_length) < wavelength - ((Lsyn * k1 + block_length)))
{
int bb = begin + (i - 1) * (Lsyn * k1 + block_length);
cout << "\n embed barker code form " << bb << " to " << bb + Lsyn * k1 << endl;
for (int mm = 0; mm < Lsyn; mm++)
{
//vector<double> temp_vec_subsyn;
int front = bb + (mm * k1);
int back = bb + ((mm + 1) * k1);
//计算指定范围均值
double tempmean = calculateMean(audio_data, front + 1, back, 0); // front = 4096 back = 4100
int temp = static_cast<int>(floor(tempmean / D));
double tempmeanl;
if ((temp % 2 + 2) % 2 == syn[mm])
{
tempmeanl = temp * D + D / 2.0;
}
else {
tempmeanl = temp * D - D / 2.0;
}
// 更新指定范围的yo
for (int j = front; j <= back; j++)
{
audio_data[j][0] += tempmeanl - tempmean;
}
}
t0.push_back(begin + (i * Lsyn * k1) + ((i - 1) * block_length) + 1);
vector<double> BLOCK1;
for (int j = t0[i - 1]; j < t0[i - 1] + block_length; j++)
{
BLOCK1.push_back(audio_data[j][0]);
}
vector<double> result = wavelet(BLOCK1, 1);
result.resize(65536);
BLOCK1.clear();
vector<vector<double>> I = ott(result, 256);
int n = I.size(); // 行数
int m = I[0].size(); // 列数
// 极坐标转换相关参数
int M = 4 * n;
//vector<vector<double>> fp(M, vector<double>(M, 0.0));
//vector<vector<double>> Gp(M, vector<double>(M, 0.0));
vector<vector<double>> rr(M, vector<double>(M, 0.0));
vector<vector<double>> oo(M, vector<double>(M, 0.0));
// 声明和初始化 vv 和 uu 矩阵
vector<vector<int>> vv(M, vector<int>(M, 0));
vector<vector<int>> uu(M, vector<int>(M, 0));
MatrixXd fp(M, M);
MatrixXd Gp(M, M);
// 填充 fp 和 Gp 数组
for (int u = 0; u < M; u++) {
for (int v = 0; v < M; v++) {
double rrr = static_cast<double> (u) / M;
double ooo = (2 * PI * v) / M;
int kk = ceil(rrr * (n / 2) * sin(ooo));
int ll = ceil(rrr * (n / 2) * cos(ooo));
fp(u, v) = I[(-1) * kk + (n / 2)][ll + (n / 2) - 1];
Gp(u, v) = fp(u, v) * std::sqrt(static_cast<double> (u) / (2 * M));
}
}
// 填充 vv 和 uu 矩阵
for (int k = 0; k < M; k++) {
for (int j = 0; j < M; j++) {
vv[k][j] = j + 1;
uu[k][j] = k + 1;
}
}
// 计算 rr 和 oo 矩阵
for (int k = 0; k < M; k++) {
for (int j = 0; j < M; j++) {
rr[k][j] = static_cast<double>(uu[k][j] - 1) / M;
oo[k][j] = static_cast<double>(2 * PI * (vv[k][j] - 1)) / M;
}
}
vector<vector<double>> Gp_watermarked(M, vector<double>(M, 0.0));
PQIMfft_embed(Gp, fp, w1, M, DD, EE, oo, rr, Gp_watermarked);
cout << "初始化 I_incircle 为全零矩阵" << endl;
vector<vector<double>> I_incircle(n, vector<double>(m, 0.0));
// 嵌入水印
cout << "\n 嵌入水印" << endl;
for (int u = 0; u < M; u++) {
for (int v = 0; v < M; v++) {
double r = static_cast<double>(u) / M;
double o = (2 * PI * v) / M;
int kkk = static_cast<int>(std::ceil(r * (n / 2) * std::sin(o)));
int lll = static_cast<int>(std::ceil(r * (n / 2) * std::cos(o)));
I_incircle[-kkk + (n / 2)][lll + (n / 2) - 1] = Gp_watermarked[u][v];
}
}
// 重构水印
cout << "重构水印" << endl;
// vector<vector<double>> I_watermarked = I_incircle;
cout << "I_incircle's rows:" << I_incircle.size() << "I_incircle's cols: " << I_incircle[0].size() << endl;
for (int ii = 0; ii < n; ii++) {
for (int jj = 0; jj < m; jj++) {
if (I_incircle[ii][jj] == 0) {
I_incircle[ii][jj] = I[ii][jj];
}
}
}
cout << "\n go to tto;" << endl;
vector<double> BLOCK2 = tto(I_incircle, 256);
vector<double> new_BLOCK2(BLOCK2.size(), 0.0);
BLOCK2.insert(BLOCK2.end(), new_BLOCK2.begin(), new_BLOCK2.end());
cout << "\n go to inverseWavelet;" << endl;
vector<double> signal = inverseWavelet(BLOCK2, 1);
//cout << "\n NO." << i << " , form " << t0[i - 1] << " to " << t0[i - 1] + block_length - 1 << endl;
for (int j = t0[i - 1]; j < t0[i - 1] + block_length; j++) {
audio_data[j][0] = signal[j - t0[i - 1]];
}
double sub_progress = double(i * (Lsyn * k1 + block_length)) / (wavelength - (Lsyn * k1 + block_length) * 2) * 100;
g_audio_wm_progress = sub_progress;
cout << "\n 总完成进度:" << sub_progress << endl;
cout << "==============================================================" << endl;
i++;
//left = i * (Lsyn * k1 + block_length);
}
cout << "t0:" << endl;
printIntSignal(t0, 0);
//trans audio_data to yo
yo.clear();
if (channels == 2) {
for (int j = 0; j < audio_data.size(); j++)
{
yo.push_back(audio_data[j][0]);
yo.push_back(audio_data[j][1]);
}
}
else {
for (int j = 0; j < audio_data.size(); j++)
{
yo.push_back(audio_data[j][0]);
}
}
cout << "yo.size: " << yo.size() << endl;
printSignal(yo, 10);
cout << "start: " << start << endl;
if (split)
{
for (size_t i = 0; i < yo.size(); ++i) {
yo_origin[start + i] = yo[i];
}
}
else
{
yo_origin = yo;
}
// save audio
//if (s_path.extension() != ".wav")
// s_path.replace_extension(".wav");
const wchar_t* wchar_save_path = s_path.c_str(); // 使用完整的保存路径
if (is_mp3) {
save_audio_drmp3(wchar_save_path, yo_origin, Fs, channels);
}
else {
save_audio_drwav(wchar_save_path, yo_origin, Fs, channels);
}
//fs::remove(fname);
return 0;
}
void saveAudio(const char* outputFilename, vector<double> &yo, int sampleRate, int channels) {
SF_INFO sfinfo{};
sfinfo.samplerate = sampleRate; // 设置采样率
sfinfo.channels = channels; // 设置声道数
sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16; // 设置文件格式
// todo save audio
SNDFILE* outfile = sf_open(outputFilename, SFM_WRITE, &sfinfo);
sf_count_t count = sf_write_double(outfile, yo.data(), yo.size());
cout << "\n保存地址:" << outputFilename << endl;
if (count != yo.size()) {
std::cerr << "Error writing frames to file" << std::endl;
sf_close(outfile);
return;
}
// 关闭文件
sf_close(outfile);
std::cout << "\nFile saved successfully." << std::endl;
}
vector<double> inverseWavelet(vector<double> swt_output, int level) {
vector<double> iswt_output;
iswt(swt_output, level, "haar", iswt_output);
return iswt_output;
}
void PQIMfft_embed(MatrixXd Gp, MatrixXd fp,
vector<int> &w1, int M, double DD, double EE, vector<vector<double>> &oo,
vector<vector<double>> &rr, vector<vector<double>> &Gp_watermarked)
{
G_L = w1.size();
int row = static_cast<int>(std::sqrt(G_L));
vector<vector<int>> zmlist;
vector<vector<int>> zmlist_selected;
vector<complex<double>> a_nm;
int nmax = 0;
if (row == 10) {
nmax = G_NMAX_10;
a_nm = G_A_NM_10;
zmlist = G_ZMLIST_10;
}
else {
nmax = G_NMAX_32;
a_nm = G_A_NM_32;
zmlist = G_ZMLIST_32;
}
zhishujufenjie62(Gp, M, nmax, a_nm, zmlist);
// 对应的n和m
vector<int> index_n(zmlist.size(), 0);
vector<int> index_m(zmlist.size(), 0);
for (int i = 0; i < zmlist.size(); i++) {
index_n[i] = zmlist[i][0];
index_m[i] = zmlist[i][1];
}
// 找到合适的嵌入位置
vector<int> index_suitable;
for (int i = 0; i < zmlist.size(); i++) {
if (row == 10) {
// 10*10 embed range
if (((index_m[i] == 0) && (index_n[i] < 0)) ||
((index_m[i] > 0) && (index_m[i] <= 10) && (-4 <= index_n[i]) && (index_n[i] <= 4))) {
index_suitable.push_back(i);
}
}
else {
// 32*32 embed range
if (((index_m[i] == 0) && (index_n[i] < 0)) ||
((index_m[i] > 0) && (index_m[i] <= 30) && (-16 <= index_n[i]) && (index_n[i] <= 16))) {
index_suitable.push_back(i);
}
}
}
index_n.clear();
index_m.clear();
// 随机选出嵌入水印的位置
vector<int> index_selected_embed(index_suitable.begin(), index_suitable.begin() + G_L);
index_suitable.clear();
// 得到在zmlist中的对应的数据为下一步重构准备的
//G_ZMLIST_SELECTED_10.resize(G_L, vector<int>(2, 0));
zmlist_selected.resize(G_L, vector<int>(2, 0));
G_A_NM_SELECTED.resize(G_L, (0,0));
for (int i = 0; i < G_L; i++) {
//G_ZMLIST_SELECTED_10[i] = G_ZMLIST_10[index_selected_embed[i]];
zmlist_selected[i] = zmlist[index_selected_embed[i]];
G_A_NM_SELECTED[i] = a_nm[index_selected_embed[i]];
}
index_selected_embed.clear();
G_A_NM_MODIFIED = G_A_NM_SELECTED;
vector<double> III(G_L, 0.0);
vector<double> IIII(G_L, 0.0);
for (int i = 0; i < G_L; i++) {
complex<double> A_selected = G_A_NM_MODIFIED[i];
III[i] = ((-DD) + sqrt(pow(DD, 2) + 2 * EE * abs(A_selected))) / EE;
double flag = 2 * floor((III[i] + 1) / 2);
if (flag >= III[i]) {
IIII[i] = 2 * floor((III[i] + 1) / 2) - w1[i];
}
else {
IIII[i] = 2 * floor((III[i] + 1) / 2) + w1[i];
}
double aa = DD * IIII[i];
double bb = EE * ((pow(IIII[i], 2)) * 0.5);
G_A_NM_MODIFIED[i] = complex_sign(A_selected) * (aa + bb);
}
III.clear();
IIII.clear();
G_GP_REC_BEFOREMODIFY.resize(M, vector<complex<double>>(M, complex<double>(0, 0)));
//cout << "\n go to zhishujurec622" << endl;
//zhishujurec622(G_A_NM_SELECTED, G_ZMLIST_SELECTED_10, M, oo, rr, G_GP_REC_BEFOREMODIFY);
zhishujurec622(G_A_NM_SELECTED, zmlist_selected, M, oo, rr, G_GP_REC_BEFOREMODIFY);
G_A_NM_SELECTED.clear();
//cout << "--------------------------" << endl;
G_GP_REC.resize(M, vector<complex<double>>(M, complex<double>(0, 0)));
//zhishujurec622(G_A_NM_MODIFIED, G_ZMLIST_SELECTED_10, M, oo, rr, G_GP_REC);
zhishujurec622(G_A_NM_MODIFIED, zmlist_selected, M, oo, rr, G_GP_REC);
G_A_NM_MODIFIED.clear();
G_ZMLIST_SELECTED_10.clear();
//水印图像
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
Gp_watermarked[i][j] = fp(i, j) - std::real(G_GP_REC_BEFOREMODIFY[i][j]) + std::real(G_GP_REC[i][j]);
}
}
G_GP_REC_BEFOREMODIFY.clear();
G_GP_REC_BEFOREMODIFY.clear();
G_GP_REC.clear();
cout << "rows: " << Gp_watermarked.size() << "; cols: " << Gp_watermarked[0].size() << endl;
}
void zhishujurec622(vector<complex<double>> A_nm, vector<vector<int>>& zmlist_selected, int M,
vector<vector<double>> oo, vector<vector<double>> rr, vector<vector<complex<double>>> &result) {
// Initialize matrices
//const int SIZE = static_cast<int>(std::sqrt(G_L));
//int offset = 20;
//if (SIZE == 32)
// offset = 40;
//const int COUNT_SIZE = 57;
//vector<int> count(COUNT_SIZE, 0);
//vector<double> temp_oo_row = oo[0];
//vector<double> temp_rr_col;
//vector<complex<double>> RBF1_col(M, complex<double>(0.0, 0.0));
//vector<complex<double>> RBF2_col(M, complex<double>(0.0, 0.0));
//// Iterate through the 32x32 grid
//for (int x = 0; x < SIZE; x++) {
// //start = clock();
// for (int y = 0; y < SIZE; y++) {
// int row = x * SIZE + y;
// int nj = zmlist_selected[row][0];
// int mc = zmlist_selected[row][1];
// complex<double> A_nm_value = A_nm[row];
// complex<double> conj_A_nm_value = conj(A_nm_value);
// int cnt_nj = count[nj + offset]; // 32*32 +40; 10*10 +20; 16*16 +20;
// double coefficient = 2 * nj * PI;
// for (int i = 0; i < M; i++)
// {
// double rr_val = rr[i][0]; // 行相同
// double image_rr_val = coefficient * rr_val;
// double cos_image_rr_val = cos(image_rr_val);
// double sin_image_rr_val = sin(image_rr_val);
// if (cnt_nj == 0)
// {
// double sqrt_part = sqrt(2.0 / rr_val);
// RBF1_col[i] = sqrt_part * complex<double>(cos_image_rr_val, sin_image_rr_val);
// RBF2_col[i] = sqrt_part * complex<double>(cos_image_rr_val, -sin_image_rr_val);
// }
// complex<double> coefficient1 = A_nm_value * RBF1_col[i];
// complex<double> coefficient2 = conj_A_nm_value * RBF2_col[i];
// for (int j = 0; j < M; j++)
// {
// double oo_val = temp_oo_row[j];// 列相同
// double image_rr_val = mc * oo_val;
// double cos_oo_val = cos(image_rr_val);
// double sin_oo_val = sin(image_rr_val);
// complex<double> front = coefficient1 * complex<double>(cos_oo_val, sin_oo_val);
// complex<double> behind = coefficient2 * complex<double>(cos_oo_val, -sin_oo_val);
// result[i][j] += front + behind;
// }
// }
// if (cnt_nj == 0)
// {
// count[nj + offset] = 1; // 32*32 +40; 10*10 +20; 16*16 +20;
// }
// }
//}
// ========================================================================================================================
// Initialize matrices
const int SIZE = static_cast<int>(std::sqrt(G_L));
int offset = 20;
if (SIZE == 32)
offset = 40;
const int COUNT_SIZE = 57;
MatrixXd eigen_oo(oo.size(), oo[0].size());
for (size_t i = 0; i < oo.size(); ++i) {
for (size_t j = 0; j < oo[i].size(); ++j) {
eigen_oo(i, j) = oo[i][j];
}
}
MatrixXcd eigen_A_nm(A_nm.size(), 1);
for (size_t i = 0; i < A_nm.size(); ++i) {
eigen_A_nm(i, 0) = A_nm[i];
}
MatrixXd eigen_rr(rr.size(), rr[0].size());
for (size_t i = 0; i < rr.size(); ++i) {
for (size_t j = 0; j < rr[i].size(); ++j) {
eigen_rr(i, j) = rr[i][j];
}
}
VectorXi count = VectorXi::Zero(COUNT_SIZE);
VectorXd temp_oo_row = eigen_oo.row(0);
VectorXcd RBF1_col(M);
VectorXcd RBF2_col(M);
// Iterate through the 32x32 grid
for (int x = 0; x < SIZE; x++) {
//start = clock();
for (int y = 0; y < SIZE; y++) {
int row = x * SIZE + y;
int nj = zmlist_selected[row][0];
int mc = zmlist_selected[row][1];
// complex<double> A_nm_value = A_nm[row];
complex<double> A_nm_value = eigen_A_nm(row);
complex<double> conj_A_nm_value = conj(A_nm_value);
int cnt_nj = count(nj + offset);
double coefficient = 2 * nj * PI;
for (int i = 0; i < M; i++)
{
double rr_val = eigen_rr(i, 0);
double image_rr_val = coefficient * rr_val;
double cos_image_rr_val = cos(image_rr_val);
double sin_image_rr_val = sin(image_rr_val);
if (cnt_nj == 0)
{
double sqrt_part = sqrt(2.0 / rr_val);
RBF1_col(i) = sqrt_part * complex<double>(cos_image_rr_val, sin_image_rr_val);
RBF2_col(i) = sqrt_part * complex<double>(cos_image_rr_val, -sin_image_rr_val);
}
complex<double> coefficient1 = A_nm_value * RBF1_col[i];
complex<double> coefficient2 = conj_A_nm_value * RBF2_col[i];
for (int j = 0; j < M; j++)
{
double oo_val = temp_oo_row(j);
double image_rr_val = mc * oo_val;
double cos_oo_val = cos(image_rr_val);
double sin_oo_val = sin(image_rr_val);
complex<double> front = coefficient1 * complex<double>(cos_oo_val, sin_oo_val);
complex<double> behind = coefficient2 * complex<double>(cos_oo_val, -sin_oo_val);
result[i][j] += front + behind;
}
}
if (cnt_nj == 0)
{
count(nj + offset) = 1;
}
}
}
}
// 对于复数的sign函数返回其实部和虚部的符号组成的复数
template<typename T>
std::complex<T> complex_sign(const std::complex<T>& z) {
// 处理输入为零的情况
if (z == std::complex<T>(0, 0)) {
return std::complex<T>(0, 0);
}
// 计算复数的模
T magnitude = std::abs(z);
// 返回归一化的复数
return std::complex<T>(z.real() / magnitude, z.imag() / magnitude);
}
vector<double> wavelet(vector<double> BLOCK1, int level)
{
vector<double> swt_output;
int length = 0;
swt(BLOCK1, level, "haar", swt_output, length);
return swt_output;
}
void printSignal(vector<double> &sig, int length = 0)
{
if (length == 0) length = sig.size();
for (int i = 0; i < length; i++)
{
cout << sig[i] << " ";
}
cout << endl;
}
double calculateMean(vector<vector<double>>& yo, int start, int end, int column)
{
double sum = 0.0;
int count = 0;
for (int i = start; i <= end; i++)
{
sum += yo[i][column];
count++;
}
return sum / count;
}
vector<vector<int>> general(const vector<vector<int>> &w, int m, int n, int a, int b)
{
cout << "in general" << endl;
vector<vector<int>> f(m, vector<int>(n, 0));
for (int x = 0; x < m; x++)
{
for (int y = 0; y < n; y++)
{
int x1 = (x + 1) + a * (y + 1);
if (x1 >= m || x1 < 0)
{
x1 = (x1 % m + m) % m;
if (x1 == 0) x1 = m;
}
f[x1 - 1][y] = w[x][y];
}
}
vector<vector<int>> tmp = f;
for (int x = 0; x < m; x++)
{
for (int y = 0; y < n; y++)
{
int y1 = b * (x + 1) + (y + 1);
if (y1 >= n || y1 < 0)
{
y1 = (y1 % n + n) % n;
if (y1 == 0) y1 = n;
}
f[x][y1 - 1] = tmp[x][y];
}
}
return f;
}
vector<vector<int>> matToVector(const cv::Mat &ww, int rows, int cols)
{
vector<vector<int>> ww_matrix(rows, vector<int>(cols, 0));
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
if (ww.at<uchar>(i, j) > 0)
{
ww_matrix[i][j] = 1;
}
else {
ww_matrix[i][j] = 0;
}
}
}
return ww_matrix;
}
void printIntSignal(vector<int>& signal, int length = 0)
{
if (length == 0) length = signal.size();
for (int i = 0; i < length; i++)
{
cout << signal[i] << "\t";
}
cout << endl;
}
void printMat(vector<vector<double>> mat)
{
for (std::vector<double> sub_mat : mat) {
for (double value : sub_mat) {
cout << value << "\t";
}
cout << endl;
}
cout << endl;
}
void printIntMat(std::vector<std::vector<int>> mat)
{
for (std::vector<int> sub_mat : mat) {
for (int value : sub_mat) {
cout << value << " ";
}
cout << endl;
}
cout << endl;
}
vector<double> readWav(drwav& wav, int& wavelength, int& channels, int& Fs) {
// 使用 dr_mp3 打开 MP3 文件
//drwav wav;
//if (!drwav_init_file(&wav, filename, nullptr)) {
// std::cerr << "Error opening WAV file." << std::endl;
// return {};
//}
// 获取音频信息
channels = static_cast<int>(wav.channels);
drwav_uint64 totalPCMFrameCount = wav.totalPCMFrameCount; // 获取总 PCM 帧数
// 计算总样本数
wavelength = static_cast<int>(totalPCMFrameCount);
Fs = static_cast<int>(wav.sampleRate);
// 创建存储样本的向量
std::vector<float> audio_f(totalPCMFrameCount * channels);
std::vector<double> audio(totalPCMFrameCount * channels);
// 读取 PCM 数据
drwav_read_pcm_frames_f32(&wav, totalPCMFrameCount, audio_f.data());
// 关闭 WAV 文件
drwav_uninit(&wav);
// 将 float 转换为 double
for (size_t i = 0; i < totalPCMFrameCount * channels; i++) {
audio[i] = static_cast<double>(audio_f[i]);
}
return audio;
}
bool canFormSquareMatrix(const int wm_size) {
if (wm_size < 0) return false; // 负数不能组成方阵
int root = static_cast<int>(std::sqrt(wm_size));
return (root * root == wm_size); // 检查是否为完全平方数
}
void getAudio20sFront(bool split, int max_wavelength, int Fs, int channels, int &wavelength, vector<double> yo_origin, vector<double> &yo)
{
if (split)
{
yo.reserve(max_wavelength); // 预留空间以提高性能
yo.assign(yo_origin.begin(), yo_origin.begin() + max_wavelength);
wavelength = max_wavelength / channels;
}
else {
yo = yo_origin;
}
}
void splitAudioByTime(int max_wavelength, int Fs, int channels, int& wavelength, vector<double> yo_origin, vector<double>& yo, const double start_time, const double end_time, int start)
{
yo.resize(max_wavelength);
for (int i = 0; i < max_wavelength; ++i) {
yo[i] = yo_origin[start + i];
}
wavelength = max_wavelength / channels;
}