#ifndef IMPULSEMULTICHANNELCONVERTER_H #define IMPULSEMULTICHANNELCONVERTER_H #include "GPRDataModel.h" #include #include #include class ImpulseMultiChannelConverter { public: struct ChannelInfo { int channelNumber = 0; QString iprhPath; QString iprbPath; GPRDataModel::Header header; qint64 traceCount = 0; float xOffset = 0.0f; float yOffset = 0.0f; }; struct ConversionPlan { QString dirPath; QString baseName; QVector channels; GPRDataModel::Header outputHeader; int channelCount = 0; int tracesPerChannel = 0; qint64 totalOutputTraces = 0; qint64 samplesPerTrace = 0; qint64 traceByteSize = 0; QString outputRadPath; QString outputRd3Path; }; struct Options { qint64 maxChunkBytes = 32 * 1024 * 1024; bool overwriteExisting = true; bool reuseExistingIfValid = false; }; struct Progress { qint64 tracesDone = 0; qint64 tracesTotal = 0; QString message; }; using CancelFn = std::function; using ProgressFn = std::function; static bool isMultiChannelImpulseHeader(const QString &headerPath, QString *dirPath = nullptr, QString *baseName = nullptr); static bool buildPlan(const QString &dirPath, const QString &baseName, ConversionPlan &plan, QString *errorMessage = nullptr); static bool convertStreaming(const ConversionPlan &plan, const Options &options, QString *radFilePath = nullptr, QString *errorMessage = nullptr, CancelFn cancel = {}, ProgressFn progress = {}); private: static bool writeRadHeader(const QString &radFilePath, const ConversionPlan &plan, QString *errorMessage); static bool convertedFilesAreValid(const ConversionPlan &plan); static QString formatFloatList(const QVector &values); }; #endif // IMPULSEMULTICHANNELCONVERTER_H