@@ 16,6 16,7 @@
### Other
* `[appmgr]` Application manager documentation added.
+* `[audio]` Improve synchronization during calls.
## [0.43.1 2020-10-23]
@@ 8,9 8,15 @@
#include <bsp_audio.hpp>
#include <log/log.hpp>
+#include <mutex.hpp>
+#include <algorithm>
#include <optional>
-#include <cstring>
+#include <vector>
+
+// enforced optimization is needed for std::vector::insert and std::fill to be
+// as quick as memcpy and memset respectively
+#pragma GCC optimize("O3")
namespace audio
{
@@ 23,19 29,32 @@ namespace audio
audioDeviceCallback =
[this](const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer) -> std::int32_t {
if (inputBuffer != nullptr) {
+ cpp_freertos::LockGuard lock(audioMutex);
+ receivedFramesDiffAudio++;
+
if (framesPerBuffer > audioDeviceBuffer.size()) {
audioDeviceBuffer.resize(framesPerBuffer, 0);
}
if (muteEnable) {
- memset(&audioDeviceBuffer[0], 0, framesPerBuffer * sizeof(std::int16_t));
+ std::fill(std::begin(audioDeviceBuffer), std::end(audioDeviceBuffer), 0);
}
else {
- memcpy(&audioDeviceBuffer[0], inputBuffer, framesPerBuffer * sizeof(std::int16_t));
+ auto rangeStart = static_cast<const std::uint16_t *>(inputBuffer);
+ auto rangeEnd = rangeStart + framesPerBuffer;
+ std::copy(rangeStart, rangeEnd, std::begin(audioDeviceBuffer));
}
}
if (outputBuffer != nullptr) {
+ cpp_freertos::LockGuard lock(cellularMutex);
+ receivedFramesDiffCellular--;
+
+ if (receivedFramesDiffCellular != 0) {
+ LOG_FATAL("Audio router synchronization fail, diff = %d", receivedFramesDiffCellular);
+ receivedFramesDiffCellular = 0;
+ }
+
if (framesPerBuffer > audioDeviceCellularBuffer.size()) {
audioDeviceCellularBuffer.resize(framesPerBuffer, 0);
}
@@ 48,14 67,27 @@ namespace audio
audioDeviceCellularCallback =
[this](const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer) -> std::int32_t {
if (inputBuffer != nullptr) {
+ cpp_freertos::LockGuard lock(cellularMutex);
+ receivedFramesDiffCellular++;
+
if (framesPerBuffer > audioDeviceCellularBuffer.size()) {
audioDeviceCellularBuffer.resize(framesPerBuffer, 0);
}
- memcpy(&audioDeviceCellularBuffer[0], inputBuffer, framesPerBuffer * sizeof(std::int16_t));
+ auto rangeStart = static_cast<const std::uint16_t *>(inputBuffer);
+ auto rangeEnd = rangeStart + framesPerBuffer;
+ std::copy(rangeStart, rangeEnd, std::begin(audioDeviceCellularBuffer));
}
if (outputBuffer != nullptr) {
+ cpp_freertos::LockGuard lock(audioMutex);
+ receivedFramesDiffAudio--;
+
+ if (receivedFramesDiffAudio != 0) {
+ LOG_FATAL("Audio router synchronization fail, diff = %d", receivedFramesDiffAudio);
+ receivedFramesDiffAudio = 0;
+ }
+
if (framesPerBuffer > audioDeviceBuffer.size()) {
audioDeviceBuffer.resize(framesPerBuffer, 0);
}
@@ 65,8 97,8 @@ namespace audio
return framesPerBuffer;
};
- audioDeviceBuffer.resize(1024, 0);
- audioDeviceCellularBuffer.resize(1024, 0);
+ audioDeviceBuffer.resize(INPUT_BUFFER_START_SIZE, 0);
+ audioDeviceCellularBuffer.resize(INPUT_BUFFER_START_SIZE, 0);
constexpr audio::Gain defaultRoutingEarspeakerGain = 20;
constexpr audio::Volume defaultRoutingEarspeakerVolume = 10;
@@ 9,6 9,7 @@
#include <Audio/AudioCommon.hpp>
#include <Audio/Profiles/Profile.hpp>
#include <bsp/audio/bsp_audio.hpp>
+#include <mutex.hpp>
#include <memory>
#include <functional>
@@ 21,6 22,10 @@ namespace audio
{
class RouterOperation : public Operation
{
+ using AudioCallback =
+ std::function<std::int32_t(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer)>;
+ static const std::size_t INPUT_BUFFER_START_SIZE = 1024;
+
public:
RouterOperation(
const char *file,
@@ 45,17 50,21 @@ namespace audio
bool muteEnable = false;
std::unique_ptr<Encoder> enc;
+
std::unique_ptr<bsp::AudioDevice> audioDevice;
std::unique_ptr<bsp::AudioDevice> audioDeviceCellular;
- std::function<std::int32_t(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer)>
- audioDeviceCallback = nullptr;
- std::function<std::int32_t(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer)>
- audioDeviceCellularCallback = nullptr;
+
+ AudioCallback audioDeviceCallback = nullptr;
+ AudioCallback audioDeviceCellularCallback = nullptr;
+
std::vector<std::int16_t> audioDeviceBuffer;
std::vector<std::int16_t> audioDeviceCellularBuffer;
- std::vector<std::int16_t> channel1Buffer;
- std::vector<std::int16_t> channel2Buffer;
- std::vector<std::int16_t> mixBuffer;
+
+ cpp_freertos::MutexStandard audioMutex;
+ cpp_freertos::MutexStandard cellularMutex;
+
+ int receivedFramesDiffAudio = 0;
+ int receivedFramesDiffCellular = 0;
};
} // namespace audio