¿ªÔÆÌåÓý

hacking the audio system of sbitx DE, V2, V3


 

The audio system uses a WM8731 codec. This samples 96000 times a second and produces 32 bit samples in stereo (only 24 bits have actual data).
This means that there are 96000x32x2 , approximately 6.144 million bits per second in each direction (record and play). This is transferred?over the I2S bus. The BCLK runs at twice this frequency?of 12.288 MHz.
An Unfortunate confusion
The WM8731's I2S uses the word "frame" and so does the alsa sound system of linux. for entirely different reasons. The WM8731 frame refers to a pair of single left and right samples of audio (a total of 64 bits). In alsa, it refers to a few hundred of the pairs of left and right samples. So, the ALSA's frame is made of a number of WM8731 frames!
How audio is organized
The audio?system uses the right channel to transmit and the left channel to receive (yes, both can theoretically work at once, we need to write the software that way). The demodulator output?is fed to the left channel line input and the microphone is connected to the right channel. Each time 1024 samples of left and right are ready, the system calls sound_process(). Here the sbitx takes over, depending upon the transmit or receive status, right or left channel is processed and returned to the sound subsystem to be played to the speaker and/or the transmission system.
Hacking the system
The sound system has been abstracted to just two calls: first, sound_thread_start is called and in a seperate thread, sound_process is called with left, right input and output pcm streams at 32-bit arrays. depending upon the transmit/receive status, the appropriate processing is done by sdr.c of these samples. Remember not to call any GUI related code from sound_process as it needs to get back within a few milliseconds to handle the next block of audio.
Playing around
You could (at one time, I havent tried it for a few years) compile the sbitx_sound.c as a separate program? by uncommenting the main() function. You may have to comment out some code to remove the dependencies from sbitx specific code.
- f



 

Thanks!

In the tx_process, when you have the modulation in the frequency domain, is there a reason not to assign 0.0 to the bins that are above the highest audio component expected?? ??

In this section of code, from tx_process(), you applied zeroes to cancel out the undesired sideband.? ?What about energy above the 3kHz voice expected range on the desired sideband?? ? (There may be a reason I just don't know about) -- I might have expected that you might zero out the frequency bins above say, 3.4 kHz or so on the desired side also??? ?(I was fascinated by the possibility of wideband transmission that your current architecture allows, possibly for wideband data on vhf/uhf bands, for example.)? ?But curious about the bins beyond 3.4 kHz or so in the transmit process.....

Sorry if this is a dumb question, just trying to learn!? ?I'll be demo'ing the treble emphasis software for the high school kids tomorrow.? ? It appears to work well.? ?The plan is to add graded amounts of white noise and see if we can prove, with experimental measurements of random 5-letter groups or so, that aged males do better with emphasis beginning around 2kHz and de-emphasis below say 300 Hz.? ? There are multiple papers suggesting this, due to the rapid fall-off of high frequency response in us oldsters.? ? Aiming for a small school science fair in March or April at our school.

Gordon KX4Z??
(code below)


// apply the filter
for (i = 0; i < MAX_BINS; i++)
fft_out[i] *= tx_filter->fir_coeff[i];
?
// the usb extends from 0 to MAX_BINS/2 - 1,?
// the lsb extends from MAX_BINS - 1 to MAX_BINS/2 (reverse direction)
// zero out the other sideband
?
// TBD: Something strange is going on, this should have been the otherway
?
if (r->mode == MODE_LSB || r->mode == MODE_CWR)
// zero out the LSB
for (i = 0; i < MAX_BINS/2; i++){
__real__ fft_out[i] = 0;
__imag__ fft_out[i] = 0;
}
else
// zero out the USB
for (i = MAX_BINS/2; i < MAX_BINS; i++){
__real__ fft_out[i] = 0;
__imag__ fft_out[i] = 0;
}
// GLG - potentially zero out energy above necessary bandwidth???

//now rotate to the tx_bin?
for (i = 0; i < MAX_BINS; i++){
int b = i + tx_shift;
if (b >= MAX_BINS)
b = b - MAX_BINS;
if (b < 0)
b = b + MAX_BINS;
r->fft_freq[b] = fft_out[i];
}


 

¿ªÔÆÌåÓý

?
Ashar ...
?
is it possible to use and connect an wireless headset (with a USB-dongle) to the sBITX v3 ?
(Like this headset which works with LINUX :
? )
?
What and how must be choosed and programmed in the sBITX the setup about the audio in-& output ?
?
73 , Jens / HB9JOI
?
+++
?
?

From: Ashhar Farhan
Sent: Wednesday, January 17, 2024 7:39 AM
Subject: [BITX20] hacking the audio system of sbitx DE, V2, V3
?
The audio system uses a WM8731 codec. This samples 96000 times a second and produces 32 bit samples in stereo (only 24 bits have actual data).
This means that there are 96000x32x2 , approximately 6.144 million bits per second in each direction (record and play). This is transferred over the I2S bus. The BCLK runs at twice this frequency of 12.288 MHz.
An Unfortunate confusion
The WM8731's I2S uses the word "frame" and so does the alsa sound system of linux. for entirely different reasons. The WM8731 frame refers to a pair of single left and right samples of audio (a total of 64 bits). In alsa, it refers to a few hundred of the pairs of left and right samples. So, the ALSA's frame is made of a number of WM8731 frames!
How audio is organized
The audio system uses the right channel to transmit and the left channel to receive (yes, both can theoretically work at once, we need to write the software that way). The demodulator output is fed to the left channel line input and the microphone is connected to the right channel. Each time 1024 samples of left and right are ready, the system calls sound_process(). Here the sbitx takes over, depending upon the transmit or receive status, right or left channel is processed and returned to the sound subsystem to be played to the speaker and/or the transmission system.
Hacking the system
The sound system has been abstracted to just two calls: first, sound_thread_start is called and in a seperate thread, sound_process is called with left, right input and output pcm streams at 32-bit arrays. depending upon the transmit/receive status, the appropriate processing is done by sdr.c of these samples. Remember not to call any GUI related code from sound_process as it needs to get back within a few milliseconds to handle the next block of audio.
Playing around
You could (at one time, I havent tried it for a few years) compile the sbitx_sound.c as a separate program? by uncommenting the main() function. You may have to comment out some code to remove the dependencies from sbitx specific code.
- f
?
?


 

Dear Farhan,

Thanks for the message. I've being dealing with you DSP code for some time (the rest I re-wrote). My main issue with interacting with the DSP is the correct level to feed the fft in order to get optimal results. Some patches are flying around with automatic IF gain (we could just play with Alsa controls). Ashhar, do you think we should have some adaptive IF adjustment, both in tx and rx? Right now I can only see constants in the code without a clear meaning for me.

- Rafael

On 1/17/24 06:39, Ashhar Farhan wrote:
The audio system uses a WM8731 codec. This samples 96000 times a second and produces 32 bit samples in stereo (only 24 bits have actual data).
This means that there are 96000x32x2 , approximately 6.144 million bits per second in each direction (record and play). This is transferred?over the I2S bus. The BCLK runs at twice this frequency?of 12.288 MHz.
*An Unfortunate confusion*
The WM8731's I2S uses the word "frame" and so does the alsa sound system of linux. for entirely different reasons. The WM8731 frame refers to a pair of single left and right samples of audio (a total of 64 bits). In alsa, it refers to a few hundred of the pairs of left and right samples. So, the ALSA's frame is made of a number of WM8731 frames!
*How audio is organized*
The audio?system uses the right channel to transmit and the left channel to receive (yes, both can theoretically work at once, we need to write the software that way). The demodulator output?is fed to the left channel line input and the microphone is connected to the right channel. Each time 1024 samples of left and right are ready, the system calls sound_process(). Here the sbitx takes over, depending upon the transmit or receive status, right or left channel is processed and returned to the sound subsystem to be played to the speaker and/or the transmission system.
*Hacking the system*
The sound system has been abstracted to just two calls: first, sound_thread_start is called and in a seperate thread, sound_process is called with left, right input and output pcm streams at 32-bit arrays. depending upon the transmit/receive status, the appropriate processing is done by sdr.c of these samples. Remember not to call any GUI related code from sound_process as it needs to get back within a few milliseconds to handle the next block of audio.
*Playing around*
You could (at one time, I havent tried it for a few years) compile the sbitx_sound.c as a separate program? by uncommenting the main() function. You may have to comment out some code to remove the dependencies from sbitx specific code.
- f



 

Dear Farhan,

I just saw you added to the fft code the support for "wisdom" file. How is it created? I don't understand why we need to create some fft parameters in runtime, during initialization, from the received signal, as far as I understand (sorry my ignorance in DSP matters).

Cheers,
Rafael Dini

On 1/18/24 09:34, Rafael Diniz wrote:
Dear Farhan,

Thanks for the message. I've being dealing with you DSP code for some time (the rest I re-wrote). My main issue with interacting with the DSP is the correct level to feed the fft in order to get optimal results. Some patches are flying around with automatic IF gain (we could just play with Alsa controls). Ashhar, do you think we should have some adaptive IF adjustment, both in tx and rx? Right now I can only see constants in the code without a clear meaning for me.

- Rafael

On 1/17/24 06:39, Ashhar Farhan wrote:
The audio system uses a WM8731 codec. This samples 96000 times a second and produces 32 bit samples in stereo (only 24 bits have actual data).
This means that there are 96000x32x2 , approximately 6.144 million bits per second in each direction (record and play). This is transferred?over the I2S bus. The BCLK runs at twice this frequency?of 12.288 MHz.
*An Unfortunate confusion*
The WM8731's I2S uses the word "frame" and so does the alsa sound system of linux. for entirely different reasons. The WM8731 frame refers to a pair of single left and right samples of audio (a total of 64 bits). In alsa, it refers to a few hundred of the pairs of left and right samples. So, the ALSA's frame is made of a number of WM8731 frames!
*How audio is organized*
The audio?system uses the right channel to transmit and the left channel to receive (yes, both can theoretically work at once, we need to write the software that way). The demodulator output?is fed to the left channel line input and the microphone is connected to the right channel. Each time 1024 samples of left and right are ready, the system calls sound_process(). Here the sbitx takes over, depending upon the transmit or receive status, right or left channel is processed and returned to the sound subsystem to be played to the speaker and/or the transmission system.
*Hacking the system*
The sound system has been abstracted to just two calls: first, sound_thread_start is called and in a seperate thread, sound_process is called with left, right input and output pcm streams at 32-bit arrays. depending upon the transmit/receive status, the appropriate processing is done by sdr.c of these samples. Remember not to call any GUI related code from sound_process as it needs to get back within a few milliseconds to handle the next block of audio.
*Playing around*
You could (at one time, I havent tried it for a few years) compile the sbitx_sound.c as a separate program? by uncommenting the main() function. You may have to comment out some code to remove the dependencies from sbitx specific code.
- f





Paul
 

Re the wireless headset question - I would like to know the answer to this one too as I would love to be able to use my USB headset with the radio. However, I suspect this may not be easily achievable having had a brief play around as the audio primarily appears to be hardwired to deliver/accept audio to the sockets on the side of the radio or the physical speaker within (Arfan correct me please if I am wrong).
It may be possible using the loopback device capabilities but this seems a little complicated at first glance and needs some clearer description on how to route the audio from maybe one of the loopback devices to the USB or Bluetooth connected device.
My immediate approach is to work on getting a PC headset working via the connectors on the side of the radio at the moment using a splitter based approach that is wired from a small project box to house the TRRS connector that most PC headsets can use and the box has the PTT button on it as well. This approach works so far but the audio level on SSB is too low to get the power out of the radio (commented on many times elsewhere in the forum), this I am hoping to solve using a microphone pre-amplifier based on an SSM2167 module that I will fit into the radio, need to find a suitable 4-5v tapping point to power it - to be continued. will perhaps start a separate thread for this one once I have it sorted. I would like to know though if it is possible to use either Bluetooth(built into the pi) or USB type headsets as it will add to the versatility of the radio especially for portable voice communications which is how I would like to primarily use this radio, Paul G0KAO


 

¿ªÔÆÌåÓý

You just need to change to a electret cartridge that has -24DB?




On Jan 24, 2024, at 11:19, Paul <g0kaohx@...> wrote:

?Re the wireless headset question - I would like to know the answer to this one too as I would love to be able to use my USB headset with the radio. However, I suspect this may not be easily achievable having had a brief play around as the audio primarily appears to be hardwired to deliver/accept audio to the sockets on the side of the radio or the physical speaker within (Arfan correct me please if I am wrong).
It may be possible using the loopback device capabilities but this seems a little complicated at first glance and needs some clearer description on how to route the audio from maybe one of the loopback devices to the USB or Bluetooth connected device.
My immediate approach is to work on getting a PC headset working via the connectors on the side of the radio at the moment using a splitter based approach that is wired from a small project box to house the TRRS connector that most PC headsets can use and the box has the PTT button on it as well. This approach works so far but the audio level on SSB is too low to get the power out of the radio (commented on many times elsewhere in the forum), this I am hoping to solve using a microphone pre-amplifier based on an SSM2167 module that I will fit into the radio, need to find a suitable 4-5v tapping point to power it - to be continued. will perhaps start a separate thread for this one once I have it sorted. I would like to know though if it is possible to use either Bluetooth(built into the pi) or USB type headsets as it will add to the versatility of the radio especially for portable voice communications which is how I would like to primarily use this radio, Paul G0KAO


 

On Fri, Jan 19, 2024 at 04:02 AM, Rafael Diniz wrote:
I just saw you added to the fft code the support for "wisdom" file. How is it created?
I'm sorry if this has already been answered but it has popped up again recently.

The wisdom file gets created by a function in the fftw library.? If the wisdom file is not present, the fftw runtime creates it.?? Once one is created, that same data is reused till it is erased.


I don't understand why we need to create some fft parameters in runtime, during initialization, from the received signal, as far as I understand (sorry my ignorance in DSP matters).
A bit of googling says "wisdom files contain saved information about how to optimally compute (Fourier) transforms of various sizes".? The parameters are created? at runtime based on how fast the current processor runs certain algorithms from the current fftw library.? As I understand it, all Pi 4s running the same code should create similar data.? It is not using the received signal, it is just running standard fftw kernels to figure out the best ones to use.

The real question is what happens if wisdom data is not used.? Our observation is the fftw run time picks algorithms at startup time but it's not clear how it does this.? What is clear is some times it makes bad choices.?? This is the source of the 'ghosts' or 'hallucinations' that were seen before Steve created the wisdom fix.

--
Regards,
Dave, N1AI


 

I forgot to say that I use the term 'wisdom files' because it creates two files, one for single precision, another for double.

If one cherry picks Mark N8ME's changes to just use single precision and get rid of double, only one file is needed.

And if you are using Pi 5 you should not use any of the checked in files, they were made on Pi 4.

I actually think given how many different OSes and processors we have now and in the future, there should be no wisdom files checked in at all.

This means the first start is slow, which is very confusing to newbies, but maybe if we get rid of double precision it won't take so much time.

Ideally we'd post a "creating wisdom file, please wait" message on the UI followed by "done creating wisdom file" when appropriate.

I think each message can be posted with a single line of code.

Finally, I think my changes to put the wisdom files into $HOME/sbitx/data have not been merged.

Maybe I'll make a PR to improve this area, we shall see, or maybe someone else will beat me to it.

--
Regards,
Dave, N1AI