radiosonde_auto_rx/m10/AudioFile.cpp

172 wiersze
4.4 KiB
C++

/*
* 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;
}