-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3dc1bb0
commit 1d1a1bd
Showing
5 changed files
with
138 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,50 @@ | ||
// #pragma once | ||
|
||
// // Standard includes | ||
// #include <utility> | ||
// #include <vector> | ||
|
||
// // Bell includes | ||
// #include "TransformPipeline.h" | ||
|
||
// namespace bell::dsp { | ||
// /** | ||
// * @brief MixerTransform allows for either downmixing or upmixing of audio channels. | ||
// */ | ||
// class MixerTransform : public Transform { | ||
// public: | ||
// MixerTransform() = default; | ||
|
||
// /** | ||
// * @brief Configure the mixer with the given map of input channel to output channels | ||
// * | ||
// * For example, to downmix stereo (0, 1) to mono (0), use [ {0, 0}, {1, 0} ] | ||
// * To upmix mono (0) to stereo (0, 1), use [ {0, 0}, {0, 1} ] | ||
// * | ||
// * @param mixerMap Vector of pairs of input channel to output channel | ||
// */ | ||
// void configure(const std::vector<std::pair<int, int>>& mixerMapping); | ||
|
||
// // Transform implementation, see Transform.h for details | ||
// void process(DataSlots& sampleSlots) override; | ||
// float calculateHeadroom() override; | ||
|
||
// private: | ||
// std::vector<std::pair<int, int>> mixerMapping; | ||
|
||
// // Calculates the input and output size | ||
// int sourceChannels = 0; | ||
// int targetChannels = 0; | ||
// }; | ||
// } // namespace bell::dsp | ||
|
||
// namespace bell { | ||
// using MixerTransform = dsp::MixerTransform; | ||
// } | ||
#pragma once | ||
|
||
// Standard includes | ||
#include <utility> | ||
#include <vector> | ||
|
||
// Bell includes | ||
#include "TransformPipeline.h" | ||
|
||
namespace bell::dsp { | ||
/** | ||
* @brief MixerTransform allows for either downmixing or upmixing of audio channels. | ||
*/ | ||
class MixerTransform : public Transform { | ||
public: | ||
MixerTransform() = default; | ||
|
||
/** | ||
* @brief Configure the mixer with the given map of input channel to output channels | ||
* | ||
* For example, to downmix stereo (0, 1) to mono (0), use [ {0, 0}, {1, 0} ] | ||
* To upmix mono (0) to stereo (0, 1), use [ {0, 0}, {0, 1} ] | ||
* | ||
* @param mixerMap Vector of pairs of input channel to output channel | ||
*/ | ||
void configure(const std::vector<std::pair<int, int>>& mixerMapping); | ||
|
||
// Transform implementation, see Transform.h for details | ||
void process(DataSlots& sampleSlots) override; | ||
float calculateHeadroom() override; | ||
|
||
private: | ||
// Mixer config | ||
std::vector<std::pair<int, int>> mixerMapping; | ||
|
||
using ChannelData = std::array<float, DataSlots::maxSamples>; | ||
|
||
// A map to keep track of how many source channels are contributing to each target channel | ||
std::unordered_map<int, std::pair<ChannelData, int>> outputDataAcc{}; | ||
|
||
// Calculates the input and output size | ||
// Currently unused | ||
int sourceChannels = 0; | ||
int targetChannels = 0; | ||
}; | ||
} // namespace bell::dsp | ||
|
||
namespace bell { | ||
using MixerTransform = dsp::MixerTransform; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
#include "bell/dsp/MixerTransform.h" | ||
|
||
using namespace bell; | ||
|
||
void dsp::MixerTransform::configure( | ||
const std::vector<std::pair<int, int>>& mixerMapping) { | ||
std::scoped_lock lock(accessMutex); | ||
this->mixerMapping = mixerMapping; | ||
} | ||
|
||
float dsp::MixerTransform::calculateHeadroom() { | ||
return 0.0F; // No headroom required for mixer | ||
} | ||
|
||
void dsp::MixerTransform::process(dsp::DataSlots& sampleSlots) { | ||
std::scoped_lock lock(accessMutex); | ||
|
||
// Initialize each target channel in sampleSlots to make sure we do not run into missing keys | ||
for (const auto& [inputChannel, outputChannel] : mixerMapping) { | ||
// Clear the output data acc | ||
outputDataAcc[outputChannel].first.fill(0.0F); | ||
outputDataAcc[outputChannel].second = 0; | ||
|
||
if (sampleSlots.sampleSlots.find(outputChannel) == | ||
sampleSlots.sampleSlots.end()) { | ||
sampleSlots.sampleSlots[outputChannel] = ChannelData{}; | ||
} | ||
} | ||
|
||
// Fill each outputChannel with contributions from inputChannels | ||
for (const auto& [inputChannel, outputChannel] : mixerMapping) { | ||
const auto itInput = sampleSlots.sampleSlots.find(inputChannel); | ||
if (itInput != sampleSlots.sampleSlots.end()) { | ||
auto& [dataSum, count] = outputDataAcc[outputChannel]; | ||
auto& inputData = itInput->second; | ||
for (size_t i = 0; i < sampleSlots.numSamples; ++i) { | ||
dataSum[i] += inputData[i]; | ||
} | ||
count += 1; | ||
} | ||
} | ||
|
||
// Write back the accumulated data to sampleSlots, averaging if necessary | ||
for (auto& [outputChannel, acc] : outputDataAcc) { | ||
auto& [dataSum, count] = acc; | ||
auto& outputData = sampleSlots.sampleSlots[outputChannel]; | ||
for (size_t i = 0; i < sampleSlots.numSamples; ++i) { | ||
outputData[i] = dataSum[i] / std::max(static_cast<float>(count), 1.0F); | ||
} | ||
} | ||
|
||
// Zero out any input channels that are being downmixed (not remapped back) | ||
std::unordered_map<int, bool> inputMappedBack; | ||
for (const auto& [inputChannel, _] : mixerMapping) { | ||
inputMappedBack[inputChannel] = false; | ||
} | ||
for (const auto& [_, outputChannel] : mixerMapping) { | ||
inputMappedBack[outputChannel] = true; // mark this channel as final target | ||
} | ||
|
||
for (const auto& [inputChannel, _] : mixerMapping) { | ||
if (!inputMappedBack[inputChannel]) { | ||
std::fill(sampleSlots.sampleSlots[inputChannel].begin(), | ||
sampleSlots.sampleSlots[inputChannel].begin() + | ||
sampleSlots.numSamples, | ||
0.0F); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters