Copyright (C) Kevin Larke 2009-2020

This file is part of libcm.

libcm is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

libcm is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

See the GNU General Public License distributed with the libcm package or look here: .


cmApBufTest() demonstrates the audio buffer usage.



void cmApBufTest( cmRpt_t* rpt )
{
  unsigned devIdx         = 0;
  unsigned devCnt         = 1 ;
  unsigned dspFrameCnt    = 10;
  unsigned cycleCnt       = 3;
  unsigned framesPerCycle = 25;
  unsigned inChCnt        = 2;
  unsigned outChCnt       = inChCnt;
  unsigned sigN           = cycleCnt*framesPerCycle*inChCnt;
  double   srate          = 44100.0;
  unsigned meterMs        = 50;
  int      srateMult      = 1;
  
  unsigned          bufChCnt= inChCnt;
  cmApSample_t*     inBufArray[ bufChCnt ];
  cmApSample_t*     outBufArray[ bufChCnt ];
  cmApSample_t      iSig[ sigN ];
  cmApSample_t      oSig[ sigN ];
  cmApSample_t*     os = oSig;
  cmApAudioPacket_t pkt;
  int        i,j;
  
  // create a simulated signal
  for(i=0; i<sigN; ++i)
  {
    iSig[i]   = i;
    oSig[i] = 0;
  }
  
  pkt.devIdx         = 0;
  pkt.begChIdx       = 0;
  pkt.chCnt          = inChCnt;
  pkt.audioFramesCnt = framesPerCycle;
  pkt.bitsPerSample  = 32;
  pkt.flags          = 0;
  
  
  // initialize a the audio buffer 
  cmApBufInitialize(devCnt,meterMs);
  
  // setup the buffer with the specific parameters to by used by the host audio ports
  cmApBufSetup(devIdx,srate,dspFrameCnt,cycleCnt,inChCnt,framesPerCycle,outChCnt,framesPerCycle, srateMult);
  
  // simulate cylcing through sigN buffer transactions
  for(i=0; i<sigN; i+=framesPerCycle*inChCnt)
  {
    // setup an incoming audio packet
    pkt.audioFramesCnt = framesPerCycle;
    pkt.audioBytesPtr  = iSig+i;
    
    // simulate a call from the audio port with incoming samples 
    // (fill the audio buffers internal input buffers)    
    cmApBufUpdate(&pkt,1,NULL,0);
    
    // if all devices need to be serviced
    while( cmApBufIsDeviceReady( devIdx, kInApFl | kOutApFl ))
    {
      // get pointers to full internal input buffers
      cmApBufGet(devIdx, kInApFl, inBufArray, bufChCnt );
      
      // get pointers to empty internal output buffers
      cmApBufGet(devIdx, kOutApFl, outBufArray, bufChCnt );
      
      // Warning: pointers to disabled channels will be set to NULL.
      
      // simulate a play through by copying the incoming samples to the outgoing buffers.
      for(j=0; j<bufChCnt; ++j)
        if( outBufArray[j] != NULL )
      {
        // if the input is disabled - but the output is not then zero the output buffer
        if( inBufArray[j] == NULL )
          memset( outBufArray[j], 0, dspFrameCnt*sizeof(cmApSample_t));
        else
          // copy the input to the output
        memcpy( outBufArray[j], inBufArray[j], dspFrameCnt*sizeof(cmApSample_t));
      }
      
      // signal the buffer that this cycle is complete.
      // (marks current internal input/output buffer empty/full)      
      cmApBufAdvance( devIdx, kInApFl | kOutApFl );
    }
    
    pkt.audioBytesPtr = os;
    
    // simulate a call from the audio port picking up outgoing samples
    // (empties the audio buffers internal output buffers)    
    cmApBufUpdate(NULL,0,&pkt,1);
    
    os += pkt.audioFramesCnt * pkt.chCnt;
  }
  
  for(i=0; i<sigN; ++i)
    cmRptPrintf(rpt,"%f ",oSig[i]);
  cmRptPrintf(rpt,"\n");
  
  cmApBufFinalize();
}