Step by Step to make 48KHz work for me
I have been trying to use 48KHz for USB Audio both directions. My project is a Teensy 4.1 based SDR radio. On the PC I run a program WSJT-X (or similar digital mode apps) which prefers 48KHz.
A CW keyer project modified the Audio Library to work at 48K sample rate and with 32 blocks for lower latency. I am using a minimal version of this on a Teensy 4.0 and works well.
https://github.com/softerhardware/CWKeyer
I hand modified my library per the CW Keyer project for my SDR project but it has never worked well for me on the SDR. Receiving audio has worked well but sending data back to the Teensy for modulation and transmission over the Radio was distorted and inconsistent. Occasionally it would work.
Along came IDE 2.0 and the TeensyDuino 1.57B1 updates and I needed to modify my Audio library again. Changing only the AUDIO_SAMPLE_RATE_EXACT to 48000.0f did not work for me. Copying over the old 1.56 modified files blindly resulted in the same RX working, TX not. Then came TeensyDuino 1.57B2. This time I decided I needed to understand how to change the library line by line and maybe get it working at better at 48K.
I went through the older modified files line by line, researched this forum and think I now have a step-by-step procedure to apply to each new Audio library version. I have not tested at other sample rates yet. The key changes I think that were needed to get the TX running right was increasing various buffer sizes in the code.
Ideally these rate sensitive changes would automatically occur in future library versions.
Below is my procedure that seems to work for me. Been tried exactly on 1 computer. I have not heard from other SDR project users if it works for them yet.
I left out the CW Keyer projects feedback code for simplicity, and it seems to work for me OK to my ears and my application usage, but I have not looked at any metrics.
I documented it on my SDR project GitHub Wiki and future changes may be posted there. Here is the full text as of Dec 25, 2022 for the historical record and search results. The indentation was lost in the copy and paste, the
https://github.com/K7MDL2/KEITHSDR/wiki/48KHz-USB-Audio might be easier reading.
___________________________________________________________________________________
Dec 21, 2022 Update using IDE 2.0.3 and TeensyDuino 1.57.2
I now have the Teensy USB Audio Sample Rate running at 48KHz and get clean audio on both TX and RX. The default Teensy usb audio sample rate is 44.1KHz. We want 48KHz.
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 6 modified files (5 usb related, 1 AudioStream.h) 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
1. You can find the TeensyDuino files
a. For IDE 2.0.x go to C:\Users\Mike\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.57.2\cores\teensy4
b. For IDE 1.8.x go to C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4
2. Edit AudioStream.h
a. About line 40, after the __ASSEMBLER__ #endif section, add the line
#define USB_AUDIO_48KHZ 1
b. Find the lines
#ifndef AUDIO_SAMPLE_RATE_EXACT
#define AUDIO_SAMPLE_RATE_EXACT 48000.0f
#endif
and replace with
#ifdef USB_AUDIO_48KHZ
# define AUDIO_SAMPLE_RATE_EXACT 48000.0f
#else
#define AUDIO_SAMPLE_RATE_EXACT 44100.0f
#endif
#endif
c. 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.
3. Edit usb_desc.h
a. Insert the below line at line 113 between the comment section and teh line #if defined(USB_SERIAL)
#define USB_AUDIO_48KHZ 1
b. 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.
4. Edit usb_audio.h
a. 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;
}
...
b. 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
...
3. Edit usb_desc.c file
a. Search for "MICROPHONE". You will find it in 2 places inside #ifdef AUDIO_INTERFACE sections
b. 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
c. Change the wTerminalType to somnething else like Line Connector to get Windows to recognize the change in the cached driver
//0x01, 0x02, // wTerminalType, 0x0201 = MICROPHONE
0x03, 0x06, // wTerminalType, 0x0603 = Line Connector
//0x02, 0x06, // wTerminalType, 0x0602 = Digital Audio
d. 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
e. 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
4. Edit usb_desc.c file.
a. 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,
#else
LSB(44100), MSB(44100), 0, // tSamFreq
#endif
5. Edit usb_desc.h. This updates the sample rate length for USB_MIDI_AUDIO_SERIAL and 3 other sectoins containing Audio.
a. 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
b. Be careful to not delete or edit the #define AUDIO_TX_ENDPOINT x and #define AUDIO_RX_ENDPOINT y lines, they are mixed in.
The endpoint numbers are unique to each section so leave them as they are.
c. 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
6. Edit usb.c
a. 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
7. Uninstall the previous Record and Playback Teensy Digital Audio device instances that were likely at 44.1KHz using the Sound Control Panel or Device Manager.
8. Unplug the Teensy USB and reboot your Windows computer to finish the removal.
9. Plug the Teensy USB cable back in. You should now have new Teensy MIDI/Audio devices in both Playback and Record views.
10. Both should have an Advanced tab with 16bit 48000 Hz DVD Quality listed. Turn off any offered enhancements.
11. Rename each device from to something you prefer. I like "SDR Audio RX Input" and SDR Audio TX Output" to help identify these easier. Change the icon if you like.
12. Enable listen on the SDR Line In record device and play it back to your speakers and see if it sounds proper.
13. In usb_desc.c you can change the Headphone and Line devices wTerminal type 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.