kopia lustrzana https://github.com/projecthorus/radiosonde_auto_rx
Behave correctly with aux data (not decoding)
Added fundamental stats system Moved audio file operations to another class for better modularitypull/96/head
rodzic
659c5ca3fe
commit
5dcb126762
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* File: AudioFile.cpp
|
||||
* Author: Viproz
|
||||
* Used code from rs1729
|
||||
* Created on January 6, 2019, 10:23 AM
|
||||
*/
|
||||
|
||||
#include "AudioFile.h"
|
||||
|
||||
AudioFile::AudioFile(std::string filename, int baudrate, int* errors) {
|
||||
baudRate = baudrate;
|
||||
if (filename == "" || filename == "-")
|
||||
fp = stdin;
|
||||
else
|
||||
fp = fopen(filename.c_str(), "rb");
|
||||
|
||||
if (!fp) {
|
||||
fprintf(stderr, "%s could not be opened.\n", filename.c_str());
|
||||
*errors = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (read_wav_header()) {
|
||||
fprintf(stderr, "Could not read the header.\n");
|
||||
*errors = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
*errors = 0;
|
||||
}
|
||||
|
||||
AudioFile::~AudioFile() {
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
int AudioFile::read_wav_header() {
|
||||
char txt[4 + 1] = "\0\0\0\0";
|
||||
unsigned char dat[4];
|
||||
int byte, p = 0;
|
||||
|
||||
if (fread(txt, 1, 4, fp) < 4) return -1;
|
||||
if (strncmp(txt, "RIFF", 4)) return -1;
|
||||
if (fread(txt, 1, 4, fp) < 4) return -1;
|
||||
// pos_WAVE = 8L
|
||||
if (fread(txt, 1, 4, fp) < 4) return -1;
|
||||
if (strncmp(txt, "WAVE", 4)) return -1;
|
||||
// pos_fmt = 12L
|
||||
for (;;) {
|
||||
if ((byte = fgetc(fp)) == EOF) return -1;
|
||||
txt[p % 4] = byte;
|
||||
p++;
|
||||
if (p == 4) p = 0;
|
||||
if (findstr(txt, "fmt ", p) == 4) break;
|
||||
}
|
||||
if (fread(dat, 1, 4, fp) < 4) return -1;
|
||||
if (fread(dat, 1, 2, fp) < 2) return -1;
|
||||
|
||||
if (fread(dat, 1, 2, fp) < 2) return -1;
|
||||
channels = dat[0] + (dat[1] << 8);
|
||||
|
||||
if (fread(dat, 1, 4, fp) < 4) return -1;
|
||||
memcpy(&sample_rate, dat, 4); //sample_rate = dat[0]|(dat[1]<<8)|(dat[2]<<16)|(dat[3]<<24);
|
||||
|
||||
if (fread(dat, 1, 4, fp) < 4) return -1;
|
||||
if (fread(dat, 1, 2, fp) < 2) return -1;
|
||||
//byte = dat[0] + (dat[1] << 8);
|
||||
|
||||
if (fread(dat, 1, 2, fp) < 2) return -1;
|
||||
bits_sample = dat[0] + (dat[1] << 8);
|
||||
|
||||
// pos_dat = 36L + info
|
||||
for (;;) {
|
||||
if ((byte = fgetc(fp)) == EOF) return -1;
|
||||
txt[p % 4] = byte;
|
||||
p++;
|
||||
if (p == 4) p = 0;
|
||||
if (findstr(txt, "data", p) == 4) break;
|
||||
}
|
||||
if (fread(dat, 1, 4, fp) < 4) return -1;
|
||||
|
||||
|
||||
fprintf(stderr, "sample_rate: %d\n", sample_rate);
|
||||
fprintf(stderr, "bits : %d\n", bits_sample);
|
||||
fprintf(stderr, "channels : %d\n", channels);
|
||||
|
||||
if ((bits_sample != 8) && (bits_sample != 16))
|
||||
return -1;
|
||||
|
||||
samplesPerBit = sample_rate / (double) baudRate;
|
||||
|
||||
fprintf(stderr, "samples/bit: %.2f\n", samplesPerBit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AudioFile::findstr(char* buf, const char* str, int pos) {
|
||||
int i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (buf[(pos + i) % 4] != str[i]) break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int AudioFile::readSignedSample() {
|
||||
int byte, i, sample = 0, s = 0; // EOF -> 0x1000000
|
||||
|
||||
for (i = 0; i < channels; i++) {
|
||||
// i = 0: links bzw. mono
|
||||
byte = fgetc(fp);
|
||||
if (byte == EOF)
|
||||
return EOF_INT;
|
||||
if (i == targetedChannel)
|
||||
sample = byte;
|
||||
|
||||
if (bits_sample == 16) {
|
||||
byte = fgetc(fp);
|
||||
if (byte == EOF)
|
||||
return EOF_INT;
|
||||
if (i == targetedChannel)
|
||||
sample += byte << 8;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (bits_sample == 8) s = sample - 128; // 8bit: 00..FF, centerpoint 0x80=128
|
||||
if (bits_sample == 16) s = (short) sample;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int AudioFile::readSignedSampleAveraged() {
|
||||
return averageSample(readSignedSample());
|
||||
}
|
||||
|
||||
int AudioFile::readSignedSampleNormalized() {
|
||||
return normalizeSample(readSignedSample());
|
||||
}
|
||||
|
||||
int AudioFile::readSignedSampleAveragedNormalized() {
|
||||
return averageNormalizeSample(readSignedSample());
|
||||
}
|
||||
|
||||
int AudioFile::averageSample(int sample) {
|
||||
if (sample == EOF_INT)
|
||||
return EOF_INT;
|
||||
// Average over the last AVG_NUM samples to comply with a global offset
|
||||
activeSum = (activeSum + (double) sample)*(samplesPerBit * AVG_NUM) / (samplesPerBit * AVG_NUM + 1.);
|
||||
return sample - activeSum / (samplesPerBit * AVG_NUM);
|
||||
}
|
||||
|
||||
int AudioFile::normalizeSample(int sample) {
|
||||
if (sample == EOF_INT)
|
||||
return EOF_INT;
|
||||
return sample > 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
int AudioFile::averageNormalizeSample(int sample) {
|
||||
if (sample == EOF_INT)
|
||||
return EOF_INT;
|
||||
// Average over the last AVG_NUM samples to comply with a global offset
|
||||
activeSum = (activeSum + (double) sample)*(samplesPerBit * AVG_NUM) / (samplesPerBit * AVG_NUM + 1.);
|
||||
sample = sample - activeSum / (samplesPerBit * AVG_NUM);
|
||||
return sample > 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
void AudioFile::resetActiveSum() {
|
||||
activeSum = 0;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* File: AudioFile.h
|
||||
* Author: Viproz
|
||||
* Used code from rs1729
|
||||
* Created on January 6, 2019, 10:23 AM
|
||||
*/
|
||||
|
||||
#ifndef AUDIOFILE_H
|
||||
#define AUDIOFILE_H
|
||||
#define EOF_INT 0x1000000
|
||||
#define AVG_NUM 5.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
class AudioFile {
|
||||
public:
|
||||
AudioFile(std::string filename, int baudrate, int* errors);
|
||||
virtual ~AudioFile();
|
||||
|
||||
int read_wav_header();
|
||||
|
||||
int readSignedSample();
|
||||
int readSignedSampleAveraged();
|
||||
int readSignedSampleNormalized();
|
||||
int readSignedSampleAveragedNormalized();
|
||||
|
||||
int averageSample(int sample);
|
||||
int normalizeSample(int sample);
|
||||
int averageNormalizeSample(int sample);
|
||||
|
||||
void resetActiveSum();
|
||||
|
||||
// Getters
|
||||
int getSampleRate() { return sample_rate; }
|
||||
double getSamplesPerBit() { return samplesPerBit; }
|
||||
|
||||
// Setters
|
||||
void setTargetedChannel(int channel) { targetedChannel = channel; }
|
||||
void setBaudRate(int baudv) { baudRate = baudv; }
|
||||
private:
|
||||
int findstr(char* buf, const char* str, int pos);
|
||||
|
||||
double activeSum = 0;
|
||||
int targetedChannel = 0;
|
||||
int sample_rate = 0;
|
||||
int bits_sample = 0;
|
||||
int channels = 0;
|
||||
int baudRate;
|
||||
double samplesPerBit = 0;
|
||||
|
||||
FILE *fp;
|
||||
};
|
||||
|
||||
#endif /* AUDIOFILE_H */
|
||||
|
10
m10/M10.cpp
10
m10/M10.cpp
|
@ -27,9 +27,10 @@ int main(int argc, char** argv) {
|
|||
fprintf(stderr, " options:\n");
|
||||
fprintf(stderr, " -v, --verbose Display even when CRC is wrong\n");
|
||||
fprintf(stderr, " -R Show result at the end decoded/total\n");
|
||||
fprintf(stderr, " -r Display raw information\n");
|
||||
fprintf(stderr, " -r, --raw Display raw information\n");
|
||||
fprintf(stderr, " -b Try alternative method after main method if it failed\n");
|
||||
fprintf(stderr, " -b2 Try to repair data with the previous line\n");
|
||||
fprintf(stderr, " -s Try to repair data with stats if no data has been correctly decoded\n");
|
||||
fprintf(stderr, " --ch2 Decode the second channel\n");
|
||||
|
||||
return 0;
|
||||
|
@ -41,12 +42,13 @@ int main(int argc, char** argv) {
|
|||
decoder.setTryMethodSign(true);
|
||||
} else if (strcmp(*argv, "-b2") == 0) {
|
||||
decoder.setTryMethodRepair(true);
|
||||
} else if (strcmp(*argv, "-s") == 0) {
|
||||
decoder.setTryStats(true);
|
||||
} else if (strcmp(*argv, "-R") == 0) {
|
||||
decoder.setDispResult(true);
|
||||
} else if (strcmp(*argv, "--ch2") == 0) {
|
||||
decoder.setChannel(1);
|
||||
}// right channel (default: 0=left)
|
||||
else {
|
||||
decoder.setChannel(1); // right channel (default: 0=left)
|
||||
} else {
|
||||
filename = *argv;
|
||||
}
|
||||
++argv;
|
||||
|
|
|
@ -21,49 +21,47 @@ M10Decoder::~M10Decoder() {
|
|||
delete m10GTop;
|
||||
delete m10Ptu;
|
||||
|
||||
if (samplesPerBit != 0)
|
||||
if (audioFile)
|
||||
delete frameSamples;
|
||||
|
||||
if (audioFile)
|
||||
delete audioFile;
|
||||
}
|
||||
|
||||
int M10Decoder::startDecode(std::string fname) {
|
||||
filename = fname;
|
||||
if (filename == "" || filename == "-")
|
||||
fp = stdin;
|
||||
else
|
||||
fp = fopen(filename.c_str(), "rb");
|
||||
int error = 0;
|
||||
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "%s could not be opened.\n", filename.c_str());
|
||||
return -1;
|
||||
audioFile = new AudioFile(fname, baudRate, &error);
|
||||
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
if (read_wav_header()) {
|
||||
fprintf(stderr, "Could not read the header.\n");
|
||||
return -1;
|
||||
}
|
||||
samplesPerBit = audioFile->getSamplesPerBit();
|
||||
|
||||
samplesBufLength = (DATA_LENGTH * 8 + 100) * samplesPerBit * 2;
|
||||
frameSamples = new std::vector<int>(samplesBufLength);
|
||||
|
||||
double res = 1;
|
||||
int c = 0;
|
||||
int correct = 0;
|
||||
bool supported = true;
|
||||
while (res) {
|
||||
while (res != EOF_INT) {
|
||||
res = findFrameStart();
|
||||
if (res == 0)
|
||||
if (res == EOF_INT)
|
||||
break;
|
||||
c++;
|
||||
|
||||
totalFrames++;
|
||||
if (decodeMessage(res) == EOF_INT)
|
||||
break;
|
||||
|
||||
long sondeType = ((long) frame_bytes[0] << 16) + ((long) frame_bytes[1] << 8) + (long) frame_bytes[2];
|
||||
long sondeType = ((long) frame_bytes[1] << 8) + (long) frame_bytes[2];
|
||||
frameLength = frame_bytes[0];
|
||||
supported = true;
|
||||
switch (sondeType) {
|
||||
case 0x64AF02:
|
||||
case 0xAF02:
|
||||
m10Parser = m10GTop;
|
||||
break;
|
||||
case 0x649F20:
|
||||
case 0x9F20:
|
||||
m10Parser = m10Ptu;
|
||||
break;
|
||||
default:
|
||||
|
@ -77,19 +75,26 @@ int M10Decoder::startDecode(std::string fname) {
|
|||
continue;
|
||||
}
|
||||
if (correctCRC) {
|
||||
correct++;
|
||||
correctFrames++;
|
||||
lastGoodFrame = frame_bytes;
|
||||
}
|
||||
|
||||
m10Parser->changeData(frame_bytes, correctCRC);
|
||||
m10Parser->printFrame();
|
||||
|
||||
if (!correctCRC && tryRepair)
|
||||
m10Parser->changeData(lastGoodFrame, true);
|
||||
if (!correctCRC) {
|
||||
if (correctFrames == 0 && tryStats) // Add the frame to the record
|
||||
m10Parser->addToStats();
|
||||
else if (tryRepair && correctFrames != 0) // Put the last correct to repair
|
||||
m10Parser->changeData(lastGoodFrame, correctFrames > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tryStats && verboseLevel >= 1)
|
||||
m10Parser->printStatsFrame();
|
||||
|
||||
if (dispResult)
|
||||
fprintf(stderr, "Result of %i/%i decoding\n", correct, c);
|
||||
fprintf(stderr, "Result of %i/%i decoding\n", correctFrames, totalFrames);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -108,11 +113,12 @@ double M10Decoder::findFrameStart() {
|
|||
int smallBufLen = (int) (samplesPerBit * 5.);
|
||||
std::vector<int> vals(smallBufLen);
|
||||
int valIndex = 0;
|
||||
double activeSum = 0;
|
||||
for (int j = 0; 1; ++j) {
|
||||
v = readSignedSample(false);
|
||||
v = audioFile->readSignedSample();
|
||||
vals[valIndex++ % smallBufLen] = v;
|
||||
if (v == EOF_INT)
|
||||
return 0;
|
||||
return EOF_INT;
|
||||
// Average over the last 6 samples to comply with a global offset
|
||||
activeSum = (activeSum + (double) v)*(samplesPerBit * AVG_NUM) / (samplesPerBit * AVG_NUM + 1.);
|
||||
v = v - activeSum / (samplesPerBit * AVG_NUM);
|
||||
|
@ -127,36 +133,31 @@ double M10Decoder::findFrameStart() {
|
|||
else
|
||||
decoded[currentIndex] = '0';
|
||||
|
||||
// Store the position of the start of the bit
|
||||
posData[currentIndex] = (double) j - (1. - (double) i / round((double) len / samplesPerBit))*(double) len;
|
||||
|
||||
char normal = 1;
|
||||
char inv = 1;
|
||||
int headerIndex = 0;
|
||||
// currentIndex to the end
|
||||
for (int l = currentIndex + 1; l < headerLength; ++l) {
|
||||
if (decoded[l] == header[headerIndex])
|
||||
inv = 0;
|
||||
else
|
||||
normal = 0;
|
||||
headerIndex++;
|
||||
}
|
||||
// The start to currentIndex
|
||||
for (int l = 0; l < currentIndex; ++l) {
|
||||
if (decoded[l] == header[headerIndex])
|
||||
inv = 0;
|
||||
else
|
||||
normal = 0;
|
||||
headerIndex++;
|
||||
}
|
||||
if (normal || inv) {
|
||||
// Calculate the real position of the data averaging over the 16 samples
|
||||
double pos = 0;
|
||||
for (int k = currentIndex; k < headerLength; ++k)
|
||||
pos += posData[k] + (double) (headerLength - k) * samplesPerBit;
|
||||
for (int k = 0; k < currentIndex; ++k)
|
||||
pos += posData[k] + (double) (headerLength - k) * samplesPerBit;
|
||||
|
||||
pos /= headerLength;
|
||||
// Check if the header is correct
|
||||
for (int k = 0; k < headerLength; ++k) {
|
||||
if (decoded[(k + currentIndex + 1) % headerLength] == header[headerIndex])
|
||||
inv = 0;
|
||||
else
|
||||
normal = 0;
|
||||
headerIndex++;
|
||||
}
|
||||
|
||||
if (normal || inv) {
|
||||
// Calculate the real position of the data averaging over the headerLength samples
|
||||
double pos = 0;
|
||||
for (int k = 0; k < headerLength; ++k) {
|
||||
pos += posData[(k + currentIndex + 1) % headerLength] + (double) (headerLength - k) * samplesPerBit;
|
||||
//fprintf(stderr, "%.2f\n", posData[(k + currentIndex + 1) % headerLength] + (double) (headerLength - k) * samplesPerBit);
|
||||
}
|
||||
|
||||
pos /= (double) headerLength;
|
||||
|
||||
int tmpIndex = 0;
|
||||
valIndex--;
|
||||
|
@ -171,8 +172,8 @@ double M10Decoder::findFrameStart() {
|
|||
frameSamples->at(curIndex) = vals.at(tmpIndex);
|
||||
}
|
||||
|
||||
pos = pos - (int) pos;
|
||||
return pos;
|
||||
// Only the weight of the first bit is useful, they are stored already
|
||||
return pos - (int) pos;
|
||||
}
|
||||
|
||||
currentIndex = (currentIndex + 1) % headerLength;
|
||||
|
@ -180,13 +181,13 @@ double M10Decoder::findFrameStart() {
|
|||
len = 0;
|
||||
prevV = v;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int M10Decoder::decodeMessage(double initialPos) {
|
||||
std::array<unsigned char, DATA_LENGTH> frameBackup;
|
||||
int v;
|
||||
for (; curIndex < samplesBufLength; ++curIndex) {
|
||||
v = readSignedSample(false);
|
||||
v = audioFile->readSignedSample();
|
||||
if (v == EOF_INT)
|
||||
return EOF_INT;
|
||||
frameSamples->at(curIndex) = v;
|
||||
|
@ -203,10 +204,12 @@ int M10Decoder::decodeMessage(double initialPos) {
|
|||
if (ret == EOF_INT)
|
||||
return EOF_INT;
|
||||
|
||||
if (tryRepair) {
|
||||
if ((tryRepair && correctFrames != 0) || (correctFrames == 0 && tryStats)) {
|
||||
frameBackup = frame_bytes;
|
||||
frame_bytes = m10Parser->replaceWithPrevious(frame_bytes);
|
||||
if (checkCRC())
|
||||
return 0;
|
||||
frame_bytes = frameBackup;
|
||||
}
|
||||
|
||||
if (trySign) {
|
||||
|
@ -218,10 +221,12 @@ int M10Decoder::decodeMessage(double initialPos) {
|
|||
if (ret == EOF_INT)
|
||||
return EOF_INT;
|
||||
|
||||
if (tryRepair) {
|
||||
if ((tryRepair && correctFrames != 0) || (correctFrames == 0 && tryStats)) {
|
||||
frameBackup = frame_bytes;
|
||||
frame_bytes = m10Parser->replaceWithPrevious(frame_bytes);
|
||||
if (checkCRC())
|
||||
return 0;
|
||||
frame_bytes = frameBackup;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,9 +238,8 @@ int M10Decoder::decodeMethodCompare(double initialPos) {
|
|||
|
||||
double j = initialPos;
|
||||
double sum = 0;
|
||||
int val = readSignedSample(); // Read the first value
|
||||
fpos_t tmp;
|
||||
fgetpos(fp, &tmp);
|
||||
int val = getNextBufferValue(); // Read the first value
|
||||
|
||||
if (val == EOF_INT)
|
||||
return EOF_INT;
|
||||
for (int k = 0; k < FRAME_LEN * 8 + AUX_LEN * 8 + 8; ++k) { // Iterate through needed bits
|
||||
|
@ -243,12 +247,12 @@ int M10Decoder::decodeMethodCompare(double initialPos) {
|
|||
// Add the first part of the value weighted correctly
|
||||
sum = (1. - (j - floor(j)))*(double) val;
|
||||
for (int i = ceil(j); i < j + samplesPerBit - 1; ++i) { // Full vals in the middle
|
||||
val = readSignedSample();
|
||||
val = getNextBufferValue();
|
||||
if (val == EOF_INT)
|
||||
return EOF_INT;
|
||||
sum += (double) val;
|
||||
}
|
||||
val = readSignedSample();
|
||||
val = getNextBufferValue();
|
||||
if (val == EOF_INT)
|
||||
return EOF_INT;
|
||||
// Add the rest of the value
|
||||
|
@ -261,12 +265,12 @@ int M10Decoder::decodeMethodCompare(double initialPos) {
|
|||
// Same for the second bit
|
||||
sum = (1 - (j - floor(j)))*(double) val;
|
||||
for (int i = ceil(j); i < j + samplesPerBit - 1; ++i) { // Full vals in the middle
|
||||
val = readSignedSample();
|
||||
val = getNextBufferValue();
|
||||
if (val == EOF_INT)
|
||||
return EOF_INT;
|
||||
sum += (double) val;
|
||||
}
|
||||
val = readSignedSample();
|
||||
val = getNextBufferValue();
|
||||
if (val == EOF_INT)
|
||||
return EOF_INT;
|
||||
sum += (j + samplesPerBit - floor(j + samplesPerBit))*(double) val;
|
||||
|
@ -299,9 +303,8 @@ int M10Decoder::decodeMethodSign(double initialPos) {
|
|||
|
||||
double j = initialPos;
|
||||
double sum = 0;
|
||||
int val = readSignedSampleNormalized(); // Read the first value
|
||||
fpos_t tmp;
|
||||
fgetpos(fp, &tmp);
|
||||
int val = audioFile->averageNormalizeSample(getNextBufferValue()); // Read the first value
|
||||
|
||||
if (val == EOF_INT)
|
||||
return EOF_INT;
|
||||
for (int k = 0; k < FRAME_LEN * 8 + AUX_LEN * 8 + 8; ++k) { // Iterate through needed bits
|
||||
|
@ -309,13 +312,13 @@ int M10Decoder::decodeMethodSign(double initialPos) {
|
|||
// Add the first part of the value weighted correctly
|
||||
sum = (1. - (j - floor(j)))*(double) val;
|
||||
for (int i = ceil(j); i < j + samplesPerBit - 1; ++i) { // Full vals in the middle
|
||||
val = readSignedSampleNormalized();
|
||||
val = audioFile->averageNormalizeSample(getNextBufferValue());
|
||||
if (val == EOF_INT)
|
||||
return EOF_INT;
|
||||
sum += val;
|
||||
}
|
||||
|
||||
val = readSignedSampleNormalized();
|
||||
val = audioFile->averageNormalizeSample(getNextBufferValue());
|
||||
if (val == EOF_INT)
|
||||
return EOF_INT;
|
||||
|
||||
|
@ -329,12 +332,12 @@ int M10Decoder::decodeMethodSign(double initialPos) {
|
|||
// Same for the second bit
|
||||
sum = (1 - (j - floor(j)))*(double) val;
|
||||
for (int i = ceil(j); i < j + samplesPerBit - 1; ++i) { // Full vals in the middle
|
||||
val = readSignedSampleNormalized();
|
||||
val = audioFile->averageNormalizeSample(getNextBufferValue());
|
||||
if (val == EOF_INT)
|
||||
return EOF_INT;
|
||||
sum += (double) val;
|
||||
}
|
||||
val = readSignedSampleNormalized();
|
||||
val = audioFile->averageNormalizeSample(getNextBufferValue());
|
||||
if (val == EOF_INT)
|
||||
return EOF_INT;
|
||||
sum += (j + samplesPerBit - floor(j + samplesPerBit))*(double) val;
|
||||
|
@ -368,125 +371,24 @@ void M10Decoder::setRaw(bool b) {
|
|||
m10Ptu->setRaw(b);
|
||||
}
|
||||
|
||||
int M10Decoder::read_wav_header() {
|
||||
char txt[4 + 1] = "\0\0\0\0";
|
||||
unsigned char dat[4];
|
||||
int byte, p = 0;
|
||||
|
||||
if (fread(txt, 1, 4, fp) < 4) return -1;
|
||||
if (strncmp(txt, "RIFF", 4)) return -1;
|
||||
if (fread(txt, 1, 4, fp) < 4) return -1;
|
||||
// pos_WAVE = 8L
|
||||
if (fread(txt, 1, 4, fp) < 4) return -1;
|
||||
if (strncmp(txt, "WAVE", 4)) return -1;
|
||||
// pos_fmt = 12L
|
||||
for (;;) {
|
||||
if ((byte = fgetc(fp)) == EOF) return -1;
|
||||
txt[p % 4] = byte;
|
||||
p++;
|
||||
if (p == 4) p = 0;
|
||||
if (findstr(txt, "fmt ", p) == 4) break;
|
||||
}
|
||||
if (fread(dat, 1, 4, fp) < 4) return -1;
|
||||
if (fread(dat, 1, 2, fp) < 2) return -1;
|
||||
|
||||
if (fread(dat, 1, 2, fp) < 2) return -1;
|
||||
channels = dat[0] + (dat[1] << 8);
|
||||
|
||||
if (fread(dat, 1, 4, fp) < 4) return -1;
|
||||
memcpy(&sample_rate, dat, 4); //sample_rate = dat[0]|(dat[1]<<8)|(dat[2]<<16)|(dat[3]<<24);
|
||||
|
||||
if (fread(dat, 1, 4, fp) < 4) return -1;
|
||||
if (fread(dat, 1, 2, fp) < 2) return -1;
|
||||
//byte = dat[0] + (dat[1] << 8);
|
||||
|
||||
if (fread(dat, 1, 2, fp) < 2) return -1;
|
||||
bits_sample = dat[0] + (dat[1] << 8);
|
||||
|
||||
// pos_dat = 36L + info
|
||||
for (;;) {
|
||||
if ((byte = fgetc(fp)) == EOF) return -1;
|
||||
txt[p % 4] = byte;
|
||||
p++;
|
||||
if (p == 4) p = 0;
|
||||
if (findstr(txt, "data", p) == 4) break;
|
||||
}
|
||||
if (fread(dat, 1, 4, fp) < 4) return -1;
|
||||
|
||||
|
||||
fprintf(stderr, "sample_rate: %d\n", sample_rate);
|
||||
fprintf(stderr, "bits : %d\n", bits_sample);
|
||||
fprintf(stderr, "channels : %d\n", channels);
|
||||
|
||||
if ((bits_sample != 8) && (bits_sample != 16)) return -1;
|
||||
|
||||
samplesPerBit = sample_rate / (double) baudRate;
|
||||
|
||||
fprintf(stderr, "samples/bit: %.2f\n", samplesPerBit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int M10Decoder::readSignedSample(bool buffer) {
|
||||
if (buffer) {
|
||||
if (curIndex < samplesBufLength)
|
||||
return frameSamples->at(curIndex++);
|
||||
else {
|
||||
fprintf(stderr, "Error, end of buffer.\n");
|
||||
return EOF_INT;
|
||||
}
|
||||
}
|
||||
|
||||
int byte, i, sample = 0, s = 0; // EOF -> 0x1000000
|
||||
|
||||
for (i = 0; i < channels; i++) {
|
||||
// i = 0: links bzw. mono
|
||||
byte = fgetc(fp);
|
||||
if (byte == EOF) return EOF_INT;
|
||||
if (i == targetedChannel) sample = byte;
|
||||
|
||||
if (bits_sample == 16) {
|
||||
byte = fgetc(fp);
|
||||
if (byte == EOF) return EOF_INT;
|
||||
if (i == targetedChannel) sample += byte << 8;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (bits_sample == 8) s = sample - 128; // 8bit: 00..FF, centerpoint 0x80=128
|
||||
if (bits_sample == 16) s = (short) sample;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int M10Decoder::readSignedSampleNormalized(bool buffer) {
|
||||
int v = readSignedSample(buffer);
|
||||
if (v == EOF_INT)
|
||||
int M10Decoder::getNextBufferValue() {
|
||||
if (curIndex < samplesBufLength)
|
||||
return frameSamples->at(curIndex++);
|
||||
else {
|
||||
fprintf(stderr, "Error, end of buffer.\n");
|
||||
return EOF_INT;
|
||||
// Average over the last 6 samples to comply with a global offset
|
||||
activeSum = (activeSum + (double) v)*(samplesPerBit * AVG_NUM) / (samplesPerBit * AVG_NUM + 1.);
|
||||
v = v - activeSum / (samplesPerBit * AVG_NUM);
|
||||
return v > 0 ? 1 : -1;
|
||||
|
||||
}
|
||||
|
||||
int M10Decoder::findstr(char* buf, const char* str, int pos) {
|
||||
int i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (buf[(pos + i) % 4] != str[i]) break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
bool M10Decoder::checkCRC() {
|
||||
int i, cs;
|
||||
|
||||
cs = 0;
|
||||
for (i = 0; i < pos_Check; i++) {
|
||||
for (i = 0; i < frameLength-1; i++) {
|
||||
cs = update_checkM10(cs, frame_bytes[i]);
|
||||
}
|
||||
|
||||
return ((cs & 0xFFFF) != 0) && ((cs & 0xFFFF) == ((frame_bytes[pos_Check] << 8) | frame_bytes[pos_Check + 1]));
|
||||
return ((cs & 0xFFFF) != 0) && ((cs & 0xFFFF) == ((frame_bytes[frameLength-1] << 8) | frame_bytes[frameLength]));
|
||||
}
|
||||
|
||||
int M10Decoder::update_checkM10(int c, unsigned short b) {
|
||||
|
|
|
@ -17,12 +17,12 @@
|
|||
|
||||
#define AVG_NUM 5.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
#include "M10GeneralParser.h"
|
||||
#include "AudioFile.h"
|
||||
|
||||
class M10Decoder {
|
||||
public:
|
||||
|
@ -37,14 +37,13 @@ public:
|
|||
void setChannel(int c) {targetedChannel = c;}
|
||||
void setTryMethodSign(bool b) {trySign = b;}
|
||||
void setTryMethodRepair(bool b) {tryRepair = b;}
|
||||
void setTryStats(bool b) {tryStats = b;}
|
||||
void setVerboseLevel(int level) {verboseLevel = level;}
|
||||
private:
|
||||
|
||||
protected:
|
||||
int decodeMethodCompare(double initialPos);
|
||||
int decodeMethodSign(double initialPos);
|
||||
int read_wav_header();
|
||||
int readSignedSample(bool buffer = true);
|
||||
int readSignedSampleNormalized(bool buffer = true);
|
||||
int findstr(char *buf, const char *str, int pos);
|
||||
int getNextBufferValue();
|
||||
bool checkCRC();
|
||||
int update_checkM10(int c, unsigned short b);
|
||||
void bits2bytes();
|
||||
|
@ -52,25 +51,27 @@ private:
|
|||
M10GeneralParser *m10Parser;
|
||||
M10GeneralParser *m10GTop;
|
||||
M10GeneralParser *m10Ptu;
|
||||
FILE *fp;
|
||||
|
||||
AudioFile *audioFile;
|
||||
|
||||
bool dispResult = false;
|
||||
bool dispRaw = false;
|
||||
bool trySign = false;
|
||||
bool tryRepair = false;
|
||||
bool tryStats = false;
|
||||
int verboseLevel = 0;
|
||||
int targetedChannel = 0;
|
||||
int sample_rate = 0;
|
||||
int bits_sample = 0;
|
||||
int channels = 0;
|
||||
double samplesPerBit = 0;
|
||||
double baudRate = 9615;
|
||||
double activeSum = 0;
|
||||
static char header[];
|
||||
std::string filename;
|
||||
|
||||
std::vector<int> *frameSamples;
|
||||
int curIndex = 0;
|
||||
int samplesBufLength = 0;
|
||||
int correctFrames = 0;
|
||||
int totalFrames = 0;
|
||||
int frameLength = 0;
|
||||
|
||||
std::array<unsigned char, DATA_LENGTH> frame_bytes;
|
||||
std::array<unsigned char, (DATA_LENGTH)*8> frame_bits;
|
||||
|
|
|
@ -29,8 +29,7 @@ M10GTopParser::~M10GTopParser() {
|
|||
}
|
||||
|
||||
void M10GTopParser::changeData(std::array<unsigned char, DATA_LENGTH> data, bool good) {
|
||||
correctCRC = good;
|
||||
frame_bytes = data;
|
||||
M10GeneralParser::changeData(data, good);
|
||||
|
||||
int i;
|
||||
unsigned short bytes[4];
|
||||
|
@ -236,7 +235,7 @@ std::string M10GTopParser::getdxlSerialNumber() {
|
|||
|
||||
void M10GTopParser::printFrame() {
|
||||
if (dispRaw) {
|
||||
for (int i = 0; i < FRAME_LEN; ++i) {
|
||||
for (int i = 0; i < frameLength + 1; ++i) {
|
||||
printf("%02X", frame_bytes[i]);
|
||||
}
|
||||
if (correctCRC)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
#include "M10GeneralParser.h"
|
||||
#include "M10PtuParser.h"
|
||||
|
||||
M10GeneralParser::M10GeneralParser() {
|
||||
}
|
||||
|
@ -16,6 +17,7 @@ M10GeneralParser::~M10GeneralParser() {
|
|||
void M10GeneralParser::changeData(std::array<unsigned char, DATA_LENGTH> data, bool good) {
|
||||
correctCRC = good;
|
||||
frame_bytes = data;
|
||||
frameLength = frame_bytes[0];
|
||||
}
|
||||
|
||||
double M10GeneralParser::getLatitude() {
|
||||
|
@ -74,4 +76,30 @@ std::array<unsigned char, DATA_LENGTH> M10GeneralParser::replaceWithPrevious(std
|
|||
return data;
|
||||
}
|
||||
|
||||
void M10GeneralParser::addToStats() {
|
||||
for (int i = 0; i < DATA_LENGTH; ++i) {
|
||||
++statValues[i][frame_bytes[i]];
|
||||
}
|
||||
}
|
||||
|
||||
void M10GeneralParser::printStatsFrame() {
|
||||
u_short valMax;
|
||||
u_short posMax;
|
||||
|
||||
for (int i = 0; i < FRAME_LEN; ++i) {
|
||||
valMax = 0;
|
||||
posMax = 0;
|
||||
for (u_short k = 0; k < 0xFF+1; ++k) { // Find maximum
|
||||
if (statValues[i][k] > valMax) {
|
||||
valMax = statValues[i][k];
|
||||
posMax = k;
|
||||
}
|
||||
}
|
||||
frame_bytes[i] = posMax;
|
||||
}
|
||||
|
||||
changeData(frame_bytes, false);
|
||||
|
||||
printf("Stats frame:\n");
|
||||
printFrame();
|
||||
}
|
||||
|
|
|
@ -35,12 +35,16 @@ public:
|
|||
std::array<unsigned char, DATA_LENGTH> getFrameBytes() {return frame_bytes;}
|
||||
|
||||
virtual std::array<unsigned char, DATA_LENGTH> replaceWithPrevious(std::array<unsigned char, DATA_LENGTH> data);
|
||||
virtual void addToStats();
|
||||
virtual void printStatsFrame();
|
||||
|
||||
virtual void printFrame() = 0;
|
||||
protected:
|
||||
std::array<unsigned char, DATA_LENGTH> frame_bytes;
|
||||
std::array<std::array<u_short, 0xFF+1>, DATA_LENGTH> statValues = {};
|
||||
bool correctCRC;
|
||||
bool dispRaw = false;
|
||||
int frameLength = 0;
|
||||
};
|
||||
|
||||
#endif /* M10GENERALDECODER_H */
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "M10PtuParser.h"
|
||||
|
||||
char M10PtuParser::similarData[] = "xxxx----------------------xxxxxxxxxxxxxxxxxxxxxxxxxxx---xxxxxxx--xxxx-----xx----xxxxx------xxxxxxx---";
|
||||
char M10PtuParser::insertSpaces[] = "---xx-x-x-x---x---x---x---x-----x-x-----------x---x--x--x-----xx-x-x-x-xx-x-x-x-x----x---x-x-x----xx-";
|
||||
char M10PtuParser::insertSpaces[] = "---xx-x-x-x---x---x---x---x-----x-x-----------x---x--x--x-----xx-x-x-x-xx-x-x-x-x----x---x-x-x----xxxx-x-------------x";
|
||||
|
||||
M10PtuParser::M10PtuParser() {
|
||||
}
|
||||
|
@ -31,8 +31,7 @@ M10PtuParser::~M10PtuParser() {
|
|||
}
|
||||
|
||||
void M10PtuParser::changeData(std::array<unsigned char, DATA_LENGTH> data, bool good) {
|
||||
correctCRC = good;
|
||||
frame_bytes = data;
|
||||
M10GeneralParser::changeData(data, good);
|
||||
|
||||
int i;
|
||||
unsigned byte;
|
||||
|
@ -248,7 +247,7 @@ double M10PtuParser::getTemperature() {
|
|||
|
||||
unsigned char scT; // {0,1,2}, range/scale voltage divider
|
||||
unsigned short ADC_RT; // ADC12 P6.7(A7) , adr_0377h,adr_0376h
|
||||
unsigned short Tcal[2]; // adr_1000h[scT*4]
|
||||
//unsigned short Tcal[2]; // adr_1000h[scT*4]
|
||||
|
||||
float adc_max = 4095.0; // ADC12
|
||||
float x, R;
|
||||
|
@ -257,8 +256,8 @@ double M10PtuParser::getTemperature() {
|
|||
scT = frame_bytes[0x3E]; // adr_0455h
|
||||
ADC_RT = (frame_bytes[0x40] << 8) | frame_bytes[0x3F];
|
||||
ADC_RT -= 0xA000;
|
||||
Tcal[0] = (frame_bytes[0x42] << 8) | frame_bytes[0x41];
|
||||
Tcal[1] = (frame_bytes[0x44] << 8) | frame_bytes[0x43];
|
||||
//Tcal[0] = (frame_bytes[0x42] << 8) | frame_bytes[0x41]; // Unused for now
|
||||
//Tcal[1] = (frame_bytes[0x44] << 8) | frame_bytes[0x43];
|
||||
|
||||
x = (adc_max - ADC_RT) / ADC_RT; // (Vcc-Vout)/Vout
|
||||
if (scT < 3)
|
||||
|
@ -354,11 +353,31 @@ std::string M10PtuParser::getdxlSerialNumber() {
|
|||
}
|
||||
|
||||
std::array<unsigned char, DATA_LENGTH> M10PtuParser::replaceWithPrevious(std::array<unsigned char, DATA_LENGTH> data) {
|
||||
for (int i = 0; i < FRAME_LEN; ++i) {
|
||||
if (similarData[i] == 'x') {
|
||||
if(data[i] != frame_bytes[i])
|
||||
u_short valMax;
|
||||
u_short posMax;
|
||||
|
||||
if (!correctCRC) { // Use probabilities
|
||||
int threshold = statValues[0][0x64] / 2; // more than 50%
|
||||
if (threshold > 4) { // Meaning less under 4 values
|
||||
for (int i = 0; i < FRAME_LEN; ++i) {
|
||||
if (similarData[i] == 'x') {
|
||||
valMax = 0;
|
||||
posMax = 0;
|
||||
for (u_short k = 0; k < 0xFF + 1; ++k) { // Find maximum
|
||||
if (statValues[i][k] > valMax) {
|
||||
valMax = statValues[i][k];
|
||||
posMax = k;
|
||||
}
|
||||
}
|
||||
data[i] = posMax;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // Use correct frame
|
||||
for (int i = 0; i < FRAME_LEN; ++i) {
|
||||
if (similarData[i] == 'x') {
|
||||
data[i] = frame_bytes[i];
|
||||
data[i] = frame_bytes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return data;
|
||||
|
@ -366,7 +385,7 @@ std::array<unsigned char, DATA_LENGTH> M10PtuParser::replaceWithPrevious(std::ar
|
|||
|
||||
void M10PtuParser::printFrame() {
|
||||
if (dispRaw) {
|
||||
for (int i = 0; i < FRAME_LEN; ++i) {
|
||||
for (int i = 0; i < frameLength + 1; ++i) {
|
||||
if (insertSpaces[i] == 'x')
|
||||
printf(" ");
|
||||
printf("%02X", frame_bytes[i]);
|
||||
|
|
Ładowanie…
Reference in New Issue