mirror of
https://github.com/damp11113/EasyMPX.git
synced 2025-04-27 06:28:10 +00:00
new update
This commit is contained in:
parent
4a0ecf6113
commit
7eeca6f675
@ -4,10 +4,13 @@
|
||||
#include "PaDSPFunc.h"
|
||||
#include "PaMPXFunc.h"
|
||||
#include "PaFilterFunc.h"
|
||||
#include "rtfir.hpp"
|
||||
|
||||
#define INPUT_DEVICE_INDEX 16
|
||||
|
||||
#define INPUT_DEVICE_INDEX 4
|
||||
#define OUTPUT_DEVICE_INDEX 39
|
||||
|
||||
#define CompositeClipper true;
|
||||
|
||||
int main() {
|
||||
PaError err;
|
||||
@ -86,9 +89,11 @@ int main() {
|
||||
};
|
||||
float* piloToneBuffer = new float[framesPerBuffer];
|
||||
float* stereoToneBuffer = new float[framesPerBuffer];
|
||||
|
||||
SignalGenerator::GenerateSineWave(piloToneBuffer, framesPerBuffer, 19000, 0.08f);
|
||||
SignalGenerator::GenerateSineWave(stereoToneBuffer, framesPerBuffer, 38000, 1);
|
||||
|
||||
|
||||
|
||||
std::cout << "MPX encoder is running" << std::endl;
|
||||
|
||||
while (true) {
|
||||
@ -102,9 +107,6 @@ int main() {
|
||||
//AudioBuffer audio{ buffer, framesPerBuffer * inputParameters.channelCount };
|
||||
//multibandCompressor(audio, bands);
|
||||
|
||||
//LowPassFilter filter(192000, 15000, 64);
|
||||
|
||||
//filter.apply(buffer, framesPerBuffer);
|
||||
|
||||
|
||||
// MPX Processing here
|
||||
@ -119,10 +121,27 @@ int main() {
|
||||
for (int i = 0, j = 0; i < framesPerBuffer * inputParameters.channelCount; i += 2, ++j) {
|
||||
subtractBuffer[j] = 0.5f * (buffer[i] - buffer[i + 1]); // Average the two channels
|
||||
}
|
||||
|
||||
// limit mono signal
|
||||
/*
|
||||
float maxSample2 = 2.5f;
|
||||
for (int i = 0; i < framesPerBuffer; ++i) {
|
||||
if (fabsf(subtractBuffer[i]) > maxSample2) {
|
||||
maxSample2 = fabsf(subtractBuffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (maxSample2 > 1.0f) {
|
||||
for (int i = 0; i < framesPerBuffer; ++i) {
|
||||
subtractBuffer[i] /= maxSample2;
|
||||
}
|
||||
}
|
||||
*/
|
||||
for (int i = 0; i < framesPerBuffer; ++i) {
|
||||
stereoMultipledBuffer[i] = stereoToneBuffer[i] * subtractBuffer[i];
|
||||
}
|
||||
// limit mono signal
|
||||
/*
|
||||
float maxSample = 2.0f;
|
||||
for (int i = 0; i < framesPerBuffer; ++i) {
|
||||
if (fabsf(monoBuffer[i]) > maxSample) {
|
||||
@ -135,27 +154,26 @@ int main() {
|
||||
monoBuffer[i] /= maxSample;
|
||||
}
|
||||
}
|
||||
// limit mono signal
|
||||
float maxSample2 = 2.5f;
|
||||
for (int i = 0; i < framesPerBuffer; ++i) {
|
||||
if (fabsf(stereoMultipledBuffer[i]) > maxSample2) {
|
||||
maxSample2 = fabsf(stereoMultipledBuffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (maxSample2 > 1.0f) {
|
||||
for (int i = 0; i < framesPerBuffer; ++i) {
|
||||
stereoMultipledBuffer[i] /= maxSample2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
|
||||
// mix mpx
|
||||
const float* mixbuffers[3] = {monoBuffer, piloToneBuffer, stereoMultipledBuffer };
|
||||
mix(mixedBuffer, mixbuffers, 3, framesPerBuffer);
|
||||
|
||||
|
||||
if (CompositeClipper) {
|
||||
float maxSample = 2.0f;
|
||||
for (int i = 0; i < framesPerBuffer; ++i) {
|
||||
if (fabsf(mixedBuffer[i]) > maxSample) {
|
||||
maxSample = fabsf(mixedBuffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (maxSample > 1.0f) {
|
||||
for (int i = 0; i < framesPerBuffer; ++i) {
|
||||
mixedBuffer[i] /= maxSample;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
err = Pa_WriteStream(outputStream, mixedBuffer, framesPerBuffer);
|
||||
@ -167,7 +185,7 @@ int main() {
|
||||
delete[] subtractBuffer;
|
||||
delete[] mixedBuffer;
|
||||
delete[] stereoMultipledBuffer;
|
||||
|
||||
//delete[] lowpassed15KBuffer;
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
|
@ -131,6 +131,7 @@
|
||||
<ClCompile Include="PaDSPFunc.cpp" />
|
||||
<ClCompile Include="PaFilterFunc.cpp" />
|
||||
<ClCompile Include="PaMPXFunc.cpp" />
|
||||
<ClCompile Include="rtfir.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\..\..\radioconda\pkgs\portaudio-19.6.0-h63175ca_9\Library\bin\portaudio.dll" />
|
||||
@ -141,6 +142,7 @@
|
||||
<ClInclude Include="PaDSPFunc.h" />
|
||||
<ClInclude Include="PaFilterFunc.h" />
|
||||
<ClInclude Include="PaMPXFunc.h" />
|
||||
<ClInclude Include="rtfir.hpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Library Include="..\..\..\..\radioconda\pkgs\portaudio-19.6.0-h63175ca_9\Library\lib\portaudio.lib" />
|
||||
|
@ -27,6 +27,9 @@
|
||||
<ClCompile Include="PaFilterFunc.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rtfir.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
@ -47,6 +50,9 @@
|
||||
<ClInclude Include="PaFilterFunc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rtfir.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Library Include="..\..\..\..\radioconda\pkgs\portaudio-19.6.0-h63175ca_9\Library\lib\portaudio.lib">
|
||||
|
@ -1,40 +1 @@
|
||||
#include "PaFilterFunc.h"
|
||||
#include <cmath>
|
||||
|
||||
LowPassFilter::LowPassFilter(double sampleRate, double cutoffFreq, int order) {
|
||||
coefficients = calculateCoefficients(sampleRate, cutoffFreq, order);
|
||||
delayLine.resize(coefficients.size(), 0.0);
|
||||
}
|
||||
|
||||
std::vector<double> LowPassFilter::calculateCoefficients(double sampleRate, double cutoffFreq, int order) {
|
||||
std::vector<double> coeffs(order + 1);
|
||||
double omegaC = 2.0 * M_PI * cutoffFreq / sampleRate;
|
||||
|
||||
for (int n = 0; n <= order; ++n) {
|
||||
if (n == order / 2) {
|
||||
coeffs[n] = omegaC / M_PI;
|
||||
}
|
||||
else {
|
||||
coeffs[n] = sin(omegaC * (n - order / 2)) / (M_PI * (n - order / 2));
|
||||
}
|
||||
}
|
||||
|
||||
return coeffs;
|
||||
}
|
||||
|
||||
void LowPassFilter::apply(float* buffer, int bufferSize) {
|
||||
for (int i = 0; i < bufferSize; ++i) {
|
||||
double output = 0.0;
|
||||
delayLine[0] = buffer[i];
|
||||
|
||||
for (size_t j = 0; j < coefficients.size(); ++j) {
|
||||
output += coefficients[j] * delayLine[j];
|
||||
}
|
||||
|
||||
for (size_t j = coefficients.size() - 1; j >= 1; --j) {
|
||||
delayLine[j] = delayLine[j - 1];
|
||||
}
|
||||
|
||||
buffer[i] = static_cast<float>(output);
|
||||
}
|
||||
}
|
||||
#include "PaFilterFunc.h"
|
@ -1,18 +1,5 @@
|
||||
#ifndef PAFILTERFUNC_H
|
||||
#define M_PI 3.14159265358979323846
|
||||
#include <vector>
|
||||
|
||||
class LowPassFilter {
|
||||
public:
|
||||
LowPassFilter(double sampleRate, double cutoffFreq, int order);
|
||||
void apply(float* buffer, int bufferSize);
|
||||
|
||||
private:
|
||||
std::vector<double> calculateCoefficients(double sampleRate, double cutoffFreq, int order);
|
||||
|
||||
std::vector<double> coefficients;
|
||||
std::vector<double> delayLine;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif // AUDIO_FILTER_H
|
144
FMPX generator/rtfir.cpp
Normal file
144
FMPX generator/rtfir.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
#include <stdexcept>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "rtfir.hpp"
|
||||
|
||||
// Some math.h implementations don't define M_PI
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
|
||||
/*!\brief Constructor for base FIR object
|
||||
* \param Taps Number of taps in the filter
|
||||
*/
|
||||
RTFIR::RTFIR(const unsigned int &Taps){
|
||||
coeff=new double[Taps];
|
||||
buffer=new double[Taps];
|
||||
memset(buffer,0,Taps*sizeof(double));
|
||||
taps=Taps;
|
||||
}
|
||||
|
||||
/*!\brief Deconstructor for base FIR object
|
||||
*/
|
||||
RTFIR::~RTFIR(){
|
||||
delete [] coeff;
|
||||
delete [] buffer;
|
||||
}
|
||||
|
||||
/*!\brief Filters input data
|
||||
* \param Sample Sample to filter
|
||||
* \return Filtered sample
|
||||
*/
|
||||
double RTFIR::Filter(const double &Sample){
|
||||
// Roll back samplebuffer
|
||||
memmove(&buffer[1],&buffer[0],(taps-1)*sizeof(*buffer));
|
||||
buffer[0]=Sample;
|
||||
|
||||
// Perform multiplication
|
||||
double output=0;
|
||||
for(unsigned int i=0;i<taps;i++){
|
||||
output+=buffer[i]*coeff[i];
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/*!\brief Get a list of coefficients for debugging
|
||||
* \return List of FIR coefficients
|
||||
*/
|
||||
std::vector<double> RTFIR::GetCoefficients() const{
|
||||
std::vector<double> c;
|
||||
c.resize(taps);
|
||||
for(unsigned int i=0;i<taps;i++){
|
||||
c[i]=coeff[i];
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/*!\brief Constructor for lowpass FIR filter
|
||||
* \param Taps Number of taps in the FIR filter
|
||||
* \param Freq Normalized cutoff-frequency (f/fs)
|
||||
*/
|
||||
RTFIR_lowpass::RTFIR_lowpass(const unsigned int &Taps,const double &Freq) : RTFIR(Taps){
|
||||
if (Freq<0.0 || Freq>0.5){
|
||||
throw std::invalid_argument("Frequencies must be normalized");
|
||||
}
|
||||
else{
|
||||
int W=Taps/2;
|
||||
for(int i=-W;i<W;i++){
|
||||
if(i==0){
|
||||
coeff[W]=2*Freq;
|
||||
}
|
||||
else{
|
||||
coeff[i+W]=sin(2*(M_PI)*Freq*i)/(i*(M_PI));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!\brief Constructor for highpass FIR filter
|
||||
* \param Taps Number of taps in the FIR filter
|
||||
* \param Freq Normalized cutoff-frequency (f/fs)
|
||||
*/
|
||||
RTFIR_highpass::RTFIR_highpass(const unsigned int &Taps,const double &Freq) : RTFIR(Taps){
|
||||
if (Freq<0.0 || Freq>0.5){
|
||||
throw std::invalid_argument("Frequencies must be normalized");
|
||||
}
|
||||
else{
|
||||
int W=Taps/2;
|
||||
for(int i=-W;i<W;i++){
|
||||
if(i==0){
|
||||
coeff[W]=1-(2*Freq);
|
||||
}
|
||||
else{
|
||||
coeff[i+W]=-sin(2*M_PI*Freq*i)/(i*M_PI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!\brief Constructor for bandpass FIR filter
|
||||
* \param Taps Number of taps in the FIR filter
|
||||
* \param Low Normalized lower cutoff-frequency (f/fs)
|
||||
* \param High Normalized higher cutoff-frequency (f/fs)
|
||||
*/
|
||||
RTFIR_bandpass::RTFIR_bandpass(const unsigned int &Taps,const double &Low,const double &High) : RTFIR(Taps){
|
||||
if (Low<0.0 || Low>0.5 || High<0.0 || High>0.5){
|
||||
throw std::invalid_argument("Frequencies must be normalized");
|
||||
}
|
||||
else{
|
||||
int W=Taps/2;
|
||||
for(int i=-W;i<W;i++){
|
||||
if(i==0){
|
||||
coeff[W]=((2*M_PI*High)-(2*M_PI*Low))/M_PI;
|
||||
}
|
||||
else{
|
||||
coeff[i+W]=(sin(2*M_PI*High*i)-sin(2*M_PI*Low*i))/(i*M_PI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!\brief Constructor for bandstop FIR filter
|
||||
* \param Taps Number of taps in the FIR filter
|
||||
* \param Low Normalized lower cutoff-frequency (f/fs)
|
||||
* \param High Normalized higher cutoff-frequency (f/fs)
|
||||
*/
|
||||
RTFIR_bandstop::RTFIR_bandstop(const unsigned int &Taps,const double &Low,const double &High) : RTFIR(Taps){
|
||||
if (Low<0.0 || Low>0.5 || High<0.0 || High>0.5){
|
||||
throw std::invalid_argument("Frequencies must be normalized");
|
||||
}
|
||||
else{
|
||||
int W=Taps/2;
|
||||
for(int i=-W;i<W;i++){
|
||||
if(i==0){
|
||||
coeff[W]=1+((2*M_PI*Low)-(2*M_PI*High))/M_PI;
|
||||
}
|
||||
else{
|
||||
coeff[i+W]=(sin(2*M_PI*Low*i)-sin(2*M_PI*High*i))/(i*M_PI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
46
FMPX generator/rtfir.hpp
Normal file
46
FMPX generator/rtfir.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
/*!\file rtfir.hpp
|
||||
* \brief Implements realtime FIR filtering for C++
|
||||
* \author Vegard Fiksdal
|
||||
*/
|
||||
|
||||
#ifndef _RTFIR_HPP_
|
||||
#define _RTFIR_HPP_
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
class RTFIR {
|
||||
protected:
|
||||
double *coeff; //!< Coefficients of the FIR filter
|
||||
double *buffer; //!< Sample buffer for FIR filter
|
||||
unsigned int taps; //!< Number of coefficients of the FIR filter
|
||||
public:
|
||||
RTFIR(const unsigned int &Taps);
|
||||
~RTFIR();
|
||||
double Filter(const double &x);
|
||||
std::vector<double> GetCoefficients() const;
|
||||
};
|
||||
|
||||
class RTFIR_lowpass : public RTFIR {
|
||||
public:
|
||||
RTFIR_lowpass(const unsigned int &Taps,const double &Freq);
|
||||
};
|
||||
|
||||
class RTFIR_highpass : public RTFIR {
|
||||
public:
|
||||
RTFIR_highpass(const unsigned int &Taps,const double &Freq);
|
||||
};
|
||||
|
||||
class RTFIR_bandpass : public RTFIR {
|
||||
public:
|
||||
RTFIR_bandpass(const unsigned int &Taps,const double &Freq1,const double &Freq2);
|
||||
};
|
||||
|
||||
class RTFIR_bandstop : public RTFIR {
|
||||
public:
|
||||
RTFIR_bandstop(const unsigned int &Taps,const double &Freq1,const double &Freq2);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user