24 #include "cheetah/sigproc/SigProcFileStream.h" 25 #include "cheetah/data/TimeFrequency.h" 27 #include "panda/Error.h" 28 #include <boost/filesystem.hpp> 29 #include <type_traits> 40 void char2ints (
unsigned char c,
int *i,
int *j)
43 *j = (c & HI4BITS) >> 4;
46 void char4ints (
unsigned char c,
int *i,
int *j,
int *k,
int *l)
56 std::size_t read_block(std::istream& input,
int nbits,
float *block,
unsigned long nread)
58 int j, k, s1, s2, s3, s4;
60 short *shortblock=
nullptr;
61 char *charblock=
nullptr;
70 charblock = (
char *) malloc(nread / 8);
72 input.read(charblock, nread / 8);
83 iread = input.gcount();
84 for (std::size_t i = 0; i < iread; ++i)
85 for (j = 0; j < 8; ++j) {
86 block[k++] = charblock[i] & 1;
96 charblock = (
char *) malloc(nread / 4);
98 input.read(charblock, nread / 4);
108 iread = input.gcount();
109 for(i = 0; i < iread; i++) {
110 char4ints(charblock[i], &s1, &s2, &s3, &s4);
111 block[j++] = (float) s1;
112 block[j++] = (float) s2;
113 block[j++] = (float) s3;
114 block[j++] = (float) s4;
123 charblock = (
char *) malloc(nread / 2);
125 input.read(charblock, nread / 2);
136 iread = input.gcount();
137 for (i = 0; i < iread; i++) {
138 char2ints(charblock[i], &s1, &s2);
139 block[j++] = (float) s1;
140 block[j++] = (float) s2;
149 charblock = (
char *) malloc(nread);
151 input.read(charblock, nread);
159 iread = input.gcount();
160 for (i = 0; i < iread; i++)
161 block[i] = (
float) charblock[i];
170 shortblock = (
short *) malloc(2 * nread);
172 input.read(reinterpret_cast<char*>(shortblock), 2 * nread);
181 iread = input.gcount() / 2;
182 for (i = 0; i < iread; i++) {
183 block[i] = (float) shortblock[i];
192 input.read(reinterpret_cast<char*>(block), 4 * nread);
200 iread = input.gcount() / 4;
204 throw panda::Error(
"SigProcStream : read_block - nbits can only be 4, 8, 16 or 32!");
208 if(shortblock) free(shortblock);
209 if(charblock) free(charblock);
210 iread = input.gcount() * 8/nbits;
220 SigProcFileStream::SigProcFileStream(Config
const& config)
223 , _filenames(config.sigproc_files())
224 , _file_it(_filenames.cbegin())
226 _header.number_of_bits(config.nbits());
229 SigProcFileStream::~SigProcFileStream()
233 void SigProcFileStream::transfer_header_info(data::TimeFrequency<Cpu, uint8_t>& chunk)
235 if( chunk.number_of_spectra() != 0 ){
237 chunk.resize( data::DimensionSize<data::Time>(chunk.number_of_spectra())
238 , data::DimensionSize<data::Frequency>(_header.number_of_channels()));
240 else if(number_of_data_samples() > 0 ) {
242 chunk.resize( data::DimensionSize<data::Time>(number_of_data_samples()/ _header.number_of_channels())
243 , data::DimensionSize<data::Frequency>(_header.number_of_channels()));
247 if( _header.number_of_bits() > 0 ) {
249 data::DimensionSize<data::Time>(
sizeof(
float)*8/_header.number_of_bits()),
250 data::DimensionSize<data::Frequency>(_header.number_of_channels()));
253 throw panda::Error(
"unable to determine number of sigproc samples required");
256 chunk.sample_interval(_header.sample_interval());
257 if(chunk.channel_frequencies().size() > 1) {
258 chunk.set_channel_frequencies(_header.frequency_channels().begin(), _header.frequency_channels().end());
261 chunk.set_channel_frequencies_const_width(
static_cast<typename data::TimeFrequency<Cpu, uint8_t>::FrequencyType
>(*_header.fch1())
262 ,
static_cast<typename data::TimeFrequency<Cpu, uint8_t>::FrequencyType
>(*_header.foff()));
268 if( _nsamples == 0) {
269 _nsamples = (boost::filesystem::file_size(*(_file_it -1)) - _header.size() ) * (8/_header.number_of_bits());
276 if(!_file_stream.is_open() || _file_stream.eof() || _file_stream.peek() == decltype(_file_stream)::traits_type::eof()) {
277 if(!next_file())
return true;
283 auto chunk = get_chunk<TimeFrequencyType>(data::DimensionSize<data::Time>(_config.chunk_samples()), data::DimensionSize<data::Frequency>(0));
286 transfer_header_info(*chunk);
287 chunk->start_time(_start_time);
288 auto it = chunk->begin();
289 return fill_chunk(*chunk, 0, it);
298 std::size_t data_read;
301 float* tmp = (
float*)malloc(data_to_read *
sizeof(
float));
302 if(!tmp)
throw std::bad_alloc();
305 data_read = read_block(_file_stream, _header.number_of_bits(), tmp, data_to_read);
311 assert(data_read <= data_to_read);
317 std::copy(tmp,tmp+data_read,it);
324 _start_time += std::chrono::duration<double>((double)valid_samples * _header.sample_interval().value());
325 if(data_read != data_to_read)
327 if( _file_stream.eof()) {
328 auto expected_header = _header;
331 if(!rv || expected_header.tstart() != _start_time || expected_header != _header) {
334 PANDA_LOG <<
"resizing to " << valid_samples;
335 chunk.resize( data::DimensionSize<data::Time>(valid_samples) );
339 fill_chunk(chunk, offset + data_read, it);
348 bool SigProcFileStream::next_file()
352 if(_file_it == _filenames.cend())
return false;
355 _file_stream.exceptions();
356 _file_stream.clear();
357 _file_stream.open(*_file_it, std::ios::binary);
359 if(!_file_stream.is_open()) {
360 std::cerr <<
"could not open file '" << *_file_it <<
"'" << std::endl;
363 _file_stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
370 _header.read(_file_stream);
371 }
catch(std::exception& e) {
373 err <<
" in file " << *_file_it;
380 _file_stream.close();
383 _start_time = *_header.tstart();
std::size_t number_of_data_samples() const
return the number of samples (time * channels) in the currently opened file
Some limits and constants for FLDO.
NumericalT DataType
the underlying data storage type for the amplitude of the signal
std::size_t number_of_channels() const
std::size_t number_of_spectra() const