mirror of
https://github.com/damp11113/EasyMPX.git
synced 2025-04-27 22:48:09 +00:00
stereo update (not smooth)
This commit is contained in:
parent
cda55995da
commit
a623d567d0
@ -3,9 +3,10 @@
|
|||||||
#include "portaudio.h"
|
#include "portaudio.h"
|
||||||
#include "PaDSPFunc.h"
|
#include "PaDSPFunc.h"
|
||||||
#include "PaMPXFunc.h"
|
#include "PaMPXFunc.h"
|
||||||
|
#include "PaFilterFunc.h"
|
||||||
|
|
||||||
#define INPUT_DEVICE_INDEX 16
|
#define INPUT_DEVICE_INDEX 16
|
||||||
#define OUTPUT_DEVICE_INDEX 47
|
#define OUTPUT_DEVICE_INDEX 39
|
||||||
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
@ -83,6 +84,11 @@ int main() {
|
|||||||
{6910, -24.8, 0, 2, 1, 100} // Example parameters for Band 3
|
{6910, -24.8, 0, 2, 1, 100} // Example parameters for Band 3
|
||||||
// Add more bands with their parameters
|
// Add more bands with their parameters
|
||||||
};
|
};
|
||||||
|
float* piloToneBuffer = new float[framesPerBuffer];
|
||||||
|
float* stereoToneBuffer = new float[framesPerBuffer];
|
||||||
|
generateSineWave(piloToneBuffer, framesPerBuffer, 192000, 19000, 0.08f);
|
||||||
|
generateSineWave(stereoToneBuffer, framesPerBuffer, 192000, 38000, 1);
|
||||||
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
err = Pa_ReadStream(inputStream, buffer, framesPerBuffer);
|
err = Pa_ReadStream(inputStream, buffer, framesPerBuffer);
|
||||||
@ -91,13 +97,17 @@ int main() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioBuffer audio{ buffer, framesPerBuffer * inputParameters.channelCount };
|
//AudioBuffer audio{ buffer, framesPerBuffer * inputParameters.channelCount };
|
||||||
multibandCompressor(audio, bands);
|
//multibandCompressor(audio, bands);
|
||||||
|
|
||||||
//limiterProcess(buffer, framesPerBuffer, limiter);
|
//limiterProcess(buffer, framesPerBuffer, limiter);
|
||||||
|
|
||||||
// Normalize the output to prevent extreme volume fluctuations
|
// Normalize the output to prevent extreme volume fluctuations
|
||||||
|
|
||||||
|
//LowPassFilter filter(192000, 15000, 64);
|
||||||
|
|
||||||
|
//filter.apply(buffer, framesPerBuffer);
|
||||||
|
|
||||||
float maxSample = 1.0f;
|
float maxSample = 1.0f;
|
||||||
for (int i = 0; i < framesPerBuffer * inputParameters.channelCount; ++i) {
|
for (int i = 0; i < framesPerBuffer * inputParameters.channelCount; ++i) {
|
||||||
if (fabsf(buffer[i]) > maxSample) {
|
if (fabsf(buffer[i]) > maxSample) {
|
||||||
@ -114,22 +124,36 @@ int main() {
|
|||||||
// Merge stereo channels into mono
|
// Merge stereo channels into mono
|
||||||
float* monoBuffer = new float[framesPerBuffer];
|
float* monoBuffer = new float[framesPerBuffer];
|
||||||
float* subtractBuffer = new float[framesPerBuffer];
|
float* subtractBuffer = new float[framesPerBuffer];
|
||||||
|
float* stereoMultipledBuffer = new float[framesPerBuffer];
|
||||||
|
float* mixedBuffer = new float[framesPerBuffer];
|
||||||
|
|
||||||
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) {
|
||||||
monoBuffer[j] = 0.5f * (buffer[i] + buffer[i + 1]); // Average the two channels
|
monoBuffer[j] = 0.5f * (buffer[i] + buffer[i + 1]); // Average the two channels
|
||||||
}
|
}
|
||||||
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
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < framesPerBuffer; ++i) {
|
||||||
|
stereoMultipledBuffer[i] = stereoToneBuffer[i] * subtractBuffer[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const float* mixbuffers[3] = {monoBuffer, piloToneBuffer, stereoMultipledBuffer };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
mix(mixedBuffer, mixbuffers, 3, framesPerBuffer);
|
||||||
|
|
||||||
|
|
||||||
err = Pa_WriteStream(outputStream, subtractBuffer, framesPerBuffer);
|
err = Pa_WriteStream(outputStream, mixedBuffer, framesPerBuffer);
|
||||||
if (err != paNoError) {
|
if (err != paNoError) {
|
||||||
std::cout << "PortAudio output stream error: " << Pa_GetErrorText(err) << std::endl;
|
std::cout << "PortAudio output stream error: " << Pa_GetErrorText(err) << std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
delete[] monoBuffer;
|
delete[] monoBuffer;
|
||||||
delete[] subtractBuffer;
|
delete[] subtractBuffer;
|
||||||
|
delete[] mixedBuffer;
|
||||||
|
delete[] stereoMultipledBuffer;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,6 +129,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="FMPX generator.cpp" />
|
<ClCompile Include="FMPX generator.cpp" />
|
||||||
<ClCompile Include="PaDSPFunc.cpp" />
|
<ClCompile Include="PaDSPFunc.cpp" />
|
||||||
|
<ClCompile Include="PaFilterFunc.cpp" />
|
||||||
<ClCompile Include="PaMPXFunc.cpp" />
|
<ClCompile Include="PaMPXFunc.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -138,6 +139,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\..\..\radioconda\pkgs\portaudio-19.6.0-h63175ca_9\Library\include\portaudio.h" />
|
<ClInclude Include="..\..\..\..\radioconda\pkgs\portaudio-19.6.0-h63175ca_9\Library\include\portaudio.h" />
|
||||||
<ClInclude Include="PaDSPFunc.h" />
|
<ClInclude Include="PaDSPFunc.h" />
|
||||||
|
<ClInclude Include="PaFilterFunc.h" />
|
||||||
<ClInclude Include="PaMPXFunc.h" />
|
<ClInclude Include="PaMPXFunc.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
<ClCompile Include="PaMPXFunc.cpp">
|
<ClCompile Include="PaMPXFunc.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="PaFilterFunc.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
@ -41,6 +44,9 @@
|
|||||||
<ClInclude Include="PaMPXFunc.h">
|
<ClInclude Include="PaMPXFunc.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="PaFilterFunc.h">
|
||||||
|
<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">
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
struct AudioBuffer {
|
struct AudioBuffer {
|
||||||
float* data; // Audio data
|
float* data; // Audio data
|
||||||
@ -10,7 +11,7 @@ struct Band {
|
|||||||
float threshold;
|
float threshold;
|
||||||
float gain;
|
float gain;
|
||||||
float ratio;
|
float ratio;
|
||||||
float attackTime; // Attack time in milliseconds
|
float attackTime; // Attack time in millsiseconds
|
||||||
float releaseTime; // Release time in milliseconds
|
float releaseTime; // Release time in milliseconds
|
||||||
float currentGain; // Current gain level for dynamic changes
|
float currentGain; // Current gain level for dynamic changes
|
||||||
float envelope; // Envelope for dynamic changes
|
float envelope; // Envelope for dynamic changes
|
||||||
@ -95,6 +96,8 @@ struct Limiter {
|
|||||||
float envelope; // Envelope for dynamic changes
|
float envelope; // Envelope for dynamic changes
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void limiterProcess(float* buffer, int size, Limiter& limiter) {
|
void limiterProcess(float* buffer, int size, Limiter& limiter) {
|
||||||
const float attackCoef = 1.0f - expf(-1.0f / (0.001f * limiter.attackTime * 44100.0f)); // Calculate attack coefficient
|
const float attackCoef = 1.0f - expf(-1.0f / (0.001f * limiter.attackTime * 44100.0f)); // Calculate attack coefficient
|
||||||
const float releaseCoef = 1.0f - expf(-1.0f / (0.001f * limiter.releaseTime * 44100.0f)); // Calculate release coefficient
|
const float releaseCoef = 1.0f - expf(-1.0f / (0.001f * limiter.releaseTime * 44100.0f)); // Calculate release coefficient
|
||||||
@ -127,4 +130,4 @@ void limiterProcess(float* buffer, int size, Limiter& limiter) {
|
|||||||
buffer[i] *= limitedGain;
|
buffer[i] *= limitedGain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef PADSPFUNC_H
|
#ifndef PADSPFUNC_H
|
||||||
#define PADSPFUNC_H
|
#define PADSPFUNC_H
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
void audioCompressor(float* audioBuffer, int bufferSize, float threshold, float ratio);
|
void audioCompressor(float* audioBuffer, int bufferSize, float threshold, float ratio);
|
||||||
|
|
||||||
|
40
FMPX generator/PaFilterFunc.cpp
Normal file
40
FMPX generator/PaFilterFunc.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
|
}
|
18
FMPX generator/PaFilterFunc.h
Normal file
18
FMPX generator/PaFilterFunc.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#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
|
@ -1,40 +1,24 @@
|
|||||||
#include <vector>
|
#include <cmath>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
// Function to mix left and right channels (L + R)
|
void generateSineWave(float* buffer, int frames, int sampleRate, float frequency, float amplitude = 0.5f) {
|
||||||
std::vector<float> mixChannels(const std::vector<float>& leftChannel, const std::vector<float>& rightChannel) {
|
const float twoPi = 2.0f * 3.14159f;
|
||||||
// Ensure both channels have the same size
|
float phaseIncrement = (frequency / sampleRate) * twoPi;
|
||||||
if (leftChannel.size() != rightChannel.size()) {
|
float phase = 0.0f;
|
||||||
std::cerr << "Channels have different sizes. Mixing aborted." << std::endl;
|
|
||||||
return {};
|
for (int i = 0; i < frames; ++i) {
|
||||||
|
buffer[i] = amplitude * sin(phase);
|
||||||
|
phase += phaseIncrement;
|
||||||
|
if (phase > twoPi) {
|
||||||
|
phase -= twoPi;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<float> mixedChannel;
|
|
||||||
mixedChannel.reserve(leftChannel.size()); // Reserve space for the mixed channel
|
|
||||||
|
|
||||||
// Perform mixing (L + R)
|
|
||||||
for (size_t i = 0; i < leftChannel.size(); ++i) {
|
|
||||||
mixedChannel.push_back(leftChannel[i] + rightChannel[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mixedChannel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to subtract left from right channel (L - R)
|
void mix(float* mixedBuffer, const float* buffers[], int numBuffers, int frames) {
|
||||||
std::vector<float> subtractChannels(const std::vector<float>& leftChannel, const std::vector<float>& rightChannel) {
|
for (int i = 0; i < frames; ++i) {
|
||||||
// Ensure both channels have the same size
|
mixedBuffer[i] = 0.0f; // Initialize mixed buffer with zeros
|
||||||
if (leftChannel.size() != rightChannel.size()) {
|
for (int j = 0; j < numBuffers; ++j) {
|
||||||
std::cerr << "Channels have different sizes. Subtraction aborted." << std::endl;
|
mixedBuffer[i] += buffers[j][i]; // Accumulate samples from each buffer
|
||||||
return {};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<float> subtractedChannel;
|
|
||||||
subtractedChannel.reserve(leftChannel.size()); // Reserve space for the subtracted channel
|
|
||||||
|
|
||||||
// Perform subtraction (L - R)
|
|
||||||
for (size_t i = 0; i < leftChannel.size(); ++i) {
|
|
||||||
subtractedChannel.push_back(leftChannel[i] - rightChannel[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return subtractedChannel;
|
|
||||||
}
|
}
|
@ -1,9 +1,10 @@
|
|||||||
#ifndef PAMPXFUNC_H
|
#ifndef PAMPXFUNC_H
|
||||||
#define PAMPXFUNC_H
|
#define PAMPXFUNC_H
|
||||||
|
|
||||||
#include <vector>
|
#include <cmath>
|
||||||
|
|
||||||
std::vector<float> mixChannels(const std::vector<float>& leftChannel, const std::vector<float>& rightChannel);
|
void generateSineWave(float* buffer, int frames, int sampleRate, float frequency, float amplitude = 0.5f);
|
||||||
std::vector<float> subtractChannels(const std::vector<float>& leftChannel, const std::vector<float>& rightChannel);
|
|
||||||
|
void mix(float* mixedBuffer, const float* buffers[], int numBuffers, int frames);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user