RadioDecoder.C
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "Devices/RadioDecoder.H"
00039
00040 #include "Component/ParamMap.H"
00041 #include "Devices/AudioGrabber.H"
00042 #include "Devices/AudioMixer.H"
00043 #include "Devices/DeviceOpts.H"
00044 #include "Util/Assert.H"
00045 #include "Util/Types.H"
00046 #include "Util/log.H"
00047
00048 #include <cstdio>
00049 #include <cmath>
00050
00051
00052 #define RD_WIN 2
00053
00054
00055 #define RD_THRESH (255 - 20)
00056
00057
00058 #define MINRDPULSE 30
00059 #define MAXRDPULSE 150
00060
00061 void* RadioDecoder_run(void *r0);
00062
00063
00064 void* RadioDecoder_run(void *r0)
00065 {
00066 RadioDecoder *r = (RadioDecoder *)r0;
00067 r->run(); return NULL;
00068 }
00069
00070
00071 RadioDecoder::RadioDecoder(OptionManager& mgr,
00072 const std::string& descrName,
00073 const std::string& tagName) :
00074 ModelComponent(mgr, descrName, tagName)
00075 {
00076 #ifndef HAVE_SYS_SOUNDCARD_H
00077 CLFATAL("Oops! I can't run without <sys/soundcard.h>");
00078 #else
00079 running = false;
00080
00081 agb = nub::soft_ref<AudioGrabber>
00082 (new AudioGrabber(mgr, "RadioDecoder Grabber", "RadioDecoderGrabber"));
00083
00084
00085 agb->setModelParamVal("AudioGrabberFreq", uint(48000));
00086 agb->setModelParamVal("AudioGrabberChans", 1);
00087 agb->setModelParamVal("AudioGrabberBufSamples", uint(1000));
00088
00089
00090 nub::soft_ref<AudioMixer>
00091 mix(new AudioMixer(mgr, "RadioDecoder Mixer", "RadioDecoderMixer"));
00092 addSubComponent(mix);
00093 addSubComponent(agb);
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 agb->forgetExports();
00105 mix->forgetExports();
00106
00107 agb->doRequestOption(&OPT_AudioGrabberDevice);
00108 agb->doRequestOption(&OPT_AudioGrabberChans, true);
00109 mix->doRequestOption(&OPT_AudioMixerDevice);
00110 mix->doRequestOption(&OPT_AudioMixerLineIn);
00111 mix->doRequestOption(&OPT_AudioMixerCdIn);
00112 mix->doRequestOption(&OPT_AudioMixerMicIn);
00113 #endif // HAVE_SYS_SOUNDCARD_H
00114 }
00115
00116
00117 void RadioDecoder::start1()
00118 {
00119 #ifndef HAVE_SYS_SOUNDCARD_H
00120 CLFATAL("Oops! I can't run without <sys/soundcard.h>");
00121 #else
00122 const bool stereo = agb->getModelParamVal<uint>("AudioGrabberChans");
00123 nch = stereo ? 2 : 1;
00124
00125
00126 zero = new rutz::shared_ptr<NModelParam<float> >[nch];
00127 posmult = new rutz::shared_ptr<NModelParam<float> >[nch];
00128 negmult = new rutz::shared_ptr<NModelParam<float> >[nch];
00129 servoval = new float[nch];
00130 for (int i = 0; i < nch; i ++)
00131 {
00132 servoval[i] = 0.0F; char buf[20];
00133
00134 sprintf(buf, "Zero%d", i);
00135 zero[i] = NModelParam<float>::make(buf, this, 0.0F);
00136
00137 sprintf(buf, "PosMult%d", i);
00138 posmult[i] = NModelParam<float>::make(buf, this, 1.0F);
00139
00140 sprintf(buf, "NegMult%d", i);
00141 negmult[i] = NModelParam<float>::make(buf, this, 1.0F);
00142 }
00143 #endif // HAVE_SYS_SOUNDCARD_H
00144 }
00145
00146
00147 void RadioDecoder::start2()
00148 {
00149
00150 pthread_create(&runner, NULL, &RadioDecoder_run, (void *)this);
00151 }
00152
00153
00154 void RadioDecoder::stop1()
00155 {
00156
00157 running = false; while(running == false) usleep(5);
00158 usleep(50); running = false;
00159
00160 delete [] servoval; servoval = 0;
00161 delete [] zero; zero = 0;
00162 delete [] posmult; posmult = 0;
00163 delete [] negmult; negmult = 0;
00164 }
00165
00166
00167 RadioDecoder::~RadioDecoder()
00168 { }
00169
00170
00171 float RadioDecoder::getVal(const int channel) const
00172 {
00173 ASSERT(channel >= 0 && channel < nch);
00174 float val;
00175 if (servoval[channel] >= zero[channel]->getVal())
00176 {
00177 val = (servoval[channel] - zero[channel]->getVal()) *
00178 posmult[channel]->getVal();
00179 if (val >= 1.0F) val = 0.999999F;
00180 }
00181 else
00182 {
00183 val = (servoval[channel] - zero[channel]->getVal()) *
00184 negmult[channel]->getVal();
00185 if (val <= -1.0F) val = -0.999999F;
00186 }
00187 return val;
00188 }
00189
00190
00191 void RadioDecoder::zeroCalibrate(const int nbiter)
00192 {
00193 LINFO("Starting zero calibration. Put controls to rest.");
00194 float avg[nch]; for (int i = 0; i < nch; i ++) avg[i] = 0.0F;
00195
00196
00197
00198 usleep(2000000);
00199
00200 for (int i = 0; i < nbiter; i ++)
00201 {
00202 for (int j = 0; j < nch; j ++) avg[j] += servoval[j];
00203 usleep(30000);
00204 }
00205 for (int i = 0; i < nch; i ++) zero[i]->setVal(avg[i] / ((float)nbiter));
00206 LINFO("Zero calibration done.");
00207 }
00208
00209
00210 void RadioDecoder::rangeCalibrate(const int nbiter)
00211 {
00212 LINFO("Range calibration: Full-swing all controls now!");
00213 float pmax[nch], nmax[nch];
00214 for (int i = 0; i < nch; i ++) { pmax[i] = -10000.0; nmax[i] = 10000.0; }
00215
00216 for (int i = 0; i < nbiter; i ++)
00217 {
00218 for (int j = 0; j < nch; j ++)
00219 {
00220 float x = servoval[j];
00221 if (x > pmax[j]) pmax[j] = x;
00222 if (x < nmax[j]) nmax[j] = x;
00223 }
00224 usleep(20000);
00225 }
00226 for (int i = 0; i < nch; i ++)
00227 {
00228 if (fabs(pmax[i] - zero[i]->getVal()) < 0.001F)
00229 {
00230 LERROR("ZERO positive range? Setting multiplier to 1");
00231 posmult[i]->setVal(1.0F);
00232 }
00233 else
00234 posmult[i]->setVal(0.99999F / (pmax[i] - zero[i]->getVal()));
00235
00236 if (fabs(zero[i]->getVal() - nmax[i]) < 0.001F)
00237 {
00238 LERROR("ZERO negative range? Setting multiplier to 1");
00239 negmult[i]->setVal(1.0F);
00240 }
00241 else
00242 negmult[i]->setVal(-0.99999F / (nmax[i] - zero[i]->getVal()));
00243 }
00244 LINFO("Range calibration done.");
00245 }
00246
00247
00248 void RadioDecoder::run()
00249 {
00250 #ifndef HAVE_SYS_SOUNDCARD_H
00251 CLFATAL("Oops! I can't run without <sys/soundcard.h>");
00252 #else
00253 running = true;
00254 int scoreStart[nch], idxUp[nch], scoreEnd[nch], idxDown[nch],
00255 first[nch], middle[nch], last[nch], bestUp[nch], bestDown[nch];
00256
00257 while(running)
00258 {
00259
00260 AudioBuffer<byte> buffer;
00261 agb->grab(buffer);
00262 int nsamples = int(buffer.nsamples());
00263
00264
00265
00266 for (int i = 0; i < nch; i ++) {
00267 scoreStart[i] = 0; scoreEnd[i] = 0; idxUp[i] = -1; idxDown[i] = -1;
00268 bestUp[i] = 0; bestDown[i] = 0;
00269 }
00270 const byte *bptr = buffer.getDataPtr();
00271
00272
00273 for (int i = 0; i < RD_WIN; i ++)
00274 for (int j = 0; j < nch; j ++)
00275 {
00276 if (*bptr > RD_THRESH) scoreStart[j] ++;
00277 if (bptr[RD_WIN] > RD_THRESH) scoreEnd[j] ++;
00278 bptr ++;
00279 }
00280
00281 int mid = RD_WIN * nch, end = (2 * RD_WIN - 1) * nch;
00282 bptr = buffer.getDataPtr();
00283 for (int i = 0; i < nch; i ++)
00284 {
00285 if (*bptr > RD_THRESH) first[i] = 1; else first[i] = 0;
00286 if (bptr[mid] > RD_THRESH) middle[i] = 1; else middle[i] = 0;
00287 if (bptr[end] > RD_THRESH) last[i] = 1; else last[i] = 0;
00288 bptr ++;
00289 }
00290
00291
00292
00293 bptr = buffer.getDataPtr() + nch;
00294 for (int i = RD_WIN + 1; i < nsamples - RD_WIN; i ++)
00295 for (int j = 0; j < nch; j ++)
00296 {
00297 if (idxUp[j] != -1 && scoreStart[j] - scoreEnd[j] > bestDown[j]) {
00298 bestDown[j] = scoreStart[j] - scoreEnd[j];
00299 idxDown[j] = i;
00300
00301
00302 }
00303 if (idxDown[j] == -1 && scoreEnd[j] - scoreStart[j] > bestUp[j]) {
00304 bestUp[j] = scoreEnd[j] - scoreStart[j];
00305 idxUp[j] = i;
00306
00307
00308 }
00309
00310 scoreStart[j] += middle[j] - first[j];
00311 scoreEnd[j] += last[j] - middle[j];
00312
00313 if (*bptr > RD_THRESH) first[j] = 1; else first[j] = 0;
00314 if (bptr[mid] > RD_THRESH) middle[j] = 1; else middle[j] = 0;
00315 if (bptr[end] > RD_THRESH) last[j] = 1; else last[j] = 0;
00316 bptr ++;
00317 }
00318
00319
00320 for (int i = 0; i < nch; i ++)
00321 {
00322
00323 if (idxDown[i] != -1 && idxUp[i] != -1 && idxUp[i] < idxDown[i] &&
00324 idxDown[i] - idxUp[i] > MINRDPULSE &&
00325 idxDown[i] - idxUp[i] < MAXRDPULSE)
00326 servoval[i] = (float)(idxDown[i] - idxUp[i] + 1);
00327 }
00328
00329 usleep(5000);
00330 }
00331
00332
00333 running = true;
00334 pthread_exit(0);
00335 #endif // HAVE_SYS_SOUNDCARD_H
00336 }
00337
00338
00339
00340
00341
00342