整理:<cmath> (<math.h>)

本文详细介绍了math.h头文件中的宏定义、三角函数、指数与对数函数等数学运算功能,以及C++标准库&lt;cmath&gt;提供的高级数学函数。


资料一:

math.h头定义了各种数学函数和一个宏。这个库中所有可用的函数取double参数并返回double的结果。

库宏

只有一个在这个库中定义的宏:

S.N. 宏及说明
1 HUGE_VAL

当函数结果可能不是一个浮点数表示。正确的结果如果幅度太大,无法表示的功能设置errno为ERANGE表示一个范围错误,并且返回一个特定的值非常大宏HUGE_VAL或其否定( - HUGE_VAL)命名。

如果结果的幅度太小,而不是一个零值,则返回。在这种情况下,将errno可能会或可能不会被设置为ERANGE。

库函数

以下是math.h的标头中定义的函数:

S.N. 函数及说明
1 double acos(double x)
返回x的反余弦弧度。
2 double asin(double x)
返回x的正弦弧线弧度。
3 double atan(double x)
返回x的反正切值,以弧度为单位。
4 double atan2(doubly y, double x)
返回y / x的以弧度为单位的反正切值,根据这两个值,以确定正确的象限上的标志。
5 double cos(double x)
返回的弧度角x的余弦值。
6 double cosh(double x)
返回x的双曲余弦。
7 double sin(double x)
返回一个弧度角x的正弦。
8 double sinh(double x)
返回x的双曲正弦。
9 double tanh(double x)
返回x的双曲正切。
10 double exp(double x)
返回e值的第x次幂。
11 double frexp(double x, int *exponent)
The returned value is the mantissa and the integer yiibaied to by exponent is the exponent. The resultant value is x = mantissa * 2 ^ exponent.
12 double ldexp(double x, int exponent)
Returns x multiplied by 2 raised to the power of exponent.
13 double log(double x)
返回自然对数的x(基准-E对数)。
14 double log10(double x)
返回x的常用对数(以10为底)。
15 double modf(double x, double *integer)
返回的值是小数成分(小数点后的部分),并设置整数的整数部分。
16 double pow(double x, double y)
返回x的y次方。
17 double sqrt(double x)
返回x的平方根。
18 double ceil(double x)
返回大于或等于x的最小整数值。
19 double fabs(double x)
返回x的绝对值
20 double floor(double x)
返回的最大整数值小于或等于x。
21 double fmod(double x, double y)
返回的x除以y的余数。

资料二:

<cmath> (math.h)

C numerics library
Header  <cmath> declares a set of functions to compute common mathematical operations and transformations:

Functions


Trigonometric functions

Hyperbolic functions

Exponential and logarithmic functions

Power functions

Error and gamma functions

Rounding and remainder functions

Floating-point manipulation functions

Minimum, maximum, difference functions

Other functions

Macros / Functions

These are implemented as macros in C and as functions in C++:
Classification macro / functions

Comparison macro / functions

Macro constants


This header also defines the following macro constants (since C99/C++11):
macrotypedescription
MATH_ERRNO 
MATH_ERREXCEPT
intBitmask value with the possible values math_errhandling can take.
FP_FAST_FMA 
FP_FAST_FMAF 
FP_FAST_FMAL
intEach, if defined, identifies for which type fma is at least as efficient as x*y+z.
FP_INFINITE 
FP_NAN 
FP_NORMAL 
FP_SUBNORMAL 
FP_ZERO
intThe possible values returned by fpclassify.
FP_ILOGB0 
FP_ILOGBNAN
intSpecial values the ilogb function may return.

Types


资料三:

Standard library header <cmath>

   

This header was originally in the C standard library as <math.h>.

This header is part of the numeric library.

Macro constants

indicates the overflow value for floatdouble and long double respectively 
(macro constant)
(C++11)
evaluates to positive infinity or the value guaranteed to overflow a float 
(macro constant)
NAN
(C++11)
evaluates to a quiet NaN of type float 
(macro constant)
defines the error handling mechanism used by the common mathematical functions 
(macro constant)
Classification
(C++11)(C++11)(C++11)(C++11)(C++11)
indicates a floating-point category 
(macro constant)

Types

float_t
(C++11)
most efficient floating-point type at least as wide as float 
(typedef)
double_t
(C++11)
most efficient floating-point type at least as wide as double 
(typedef)

Functions

Basic operations
absolute value of a floating point value (|x|
(function)
remainder of the floating point division operation 
(function)
(C++11)
signed remainder of the division operation 
(function)
(C++11)
signed remainder as well as the three last bits of the division operation 
(function)
fma
(C++11)
fused multiply-add operation 
(function)
(C++11)
larger of two floating point values 
(function)
(C++11)
smaller of two floating point values 
(function)
(C++11)
positive difference of two floating point values (max(0, x-y)
(function)
(C++11)(C++11)(C++11)
not-a-number (NaN) 
(function)
Exponential functions
exp
returns e raised to the given power (ex
(function)
(C++11)
returns 2 raised to the given power (2x
(function)
(C++11)
returns e raised to the given power, minus one (ex-1
(function)
log
computes natural (base e) logarithm (to base e) (ln(x)
(function)
computes common (base 10) logarithm (log10(x)
(function)
(C++11)
base 2 logarithm of the given number (log2(x)
(function)
(C++11)
natural logarithm (to base e) of 1 plus the given number (ln(1+x)
(function)
Power functions
pow
raises a number to the given power (xy
(function)
computes square root (x
(function)
(C++11)
computes cubic root (3x
(function)
(C++11)
computes square root of the sum of the squares of two given numbers (x2
+y2

(function)
Trigonometric functions
sin
computes sine (sin(x)
(function)
cos
computes cosine (cos(x)
(function)
tan
computes tangent (tan(x)
(function)
computes arc sine (arcsin(x)
(function)
computes arc cosine (arccos(x)
(function)
computes arc tangent (arctan(x)
(function)
arc tangent, using signs to determine quadrants 
(function)
Hyperbolic functions
computes hyperbolic sine (sh(x)
(function)
computes hyperbolic cosine (ch(x)
(function)
hyperbolic tangent 
(function)
(C++11)
computes the inverse hyperbolic sine (arsinh(x)
(function)
(C++11)
computes the inverse hyperbolic cosine (arcosh(x)
(function)
(C++11)
computes the inverse hyperbolic tangent (artanh(x)
(function)
Error and gamma functions
erf
(C++11)
error function 
(function)
(C++11)
complementary error function 
(function)
(C++11)
gamma function 
(function)
(C++11)
natural logarithm of the gamma function 
(function)
Nearest integer floating point operations
nearest integer not less than the given value 
(function)
nearest integer not greater than the given value 
(function)
(C++11)
nearest integer not greater in magnitude than the given value 
(function)
(C++11)(C++11)(C++11)
nearest integer, rounding away from zero in halfway cases 
(function)
(C++11)
nearest integer using current rounding mode 
(function)
(C++11)(C++11)(C++11)
nearest integer using current rounding mode with 
exception if the result differs 
(function)
Floating point manipulation functions
decomposes a number into significand and a power of 2 
(function)
multiplies a number by 2 raised to a power 
(function)
decomposes a number into integer and fractional parts 
(function)
(C++11)(C++11)
multiplies a number by FLT_RADIX raised to a power 
(function)
(C++11)
extracts exponent of the number 
(function)
(C++11)
extracts exponent of the number 
(function)
(C++11)(C++11)
next representable floating point value towards the given value 
(function)
(C++11)
copies the sign of a floating point value 
(function)
Classification and comparison
(C++11)
categorizes the given floating point value 
(function)
(C++11)
checks if the given number has finite value 
(function)
(C++11)
checks if the given number is infinite 
(function)
(C++11)
checks if the given number is NaN 
(function)
(C++11)
checks if the given number is normal 
(function)
(C++11)
checks if the given number is negative 
(function)
(C++11)
checks if the first floating-point argument is greater than the second 
(function)
(C++11)
checks if the first floating-point argument is greater or equal than the second 
(function)
(C++11)
checks if the first floating-point argument is less than the second 
(function)
(C++11)
checks if the first floating-point argument is less or equal than the second 
(function)
(C++11)
checks if the first floating-point argument is less or greater than the second 
(function)
(C++11)
checks if two floating-point values are unordered 
(function)

继续补全: ```cpp #define _USE_MATH_DEFINES #include "NoteDetector.h" #include <complex> #include <cmath> #include <algorithm> #include <numeric> #include <cassert> #include <map> #include <set> #include <fstream> #include <iterator> #include <iostream> // 常量定义 const size_t FFT_SIZE = 4096; // FFT窗口大小 const size_t HOP_SIZE = 1024; // 跳跃大小 const float MIN_FREQ = 65.0f; // 最低频率(C2) const float MAX_FREQ = 2093.0f; // 最高频率(C7) // 调试日志 std::ofstream logFile("debug_log.txt", std::ios::app); // FFT变换(迭代实现) void NoteDetector::FFT(std::vector<Complex>& data) { const size_t n = data.size(); if (n <= 1) return; // 位反转重排 for (size_t i = 0, j = 0; i < n; ++i) { if (j > i) std::swap(data[i], data[j]); size_t k = n; while (j & (k >>= 1)) j &= ~k; j |= k; } // 蝶形运算 for (size_t s = 1; s <= static_cast<size_t>(std::log2(n)); ++s) { size_t m = 1 << s; Complex wm = std::exp(Complex(0, -2.0 * M_PI / m)); for (size_t k = 0; k < n; k += m) { Complex w(1, 0); for (size_t j = 0; j < m/2; ++j) { Complex t = w * data[k + j + m/2]; Complex u = data[k + j]; data[k + j] = u + t; data[k + j + m/2] = u - t; w *= wm; } } } } // 获取基频 float NoteDetector::GetFundamentalFrequency(const int16_t* data, size_t size, uint32_t sampleRate) { if (size < FFT_SIZE) return 0.0f; // 1. 自相关法 std::vector<float> autocorr(size / 2, 0.0f); for (size_t lag = 1; lag < size / 2; ++lag) { float sum = 0.0f; for (size_t i = 0; i < size - lag; ++i) { sum += data[i] * data[i + lag]; } autocorr[lag] = sum / (size - lag); } // 寻找自相关峰值(在合理范围内) const size_t minLag = sampleRate / static_cast<size_t>(MAX_FREQ); const size_t maxLag = sampleRate / static_cast<size_t>(MIN_FREQ); float maxCorrelation = 0.0f; size_t bestLag = 0; for (size_t lag = minLag; lag < (std::min)(maxLag, autocorr.size()); ++lag) { if (autocorr[lag] > maxCorrelation) { maxCorrelation = autocorr[lag]; bestLag = lag; } } float frequency1 = 0.0f; if (bestLag > 0 && maxCorrelation > 0.1f){ frequency1 = static_cast<float>(sampleRate) / bestLag; } // 2. FFT频谱分析(验证) std::vector<Complex> fftData(FFT_SIZE); for (size_t i = 0; i < FFT_SIZE && i < size; ++i) { fftData[i] = Complex(static_cast<float>(data[i]), 0.0f); } // 补零 for (size_t i = size; i < FFT_SIZE; ++i) { fftData[i] = Complex(0.0f, 0.0f); } FFT(fftData); // 寻找频谱峰值 const size_t minBin = FFT_SIZE * MIN_FREQ / sampleRate; const size_t maxBin = FFT_SIZE * MAX_FREQ / sampleRate; float maxMagnitude = 0.0f; size_t peakBin = 0; for (size_t i = minBin; i <= maxBin && i < FFT_SIZE / 2; ++i) { float magnitude = std::abs(fftData[i]); if (magnitude > maxMagnitude) { maxMagnitude = magnitude; peakBin = i; } } float frequency2 = 0.0f; if (peakBin > 0 && maxMagnitude > 1000.0f) { frequency2 = static_cast<float>(peakBin) * sampleRate / FFT_SIZE; } // 3. 结合两种方法的结果 if (frequency1 > 0 && frequency2 > 0) { // 如果两种方法结果接近,取平均值 if (std::abs(frequency1 - frequency2) < 10.0f) { return (frequency1 + frequency2) / 2.0f; } // 否则取置信度更高的 else { return maxCorrelation > 0.5f ? frequency1 : frequency2; } } else if (frequency1 > 0) { return frequency1; } else if (frequency2 > 0) { return frequency2; } return 0.0f; } // 获取频谱峰值 std::vector<float> NoteDetector::GetSpectralPeaks(const std::vector<Complex>& spectrum, uint32_t sampleRate, size_t fftSize) { std::vector<float> peaks; const float threshold = 1000.0f; // 幅度阈值 for (size_t i = 1; i < fftSize / 2 - 1; ++i) { float magnitude = std::abs(spectrum[i]); // 检测局部峰值 if (magnitude > threshold && magnitude > std::abs(spectrum[i - 1]) && magnitude > std::abs(spectrum[i + 1])) { float frequency = static_cast<float>(i) * sampleRate / fftSize; // 二次插值提高精度 float alpha = std::abs(spectrum[i - 1]); float beta = std::abs(spectrum[i]); float gamma = std::abs(spectrum[i + 1]); float correction = 0.5f * (alpha - gamma) / (alpha - 2.0f * beta + gamma); frequency += correction * sampleRate / fftSize; peaks.push_back(frequency); } } // 按幅度排序(降序) std::sort(peaks.begin(), peaks.end(), [&spectrum, sampleRate, fftSize](float f1, float f2) { size_t bin1 = static_cast<size_t>(f1 * fftSize / sampleRate); size_t bin2 = static_cast<size_t>(f2 * fftSize / sampleRate); return std::abs(spectrum[bin1]) > std::abs(spectrum[bin2]); }); return peaks; } // 频率转MIDI音高 int NoteDetector::FrequencyToPitch(float frequency) { if (frequency < 20.0f) return -1; // A4 = 440Hz = MIDI 69 int pitch = static_cast<int>(12.0f * log2(frequency / 440.0f) + 69.0f + 0.5f); // 限制在合理范围内 if (pitch < 0 || pitch > 127) return -1; return pitch; } // 计算音高类轮廓(PCP) std::vector<float> NoteDetector::CalculatePCP(const std::vector<float>& frequencies, const std::vector<float>& magnitudes) { std::vector<float> pcp(12, 0.0f); // 12个半音 for (size_t i = 0; i < frequencies.size() && i < magnitudes.size(); ++i) { int pitch = FrequencyToPitch(frequencies[i]); if (phip >= 0) { int pitchClass = pitch % 12; pcp[pitchClass] += magnitudes[i]; } } // 归一化 float maxVal = *std::max_element(pcp.begin(), pcp.end()); if (maxVal > 0.0f) { for (float& val : pcp) { val /= maxVal; } } return pcp; } // 检测和弦类型 std::string NoteDetector::DetectChordType(const std::vector<int>& pitches) { if (pitches.empty()) return ""; // 计算音程 std::set<int> pitchClasses; for (int pitch : pitches) { pitchClasses.insert(pitch % 12); } // 常见和弦模式 static const std::map<std::set<int>, std::string> chordPatterns = { {{0, 4, 7}, "Major"}, // 大三和弦 {{0, 3, 7}, "Minor"}, // 小三和弦 {{0, 4, 7, 11}, "Major 7th"}, // 大七和弦 {{0, 3, 7, 10}, "Minor 7th"}, // 小七和弦 {{0, 7}, "Perfect 5th"}, // 纯五度 {{0, 5, 7}, "Sus4"}, // 挂四和弦 }; // 尝试匹配 for (const auto& [pattern, name] : chordPatterns) { if (pitchClasses == pattern) { return name; } } return "Unknown"; } // 滤波和弦音符 std::vector<Note> NoteDetector::FilterChordNotes(std::vector<Note> notes) { if (notes.size() <= 1) return notes; // 按音高排序 std::sort(notes.begin(), notes.end(), [](const Note& a, const Note& b) { return a.pitch < b.pitch; }); // 去重 auto last = std::unique(notes.begin(), notes.end(), [](const Note& a, const Note& b) { return a.pitch == b.pitch; }); notes.erase(last, notes.end()); // 限制音符数量(最多5个) if (notes.size() > 5) { notes.resize(5); } return notes; } // 计算短时能量 std::vector<float> NoteDetector::CalculateEnergy(const std::vector<int16_t>& pcmData, size_t frameSize) { std::vector<float> energy; const size_t totalFrames = pcmData.size() / frameSize; energy.reserve(totalFrames); for (size_t i = 0; i < totalFrames; ++i) { float sum = 0.0f; const size_t start = i * frameSize; const size_t end = (std::min)(start + frameSize, pcmData.size()); for (size_t j = start; j < end; ++j) { float sample = static_cast<float>(pcmData[j]) / 32768.0f; // 归一化 sum += sample * sample; } energy.push_back(sum / (end - start)); } return energy; } // 计算谱通量 std::vector<float> NoteDetector::CalculateSpectralFlux(const std::vector<Complex>& spectrum1, const std::vector<Complex>& spectrum2) { std::vector<float> flux(spectrum1.size(), 0.0f); for (size_t i = 0; i < spectrum1.size(); ++i) { float mag1 = std::abs(spectrum1[i]); float mag2 = std::abs(spectrum2[i]); flux[i] = (std::max)(0.0f, mag2 - mag1); } return flux; } // 峰值检测 std::vector<size_t> NoteDetector::DetectPeaks(const std::vector<float>& data, float threshold) { std::vector<size_t> peaks; if (data.size() < 3) return peaks; for (size_t i = 1; i < data.size() - 1; ++i) { if (data[i] > threshold && data[i] > data[i - 1] && data[i] > data[i + 1]) { peaks.push_back(i); } } return peaks; } // 检测音符起始点 std::vector<float> NoteDetector::DetectOnsets(const std::vector<int16_t>& pcmData, uint32_t sampleRate) { logFile << "开始音符起始点检测,采样率:" << sampleRate << ",总样本数:" << pcmData.size() << std::endl; std::vector<float> onsets; const size_t frameSize = FFT_SIZE; const size_t hopSize = HOP_SIZE; const size_t totalFrames = (pcmData.size() - frameSize) / hopSize; if (totalFrames < 2) { logFile << "帧数不足,跳过起始点检测" << std::endl; return onsets; } std::vector<Complex> prevSpectrum(FFT_SIZE, 0.0f); std::vector<float> spectralFlux; // 计算每个帧的谱通量 for (size_t frame = 0; frame < totalFrames; ++frame) { size_t start = frame * hopSize; // 准备FFT数据(应用汉明窗) std::vector<Complex> currentSpectrum(FFT_SIZE); for (size_t i = 0; i < FFT_SIZE && start + i < pcmData.size(); ++i) { float window = 0.54f - 0.46f * cosf(2.0f * M_PI * i / (FFT_SIZE - 1)); currentSpectrum[i] = Complex(static_cast<float>(pcmData[start + i]) * window / 32768.0f, 0.0f); } FFT(currentSpectrum); // 计算谱通量(从第二帧开始) if (frame > 0) { float flux = 0.0f; for (size_t i = 0; i < FFT_SIZE / 2; ++i) { float mag1 = std::abs(prevSpectrum[i]); float mag2 = std::abs(currentSpectrum[i]); flux += (std::max)(0.0f, mag2 - mag1); } spectralFlux.push_back(flux); } prevSpectrum = currentSpectrum; } // 检测谱通量峰值 if (!spectralFlux.empty()) { float mean = std::accumulate(spectralFlux.begin(), spectralFlux.end(), 0.0f) / spectralFlux.size(); float variance = 0.0f; for (float val : spectralFlux) { variance += (val - mean) * (val - mean); } variance /= spectralFlux.size(); float stdDev = sqrtf(variance); float threshold = mean + 2.0f * stdDev; auto peaks = DetectPeaks(spectralFlux, threshold); // 转换为时间(秒) for (size_t peak : peaks) { float time = static_cast<float>(peak * hopSize) / sampleRate; onsets.push_back(time); } } return onsets; } // 分析频谱能量 std::vector<float> NoteDetector::GetSpectralEnergy(const std::vector<int16_t>& pcmData, uint32_t sampleRate) { std::vector<float> spectralEnergy; const size_t hopSize = HOP_SIZE; const size_t totalFrames = (pcmData.size() - FFT_SIZE) / hopSize; for (size_t frame = 0; frame < totalFrames; ++frame) { size_t start = frame * hopSize; // 准备FFT数据 std::vector<Complex> fftData(FFT_SIZE); for (size_t i = 0; i < FFT_SIZE && start + i < pcmData.size(); ++i) { // 应用汉宁窗 float window = 0.5f * (1.0f - cosf(2.0f * M_PI * i / (FFT_SIZE - 1))); fftData[i] = Complex(static_cast<float>(pcmData[start + i]) * window, 0.0f); } // FFT变换 FFT(fftData); // 计算频谱能量 float energy = 0.0f; for (size_t i = 0; i < FFT_SIZE / 2; ++i) { energy += std::norm(fftData[i]); } spectralEnergy.push_back(energy); } return spectralEnergy; } // 检测和弦 std::vector<Chord> NoteDetector::DetectChords(const std::vector<int16_t>& pcmData, uint32_t sampleRate) { std::vector<Chord> chords; const size_t hopSize = HOP_SIZE; const size_t totalFrames = (pcmData.size() - FFT_SIZE) / hopSize; // 获取音符起始点 auto onsets = DetectOnsets(pcmData, sampleRate); // 按起始点分割音频 for (size_t i = 0; i < onsets.size();
最新发布
01-01
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值