1 Reply Latest reply on Feb 4, 2020 3:05 PM by JoBr_1593366

    Meaning of macros in USB_audio example

    JoBr_1593366

      I've tracked down a USB audio problem to the macros that set the sizes of different buffers, etc.  Can you clarify the meanings of each variable just to make sure I'm understanding what they're for?

       

      I'll use CY8CKIT_046_USB_audio for example:

       

      #define NUM_TDS 8
      #define OUT_TRANS_SIZE 144
      #define OUT_BUFSIZE (OUT_TRANS_SIZE*NUM_TDS)
      #define OUT_HALF (OUT_BUFSIZE/2)
      #define IN_TRANS_SIZE 144
      #define IN_BUFSIZE (IN_TRANS_SIZE*NUM_TDS)
      #define IN_HALF (IN_BUFSIZE/2)
      #define AUDIOMAXPKT (IN_BUFSIZE/4)
      #define MAX_AUDIO_SAMPLE_SIZE                6    
      #define IN_AUDIOMAXPKT  (AUDIOMAXPKT + MAX_AUDIO_SAMPLE_SIZE)
      #define OUT_AUDIOMAXPKT (AUDIOMAXPKT + MAX_AUDIO_SAMPLE_SIZE)
      

       

      I know IN/OUT_TRANS_SIZE is related to the sample rate and bit depth and number of channels, but it's not the actual packet size?

      In this example, the data is 2 channels, 24 bits, 48 kHz, so ideal total rate of 288 B per frame.  Why is IN/OUT_TRANS_SIZE half of this?

       

      NUM_TDS = number of TDs = Transaction Descriptors?  I don't know what this stands for, and there's no documentation about it.  It's related to the number of USB packets that can be stored in the circular buffer?  But not directly?

       

      IN/OUT_AUDIOMAXPKT is the actual maxpacketsize in the USB descriptors, and the maximum that can be sent when asynchronous mode adds a sample to keep up with clock drift.  So this is also the size of inRam and outRam that hold the latest packet, automatically filled from DMA as they are received.

      So those should be 48000/1000*2*24/8 + 2*24/8 = 294 B per frame (and they are).  (Good description of calculation rules is here: https://developer.apple.com/library/archive/technotes/tn2274/_index.html#//apple_ref/doc/uid/DTS40010116-CH1-TNTAG4_2)

       

      But then what is AUDIOMAXPKT?  The ideal packet size at maximum FS but without an extra sample added?  But this should be different for IN and OUT, if the IN and OUT sample rates or bit depths or channels differ, right?

      It's used to:

      • To detect OUT circular buffer filling too fast, so that feedback endpoint can tell Host to slow down. (I don't think this value is critical. It could vary by 1 sample and still work fine?)
      • Initial value of inCnt when enumerated?  (But later it is set to IN_AUDIOMAXPKT initial value when Alt setting changes.  Is one correct and the other a mistake?)
      • Clear inRam and outRam.  (But these are actually IN/OUT_AUDIOMAXPKT in size, so they can handle the variable packet size. They are not AUDIOMAXPKT in size.)
      • Also clears inRam in HandleAudioInBuffer, which also seems like the wrong size
      • Detect underflow of OUT

       

      In other words:

      for(index=0; index< AUDIOMAXPKT; index++)
      {
          outRam[index] = 0;
          inRam[index] = 0;                
      }    
      

       

      if AUDIOMAXPKT is 288, this will clear bytes 0 through 287, but inRam and outRam are both 294 bytes long, so they are not fully cleared?

       

      Then the same issue in HandleAudioInBuffer:

      for (i=0; i < sizeof(inBuffer); i++)
      {
          if(i < AUDIOMAXPKT)
          {
              inRam[i] = 0;
          }
          inBuffer[i] = 0;
      }
      

       

      Maybe instead of MAXPKT this should be called IDEALPKT or NOMINALPKT or something?  Since it's the ideal packet size if both Host and Device clocks had exactly the same frequency and never needed to adjust each other?

        • 1. Re: Meaning of macros in USB_audio example
          JoBr_1593366

          I think I understand most of the variables and buffers on the output side now.  I'm guessing that NUM_TDS and TRANS_SIZE are holdovers from an earlier implementation, because in the implementation I have they don't seem especially critical.  outBuffer is set to about 4 times the max packet size coming in, and the I2S just reads the whole thing.  Then TRANS_SIZE just divides that buffer into 8 equal chunks, and whenever it reads past one of those points, it re-calculates outLevel and checks for overflow or underflow.  I think it could probably be twice or half the size and still work?