summaryrefslogtreecommitdiff
path: root/src/refout.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/refout.cxx')
-rw-r--r--src/refout.cxx247
1 files changed, 247 insertions, 0 deletions
diff --git a/src/refout.cxx b/src/refout.cxx
new file mode 100644
index 0000000..3642380
--- /dev/null
+++ b/src/refout.cxx
@@ -0,0 +1,247 @@
+using namespace std;
+#include <iostream>
+#include <iomanip>
+#include <unistd.h>
+#include "refout.h"
+#include "lockin.h"
+#include "gui.h"
+#include <alsa/asoundlib.h>
+#ifdef TUNER
+# include <sys/ioctl.h> /* for ioctl, TCGETA */
+# include <termios.h> /* for ECHO */
+#endif
+
+datum smash(double foo) {
+ if (foo > INT_MAX) return INT_MAX;
+ if (foo < -INT_MAX) return -INT_MAX;
+ return datum(foo);
+}
+
+#ifdef TUNER
+
+int fn = fileno(stdin);
+string kbd("\t1q2we4r5t6yu8i9op-[=]");
+string keymap("C+D+EF+G+A+BC");
+const double halfstep(pow(2.0, 1.0/12.0));
+int octave(4);
+int kbkey(9); // A4 = 440 Hz
+int abskey(57);
+
+void dokey(int newkey){
+ abskey = newkey;
+ ofreq = 440*pow(halfstep, abskey-57);
+ int myoct = abskey / 12;
+ int mykey = abskey - myoct*12;
+ string keyname;
+ char keylet = keymap[mykey];
+ if (keylet == '+') {
+ keyname += keymap[mykey-1];
+ keyname += '#';
+ } else keyname += keylet;
+
+ fprintf(stderr, "\r\033[K %2s%1d %6.2f\r", keyname.c_str(), myoct, ofreq);
+ fflush(stderr);
+}
+
+int escmode(0);
+
+void chkey(){
+ char cc;
+ int nn = read(fn, &cc, 1);
+ if (nn <= 0) return;
+ if (cc == 033) {
+ escmode = 1;
+ return;
+ }
+ if (escmode) {
+ if (cc == '~') escmode = 0;
+ if (cc != 'O' && isupper(cc)) escmode = 0;
+ if (cc == 'B' || cc == 'D') dokey(abskey-1);
+ else if (cc == 'A' || cc == 'C') dokey(abskey+1);
+ return;
+ }
+ string::size_type where = kbd.find(cc);
+ if (where != kbd.npos) {
+ kbkey = where;
+ } else if (cc == ',') {
+ octave--;
+ if (octave < 0) octave = 0;
+ } else if (cc == '.') {
+ octave++;
+ if (octave > 8) octave = 8;
+ } else {
+ int foo;
+ foo = cc;
+ fprintf(stderr, "%04o\n", foo);
+ return;
+ }
+ dokey(12*octave + kbkey);
+}
+
+void setkey(){
+ kbd += char(127); // the "backspace" key
+ kbd += '\\';
+ kbd += char(10); // the "return" key
+}
+
+#else
+inline void chkey(){} // does nothing
+inline void setkey(){} // does nothing
+#endif
+
+void* refout(void* _arg){
+
+ ref_arg* arg = (ref_arg*) _arg;
+
+ setkey(); // FIXME (doesn't do anything at the moment)
+
+ double reftime = .2; // # of seconds in output buffer
+ int refframe = int(arg->pcm->rate * reftime); // # of frames
+ int bufsize(refframe * arg->pcm->nchan);
+
+ if (verbosity) cerr << "Refout starts, ofreq: " << actOutFreq
+ << " INT_MAX: " << INT_MAX
+ << " sizeof(datum): " << sizeof(datum)
+ << " refframe: " << refframe
+ << " bufsize: " << bufsize
+ << endl;
+
+#ifdef TUNER
+ {
+ termio save;
+ // If ioctl fails, we're probably not connected to a terminal.
+ int rslt;
+ rslt = ioctl(fn, TCGETA, &save);
+ termio t(save);
+ t.c_lflag &= ~ECHO;
+ t.c_lflag &= ~ICANON;
+ t.c_cc[VMIN] = 1;
+ t.c_cc[VTIME] = 0;
+ t.c_cc[VERASE] = 0;
+
+ ioctl(fn, TCSETA, &t);
+ int temp(1);
+ ioctl(fn, FIONBIO, &temp);
+ }
+#endif
+
+ Keeper keep(arg->pcm, FPP);
+
+ datum* ptr;
+ datum foo[2];
+ int flip;
+
+/////////////////
+// main refout loop
+//
+// this is a SINGLE loop over TWO variables;
+// the cap_buffer is emptied in units of refframe
+// and filled in units of fpkp.
+// Parallel code appears in krunch.cxx
+ valarray<datum> refout_buffer(bufsize);
+ int out_idx(0);
+ int ref_end(fpkp);
+ int ref_idx(0);
+ double theta0(0);
+ double theta1(0);
+ double old_cpkp(0), old_fpkp(0);
+ double dtheta0(0);
+ double dtheta1(0);
+ int kperno(0);
+
+ for (;;) { // loop over all samples
+
+// loop control for output (write) process
+ if (out_idx >= refframe) {
+ int todo = out_idx;
+ out_idx = 0;
+ datum* obuf_ptr(&refout_buffer[0]);
+
+ while (todo) { // keep trying to get this buffer out
+ int rslt = snd_pcm_writei(keep, obuf_ptr, todo);
+ if (rslt == todo) break; // good!
+ if (rslt > 0) { // short write = harmless
+ // but should be rare
+ cout << "Refout: short write; probably harmless." << endl;
+ todo -= rslt;
+ obuf_ptr += rslt;
+ continue;
+ }
+ if (rslt == -EPIPE) { // explicit underrrun
+ if (xrun_verbosity) fprintf(stderr,
+ "Refout underrun: wrote %d got %d" NL, todo, rslt);
+ snd_pcm_prepare(arg->pcm->phndl); // recover from underruns
+ continue;
+ }
+ // some error we don't understand
+ fprintf(stderr, "Refout wrote %d got %d" NL, todo, rslt);
+ snd_pcm_prepare(arg->pcm->phndl); // try to recover
+ }
+ }
+
+// Loop control for reference process.
+// Note that dtheta0 only changes at the boundary
+// between krunch periods.
+ if (ref_idx == ref_end) {
+ theta0 = 0.;
+ // theta1 is free-running
+ ref_idx = 0;
+ ref_end = fpkp;
+ dtheta0 = 2. * M_PI * cpkp / fpkp;
+ // cpkp == cycles per krunch period
+ // fpkp == frames per krunch period
+ if (old_cpkp != cpkp || old_fpkp != fpkp){
+ if (verbosity > 0) {
+ cout.precision(6);
+ cout << fixed;
+ double freq = arg->pcm->rate / fpkp * cpkp;
+ cout << "Refout switching to: " << freq
+ << setprecision(1)
+ << " cpkp: " << cpkp
+ << " fpkp: " << fpkp
+ << " dtheta: " << setprecision(20) << dtheta0
+ << " rate: " << arg->pcm->rate
+ << endl;
+ }
+ old_cpkp = cpkp;
+ old_fpkp = fpkp;
+ }
+ }
+ if (ref_idx == 0) {
+ ref_to_krunch kper(kperno, int(cpkp), int(fpkp));
+ int didwrite = write(arg->pipefd, &kper, sizeof(kper));
+ if (didwrite != sizeof(kper)) {
+ fprintf(stderr, "refout: write to pipe failed:");
+ perror(0);
+ exeunt(1);
+ }
+ kperno++;
+ }
+
+
+ dtheta1 = dtheta0 * arg->ival;
+
+ chkey(); // FIXME
+
+ double expo((refOutAmp_dB - VoCal_dB)/20);
+ if (expo > 100) expo = 100;
+ double gainFactor(pow(10, expo));
+ double amplitude(full_swing * gainFactor);
+
+ foo[0] = smash(amplitude * cos(theta0));
+ foo[1] = smash(amplitude * cos(theta1));
+
+// Fill all channels in frame (not just the first two):
+ ptr = &refout_buffer[out_idx * arg->pcm->nchan];
+ for (unsigned int jj = 0; jj < arg->pcm->nchan; jj++) {
+ flip = jj & 1; // copy foo[0] or foo[1]
+ *ptr++ = foo[flip];
+ }
+
+ theta0 += dtheta0;
+ theta1 += dtheta1;
+ out_idx++;
+ ref_idx++;
+ }
+ return 0;
+}