mirror of
https://github.com/intrepidcs/libicsneo.git
synced 2026-08-05 01:18:36 +02:00
A2B: Add initial WAV streaming support
This commit is contained in:
@@ -193,7 +193,7 @@ std::shared_ptr<LogicalDiskInfoMessage> Communication::getLogicalDiskInfoSync(st
|
||||
return std::dynamic_pointer_cast<LogicalDiskInfoMessage>(msg);
|
||||
}
|
||||
|
||||
int Communication::addMessageCallback(const MessageCallback& cb) {
|
||||
int Communication::addMessageCallback(const std::shared_ptr<MessageCallback>& cb) {
|
||||
std::lock_guard<std::mutex> lk(messageCallbacksLock);
|
||||
messageCallbacks.insert(std::make_pair(messageCallbackIDCounter, cb));
|
||||
return messageCallbackIDCounter++;
|
||||
@@ -217,7 +217,7 @@ std::shared_ptr<Message> Communication::waitForMessageSync(std::function<bool(vo
|
||||
std::shared_ptr<Message> returnedMessage;
|
||||
|
||||
std::unique_lock<std::mutex> lk(m); // Don't let the callback fire until we're waiting for it
|
||||
int cb = addMessageCallback(MessageCallback([&m, &returnedMessage, &cv](std::shared_ptr<Message> message) {
|
||||
int cb = addMessageCallback(std::make_shared<MessageCallback>([&m, &returnedMessage, &cv](std::shared_ptr<Message> message) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(m);
|
||||
returnedMessage = message;
|
||||
@@ -251,7 +251,7 @@ void Communication::dispatchMessage(const std::shared_ptr<Message>& msg) {
|
||||
EventManager::GetInstance().cancelErrorDowngradingOnCurrentThread();
|
||||
for(auto& cb : messageCallbacks) {
|
||||
if(!closing) { // We might have closed while reading or processing
|
||||
cb.second.callIfMatch(msg);
|
||||
cb.second->callIfMatch(msg);
|
||||
}
|
||||
}
|
||||
if(downgrade)
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
#include "icsneo/communication/message/callback/streamoutput/a2bwavoutput.h"
|
||||
|
||||
namespace icsneo
|
||||
{
|
||||
|
||||
void A2BWAVOutput::writeHeader(const std::shared_ptr<A2BMessage>& firstMsg) const {
|
||||
|
||||
WaveFileHeader header = WaveFileHeader(2 * firstMsg->getNumChannels(), wavSampleRate, firstMsg->getBitDepth());
|
||||
header.write(stream);
|
||||
streamStartPos = static_cast<uint32_t>(stream->tellp());
|
||||
}
|
||||
|
||||
bool A2BWAVOutput::callIfMatch(const std::shared_ptr<Message>& message) const {
|
||||
if(closed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(message->type != Message::Type::Frame)
|
||||
return false;
|
||||
|
||||
const auto& frame = std::static_pointer_cast<Frame>(message);
|
||||
|
||||
if(frame->network.getType() != Network::Type::A2B)
|
||||
return false;
|
||||
|
||||
const auto& a2bmsg = std::static_pointer_cast<A2BMessage>(frame);
|
||||
|
||||
if(firstMessageFlag) {
|
||||
writeHeader(a2bmsg);
|
||||
firstMessageFlag = false;
|
||||
}
|
||||
|
||||
if(!writeSamples(a2bmsg, A2BMessage::A2BDirection::DownStream)) {
|
||||
close();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!writeSamples(a2bmsg, A2BMessage::A2BDirection::UpStream)) {
|
||||
close();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void A2BWAVOutput::close() const
|
||||
{
|
||||
if(closed) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t streamEndPos = static_cast<uint32_t>(stream->tellp());
|
||||
|
||||
uint32_t subChunk2Size = streamEndPos - streamStartPos;
|
||||
uint32_t chunkSize = streamEndPos - 8;
|
||||
|
||||
stream->seekp(streamStartPos - 4);
|
||||
write((void*)&subChunk2Size, 4);
|
||||
stream->seekp(4, std::ios::beg);
|
||||
write((void*)&chunkSize, 4);
|
||||
|
||||
closed = true;
|
||||
}
|
||||
|
||||
bool A2BWAVOutput::writeSamples(const std::shared_ptr<A2BMessage>& msg, A2BMessage::A2BDirection dir) const
|
||||
{
|
||||
uint8_t numChannels = msg->getNumChannels();
|
||||
|
||||
uint8_t channel = 0;
|
||||
uint32_t sampleIndex = 0;
|
||||
uint8_t bitDepth = msg->getBitDepth();
|
||||
|
||||
while(true) {
|
||||
auto sample = msg->getSample(dir, channel, sampleIndex);
|
||||
|
||||
if(!sample) {
|
||||
if(channel == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t audioSample = sample.value() >> (32 - bitDepth);
|
||||
|
||||
write((void*)(&audioSample), A2BPCM_SAMPLE_SIZE);
|
||||
|
||||
channel = (channel + 1) % numChannels;
|
||||
if(channel == 0) {
|
||||
sampleIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,8 +4,7 @@
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
std::shared_ptr<Message> HardwareA2BPacket::DecodeToMessage(const std::vector<uint8_t> &bytestream)
|
||||
{
|
||||
std::shared_ptr<Message> HardwareA2BPacket::DecodeToMessage(const std::vector<uint8_t> &bytestream) {
|
||||
|
||||
constexpr uint8_t coreMiniMessageHeaderSize = 28;
|
||||
|
||||
@@ -17,9 +16,8 @@ std::shared_ptr<Message> HardwareA2BPacket::DecodeToMessage(const std::vector<ui
|
||||
auto getSampleFromBytes = [](uint8_t bytesPerSample, const uint8_t *bytes) {
|
||||
A2BPCMSample result = 0;
|
||||
|
||||
for(auto i = 0; i < bytesPerSample; i++)
|
||||
{
|
||||
result |= bytes[i] << (i * 8);
|
||||
for(auto i = 0; i < bytesPerSample; i++) {
|
||||
result |= static_cast<uint32_t>(bytes[i]) << (i * 8);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -42,8 +40,7 @@ std::shared_ptr<Message> HardwareA2BPacket::DecodeToMessage(const std::vector<ui
|
||||
|
||||
uint8_t channel = 0;
|
||||
|
||||
for(uint32_t i = 0; i < totalPackedLength; i += 2 * static_cast<uint32_t>(bytesPerChannel), bytes += 2 * bytesPerChannel, channel = (channel + 1) % numChannels)
|
||||
{
|
||||
for(uint32_t i = 0; i < totalPackedLength; i += 2 * static_cast<uint32_t>(bytesPerChannel), bytes += 2 * bytesPerChannel, channel = (channel + 1) % numChannels) {
|
||||
|
||||
msg->addSample(
|
||||
getSampleFromBytes(bytesPerChannel, bytes),
|
||||
|
||||
Reference in New Issue
Block a user