gtkIOStream  1.7.0
GTK+ << C++ IOStream operators for GTK+. Now with ORBing, numerical computation, audio client and more ...
IIOSox.C
Go to the documentation of this file.
1 /* Copyright 2000-2018 Matt Flax <flatmax@flatmax.org>
2  This file is part of GTK+ IOStream class set
3 
4  GTK+ IOStream is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  GTK+ IOStream is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You have received a copy of the GNU General Public License
15  along with GTK+ IOStream
16 */
17 
18 //#define DEBUG_OUTPUT // define this to print out Debugger information
19 
20 #include <sched.h>
21 #include "OptionParser.H"
22 
23 #include "IIO/IIOMMap.H"
24 #include <values.h>
25 
26 //#define FP_TYPE unsigned short int ///< The type to be used with sox input for file output
27 #include "Sox.H"
28 
29 #include <iomanip>
30 
31 int printUsage(string name, int N, string chip, int chCnt, float T, float fs, int periodCount) {
32  cout<<name<<" : An application to stream input from IIO devices to file."<<endl;
33  cout<<"Usage:"<<endl;
34  cout<<"\t "<<name<<" [options] outFileName"<<endl;
35  cout<<"\t -p : The number of samples to read each time from the IIO devices : (-p "<<N<<")"<<endl;
36  cout<<"\t -C : The name of the chip to look for in the available IIO devices : (-C "<<chip<<")"<<endl;
37  cout<<"\t -i : The number of channels to open, if the available number is less, then it is reduced to the available : (-i "<<chCnt<<")"<<endl;
38  cout<<"\t -t : The duration to sample for : (-t "<<T<<")"<<endl;
39  cout<<"\t -f : The sample rate to use : (-f "<<fixed<<setprecision(2)<<fs<<")"<<endl;
40  cout<<"\t -n : The number of periods : (-n "<<periodCount<<")"<<endl;
41  cout<<resetiosflags(ios::showbase);
42  Sox<float> sox;
43  vector<string> formats=sox.availableFormats();
44  cout<<"The known output file extensions (output file formats) are the following :"<<endl;
45  for (int i=0; i<formats.size(); i++)
46  cout<<formats[i]<<' ';
47  cout<<endl;
48  return 0;
49 }
50 
51 int main(int argc, char *argv[]) {
52  struct sched_param param;
53  param.sched_priority = 96;
54  if (sched_setscheduler(0, SCHED_FIFO, & param) == -1) {
55  perror("sched_setscheduler");
56  return -1;
57  }
58 
59  // defaults
60  int N=2048; // the number of samples per read
61  string chip("AD7476A"); // the chip to search for
62  int chCnt=MAXINT;
63  float T=1.; // seconds
64  float fs=1.e6; // sample rate in Hz
65  int periodCount=3;
66 
67  OptionParser op;
68 
69  int i=0;
70  string help;
71  if (op.getArg<string>("h", argc, argv, help, i=0)!=0)
72  return printUsage(argv[0], N, chip, chCnt, T, fs, periodCount);
73  if (op.getArg<string>("help", argc, argv, help, i=0)!=0)
74  return printUsage(argv[0], N, chip, chCnt, T, fs, periodCount);
75  if (argc<2)
76  return printUsage(argv[0], N, chip, chCnt, T, fs, periodCount);
77 
78  if (op.getArg<int>("p", argc, argv, N, i=0)!=0)
79  ;
80 
81  if (op.getArg<string>("C", argc, argv, chip, i=0)!=0)
82  ;
83 
84  if (op.getArg<int>("i", argc, argv, chCnt, i=0)!=0)
85  ;
86 
87  if (op.getArg<float>("t", argc, argv, T, i=0)!=0)
88  ;
89 
90  if (op.getArg<float>("f", argc, argv, fs, i=0)!=0)
91  ;
92 
93  if (op.getArg<int>("n", argc, argv, periodCount, i=0)!=0)
94  ;
95 
96  int M=T*1e6/N;
97 
98  IIOMMap iio;
99  iio.findDevicesByChipName(chip);
100 
101  iio.printInfo(); // print out detail about the devices which were found ...
102 
103  if (iio.getChCnt()<chCnt)
104  chCnt=iio.getChCnt();
105 
106  //iio.sampleRate=fs;
107 
108  cout<<"Number of samples p="<<N<<"\nNumber of channels available i="<<chCnt<<"\nChip name C="<<chip<<endl;
109  cout<<"Reading n="<<periodCount<<" period buffers of p samples each"<<endl;
110  cout<<"Duration t="<<T<<"\nSample rate f="<<fs<<endl;
111  cout<<endl;
112 
113  cout<<"Reading "<<M<<" times "<<N<<" samples, resulting in a processing time of "<<M*N/1e6<<" or "<<M*N<<" samples per channel."<<endl;
114 
115  int colCnt=(int)ceil((float)chCnt/(float)iio[0].getChCnt()); // check whether we require less then the available number of channels
116 
117 // use this if there are problems writing to file gradually
118 // // Collect all samples in memory first using the data matrix.
119 // Eigen::Matrix<unsigned short, Eigen::Dynamic, Eigen::Dynamic> dataStore;
120 // dataStore.resize(M*N*iio[0].getChCnt(), colCnt);
121 
122  int expectedWriteCnt=N*chCnt;
123 // Debugger << "opening"<<endl;
124  int ret;
125  if ((ret=iio.open(periodCount, N))!=NO_ERROR) // try to open all devices
126  return ret;
127 
128  // Debugger << "get read array"<<endl;
129  Eigen::Array<unsigned short int, Eigen::Dynamic, Eigen::Dynamic> data;
130  ret=iio.getReadArray(N, data); // resize the array to be able to read enough memory
131  if (ret!=NO_ERROR)
132  return ret;
133  if (data.cols()>colCnt) // resize the data columns to match the specified number of columns
134  data.resize(data.rows(), colCnt);
135 
136  float maxDelay=iio.getMaxDelay(fs);
137  cout<<"maxDelay = "<<maxDelay<<endl;
138 
139  // open sox
140  Sox<float> sox;
141  ret=sox.openWrite(argv[argc-1], fs, colCnt, MAXSHORT);
142  if (ret!=NO_ERROR)
143  return ret;
144 
145  struct timespec start, stop, lockStart, lockStop;
146 
147  if( clock_gettime( CLOCK_REALTIME, &start) == -1 ) {
148  cout<<"clock start get time error"<<endl;
149  exit(-1);
150  }
151 
152  double durations[M];
153  for (int i=0; i<M; i++) {
154  // Debugger << "read loop i="<<i<<endl;
155 
156  if( clock_gettime( CLOCK_REALTIME, &lockStart) == -1 ) {
157  cout<<"clock lockStart get time error"<<endl;
158  exit(-1);
159  }
160 
161  if (i==0){
162  // Debugger << "enabling"<<endl;
163  if ((ret=iio.enable(true))!=NO_ERROR) // start the DMA
164  return ret;
165  }
166 
167  ret=iio.read(N, data);
168  if (ret!=NO_ERROR) {
169  cout<<"error with i="<<i<<" out of M="<<M<<" loops."<<endl;
170  break;
171  }
172 
173  //dataStore.block(i*N*iio[0].getChCnt(), 0, N*iio[0].getChCnt(), data.cols())=data; // use this if there is problems writing to file gradually.
174  int written=sox.write(data);
175  if (written!=expectedWriteCnt) {
176  if (written>0)
177  cout<<"Attempted to write "<<N<<" samples (per channel) to the audio file, however only "<<written<<" samples were written. Exiting!"<<endl;
178  else {
179  cout<<SoxDebug().evaluateError(written)<<endl;
180  cout<<"Output matrix size (rows, cols) = ("<<data.rows()<<", "<<data.cols()<<")"<<endl;
181  cout<<"Error writing, exiting."<<endl;
182  }
183  break;
184  }
185 
186  if( clock_gettime( CLOCK_REALTIME, &lockStop) == -1 ) {
187  cout<<"clock lockStop get time error"<<endl;
188  exit(-1);
189  }
190  durations[i] = 1.e3*( lockStop.tv_sec - lockStart.tv_sec ) + (double)( lockStop.tv_nsec - lockStart.tv_nsec )/1.e6;
191  if (durations[i]>maxDelay*1.e3)
192  cout<<"Safe lock duration of "<<maxDelay<<" exceeded with a lag of "<<durations[i]<<" ms, possible sample drop.\n";
193  }
194 
195  iio.enable(false); // stop the DMA
196  cout<<"closing the devices"<<endl;
197  iio.close();
198 
199  if( clock_gettime( CLOCK_REALTIME, &stop) == -1 ) {
200  cout<<"clock stop get time error"<<endl;
201  exit(-1);
202  }
203 
204 
205  sox.closeWrite();
206 
207  ofstream outputd("/tmp/durations.txt");
208  for (int i=0; i<M; i++)
209  outputd<<durations[i]<<'\n';
210  outputd.close();
211 
212  double duration = 1.e3*( stop.tv_sec - start.tv_sec ) + (double)( stop.tv_nsec - start.tv_nsec )/1.e6;
213  cout<<"Duration "<<duration<<" ms\n";
214 
215  double expected = (float)(N*M)/1.e6*1.e3;
216  cout<<"Expected "<<expected<<" ms\n";
217 
218  cout<<"Difference "<<duration-expected<<" ms"<<endl;
219 
220 
221  return 0;
222 }
223 
virtual int openWrite(const string &fileName, double fs, int channels, double maxVal)
Definition: Sox.H:174
int N
int getArg(string key, int argc, char *argv[], TYPE &ret, int i)
Definition: OptionParser.H:43
virtual int evaluateError(int errorNum)
Definition: Debug.H:132
void printInfo()
Definition: IIO.H:146
int closeWrite(void)
Definition: Sox.C:232
int printUsage(string name, int N, string chip, int chCnt, float T, float fs, int periodCount)
Definition: IIOSox.C:31
vector< string > availableFormats(void)
Definition: Sox.C:238
int findDevicesByChipName(std::string chipName)
Definition: IIO.H:97
int close(void)
Definition: IIOMMap.H:255
#define NO_ERROR
There is no error.
Definition: Debug.H:33
Definition: Sox.H:95
int read(uint N, const Eigen::Array< TYPE, Eigen::Dynamic, Eigen::Dynamic > &array)
Definition: IIOMMap.H:267
uint getChCnt()
Definition: IIO.H:137
int main(int argc, char *argv[])
Definition: IIOSox.C:51
Definition: Sox.H:54
int getReadArray(uint N, Eigen::Array< TYPE, Eigen::Dynamic, Eigen::Dynamic > &array)
Definition: IIO.H:222
int enable(bool enable)
Definition: IIO.H:290
double getMaxDelay(float fs)
Definition: IIOMMap.H:317
int open(void)
Definition: IIOMMap.H:199
virtual int write(const vector< vector< FP_TYPE_ > > &audioData)
Definition: Sox.C:203
gtkIOStream: /tmp/gtkiostream/applications/IIOSox.C Source File
GTK+ IOStream  Beta