コード例 #1
0
ファイル: main.cpp プロジェクト: JamesDunne/live-mixer
// Main audio processing callback.
// NOTE: Called on a separate thread from main() thread.
ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processNow)
{
    // Buffer size (in samples):
    long buffSize = drv.preferredSize;

    // Assume the buffer size is an even multiple of 32-bytes:
    assert((buffSize % sizeof(vec4_d64)) == 0);

    for (long i = 0; i < buffSize; ++i)
    {
        assert(index == 0 || index == 1);

        // Process 8 channels of 32-bit samples per iteration:
        for (long n = 0; n < inputChannels / 8; ++n)
        {
            const long ci = n * 8;
            const long co = drv.inputBuffers + ci;

            // Stripe input samples into a vector:
            const vec8_i32 inpSamples = _mm256_setr_epi32(
                ((long *)drv.bufferInfos[ci + 0].buffers[index])[i],
                ((long *)drv.bufferInfos[ci + 1].buffers[index])[i],
                ((long *)drv.bufferInfos[ci + 2].buffers[index])[i],
                ((long *)drv.bufferInfos[ci + 3].buffers[index])[i],
                ((long *)drv.bufferInfos[ci + 4].buffers[index])[i],
                ((long *)drv.bufferInfos[ci + 5].buffers[index])[i],
                ((long *)drv.bufferInfos[ci + 6].buffers[index])[i],
                ((long *)drv.bufferInfos[ci + 7].buffers[index])[i]
            );

            // Process audio effects:
            vec8_i32 outSamples;
            processEffects(inpSamples, outSamples, n * 2);
            // Copy outputs to output channel buffers:
            const long *outputs32 = (const long *)&outSamples;
            ((long *)drv.bufferInfos[co + 0].buffers[index])[i] = outputs32[0];
            ((long *)drv.bufferInfos[co + 1].buffers[index])[i] = outputs32[1];
            ((long *)drv.bufferInfos[co + 2].buffers[index])[i] = outputs32[2];
            ((long *)drv.bufferInfos[co + 3].buffers[index])[i] = outputs32[3];
            ((long *)drv.bufferInfos[co + 4].buffers[index])[i] = outputs32[4];
            ((long *)drv.bufferInfos[co + 5].buffers[index])[i] = outputs32[5];
            ((long *)drv.bufferInfos[co + 6].buffers[index])[i] = outputs32[6];
            ((long *)drv.bufferInfos[co + 7].buffers[index])[i] = outputs32[7];
        }
    }

    if (drv.postOutput)
        ASIOOutputReady();

    return 0L;
}
コード例 #2
0
//----------------------------------------------------------------------------------
long init_asio_static_data (DriverInfo *asioDriverInfo)
{	// collect the informational data of the driver
	// get the number of available channels
	if(ASIOGetChannels(&asioDriverInfo->inputChannels, &asioDriverInfo->outputChannels) == ASE_OK)
	{
		printf ("ASIOGetChannels (inputs: %d, outputs: %d);\n", asioDriverInfo->inputChannels, asioDriverInfo->outputChannels);

		// get the usable buffer sizes
		if(ASIOGetBufferSize(&asioDriverInfo->minSize, &asioDriverInfo->maxSize, &asioDriverInfo->preferredSize, &asioDriverInfo->granularity) == ASE_OK)
		{
			printf ("ASIOGetBufferSize (min: %d, max: %d, preferred: %d, granularity: %d);\n",
					 asioDriverInfo->minSize, asioDriverInfo->maxSize,
					 asioDriverInfo->preferredSize, asioDriverInfo->granularity);

			// get the currently selected sample rate
			if(ASIOGetSampleRate(&asioDriverInfo->sampleRate) == ASE_OK)
			{
				printf ("ASIOGetSampleRate (sampleRate: %f);\n", asioDriverInfo->sampleRate);
				if (asioDriverInfo->sampleRate <= 0.0 || asioDriverInfo->sampleRate > 96000.0)
				{
					// Driver does not store it's internal sample rate, so set it to a know one.
					// Usually you should check beforehand, that the selected sample rate is valid
					// with ASIOCanSampleRate().
					if(ASIOSetSampleRate(44100.0) == ASE_OK)
					{
						if(ASIOGetSampleRate(&asioDriverInfo->sampleRate) == ASE_OK)
							printf ("ASIOGetSampleRate (sampleRate: %f);\n", asioDriverInfo->sampleRate);
						else
							return -6;
					}
					else
						return -5;
				}

				// check wether the driver requires the ASIOOutputReady() optimization
				// (can be used by the driver to reduce output latency by one block)
				if(ASIOOutputReady() == ASE_OK)
					asioDriverInfo->postOutput = true;
				else
					asioDriverInfo->postOutput = false;
				printf ("ASIOOutputReady(); - %s\n", asioDriverInfo->postOutput ? "Supported" : "Not supported");

				return 0;
			}
			return -3;
		}
		return -2;
	}
	return -1;
}
コード例 #3
0
ファイル: JAsioHost.cpp プロジェクト: chummer/jasiohost
// from ASIOv2
ASIOTime* bufferSwitchTimeInfo(ASIOTime* asioTime, long bufferIndex, ASIOBool directProcess) {
  JNIEnv *env = NULL;
  jint res = jvm->AttachCurrentThreadAsDaemon((void **) &env, NULL);
  if (res == JNI_OK && env != NULL) {
    env->CallVoidMethod(
        jAsioDriver,
        fireBufferSwitchMid,
        (jlong) ASIO64toLong(asioTime->timeInfo.systemTime),
        (jlong) ASIO64toLong(asioTime->timeInfo.samplePosition),
        (jint) bufferIndex);
  }
  
  ASIOOutputReady();
  
  return asioTime;
}
コード例 #4
0
ファイル: SndASIO.cpp プロジェクト: dskinner/sndobj
SndASIO::SndASIO(int channels, int mode, char* driver, int numbuffs, 
		 SndObj** inputs, 
		 int vecsize, float sr) : 
  SndIO(channels,16,inputs,vecsize, sr){

  int i;
  m_numbuffs = numbuffs;
  m_mode = mode;
  m_running = false;
  m_driver = driver;
  m_ocurrentbuffer = m_icurrentbuffer = 1;
  m_icount = m_ocount = 0; 

  memset(&m_driverinfo, 0, sizeof(ASIODriverInfo));

  m_asiocallbacks.bufferSwitch = &bufferSwitch;
  m_asiocallbacks.sampleRateDidChange = &sampleRateChanged;
  m_asiocallbacks.asioMessage = &asioMessages;
  m_asiocallbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfo;

  // Allocate the memory for BufferInfos
  if(!(bufferinfos = new ASIOBufferInfo[(m_channels+2)*2])){
    m_error = 21;
    return;
  }


  if(!asioDrivers) asioDrivers = new AsioDrivers;

  if(asioDrivers->loadDriver(m_driver)){

    if(ASIOInit(&m_driverinfo) == ASE_OK){

      if(ASIOCanSampleRate(m_sr) == ASE_OK) 
	ASIOSetSampleRate(m_sr);
      else ASIOGetSampleRate((double *)&m_sr);
      // set buffer size
      long dump1, dump2, dump3;
      ASIOGetBufferSize(&dump1, &dump2, &buffsize, &dump3);
   
      // get number of channels
      ASIOGetChannels(&ichannels, &ochannels);
      if(ichannels < m_channels){
	m_channels = (short) ichannels;
	m_samples = m_vecsize*m_channels;
      }
      else ichannels = m_channels;
      if(ochannels < m_channels){
	m_channels = (short) ochannels;
	m_samples = m_vecsize*m_channels;
      }
      else ochannels = m_channels;
   
      if(m_mode == SND_OUTPUT) ichannels = 0;
      if(m_mode == SND_INPUT) ochannels = 0;
       
  
      // Set the channel infos
      if(!(m_channelinfos = new ASIOChannelInfo[m_channels*2])){
	m_error = 22;
	return;
      }
      
      if((m_mode == SND_IO) || (m_mode == SND_OUTPUT)){           
	outsndbuff = new float*[m_numbuffs];    
   
	for(i = 0; i< m_numbuffs; i++){
	  if(!(outsndbuff[i] = new float[buffsize*m_channels])){
	    m_error =14;
	    return;
	  }
	}

	for(i = 0; i < m_channels; i++){	
	  bufferinfos[i].isInput = ASIOFalse;
	  bufferinfos[i].channelNum = i;
	  bufferinfos[i].buffers[0] =
	    bufferinfos[i].buffers[1] = 0;

	  m_channelinfos[i].channel = bufferinfos[i].channelNum;
	  m_channelinfos[i].isInput = bufferinfos[i].isInput;

	  ASIOGetChannelInfo(&m_channelinfos[i]);

  
	  switch(m_channelinfos[i].type){

	  case ASIOSTInt16LSB:
	    encoding = SHORTSAM;
	    m_bits = 16;
	    break;

	  case ASIOSTInt24LSB:
	    encoding = S24LE;
	    m_bits = 24;
	    break;

	  case ASIOSTInt32LSB:
	    encoding = LONGSAM;
	    m_bits = 32;
	    break;

	  default:
	    encoding = SHORTSAM;
	    break;

	  }
	} 
      }
 	 
      if((m_mode == SND_IO) || (m_mode == SND_INPUT)){
	insndbuff = new float*[m_numbuffs];    
   
	for(i = 0; i< m_numbuffs; i++){
	  if(!(insndbuff[i] = new float[buffsize*m_channels])){
	    m_error =14;
	    return;
	  }
	}
   
	for(i = 0; i < m_channels; i++){
	  bufferinfos[i+ochannels].isInput = ASIOTrue;
	  bufferinfos[i+ochannels].channelNum = i;
	  bufferinfos[i+ochannels].buffers[0] =
	    bufferinfos[i+ochannels].buffers[1] = 0;

	  m_channelinfos[i+ochannels].channel = bufferinfos[i+ochannels].channelNum;
	  m_channelinfos[i+ochannels].isInput = bufferinfos[i+ochannels].isInput;
 
	  ASIOGetChannelInfo(&m_channelinfos[i+ochannels]);
     
	  switch(m_channelinfos[i+ochannels].type){

	  case ASIOSTInt16LSB:
	    encoding = SHORTSAM;
	    m_bits = 16;
	    break;

	  case ASIOSTInt24LSB:
	    encoding = S24LE;
	    m_bits = 24;
	    break;

	  case ASIOSTInt32LSB:
	    encoding = LONGSAM;
	    m_bits = 32;
	    break;

	  default:
	    encoding = SHORTSAM;
	    break;

	  }

	}
      }

      if(!(ASIOCreateBuffers(bufferinfos, ichannels+ochannels, 
			     buffsize, &m_asiocallbacks)== ASE_OK)){
	m_error = 25;
	return;
      }

    
      if(ASIOOutputReady() == ASE_OK) optimise = true;
      else optimise = false;
      // printf("channels: %d\n", m_channels);
      m_outsndbuff = outsndbuff;
      m_insndbuff = insndbuff;
      m_encoding = encoding;
      m_bufferinfos = bufferinfos;
      m_ichannels = ichannels;
      m_ochannels  = ochannels;
      m_buffsize = buffsize;
      currentbuffer = 0;
      m_called_read = false;
      buffs = m_numbuffs;
  
    } 
    else { // could not initialise
      m_error = 24;
      return;
    }
  }   
  else { // if driver could not be loaded

    m_error = 23;
    return;

  }
#ifdef DEBUG
  cout << m_bits;
#endif
}
コード例 #5
0
ファイル: SndASIO.cpp プロジェクト: dskinner/sndobj
ASIOTime*
bufferSwitchTimeInfo(ASIOTime *timeInfo,
		     long index, ASIOBool processNow){

  short* sigshort;
  long* siglong;
  _24Bit* sig24;
  int n,j;
 
  // we do the channel interleaving here

  for(int i = 0; i < ichannels+ochannels; i++){
    if(bufferinfos[i].isInput == ASIOFalse){
      //  while(ocurrentbuffer == currentbuffer) {
      //	  Sleep(1); 
      // }


      switch(encoding){

      case SHORTSAM:
	sigshort = (short *)bufferinfos[i].buffers[index];
	for(n = bufferinfos[i].channelNum, j = 0; 
	    n < buffsize*ochannels; n+=ochannels, j++){
	  sigshort[j] = (short) outsndbuff[currentbuffer][n];
	}
	break;
        
      case S24LE:
	union { char c[4]; long l;} tmp;
	sig24 = (_24Bit *)bufferinfos[i].buffers[index];
	for(n = bufferinfos[i].channelNum, j = 0; 
	    n < buffsize*ochannels; n+=ochannels, j++){
	  tmp.l = (long) outsndbuff[currentbuffer][n];
	  sig24[j].s[0] = tmp.c[1];
	  sig24[j].s[1] = tmp.c[2];
	  sig24[j].s[2] = tmp.c[3];
	}
	break;
 
      case LONGSAM:
	siglong = (long *)bufferinfos[i].buffers[index];
	for(n = bufferinfos[i].channelNum, j = 0; 
	    n < buffsize*ochannels; n+=ochannels, j++)
	  siglong[j] = (long) outsndbuff[currentbuffer][n];
	break;

      }

    }
    else{ 

 
      switch(encoding){
   
      case SHORTSAM:
	sigshort = (short *)bufferinfos[i].buffers[index];
	for(n = bufferinfos[i].channelNum, j = 0; 
	    n < buffsize*ichannels; n+=ichannels, j++)
	  insndbuff[currentbuffer][n] = (float) sigshort[j];
		  
	break;
    
      case S24LE:
	char tmp[4];
	sig24 = (_24Bit *)bufferinfos[i].buffers[index];
	for(n = bufferinfos[i].channelNum, j = 0; 
	    n < buffsize*ichannels; n+=ichannels, j++) {
	  tmp[1] = sig24[j].s[0];
	  tmp[2] = sig24[j].s[1];
	  tmp[3] = sig24[j].s[2];
	  tmp[0] = 0;
	  insndbuff[currentbuffer][n] = (float)(*(long *)tmp);
	}
	break;
        
      case LONGSAM:
	siglong = (long *)bufferinfos[i].buffers[index];
	for(n = bufferinfos[i].channelNum, j = 0; 
	    n < buffsize*ichannels; n+=ichannels, j++)
	  insndbuff[currentbuffer][n] = (float) siglong[j];
	break;
      }  
    }

  }
 
  if(optimise)ASIOOutputReady();
  memset(outsndbuff[currentbuffer], 0, sizeof(float)*buffsize*ochannels);	
  currentbuffer= (currentbuffer+1)%buffs;
  return timeInfo;

}
コード例 #6
0
ファイル: main.cpp プロジェクト: JamesDunne/live-mixer
// Main:
int main()
{
    int retval = 0;
    bool inited = false, buffersCreated = false, started = false;
    char *error = NULL;

    drv.sampleRate = 44100.0;

    // Initialize FX parameters:
    fx.f0_gain.init();
    fx.f1_compressor.init();

    // Set our own inputs:
    for (int i = 0; i < icr; ++i)
    {
        fx.f0_gain.input.gain[i] = _mm256_set1_pd(0);   // dB

        fx.f1_compressor.input.threshold[i] = _mm256_set1_pd(-30);  // dBFS
        fx.f1_compressor.input.attack[i]    = _mm256_set1_pd(1.0);  // msec
        fx.f1_compressor.input.release[i]   = _mm256_set1_pd(80);   // msec
        fx.f1_compressor.input.ratio[i]     = _mm256_set1_pd(0.25); // N:1
        fx.f1_compressor.input.gain[i]      = _mm256_set1_pd(6);    // dB
    }

    // Calculate input-dependent values:
    fx.f0_gain.recalc();
    fx.f1_compressor.recalc();

    // FX parameters are all set.

#ifdef NOT_LIVE
    // Test mode:

#if 0
    const auto t0 = mm256_if_then_else(_mm256_cmp_pd(_mm256_set1_pd(-1.0), _mm256_set1_pd(0.0), _CMP_LT_OQ), _mm256_set1_pd(0.0), _mm256_set1_pd(-1.0));
    printvec_dB(t0);
    printf("\n\n");
    const auto p0 = mm256_if_then_else(_mm256_cmp_pd(_mm256_set1_pd(-1.0), _mm256_set1_pd(0.0), _CMP_LT_OQ), _mm256_set1_pd(0.0), _mm256_set1_pd(1.0));
    printvec_dB(t0);
    printf("\n\n");
    const auto t1 = mm256_if_then_else(_mm256_cmp_pd(_mm256_set1_pd(0.0), _mm256_set1_pd(0.0), _CMP_LT_OQ), _mm256_set1_pd(0.0), _mm256_set1_pd(-1.0));
    printvec_dB(t1);
    printf("\n\n");
    const auto p1 = mm256_if_then_else(_mm256_cmp_pd(_mm256_set1_pd(0.0), _mm256_set1_pd(0.0), _CMP_LT_OQ), _mm256_set1_pd(0.0), _mm256_set1_pd(1.0));
    printvec_dB(t1);
    printf("\n\n");
    goto done;
#endif

    vec8_i32 in, out;
    long long c = 0LL;
    for (int i = 0; i < 20; ++i)
    {
        for (int n = 0; n < 48; ++n, ++c)
        {
            double s = sin(2.0 * 3.14159265358979323846 * (double)c / drv.sampleRate);
            int si = (int)(s * INT_MAX / 2);

            in = _mm256_set1_epi32(si);

            processEffects(in, out, 0);
        }

#if 1
        printf("samp:   ");
        printvec_samp(in);
        printf("\n");

        printf("input:  ");
        for (int n = 0; n < icr; ++n)
        {
            printvec_dB(fx.fi_monitor.levels[n]);
            if (n < icr - 1) printf(" ");
        }
        printf("\n");

        printf("gain:   ");
        for (int n = 0; n < icr; ++n)
        {
            printvec_dB(fx.f0_output.levels[n]);
            if (n < icr - 1) printf(" ");
        }
        printf("\n");

        printf("comp:   ");
        for (int n = 0; n < icr; ++n)
        {
            printvec_dB(fx.fo_monitor.levels[n]);
            if (n < icr - 1) printf(" ");
        }
        printf("\n");

        printf("samp:   ");
        printvec_samp(out);
        printf("\n\n");
#endif
    }
#else
    // ASIO live engine mode:
    if (!loadAsioDriver("UA-1000"))
    {
        error = "load failed.";
        goto err;
    }

    if (ASIOInit(&drv.driver) != ASE_OK)
        goto err;

    inited = true;

    if (ASIOGetChannels(&drv.inputChannels, &drv.outputChannels) != ASE_OK)
        goto err;

    printf("in: %d, out %d\n", drv.inputChannels, drv.outputChannels);

    if (ASIOGetBufferSize(&drv.minSize, &drv.maxSize, &drv.preferredSize, &drv.granularity) != ASE_OK)
        goto err;

    printf("min buf size: %d, preferred: %d, max buf size: %d\n", drv.minSize, drv.preferredSize, drv.maxSize);

    if (ASIOGetSampleRate(&drv.sampleRate) != ASE_OK)
        goto err;

    printf("rate: %f\n\n", drv.sampleRate);

    if (ASIOOutputReady() == ASE_OK)
        drv.postOutput = true;
    else
        drv.postOutput = false;

    // fill the bufferInfos from the start without a gap
    ASIOBufferInfo *info = drv.bufferInfos;

    // prepare inputs (Though this is not necessarily required, no opened inputs will work, too
    if (drv.inputChannels > kMaxInputChannels)
        drv.inputBuffers = kMaxInputChannels;
    else
        drv.inputBuffers = drv.inputChannels;
    for (int i = 0; i < drv.inputBuffers; i++, info++)
    {
        info->isInput = ASIOTrue;
        info->channelNum = i;
        info->buffers[0] = info->buffers[1] = 0;
    }

    // prepare outputs
    if (drv.outputChannels > kMaxOutputChannels)
        drv.outputBuffers = kMaxOutputChannels;
    else
        drv.outputBuffers = drv.outputChannels;
    for (int i = 0; i < drv.outputBuffers; i++, info++)
    {
        info->isInput = ASIOFalse;
        info->channelNum = i;
        info->buffers[0] = info->buffers[1] = 0;
    }

    asioCallbacks.asioMessage = asioMessage;
    asioCallbacks.bufferSwitch = bufferSwitch;
    asioCallbacks.bufferSwitchTimeInfo = bufferSwitchTimeInfo;

    // Create the buffers:
    if (ASIOCreateBuffers(drv.bufferInfos, drv.inputBuffers + drv.outputBuffers, drv.preferredSize, &asioCallbacks) != ASE_OK)
        goto err;
    else
        buffersCreated = true;

    // now get all the buffer details, sample word length, name, word clock group and activation
    for (int i = 0; i < drv.inputBuffers + drv.outputBuffers; i++)
    {
        drv.channelInfos[i].channel = drv.bufferInfos[i].channelNum;
        drv.channelInfos[i].isInput = drv.bufferInfos[i].isInput;
        if (ASIOGetChannelInfo(&drv.channelInfos[i]) != ASE_OK)
            goto err;

        //printf("%s[%2d].type = %d\n", drv.channelInfos[i].isInput ? "in " : "out", drv.channelInfos[i].channel, drv.channelInfos[i].type);
        if (drv.channelInfos[i].type != ASIOSTInt32LSB)
        {
            error = "Application assumes sample types of ASIOSTInt32LSB!";
            goto err;
        }
    }

    // get the input and output latencies
    // Latencies often are only valid after ASIOCreateBuffers()
    // (input latency is the age of the first sample in the currently returned audio block)
    // (output latency is the time the first sample in the currently returned audio block requires to get to the output)
    if (ASIOGetLatencies(&drv.inputLatency, &drv.outputLatency) != ASE_OK)
        goto err;

    printf ("latencies: input: %d, output: %d\n", drv.inputLatency, drv.outputLatency);

    // Start the engine:
    if (ASIOStart() != ASE_OK)
        goto err;
    else
        started = true;

    printf("Engine started.\n\n");
    const int total_time = 30;
    for (int i = 0; i < total_time; ++i)
    {
        printf("Engine running %2d.   \r", total_time - i);
        Sleep(1000);
    }
#endif

    goto done;

err:
    if (error == NULL)
        error = drv.driver.errorMessage;

    if (error != NULL)
        fprintf(stderr, "%s\r\n", error);

    retval = -1;

done:
    if (started)
        ASIOStop();
    if (buffersCreated)
        ASIODisposeBuffers();
    if (inited)
        ASIOExit();
    return retval;
}
コード例 #7
0
ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processNow)
{	// the actual processing callback.
	// Beware that this is normally in a seperate thread, hence be sure that you take care
	// about thread synchronization. This is omitted here for simplicity.
	static long processedSamples = 0;

	// store the timeInfo for later use
	asioDriverInfo.tInfo = *timeInfo;

	// get the time stamp of the buffer, not necessary if no
	// synchronization to other media is required
	if (timeInfo->timeInfo.flags & kSystemTimeValid)
		asioDriverInfo.nanoSeconds = ASIO64toNanoSeconds(timeInfo->timeInfo.systemTime);
	else
		asioDriverInfo.nanoSeconds = 0;

	if (timeInfo->timeInfo.flags & kSamplePositionValid)
		asioDriverInfo.samples = ASIO64toNanoSeconds(timeInfo->timeInfo.samplePosition);
	else
		asioDriverInfo.samples = 0;

	if (timeInfo->timeCode.flags & kTcValid)
		asioDriverInfo.tcSamples = ASIO64toNanoSeconds(timeInfo->timeCode.timeCodeSamples);
	else
		asioDriverInfo.tcSamples = 0;

	// get the system reference time
	asioDriverInfo.sysRefTime = get_sys_reference_time();

#if WINDOWS && _DEBUG
	// a few debug messages for the Windows device driver developer
	// tells you the time when driver got its interrupt and the delay until the app receives
	// the event notification.
	static double last_samples = 0;
	char tmp[128];
	sprintf (tmp, "diff: %d / %d ms / %d ms / %d samples                 \n", asioDriverInfo.sysRefTime - (long)(asioDriverInfo.nanoSeconds / 1000000.0), asioDriverInfo.sysRefTime, (long)(asioDriverInfo.nanoSeconds / 1000000.0), (long)(asioDriverInfo.samples - last_samples));
	OutputDebugString (tmp);
	last_samples = asioDriverInfo.samples;
#endif

	// buffer size in samples
	long buffSize = asioDriverInfo.preferredSize;

	// perform the processing
	for (int i = 0; i < asioDriverInfo.inputBuffers + asioDriverInfo.outputBuffers; i++)
	{
		if (asioDriverInfo.bufferInfos[i].isInput == true)
		{
			in_counter++;
			std::unique_ptr<ah::GenericBuffer> gbuff = ah::NewGenericBufferFromASIO_Sample_T(
				asioDriverInfo.bufferInfos[i].buffers[index],asioDriverInfo.channelInfos[i].type);
			int inbuf_ind;
			int n = buffSize/gbuff->SampleSize();
			sum=0;
			for (inbuf_ind = 0 ; inbuf_ind < n ; inbuf_ind++ )
			{
				int this_elem = *gbuff->GetElement(inbuf_ind);
				sum += this_elem*this_elem;
			}
			//fprintf(stdout,"%d",sum);
		}
		else
		{
			out_counter++;
			// OK do processing for the outputs only
			switch (asioDriverInfo.channelInfos[i].type)
			{
			case ASIOSTInt16LSB:
				memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 2);
				break;
			case ASIOSTInt24LSB:		// used for 20 bits as well
				memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 3);
				break;
			case ASIOSTInt32LSB:
				memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
				break;
			case ASIOSTFloat32LSB:		// IEEE 754 32 bit float, as found on Intel x86 architecture
				memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
				break;
			case ASIOSTFloat64LSB: 		// IEEE 754 64 bit double float, as found on Intel x86 architecture
				memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 8);
				break;

				// these are used for 32 bit data buffer, with different alignment of the data inside
				// 32 bit PCI bus systems can more easily used with these
			case ASIOSTInt32LSB16:		// 32 bit data with 18 bit alignment
			case ASIOSTInt32LSB18:		// 32 bit data with 18 bit alignment
			case ASIOSTInt32LSB20:		// 32 bit data with 20 bit alignment
			case ASIOSTInt32LSB24:		// 32 bit data with 24 bit alignment
				memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
				break;

			case ASIOSTInt16MSB:
				memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 2);
				break;
			case ASIOSTInt24MSB:		// used for 20 bits as well
				memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 3);
				break;
			case ASIOSTInt32MSB:
				memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
				break;
			case ASIOSTFloat32MSB:		// IEEE 754 32 bit float, as found on Intel x86 architecture
				memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
				break;
			case ASIOSTFloat64MSB: 		// IEEE 754 64 bit double float, as found on Intel x86 architecture
				memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 8);
				break;

				// these are used for 32 bit data buffer, with different alignment of the data inside
				// 32 bit PCI bus systems can more easily used with these
			case ASIOSTInt32MSB16:		// 32 bit data with 18 bit alignment
			case ASIOSTInt32MSB18:		// 32 bit data with 18 bit alignment
			case ASIOSTInt32MSB20:		// 32 bit data with 20 bit alignment
			case ASIOSTInt32MSB24:		// 32 bit data with 24 bit alignment
				memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4);
				break;
			}
		}
	}

	// finally if the driver supports the ASIOOutputReady() optimization, do it here, all data are in place
	if (asioDriverInfo.postOutput)
		ASIOOutputReady();

	if (processedSamples >= asioDriverInfo.sampleRate * TEST_RUN_TIME)	// roughly measured
		asioDriverInfo.stopped = true;
	else
		processedSamples += buffSize;
	return 0L;
}