diff --git a/FMPX generator/FMPX generator.cpp b/FMPX generator/FMPX generator.cpp index f8b3f5a..cc7c57b 100644 --- a/FMPX generator/FMPX generator.cpp +++ b/FMPX generator/FMPX generator.cpp @@ -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; diff --git a/FMPX generator/FMPX generator.vcxproj b/FMPX generator/FMPX generator.vcxproj index 6db6fb6..4959fdf 100644 --- a/FMPX generator/FMPX generator.vcxproj +++ b/FMPX generator/FMPX generator.vcxproj @@ -131,6 +131,7 @@ + @@ -141,6 +142,7 @@ + diff --git a/FMPX generator/FMPX generator.vcxproj.filters b/FMPX generator/FMPX generator.vcxproj.filters index fcf6a4c..536240d 100644 --- a/FMPX generator/FMPX generator.vcxproj.filters +++ b/FMPX generator/FMPX generator.vcxproj.filters @@ -27,6 +27,9 @@ Source Files + + Source Files + @@ -47,6 +50,9 @@ Header Files + + Header Files + diff --git a/FMPX generator/PaFilterFunc.cpp b/FMPX generator/PaFilterFunc.cpp index fd44283..0ed6091 100644 --- a/FMPX generator/PaFilterFunc.cpp +++ b/FMPX generator/PaFilterFunc.cpp @@ -1,40 +1 @@ -#include "PaFilterFunc.h" -#include - -LowPassFilter::LowPassFilter(double sampleRate, double cutoffFreq, int order) { - coefficients = calculateCoefficients(sampleRate, cutoffFreq, order); - delayLine.resize(coefficients.size(), 0.0); -} - -std::vector LowPassFilter::calculateCoefficients(double sampleRate, double cutoffFreq, int order) { - std::vector 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(output); - } -} +#include "PaFilterFunc.h" \ No newline at end of file diff --git a/FMPX generator/PaFilterFunc.h b/FMPX generator/PaFilterFunc.h index 2cbafa2..58b103b 100644 --- a/FMPX generator/PaFilterFunc.h +++ b/FMPX generator/PaFilterFunc.h @@ -1,18 +1,5 @@ #ifndef PAFILTERFUNC_H #define M_PI 3.14159265358979323846 -#include - -class LowPassFilter { -public: - LowPassFilter(double sampleRate, double cutoffFreq, int order); - void apply(float* buffer, int bufferSize); - -private: - std::vector calculateCoefficients(double sampleRate, double cutoffFreq, int order); - - std::vector coefficients; - std::vector delayLine; -}; -#endif +#endif // AUDIO_FILTER_H \ No newline at end of file diff --git a/FMPX generator/rtfir.cpp b/FMPX generator/rtfir.cpp new file mode 100644 index 0000000..af83b53 --- /dev/null +++ b/FMPX generator/rtfir.cpp @@ -0,0 +1,144 @@ +#include +#include +#include +#include +#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 RTFIR::GetCoefficients() const{ + std::vector c; + c.resize(taps); + for(unsigned int i=0;i0.5){ + throw std::invalid_argument("Frequencies must be normalized"); + } + else{ + int W=Taps/2; + for(int i=-W;i0.5){ + throw std::invalid_argument("Frequencies must be normalized"); + } + else{ + int W=Taps/2; + for(int i=-W;i0.5 || High<0.0 || High>0.5){ + throw std::invalid_argument("Frequencies must be normalized"); + } + else{ + int W=Taps/2; + for(int i=-W;i0.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 +#include + +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 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 +