stereo update (not smooth)

This commit is contained in:
dharm pimsen 2024-01-07 23:22:28 +07:00
parent cda55995da
commit a623d567d0
9 changed files with 122 additions and 43 deletions

View File

@ -3,9 +3,10 @@
#include "portaudio.h"
#include "PaDSPFunc.h"
#include "PaMPXFunc.h"
#include "PaFilterFunc.h"
#define INPUT_DEVICE_INDEX 16
#define OUTPUT_DEVICE_INDEX 47
#define OUTPUT_DEVICE_INDEX 39
int main() {
@ -83,6 +84,11 @@ int main() {
{6910, -24.8, 0, 2, 1, 100} // Example parameters for Band 3
// 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) {
err = Pa_ReadStream(inputStream, buffer, framesPerBuffer);
@ -91,13 +97,17 @@ int main() {
break;
}
AudioBuffer audio{ buffer, framesPerBuffer * inputParameters.channelCount };
multibandCompressor(audio, bands);
//AudioBuffer audio{ buffer, framesPerBuffer * inputParameters.channelCount };
//multibandCompressor(audio, bands);
//limiterProcess(buffer, framesPerBuffer, limiter);
// Normalize the output to prevent extreme volume fluctuations
//LowPassFilter filter(192000, 15000, 64);
//filter.apply(buffer, framesPerBuffer);
float maxSample = 1.0f;
for (int i = 0; i < framesPerBuffer * inputParameters.channelCount; ++i) {
if (fabsf(buffer[i]) > maxSample) {
@ -114,22 +124,36 @@ int main() {
// Merge stereo channels into mono
float* monoBuffer = 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) {
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) {
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) {
std::cout << "PortAudio output stream error: " << Pa_GetErrorText(err) << std::endl;
break;
}
delete[] monoBuffer;
delete[] subtractBuffer;
delete[] mixedBuffer;
delete[] stereoMultipledBuffer;
}

View File

@ -129,6 +129,7 @@
<ItemGroup>
<ClCompile Include="FMPX generator.cpp" />
<ClCompile Include="PaDSPFunc.cpp" />
<ClCompile Include="PaFilterFunc.cpp" />
<ClCompile Include="PaMPXFunc.cpp" />
</ItemGroup>
<ItemGroup>
@ -138,6 +139,7 @@
<ItemGroup>
<ClInclude Include="..\..\..\..\radioconda\pkgs\portaudio-19.6.0-h63175ca_9\Library\include\portaudio.h" />
<ClInclude Include="PaDSPFunc.h" />
<ClInclude Include="PaFilterFunc.h" />
<ClInclude Include="PaMPXFunc.h" />
</ItemGroup>
<ItemGroup>

View File

@ -24,6 +24,9 @@
<ClCompile Include="PaMPXFunc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PaFilterFunc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
@ -41,6 +44,9 @@
<ClInclude Include="PaMPXFunc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="PaFilterFunc.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Library Include="..\..\..\..\radioconda\pkgs\portaudio-19.6.0-h63175ca_9\Library\lib\portaudio.lib">

View File

@ -1,4 +1,5 @@
#include <vector>
#include <cmath>
struct AudioBuffer {
float* data; // Audio data
@ -10,7 +11,7 @@ struct Band {
float threshold;
float gain;
float ratio;
float attackTime; // Attack time in milliseconds
float attackTime; // Attack time in millsiseconds
float releaseTime; // Release time in milliseconds
float currentGain; // Current gain level for dynamic changes
float envelope; // Envelope for dynamic changes
@ -95,6 +96,8 @@ struct Limiter {
float envelope; // Envelope for dynamic changes
};
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 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;
}
}
}
}

View File

@ -1,6 +1,7 @@
#ifndef PADSPFUNC_H
#define PADSPFUNC_H
#include <vector>
#include <cmath>
void audioCompressor(float* audioBuffer, int bufferSize, float threshold, float ratio);

View 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);
}
}

View 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

View File

@ -1,40 +1,24 @@
#include <vector>
#include <iostream>
#include <cmath>
// Function to mix left and right channels (L + R)
std::vector<float> mixChannels(const std::vector<float>& leftChannel, const std::vector<float>& rightChannel) {
// Ensure both channels have the same size
if (leftChannel.size() != rightChannel.size()) {
std::cerr << "Channels have different sizes. Mixing aborted." << std::endl;
return {};
void generateSineWave(float* buffer, int frames, int sampleRate, float frequency, float amplitude = 0.5f) {
const float twoPi = 2.0f * 3.14159f;
float phaseIncrement = (frequency / sampleRate) * twoPi;
float phase = 0.0f;
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)
std::vector<float> subtractChannels(const std::vector<float>& leftChannel, const std::vector<float>& rightChannel) {
// Ensure both channels have the same size
if (leftChannel.size() != rightChannel.size()) {
std::cerr << "Channels have different sizes. Subtraction aborted." << std::endl;
return {};
void mix(float* mixedBuffer, const float* buffers[], int numBuffers, int frames) {
for (int i = 0; i < frames; ++i) {
mixedBuffer[i] = 0.0f; // Initialize mixed buffer with zeros
for (int j = 0; j < numBuffers; ++j) {
mixedBuffer[i] += buffers[j][i]; // Accumulate samples from each buffer
}
}
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;
}

View File

@ -1,9 +1,10 @@
#ifndef PAMPXFUNC_H
#define PAMPXFUNC_H
#include <vector>
#include <cmath>
std::vector<float> mixChannels(const std::vector<float>& leftChannel, const std::vector<float>& rightChannel);
std::vector<float> subtractChannels(const std::vector<float>& leftChannel, const std::vector<float>& rightChannel);
void generateSineWave(float* buffer, int frames, int sampleRate, float frequency, float amplitude = 0.5f);
void mix(float* mixedBuffer, const float* buffers[], int numBuffers, int frames);
#endif