-
Notifications
You must be signed in to change notification settings - Fork 41
/
read_kiwi_iq_wav.cc
122 lines (106 loc) · 3.23 KB
/
read_kiwi_iq_wav.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// -*- C++ -*-
#include <fstream>
#include <octave/oct.h>
class chunk_base {
public:
std::string id() const { return std::string((char*)(_id), 4); }
std::streampos size() const { return _size; }
private:
int8_t _id[4];
uint32_t _size;
} __attribute__((packed));
class chunk_riff : public chunk_base {
public:
std::string format() const { return std::string((char*)(_format), 4); }
private:
int8_t _format[4];
} __attribute__((packed));
class chunk_fmt : public chunk_base {
public:
uint16_t format() const { return _format; }
uint16_t num_channels() const { return _num_channels; }
uint32_t sample_rate() const { return _sample_rate; }
uint32_t byte_rate() const { return _byte_rate; }
uint16_t block_align() const { return _block_align; }
protected:
uint16_t _format;
uint16_t _num_channels;
uint32_t _sample_rate;
uint32_t _byte_rate;
uint16_t _block_align;
uint16_t _dummy;
} __attribute__((packed));
class chunk_kiwi : public chunk_base {
public:
uint8_t last() const { return _last; }
uint32_t gpssec() const { return _gpssec; }
uint32_t gpsnsec() const { return _gpsnsec; }
private:
uint8_t _last, _dummy;
uint32_t _gpssec, _gpsnsec;
} __attribute__((packed));
DEFUN_DLD (read_kiwi_iq_wav, args, nargout, "[d,sample_rate]=read_kiwi_wav(\"<wav file name\");")
{
octave_value_list retval;
const std::string filename = args(0).string_value();
if (error_state)
return retval;
std::ifstream file(filename, std::ios::binary);
octave_value_list cell_z, cell_last, cell_gpssec, cell_gpsnsec;
chunk_base c;
chunk_fmt fmt;
int data_counter=0;
while (file) {
std::streampos pos = file.tellg();
file.read((char*)(&c), sizeof(c));
if (!file)
break;
if (c.id() == "RIFF") {
chunk_riff cr;
file.seekg(pos);
file.read((char*)(&cr), sizeof(cr));
if (cr.format() != "WAVE") {
// complain
break;
}
} else if (c.id() == "fmt ") {
file.seekg(pos);
file.read((char*)(&fmt), sizeof(fmt));
if (fmt.format() != 1 ||
fmt.num_channels() != 2) {
// complain
break;
}
retval(1) = octave_value(fmt.sample_rate());
} else if (c.id() == "data") {
ComplexNDArray a(dim_vector(c.size()/4, 1));
int16_t i=0, q=0;
for (int j=0; j<c.size()/4 && file; ++j) {
file.read((char*)(&i), sizeof(i));
file.read((char*)(&q), sizeof(q));
a(j) = std::complex<double>(i/32768., q/32768.);
}
cell_z(data_counter++) = octave_value(a);
} else if (c.id() == "kiwi") {
file.seekg(pos);
chunk_kiwi kiwi;
file.read((char*)(&kiwi), sizeof(kiwi));
cell_last(data_counter) = octave_value(kiwi.last());
cell_gpssec(data_counter) = octave_value(kiwi.gpssec());
cell_gpsnsec(data_counter) = octave_value(kiwi.gpsnsec());
} else {
std::cout << "skipping unknown chunk " << c.id() << std::endl;
pos = file.tellg();
file.seekg(pos + c.size());
}
}
octave_map map;
map.setfield("z", cell_z);
if (cell_last.length() == cell_z.length()) {
map.setfield("gpslast", cell_last);
map.setfield("gpssec", cell_gpssec);
map.setfield("gpsnsec", cell_gpsnsec);
}
retval(0) = map;
return retval;
}