48KHz USB Audio - K7MDL2/KEITHSDR GitHub Wiki

Jan 3, 2023 Update using IDE 2.0.3 and TeensyDuino 1.57.2 and 0.58.3 (aka 1.58 beta 3). Be sure to review Adding New USB Type into the Arduino 2.x Tools Menu to make this available on your PC.

The Teensy default audio sample rate and USB Audio rate is 44.1KHz.

I now have the Teensy USB Audio Sample Rate running at 48KHz and get clean audio on both TX and RX when I have the audio sample rate set to 48KHz. We want 48KHz for optimal connection to WSJT-X running on a PC, otherwise 44.1K is fine.

NOTE: as of 1/1/2023 I have confirmed there is a link between the audio sample rate and the usb sample rate. They MUST match or you get distorted USB audio.

Thanks to threads in the PJRC forum, the work of Steve KF7O, DL1YCF, and others creating a Teensy CW Keyer with low latency audio at 48KHz, I was able to get things working. It also works with the OpenAudio_Library F32 functions.

The CW Keyer code used AUDIO_BLOCK_SAMPLES 32 and has lots of code for on-the-fly feedback correction. I am not using either so left that code out to keep things simpler.

Be aware that TeensyDuino supplied files are overwritten with each package update or manual install of TeensyDuino. You must make these file changes each time after such and update. The files typically do not change much but you need to check.

I put the following 8 modified files (5 usb related, 1 AudioStream.h, 1 for Arduino IDE menu and 1 instructions) into the repository under the libraries/cores_IDE_2.0 folder. The instructions here are also contained in readme.txt

AudioStream.h
usb_desc.h
usb_desc.c
usb.c
usb_audio.h
usb_audio.c
readme.txt
boards.txt
  1. Find the TeensyDuino files

    For IDE 2.0.x go to C:\Users\Mike\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.57.2\cores\teensy4
    For IDE 1.8.x go to C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4
  2. Step removed.

  3. Find the lines

    #ifndef AUDIO_SAMPLE_RATE_EXACT
    #define AUDIO_SAMPLE_RATE_EXACT 48000.0f
    #endif
  4. Replace with

    #ifdef USB_AUDIO_48KHZ
       #define AUDIO_SAMPLE_RATE_EXACT 48000.0f
    #else
       #define AUDIO_SAMPLE_RATE_EXACT 44100.0f
    #endif
  5. AudioStream_F32.h already sets this to 48000 but if you do not enable the #define USB32 then the 16bit version will be active, needing this #define anyway.

  6. Edit usb_desc.h. Insert the below line at line 113 between the comment section and teh line #if defined(USB_SERIAL)

    #define USB_AUDIO_48KHZ 1
  7. Editing this file first will cause to the new #ifdef USB_AUDIO_48KHZ sections to be added next to light up if using an editor like Visual Studio Code making edits color coded, shaded, and error checking far easier to deal with.

  8. Edit usb_audio.h. Find the lines below around 390

    unsigned int usb_audio_transmit_callback(void)
    {
       static uint32_t count=5;
       uint32_t avail, num, target, offset, len=0;
       audio_block_t *left, *right;
       if (++count < 10) {   // TODO: dynamic adjust to match USB rate
          target = 44;
       } else {
          count = 0;
          target = 45;
       }
       ...
  9. Replace with these lines

    unsigned int usb_audio_transmit_callback(void)
    {
       uint32_t avail, num, target, offset, len=0;
       audio_block_t *left, *right;
       #ifdef USB_AUDIO_48KHZ
         target = 48;
       #else
         static uint32_t count=5;
         if (++count < 10) {   // TODO: dynamic adjust to match USB rate
            target = 44;
         } else {
            count = 0;
            target = 45;
         }
       #endif
       ...
  10. Edit usb_desc.c file.

    Search for "MICROPHONE".  You will find it in 2 places inside #ifdef AUDIO_INTERFACE sections.  The 3 lines for wTerminalType will look like below with the Digital Audio likely set.
      //0x01, 0x02,				// wTerminalType, 0x0201 = MICROPHONE
      //0x03, 0x06,				// wTerminalType, 0x0603 = Line Connector
      0x02, 0x06,				// wTerminalType, 0x0602 = Digital Audio
    Change the wTerminalType to something else like Line Connector to get Windows to recognize the change in the cached driver, or just present your
    preference.
      //0x01, 0x02,				// wTerminalType, 0x0201 = MICROPHONE
      0x03, 0x06,				// wTerminalType, 0x0603 = Line Connector
      //0x02, 0x06,				// wTerminalType, 0x0602 = Digital Audio
    Search for "Headphones".  You will find it in 2 places inside #ifdef AUDIO_INTERFACE sections
      //0x02, 0x03,				// wTerminalType, 0x0302 = Headphones
      0x02, 0x06,				// wTerminalType, 0x0602 = Digital Audio
    Change the wTerminalType from Digital Audio to Headphones to get Windows to recognize the change in the cached driver
      0x02, 0x03,				// wTerminalType, 0x0302 = Headphones
      //0x02, 0x06,				// wTerminalType, 0x0602 = Digital Audio
  11. Edit usb_desc.c file. Search for LSB(44100). You will find it in 4 places

    Replace
     LSB(44100), MSB(44100), 0,      // tSamFreq
    with
     #ifdef USB_AUDIO_48KHZ
       LSB(48000), MSB(48000), 0,      // tSamFreq
     #else
       LSB(44100), MSB(44100), 0,      // tSamFreq
     #endif
  12. Edit usb_desc.h. This updates the sample rate length for USB_MIDI_AUDIO_SERIAL and 3 other sections containing Audio.

    In the #elif defined(USB_XXXXXXX) sections
     replace
      #define AUDIO_TX_SIZE         180
      #define AUDIO_RX_SIZE         180
     with
      #ifdef USB_AUDIO_48KHZ
        #define AUDIO_TX_SIZE         196   // longer buffer
        #define AUDIO_RX_SIZE         196
      #else
        #define AUDIO_TX_SIZE         180
        #define AUDIO_RX_SIZE         180
      #endif
    Be careful to not delete or edit the  #define AUDIO_TX_ENDPOINT and #define AUDIO_RX_ENDPOINT lines, they are mixed in.
    The endpoint numbers are unique to each section so leave them as they are.  I grouped them as shown above.
  13. I chose to customize the Product Name to use my call sign. Each section contain a product name. Since we are only using USB_MIDI_AUDIO_SERIAL for this SDR project I chose to only edit this section replacing the MIDI/Audio name with my own string. #define PRODUCT_NAME {'K','7','M','D','L',' ','S','D','R'} #define PRODUCT_NAME_LEN 9

  14. Edit usb.c

    Search for 0x81A2 around line 662 and
    replace
       endpoint0_buffer[0] = 44100 & 255;
       endpoint0_buffer[1] = 44100 >> 8;
    with
       #ifdef USB_AUDIO_48KHZ
         endpoint0_buffer[0] = 48000 & 255;
         endpoint0_buffer[1] = 48000 >> 8;
       #else
         endpoint0_buffer[0] = 44100 & 255;
         endpoint0_buffer[1] = 44100 >> 8;
       #endif
  15. See Adding New USB Type into the Arduino 2.x Tools Menu to make the USB device propely appear on your PC. Program the Teensy then unplug the Teensy USB cable.

  16. Using Device Manager, enable View:Show Hidden Devices. Uninstall the greyed-out USB devices with VID 0x016C0 (look under events normally shows the VID/PID) found under several device categories: Ports (COM & LPT), Human Interface Devices, Software Devices (for MIDI), Audio Inputs and Outputs, and Universal Serial Bus Controllers.

  17. Plug the Teensy USB cable back in. You should now have new Teensy Devices in Audio Playback, Record views of the Sound control panel app. You should also have new COM ports.

  18. Both devices under Playback and Recording should have an Advanced tab with 16bit 48000 Hz DVD Quality listed. Turn off any offered enhancements.

  19. Rename each device to something you prefer. I like 'Teensy SDR Audio USB Line In' and 'Teensy SDR USB Audio Line Out' to help identify these devices in application menus like WSJT-X easier. Change the icon if you like. I like the RCA plugs to imply these are line level devices.

  20. Enable listen on the 'Teensy SDR Audio Line In' record device and play it back on your speakers and see if it sounds proper, no distortion.

  21. In usb_desc.c you can change the Headphone and Line devices wTerminaltype back to Digital Audio if desired. Sometimes this is needed to get your low level edits to register correctly due to the device caching. May also need to reboot. I found that uninstalling all the VID=0x16C0 related devices per Step 15 above was sufficient.

⚠️ **GitHub.com Fallback** ⚠️