コード例 #1
0
void
SDROMnoiseblanker (NB nb)
{
  int i;
  for (i = 0; i < CXBsize (nb->sigbuf); i++)
    {
      REAL cmag = Cmag (CXBdata (nb->sigbuf, i));
      nb->average_sig = Cadd (Cscl (nb->average_sig, 0.75),
			      Cscl (CXBdata (nb->sigbuf, i), 0.25));
      nb->average_mag = (REAL) (0.999 * (nb->average_mag) + 0.001 * cmag);
      if (cmag > (nb->threshold * nb->average_mag))
	CXBdata (nb->sigbuf, i) = nb->average_sig;
    }
}
コード例 #2
0
BOOLEAN
SpotTone (SpotToneGen st)
{
  int i, n = st->size;

  ComplexOSC (st->osc.gen);

  for (i = 0; i < n; i++)
    {

      // in an envelope stage?

      if (st->stage == SpotTone_RISE)
	{

	  // still going?
	  if (st->rise.have++ < st->rise.want)
	    {
	      st->curr += st->rise.incr;
	      st->mul = (REAL) (st->scl * sin (st->curr * M_PI / 2.0));
	    }
	  else
	    {
	      // no, assert steady-state, force level
	      st->curr = 1.0;
	      st->mul = st->scl;
	      st->stage = SpotTone_STDY;
	      // won't come back into envelopes
	      // until FALL asserted from outside
	    }

	}
      else if (st->stage == SpotTone_FALL)
	{

	  // still going?
	  if (st->fall.have++ < st->fall.want)
	    {
	      st->curr -= st->fall.incr;
	      st->mul = (REAL) (st->scl * sin (st->curr * M_PI / 2.0));
	    }
	  else
	    {
	      // no, assert trailing, force level
	      st->curr = 0.0;
	      st->mul = 0.0;
	      st->stage = SpotTone_HOLD;
	      // won't come back into envelopes hereafter
	    }
	}
      // apply envelope
      // (same base as osc.gen internal buf)
      CXBdata (st->buf, i) = Cscl (CXBdata (st->buf, i), st->mul);
    }

  // indicate whether it's turned itself off
  // sometime during this pass

  return st->stage != SpotTone_HOLD;
}
コード例 #3
0
void
correctIQ (CXB sigbuf, IQ iq, BOOLEAN isTX, int subchan)
{
	int i;
	REAL doit;
	if (IQdoit == 0) return;
	if (subchan == 0) doit = iq->mu;
	else doit = 0;
	if(!isTX)
	{
		// if (subchan == 0) // removed so that sub rx's will get IQ correction
		for (i = 0; i < CXBhave (sigbuf); i++)
		{
			iq->del[iq->index] = CXBdata(sigbuf,i);
			iq->y[iq->index] = Cadd(iq->del[iq->index],Cmul(iq->w[0],Conjg(iq->del[iq->index])));
			iq->y[iq->index] = Cadd(iq->y[iq->index],Cmul(iq->w[1],Conjg(iq->y[iq->index])));
			iq->w[1] = Csub(iq->w[1], Cscl(Cmul(iq->y[iq->index],iq->y[iq->index]), doit));  // this is where the adaption happens

			CXBdata(sigbuf,i)=iq->y[iq->index];
			iq->index = (iq->index+iq->MASK)&iq->MASK;
		}
		//fprintf(stderr, "w1 real: %g, w1 imag: %g\n", iq->w[1].re, iq->w[1].im); fflush(stderr); 
	}
	else
	{
		for (i = 0; i < CXBhave (sigbuf); i++)
		{
			CXBimag (sigbuf, i) += iq->phase * CXBreal (sigbuf, i);
			CXBreal (sigbuf, i) *= iq->gain;
		}
	}

}
コード例 #4
0
REAL
normalize_vec_COMPLEX (COMPLEX * z, int n)
{
  if (z && (n > 0))
    {
      int i;
      REAL big = -(REAL) MONDO;
      for (i = 0; i < n; i++)
	{
	  REAL a = Cabs (z[i]);
	  big = max (big, a);
	}
      if (big > 0.0)
	{
	  REAL scl = (REAL) (1.0 / big);
	  for (i = 0; i < n; i++)
	    z[i] = Cscl (z[i], scl);
	  return scl;
	}
      else
	return 0.0;
    }
  else
    return 0.0;
}
コード例 #5
0
void
blms_adapt (BLMS blms)
{
  int sigsize = CXBhave (blms->signal);
  int sigidx = 0;

 // fputs("Inside\n",stderr),fflush(stderr);
  do {
      int j;
      memcpy (blms->delay_line, &blms->delay_line[128], sizeof (COMPLEX) * 128);	// do overlap move
      memcpy (&blms->delay_line[128], &CXBdata (blms->signal, sigidx), sizeof (COMPLEX) * 128);	// copy in new data
      fftwf_execute (blms->Xplan);	// compute transform of input data
      for (j = 0; j < 256; j++) {
          blms->Yhat[j] = Cmul (blms->What[j], blms->Xhat[j]);	// Filter new signal in freq. domain
		  blms->Xhat[j] = Conjg (blms->Xhat[j]);	// take input data's complex conjugate
	  }
      fftwf_execute (blms->Yplan);	//compute output signal transform
      for (j = 128; j < 256; j++)
		  blms->y[j] = Cscl (blms->y[j], BLKSCL);
      memset (blms->y, 0, 128 * sizeof (COMPLEX));
      for (j = 128; j < 256; j++)
		  blms->error[j] = Csub (blms->delay_line[j], blms->y[j]);	// compute error signal

      if (blms->filter_type)
		  memcpy (&CXBdata (blms->signal, sigidx), &blms->y[128], 128 * sizeof (COMPLEX));	// if noise filter, output y
      else
		  memcpy (&CXBdata (blms->signal, sigidx), &blms->error[128], 128 * sizeof (COMPLEX));	// if notch filter, output error

      fftwf_execute (blms->Errhatplan);	// compute transform of the error signal
      for (j = 0; j < 256; j++)
		  blms->Errhat[j] = Cmul (blms->Errhat[j], blms->Xhat[j]);	// compute cross correlation transform
      fftwf_execute (blms->UPDplan);	// compute inverse transform of cross correlation transform
      for (j = 0; j < 128; j++)
		  blms->update[j] = Cscl (blms->update[j], BLKSCL);
      memset (&blms->update[128], 0, sizeof (COMPLEX) * 128);	// zero the last block of the update, so we get
      // filter coefficients only at front of buffer
      fftwf_execute (blms->Wplan);
      for (j = 0; j < 256; j++)
	  {
		blms->What[j] = Cadd (Cscl (blms->What[j], blms->leak_rate),	// leak the W away
				Cscl (blms->Update[j], blms->adaptation_rate));	// update at adaptation rate
	  }
      sigidx += 128;		// move to next block in the signal buffer
  }	while (sigidx < sigsize);	// done?
}
コード例 #6
0
BOOLEAN
CWTone (CWToneGen cwt)
{
	int i, n = cwt->size;

	ComplexOSC (cwt->osc.gen);

	for (i = 0; i < n; i++)
	{
		// in an envelope stage?
		if (cwt->stage == CWTone_RISE)
		{
			// still going?
			if (cwt->rise.have++ < cwt->rise.want)
			{
				cwt->curr += cwt->rise.incr;
				cwt->mul = cwt->scl * (REAL) CWSIN (cwt->curr * M_PI / 2.0);
			}
			else
			{
				// no, assert steady-state, force level
				cwt->curr = 1.0;
				cwt->mul = cwt->scl;
				cwt->stage = CWTone_STDY;
				// won't come back into envelopes
				// until FALL asserted from outside
			}
		}
		else if (cwt->stage == CWTone_FALL)
		{
            // still going?
			if (cwt->fall.have++ < cwt->fall.want)
			{
				cwt->curr -= cwt->fall.incr;
				cwt->mul = cwt->scl * (REAL) CWSIN (cwt->curr * M_PI / 2.0);
			}
			else
			{
				// no, assert trailing, force level
				cwt->curr = 0.0;
				cwt->mul = 0.0;
				cwt->stage = CWTone_HOLD;
				// won't come back into envelopes hereafter
			}
		}
		// apply envelope
		// (same base as osc.gen internal buf)
		CXBdata (cwt->buf, i) = Cscl (CXBdata (cwt->buf, i), cwt->mul);
	}
	CXBhave(cwt->buf) = n; /* kd5tfd added - set have field of buf so correctIQ works */ 

	// indicate whether it's turned itself off
	// sometime during this pass
	return cwt->stage != CWTone_HOLD;
}
コード例 #7
0
ファイル: lmadf.c プロジェクト: hdkippa/ghpsdr2
static void
lmsr_adapt_i (LMSR lms)
{
  int i, j, k;
  REAL sum_sq, scl1, scl2;
  COMPLEX accum, error;

  scl1 = (REAL) (1.0 - rate * leak);

  for (i = 0; i < ssiz; i++)
    {

      dlay (dptr) = CXBdata (lms->signal, i);
      accum = cxzero;
      sum_sq = 0;

      for (j = 0; j < asiz; j+=2)
		{
			k = wrap (j);
			sum_sq += Csqrmag (dlay (k));
			accum.re += afil (j).re * dlay (k).re;
			accum.im += afil (j).im * dlay (k).im;

			k = wrap (j+1);
			sum_sq += Csqrmag (dlay (k));
			accum.re += afil (j+1).re * dlay (k).re;
			accum.im += afil (j+1).im * dlay (k).im;
		}

      error = Csub(cssig(i),accum);
	  cssig(i) = error;
//     ssig_i (i) = error.im;
//	  ssig (i) = error.re;

      scl2 = (REAL) (rate / (sum_sq + 1.19e-7));
      error = Cscl(error,scl2);
      for (j = 0; j < asiz; j+=2)
		{
			k = wrap (j);
			afil (j).re = afil (j).re * scl1 + error.re * dlay (k).re;
			afil (j).im = afil (j).im * scl1 + error.im * dlay (k).im;

			k = wrap (j+1);
			afil (j+1).re = afil (j+1).re * scl1 + error.re * dlay (k).re;
			afil (j+1).im = afil (j+1).im * scl1 + error.im * dlay (k).im;
		}

      dptr = bump (dptr);
    }
}
コード例 #8
0
ファイル: wscompand.c プロジェクト: wa1gon/PowerSDR
void
WSCompand (WSCompander wsc)
{
	int i, n = CXBsize (wsc->buff);

	//if (wsc->fac != 0.0) 
	{
		for (i = 0; i < n ; i++)
		{
			COMPLEX val = CXBdata (wsc->buff, i);
			REAL mag = Cmag (val), scl = WSCLookup (wsc, mag);
			CXBdata (wsc->buff, i) = Cscl (val,scl);
		}
	}
}
コード例 #9
0
ファイル: spectrum.c プロジェクト: wa1gon/PowerSDR
// snapshot of current signal
void
snap_spectrum (SpecBlock * sb, int label)
{
	int i, j;

	// where most recent signal started
	j = sb->fill;

	// copy starting from there in circular fashion,
	// applying window as we go
	if (!sb->polyphase)
	{
		for (i = 0; i < sb->size; i++)
		{
			CXBdata (sb->timebuf, i) =
				Cscl (CXBdata (sb->accum, j), sb->window[i]);
			j = (++j & sb->mask);
		}
	}
	else
	{
		int k;
		for (i = 0; i < sb->size; i++)
		{
			CXBreal (sb->timebuf, i) = CXBreal (sb->accum, j) * sb->window[i];
			CXBimag (sb->timebuf, i) = CXBimag (sb->accum, j) * sb->window[i];
			for (k = 1; k < 8; k++)
			{
				int accumidx = (j + k * sb->size) & sb->mask;
				int winidx = i + k * sb->size;
				CXBreal (sb->timebuf, i) +=
					CXBreal (sb->accum, accumidx) * sb->window[winidx];
				CXBimag (sb->timebuf, i) +=
					CXBimag (sb->accum, accumidx) * sb->window[winidx];
			}
			j = (++j & sb->mask);
		}

	}
	sb->label = label;
}
コード例 #10
0
DttSP_EXP void
PolyPhaseFIR (ResSt resst)
/******************************************************************************
* CALLING PARAMETERS:
* Name          Use    Description
* ____          ___    ___________
* *input               pointer to input COMPLEX data array
* *output              pointer to output COMPLEX data array
* RealFIR filter           pointer to filter coefficients array
* *filterMemoryBuff    pointer to buffer used as filter memory. Initialized
*                      all data to 0 before 1st call.  length is calculated
*                      from numFiltTaps
* filterMemoryBuffLength length of filterMemoryBuff
* inputArrayLength     length of input array :note that "output" may differ
*                      in length
* numFiltTaps          number of filter taps in array "filtcoeff": <filterMemoryBuffLength
* indexfiltMemBuf     index to where next input sample is to be stored in
*                      "filterMemoryBuff",initalized 0 to before first call
* interpFactor         interpolation factor: output rate = input rate *
*                      "interpFactor" / "deciFactor".
* filterPhaseNum      filter phase number (index), initialized to 0 before
*                      first call
* deciFactor           decimation factor:
*                      output rate = (input rate * "interpFactor"/"deciFactor")
* numOutputSamples    number of output samples placed in array "output"
*
* CALLED BY:
*
* RETURN VALUE:
* Name      Description
* ____      ___________
* none
*
* DESCRIPTION: This function is used to change the sampling rate of the data.
*              The input is first upsampled to a multiple of the desired
*              sampling rate and then down sampled to the desired sampling rate.
*
*              Ex. If we desire a 7200 Hz sampling rate for a signal that has
*                  been sampled at 8000 Hz the signal can first be upsampled
*                  by a factor of 9 which brings it up to 72000 Hz and then
*                  down sampled by a factor of 10 which results in a sampling
*                  rate of 7200 Hz.
*
* NOTES:
*        Also, the "*filterMemoryBuff" MUST be 2^N REALs long. This
*        routine uses circular addressing on this buffer assuming that
*        it is 2^N REALs in length.
*
******************************************************************************/
{
/******************************************************************************
*               LOCAL VARIABLE DECLARATIONS
*******************************************************************************
* Type              Name                 Description
* ____              ____                 ___________                         */
  int i, j, k, jj;		/* counter variables */
  COMPLEX *outptr;

  resst->numOutputSamples = 0;


  for (i = 0; i < resst->inputArrayLength; i++)
    {

      /*
       * save data in circular buffer
       */

      resst->filterMemoryBuff[resst->indexfiltMemBuf] = resst->input[i];
      j = resst->indexfiltMemBuf;
      jj = j;


      /*
       * circular addressing
       */

      resst->indexfiltMemBuf = (resst->indexfiltMemBuf + 1) & resst->MASK;

      /*
       * loop through each filter phase: interpolate then decimate
       */

      while (resst->filterPhaseNum < resst->interpFactor)
	{
	  j = jj;
	  /*         output[*numOutputSamples] = 0.0; */
	  outptr = resst->output + resst->numOutputSamples;
	  *outptr = cxzero;

	  /*
	   * perform convolution
	   */

	  for (k = resst->filterPhaseNum; k < resst->numFiltTaps;
	       k += resst->interpFactor)
	    {
	      /*            output[*numOutputSamples] += filtcoeff[k]*filterMemoryBuff[j]; */
	      //*outptr += resst->filtcoeff[k]* resst->filterMemoryBuff[j];
	      *outptr =
		Cadd (*outptr,
		      Cscl (resst->filterMemoryBuff[j],
			    FIRtap (resst->filter, k)));


	      /*
	       * circular adressing
	       */

	      j = (j + resst->MASK) & resst->MASK;
	    }

	  /*
	   * scale the data
	   */

	  /*         output[*numOutputSamples]*=(REAL)interpFactor; */
	  *outptr = Cscl (*outptr, (REAL) resst->interpFactor);
	  resst->numOutputSamples += 1;

	  /*
	   * increment interpolation phase # by decimation factor
	   */

	  resst->filterPhaseNum += (resst->deciFactor);

	}			/* end while *filterPhaseNum < interpFactor */

      resst->filterPhaseNum -= resst->interpFactor;

    }				/* end for inputArrayLength */
}				/* end PolyPhaseFir */
コード例 #11
0
ファイル: dttspagc.c プロジェクト: hdkippa/ghpsdr2
void
DttSPAgc (DTTSPAGC a, int tick)
{
	int i;
	int hangtime = (int) (uni[0].samplerate * a->hangtime); // hangtime in samples
	int fasthangtime = (int) (uni[0].samplerate * a->fasthangtime); // fast track hangtime in samples

	REAL hangthresh; // gate for whether to hang or not

//	if (a->hangthresh > 0)
		hangthresh =
			a->gain.top * a->hangthresh + a->gain.bottom * (REAL) (1.0 - a->hangthresh);
//	else
//		hangthresh = 0.;

	if (a->mode == 0)
	{
		for (i = 0; i < CXBsize (a->buff); i++)
			CXBdata (a->buff, i) = Cscl (CXBdata (a->buff, i), a->gain.fix);
		return;
	}

	for (i = 0; i < CXBsize (a->buff); i++)
	{
		REAL tmp;
		a->circ[a->slowindx] = CXBdata (a->buff, i);	/* Drop sample into circular buffer */

		// first, calculate slow gain
		tmp = Cmag (a->circ[a->slowindx]);
		if (tmp > 0.0f)
			tmp = a->gain.target / tmp;	// if mag(sample) not too small, calculate putative gain
										// all the rest of the code which follows is running this
										// signal through the control laws.
		else
			tmp = a->gain.now;	// sample too small, just use old gain
		if (tmp < hangthresh)
			a->hangindex = hangtime;  // If the gain is less than the current hang threshold, then stop hanging.

		if (tmp >= a->gain.now)     // If the putative gain is greater than the current gain then we are in decay.
									// That is, we need to "decay the ALC voltage", or increase the gain.
		{
			//a->gain.raw = a->one_m_decay * a->gain.now + a->decay * tmp;
			if (a->hangindex++ > hangtime)  // Have we HUNG around long enough?
			{
				a->gain.now =  // Compute the applicable slow channel gain through the decay control law.
					a->one_m_decay * a->gain.now +
					a->decay * min (a->gain.top, tmp);
			}
		}
		else // if the putative gain is greater than the current gain,  we are in attack mode and need to decrease gain 
		{
			a->hangindex = 0;  // We don't need to hang, we need to attack so we reset the hang index to zero
			//a->gain.raw = a->one_m_attack * a->gain.now + a->attack * tmp;
			a->gain.now =      // Compute the applicable slow channel gain through the attack control law.
				a->one_m_attack * a->gain.now + a->attack * max (tmp,
				a->gain.bottom); 
		}

		// then, calculate fast gain
		// Fast channel to handle short duration events and not capture the slow channel decay
		tmp = Cmag (a->circ[a->fastindx]);
		if (tmp > 0.0f)
			tmp = a->gain.target / tmp; // if mag(sample) not too small, calculate putative gain
										// all the rest of the code which follows is running this
										// signal through the control laws.
		else
			tmp = a->gain.fastnow;      // too small, just use old gain
		if (tmp > a->gain.fastnow)		// If the putative gain is greater than the current gain then we are in decay.
										// That is, we need to "decay the ALC voltage", or increase the gain.
		{
			if (a->fasthang++ > fasthangtime) // Have we HUNG around long enough?
			{
				a->gain.fastnow =  // Compute the applicable fast channel gain through the decay control law.
					a->one_m_fastdecay * a->gain.fastnow +
					a->fastdecay * min (a->gain.top, tmp);
			}
		}
		else
		{
			a->fasthang = 0; // We don't need to hang, we need to attack so we reset the hang index to zero
			a->gain.fastnow = // Compute the applicable fast channel gain through the fast attack control law.
				a->one_m_fastattack * a->gain.fastnow +
				a->fastattack * max (tmp, a->gain.bottom);
		}
		// Are these two lines necessary? I don't think so.  Let's test that.  tmp is bounded in the statements
		// above to be inside the gain limits
//		a->gain.fastnow =
//			max (min (a->gain.fastnow, a->gain.top), a->gain.bottom);
//		a->gain.now = max (min (a->gain.now, a->gain.top), a->gain.bottom);
		// Always apply the lower gain.
		CXBdata (a->buff, i) =
			Cscl (a->circ[a->out_indx],
			min (a->gain.fastnow, (a->slope * a->gain.now)));

		// Move the indices to prepare for the next sample to be processed
		a->slowindx = (a->slowindx + a->mask) & a->mask; 
		a->out_indx = (a->out_indx + a->mask) & a->mask;
		a->fastindx = (a->fastindx + a->mask) & a->mask;
	}
}
コード例 #12
0
void
DttSPAgc (DTTSPAGC a, int tick)
{
	int i;
	int hangtime = (int) (uni[0].samplerate * a->hangtime);
	int fasthangtime = (int) (uni[0].samplerate * a->fasthangtime);

	REAL hangthresh;

	if (a->hangthresh > 0)
		hangthresh =
			a->gain.top * a->hangthresh + a->gain.bottom * (REAL) (1.0 -
			a->hangthresh);
	else
		hangthresh = 0.;

	if (a->mode == 0)
	{
		for (i = 0; i < CXBsize (a->buff); i++)
			CXBdata (a->buff, i) = Cscl (CXBdata (a->buff, i), a->gain.fix);
		return;
	}

	for (i = 0; i < CXBsize (a->buff); i++)
	{
		REAL tmp;
		a->circ[a->indx] = CXBdata (a->buff, i);	/* Drop sample into circular buffer */
		tmp = Cmag (a->circ[a->indx]);
		if (tmp > 0.00000005f)
			tmp = a->gain.limit / tmp;	// if not zero sample, calculate gain
		else
			tmp = a->gain.now;	// update. If zero, then use old gain
		if (tmp < hangthresh)
			a->hangindex = hangtime;
		if (tmp >= a->gain.now)
		{
			//a->gain.raw = a->one_m_decay * a->gain.now + a->decay * tmp;
			if (a->hangindex++ > hangtime)
			{
				a->gain.now =
					a->one_m_decay * a->gain.now +
					a->decay * min (a->gain.top, tmp);
			}
		}
		else
		{
			a->hangindex = 0;
			//a->gain.raw = a->one_m_attack * a->gain.now + a->attack * tmp;
			a->gain.now =
				a->one_m_attack * a->gain.now + a->attack * max (tmp,
				a->gain.bottom);
		}
		tmp = Cmag (a->circ[a->fastindx]);
		if (tmp > 0.00000005f)
			tmp = a->gain.limit / tmp;
		else
			tmp = a->gain.fastnow;
		if (tmp > a->gain.fastnow)
		{
			if (a->fasthang++ > fasthangtime)
			{
				a->gain.fastnow =
					min (a->one_m_fastdecay * a->gain.fastnow +
					a->fastdecay * min (a->gain.top, tmp), a->gain.top);
			}
		}
		else
		{
			a->fasthang = 0;
			a->gain.fastnow =
				max (a->one_m_fastattack * a->gain.fastnow +
				a->fastattack * max (tmp, a->gain.bottom), a->gain.bottom);
		}
		a->gain.fastnow =
			max (min (a->gain.fastnow, a->gain.top), a->gain.bottom);
		a->gain.now = max (min (a->gain.now, a->gain.top), a->gain.bottom);
		CXBdata (a->buff, i) =
			Cscl (a->circ[a->sndx],
			min (a->gain.fastnow,
			min (a->slope * a->gain.now, a->gain.top)));

		a->indx = (a->indx + a->mask) & a->mask;
		a->sndx = (a->sndx + a->mask) & a->mask;
		a->fastindx = (a->fastindx + a->mask) & a->mask;
	}
}
コード例 #13
0
ファイル: winmain.c プロジェクト: w3sz/ghpsdr3-w3sz
DttSP_EXP void
Audio_Callback2 (float **input, float **output, unsigned int nframes)
{
	unsigned int thread;
	BOOLEAN b = reset_em;
	BOOLEAN return_empty=FALSE;
	unsigned int i;
	for(thread=0;thread<threadno;thread++)
	{
		if (top[thread].susp) return_empty = TRUE;
	}

	if (return_empty)
	{
		for(thread=0;thread<threadno;thread++) 
		{
			memset (output[2*thread], 0, nframes * sizeof (float));
			memset (output[2*thread+1], 0, nframes * sizeof (float));
		}
		return;
	}

	if (b)
	{
		//fprintf(stderr, "reset_em!\n"); fflush(stderr);
		//fprintf(stdout,"Audio_Callback2: reset_em = TRUE\n"), fflush(stdout);
		reset_system_audio(nframes);
		for(thread=0;thread<threadno;thread++) {
			memset (output[2*thread], 0, nframes * sizeof (float));
			memset (output[2*thread+1], 0, nframes * sizeof (float));
		}
		return;
    }
#if 0
	if (diversity.flag) {
		// Deal with the transmitter first
		if ((ringb_float_read_space (top[1].jack.ring.o.l) >= nframes)
			&& (ringb_float_read_space (top[1].jack.ring.o.r) >= nframes))
		{
			ringb_float_read (top[1].jack.ring.o.l, output[2], nframes);
			ringb_float_read (top[1].jack.ring.o.r, output[3], nframes);
		}
		else
		{	
			// rb pathology
			//reset_system_audio(nframes);
			for(thread=0;thread<threadno;thread++) 
			{
				memset (output[thread], 0, nframes * sizeof (float));
				memset (output[thread], 0, nframes * sizeof (float));
			}
			return;
		}

		// input: copy from port to ring
		if ((ringb_float_write_space (top[1].jack.ring.i.l) >= nframes)
			&& (ringb_float_write_space (top[1].jack.ring.i.r) >= nframes))
		{
			ringb_float_write (top[1].jack.ring.i.l, input[2], nframes);
			ringb_float_write (top[1].jack.ring.i.r, input[3], nframes);
		}
		else
		{	
			// rb pathology
			for(thread=0;thread<threadno;thread++) 
			{
				memset (output[thread], 0, nframes * sizeof (float));
				memset (output[thread], 0, nframes * sizeof (float));
			}
			return;
		}
		
		// if enough accumulated in ring, fire dsp
		if ((ringb_float_read_space (top[1].jack.ring.i.l) >= top[1].hold.size.frames) &&
			(ringb_float_read_space (top[1].jack.ring.i.r) >= top[1].hold.size.frames))
			sem_post (&top[1].sync.buf.sem);

		//		
		// Deal with the diversity channel next
		//
		if ((ringb_float_read_space (top[0].jack.ring.o.l) >= nframes)
			&& (ringb_float_read_space (top[0].jack.ring.o.r) >= nframes))
		{
			/*ringb_float_read (top[thread].jack.auxr.o.l, output[l], nframes);
			ringb_float_read (top[thread].jack.auxr.o.r, output[r], nframes);*/
			ringb_float_read (top[0].jack.ring.o.l, output[2], nframes);
			ringb_float_read (top[0].jack.ring.o.r, output[3], nframes);
		}
		else
		{	
			// rb pathology
			//reset_system_audio(nframes);
			for(thread=0;thread<threadno;thread++) 
			{
				memset (output[thread], 0, nframes * sizeof (float));
				memset (output[thread], 0, nframes * sizeof (float));
			}
			return;
		}

		// Deal with the diversity/phased array channel next

		// input: copy from port to ring
		if ((ringb_float_write_space (top[0].jack.ring.i.l) >= nframes)
			&& (ringb_float_write_space (top[0].jack.ring.i.r) >= nframes) &&
			(ringb_float_write_space (top[2].jack.ring.i.l) >= nframes)
			&& (ringb_float_write_space (top[2].jack.ring.i.r) >= nframes))
		{
			REAL *l0 = input[0];
			REAL *r0 = input[1];
			REAL *l2 = input[4];
			REAL *r2 = input[5];
			for (i=0;i<nframes;i++) {
				COMPLEX A = Cmplx(l0[i],r0[i]);
				COMPLEX B = Cmplx(l2[i],r2[i]);
				A = Cscl(Cadd(A,Cmul(B,diversity.scalar)),diversity.gain);
				ringb_float_write (top[0].jack.ring.i.l, &A.re, 1);
				ringb_float_write (top[0].jack.ring.i.r, &A.im, 1);
			}
			/*ringb_float_write (top[thread].jack.auxr.i.l, input[l], nframes);
			ringb_float_write (top[thread].jack.auxr.i.r, input[r], nframes);*/
		}
		else
		{	
			// rb pathology
			//reset_system_audio(nframes);
			for(thread=0;thread<threadno;thread++) 
			{
				memset (output[thread], 0, nframes * sizeof (float));
				memset (output[thread], 0, nframes * sizeof (float));
			}
			return;
		}
		
		// if enough accumulated in ring, fire dsp
		if ((ringb_float_read_space (top[0].jack.ring.i.l) >= top[0].hold.size.frames) &&
			(ringb_float_read_space (top[0].jack.ring.i.r) >= top[0].hold.size.frames))
			sem_post (&top[0].sync.buf.sem);


		//
		//  Deal with 2nd receiver channel now
		//

		if ((ringb_float_read_space (top[2].jack.ring.o.l) >= nframes)
			&& (ringb_float_read_space (top[2].jack.ring.o.r) >= nframes))
		{
			/*ringb_float_read (top[thread].jack.auxr.o.l, output[l], nframes);
			ringb_float_read (top[thread].jack.auxr.o.r, output[r], nframes);*/
			ringb_float_read (top[2].jack.ring.o.l, output[4], nframes);
			ringb_float_read (top[2].jack.ring.o.r, output[5], nframes);
		}
		else
		{	
			// rb pathology
			//reset_system_audio(nframes);
			for(thread=0;thread<threadno;thread++) 
			{
				memset (output[thread], 0, nframes * sizeof (float));
				memset (output[thread], 0, nframes * sizeof (float));
			}
			return;
		}

		// input: copy from port to ring
		if ((ringb_float_write_space (top[2].jack.ring.i.l) >= nframes)
			&& (ringb_float_write_space (top[2].jack.ring.i.r) >= nframes))
		{
			ringb_float_write (top[2].jack.ring.i.l, input[4], nframes);
			ringb_float_write (top[2].jack.ring.i.r, input[5], nframes);
		}
		else
		{	
			// rb pathology
			for(thread=0;thread<threadno;thread++) 
			{
				memset (output[thread], 0, nframes * sizeof (float));
				memset (output[thread], 0, nframes * sizeof (float));
			}
			return;
		}
		
		// if enough accumulated in ring, fire dsp
		if ((ringb_float_read_space (top[2].jack.ring.i.l) >= top[2].hold.size.frames) &&
			(ringb_float_read_space (top[2].jack.ring.i.r) >= top[2].hold.size.frames))
			sem_post (&top[2].sync.buf.sem);

	} else
#endif
	for(thread=0; thread<threadno; thread++) 
	{
		int l=2*thread, r = 2*thread+1;
		if ((ringb_float_read_space (top[thread].jack.ring.o.l) >= nframes)
			&& (ringb_float_read_space (top[thread].jack.ring.o.r) >= nframes))
		{
			/*ringb_float_read (top[thread].jack.auxr.o.l, output[l], nframes);
			ringb_float_read (top[thread].jack.auxr.o.r, output[r], nframes);*/
			ringb_float_read (top[thread].jack.ring.o.l, output[l], nframes);
			ringb_float_read (top[thread].jack.ring.o.r, output[r], nframes);
		}
		else
		{	
			// rb pathology
			//reset_system_audio(nframes);
			for(thread=0;thread<threadno;thread++) 
			{
				memset (output[2*thread  ], 0, nframes * sizeof (float));
				memset (output[2*thread+1], 0, nframes * sizeof (float));
			}
			return;
		}

		// input: copy from port to ring
		if ((ringb_float_write_space (top[thread].jack.ring.i.l) >= nframes)
			&& (ringb_float_write_space (top[thread].jack.ring.i.r) >= nframes))
		{
			if (diversity.flag && (thread == 0)) {
				if ((ringb_float_write_space (top[2].jack.ring.i.l) >= nframes)
					&& (ringb_float_write_space (top[2].jack.ring.i.r) >= nframes))
				{
					REAL *l0 = input[0];
					REAL *r0 = input[1];
					REAL *l2 = input[4];
					REAL *r2 = input[5];
					for (i=0;i<nframes;i++) {
						COMPLEX A = Cmplx(l0[i],r0[i]);
						COMPLEX B = Cmplx(l2[i],r2[i]);
						A = Cscl(Cadd(A,Cmul(B,diversity.scalar)),diversity.gain);
						ringb_float_write (top[0].jack.ring.i.l, &A.re, 1);
						ringb_float_write (top[0].jack.ring.i.r, &A.im, 1);
					}
					/*ringb_float_write (top[thread].jack.auxr.i.l, input[l], nframes);
					ringb_float_write (top[thread].jack.auxr.i.r, input[r], nframes);*/
				} else {
					// rb pathology
					//reset_system_audio(nframes);
					for(thread=0;thread<threadno;thread++) 
					{
						memset (output[2*thread  ], 0, nframes * sizeof (float));
						memset (output[2*thread+1], 0, nframes * sizeof (float));
					}
					return;
				}
			} else {
				ringb_float_write (top[thread].jack.ring.i.l, input[l], nframes);
				ringb_float_write (top[thread].jack.ring.i.r, input[r], nframes);
				/*ringb_float_write (top[thread].jack.auxr.i.l, input[l], nframes);
				ringb_float_write (top[thread].jack.auxr.i.r, input[r], nframes);*/
			}
		}
		else
		{	
			// rb pathology
			//reset_system_audio(nframes);
			for(thread=0;thread<threadno;thread++) 
			{
				memset (output[2*thread  ], 0, nframes * sizeof (float));
				memset (output[2*thread+1], 0, nframes * sizeof (float));
			}
			return;
		}
		
		// if enough accumulated in ring, fire dsp
		if ((ringb_float_read_space (top[thread].jack.ring.i.l) >= top[thread].hold.size.frames) &&
			(ringb_float_read_space (top[thread].jack.ring.i.r) >= top[thread].hold.size.frames))
			sem_post (&top[thread].sync.buf.sem);
	}
}