new update

This commit is contained in:
dharm pimsen 2024-02-05 20:47:23 +07:00
parent 4a0ecf6113
commit 7eeca6f675
7 changed files with 240 additions and 76 deletions

View File

@ -4,10 +4,13 @@
#include "PaDSPFunc.h" #include "PaDSPFunc.h"
#include "PaMPXFunc.h" #include "PaMPXFunc.h"
#include "PaFilterFunc.h" #include "PaFilterFunc.h"
#include "rtfir.hpp"
#define INPUT_DEVICE_INDEX 16
#define INPUT_DEVICE_INDEX 4
#define OUTPUT_DEVICE_INDEX 39 #define OUTPUT_DEVICE_INDEX 39
#define CompositeClipper true;
int main() { int main() {
PaError err; PaError err;
@ -86,9 +89,11 @@ int main() {
}; };
float* piloToneBuffer = new float[framesPerBuffer]; float* piloToneBuffer = new float[framesPerBuffer];
float* stereoToneBuffer = new float[framesPerBuffer]; float* stereoToneBuffer = new float[framesPerBuffer];
SignalGenerator::GenerateSineWave(piloToneBuffer, framesPerBuffer, 19000, 0.08f); SignalGenerator::GenerateSineWave(piloToneBuffer, framesPerBuffer, 19000, 0.08f);
SignalGenerator::GenerateSineWave(stereoToneBuffer, framesPerBuffer, 38000, 1); SignalGenerator::GenerateSineWave(stereoToneBuffer, framesPerBuffer, 38000, 1);
std::cout << "MPX encoder is running" << std::endl; std::cout << "MPX encoder is running" << std::endl;
while (true) { while (true) {
@ -102,9 +107,6 @@ int main() {
//AudioBuffer audio{ buffer, framesPerBuffer * inputParameters.channelCount }; //AudioBuffer audio{ buffer, framesPerBuffer * inputParameters.channelCount };
//multibandCompressor(audio, bands); //multibandCompressor(audio, bands);
//LowPassFilter filter(192000, 15000, 64);
//filter.apply(buffer, framesPerBuffer);
// MPX Processing here // MPX Processing here
@ -119,10 +121,27 @@ int main() {
for (int i = 0, j = 0; i < framesPerBuffer * inputParameters.channelCount; i += 2, ++j) { 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 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) { for (int i = 0; i < framesPerBuffer; ++i) {
stereoMultipledBuffer[i] = stereoToneBuffer[i] * subtractBuffer[i]; stereoMultipledBuffer[i] = stereoToneBuffer[i] * subtractBuffer[i];
} }
// limit mono signal // limit mono signal
/*
float maxSample = 2.0f; float maxSample = 2.0f;
for (int i = 0; i < framesPerBuffer; ++i) { for (int i = 0; i < framesPerBuffer; ++i) {
if (fabsf(monoBuffer[i]) > maxSample) { if (fabsf(monoBuffer[i]) > maxSample) {
@ -135,27 +154,26 @@ int main() {
monoBuffer[i] /= maxSample; 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 // mix mpx
const float* mixbuffers[3] = {monoBuffer, piloToneBuffer, stereoMultipledBuffer }; const float* mixbuffers[3] = {monoBuffer, piloToneBuffer, stereoMultipledBuffer };
mix(mixedBuffer, mixbuffers, 3, framesPerBuffer); 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); err = Pa_WriteStream(outputStream, mixedBuffer, framesPerBuffer);
@ -167,7 +185,7 @@ int main() {
delete[] subtractBuffer; delete[] subtractBuffer;
delete[] mixedBuffer; delete[] mixedBuffer;
delete[] stereoMultipledBuffer; delete[] stereoMultipledBuffer;
//delete[] lowpassed15KBuffer;
} }
delete[] buffer; delete[] buffer;

View File

@ -131,6 +131,7 @@
<ClCompile Include="PaDSPFunc.cpp" /> <ClCompile Include="PaDSPFunc.cpp" />
<ClCompile Include="PaFilterFunc.cpp" /> <ClCompile Include="PaFilterFunc.cpp" />
<ClCompile Include="PaMPXFunc.cpp" /> <ClCompile Include="PaMPXFunc.cpp" />
<ClCompile Include="rtfir.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\..\..\..\radioconda\pkgs\portaudio-19.6.0-h63175ca_9\Library\bin\portaudio.dll" /> <None Include="..\..\..\..\radioconda\pkgs\portaudio-19.6.0-h63175ca_9\Library\bin\portaudio.dll" />
@ -141,6 +142,7 @@
<ClInclude Include="PaDSPFunc.h" /> <ClInclude Include="PaDSPFunc.h" />
<ClInclude Include="PaFilterFunc.h" /> <ClInclude Include="PaFilterFunc.h" />
<ClInclude Include="PaMPXFunc.h" /> <ClInclude Include="PaMPXFunc.h" />
<ClInclude Include="rtfir.hpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Library Include="..\..\..\..\radioconda\pkgs\portaudio-19.6.0-h63175ca_9\Library\lib\portaudio.lib" /> <Library Include="..\..\..\..\radioconda\pkgs\portaudio-19.6.0-h63175ca_9\Library\lib\portaudio.lib" />

View File

@ -27,6 +27,9 @@
<ClCompile Include="PaFilterFunc.cpp"> <ClCompile Include="PaFilterFunc.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="rtfir.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />
@ -47,6 +50,9 @@
<ClInclude Include="PaFilterFunc.h"> <ClInclude Include="PaFilterFunc.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="rtfir.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Library Include="..\..\..\..\radioconda\pkgs\portaudio-19.6.0-h63175ca_9\Library\lib\portaudio.lib"> <Library Include="..\..\..\..\radioconda\pkgs\portaudio-19.6.0-h63175ca_9\Library\lib\portaudio.lib">

View File

@ -1,40 +1 @@
#include "PaFilterFunc.h" #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);
}
}

View File

@ -1,18 +1,5 @@
#ifndef PAFILTERFUNC_H #ifndef PAFILTERFUNC_H
#define M_PI 3.14159265358979323846 #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
View 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
View 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