wireless microphone digital

developing a digital wireless radio mic in both 2.4ghz and UHF

Similar projects worth following
The Wireless Microphone digital aims to be a professional UHF sub 1ghz professional wireless microphone with true diversity recievers and timecode ( merging from the timecode shield project ) I will start by using GFSK modulation ( around 200mhz rf bandwidth ) but will only use a simple IMA ADPCM compression for the incoming audio samples from I2S.
true diversity switching from the RSSI working ( last packet recieved )
timing problem fixed and numbered packets.
Circular buffers working
The first prototype wireless radio mics 2.4ghz are using TI CC8530 modules from raytac. they have a 4 layer module with the CC2590 range extender PA attached.
My first prototypes are using RODE lapel lavier mixs running on bias from supplied by the AIC3101 on a modified development board supplied by raytac.
I have also added antenna diversity to the TX body packs by adding a RF switch controlled by the CC8530 to reduce signal path fad

demo with quite bad antenna on reciever...

word of warning, if anyone wants to make wireless mics with the CC8530 and AIC3101 using the bias power to run a mic, there is some quite bad RF noise around 300hz.. I would check the TI forums about this issue before considering using the CC8530 or CC85xx chips. You can filter the noise if your using a TI codec with miniDSP build in.

  • 1 × cc8530 Application Specific ICs / Telecom ICs
  • 1 × cc2590 Evaluation, Demonstration Kits, Boards and Modules / Evaluation Kits, Boards and Modules
  • 1 × aic3101
  • 1 × SI443x modules
  • 1 × 2 x Arduino DUE

  • back on this project again !!!

    ben biles04/04/2020 at 11:53 0 comments

    this project has had a lot of neglect so I just bought 2 x Lyrat 4.3 boards

    and 2  x  RFM96 ( SX1276 modules )  radio modules.

    The lyrat 4.3 boards come with an audio codec on board and the ESP32's / audio hardware works with the ESP-IDF and ESP-ADF audio IDE

    here is the start

    as you can see in these pictures the SD cards have been removed along with some 10k pullups and diodes since there are not enough GPIO pins lefton the boards left for SPI. a lot of esp32 pins are used already for the codec push buttons and Jtag debugger pins. I ordered a cheap JTAG debugger for the board so I'm keeping them in case I can use the debugger. would be helpful. I won't need the SD card slots.

    The Lyrat 4.3 boards were cheap and there's BT 4.0 and wifi on there that I thought might come in useful. 

    The code is still a mess as i'm porting from arduino C++ based code !

    I'm a complete novice when it comes to C++

    I just learned for instance you can supply less than the defined number of params to a function or have more than one prototype of a function ! 

    amazing , but I think I'm better off converting the library to C for esp32 as there are downsides in compiling C++ with ESP-IDF and the ESP-ADF IDE environment for the time being. It might have been more work than starting from scratch from the datasheet but at least I might learn something about C++ on the way :)

    inspired by..

    I will use a better compression than CODEC_G711A if I get the audio link working.

    for now I will be concentrating on getting the radio lib working.

    I'll have to re-write the radio transmit receive functions for ESP32 ( burst mode needs CS line held low ) and now i'm looking at how to define the hardware interrupt pins in esp32. should be doable ! 

    I think I can get away with just tieing the radio reset hardware pin high. ( another possible sparse GPIO pin saved ! ) 

    The ESP32 has SPI DMA with ESP-IDF and I2S DMA from the codec in the ESP-ADF.  I think i will have much more luck with ESP32 than the last arduino attempt since I could't really figure out how to assign DMA to the I2S transfer.

    Any ideas / help with the code would be much appreciated. especially if anyone is more familiar with esp32 ? 

    the RFM96 ( SX1276 modules ) are more known for loraWan but they have high sensitivity in FSK OOK mode and should be capable of 200kbsp at fairly respectable power output.

  • to busy with multichannel field recorder

    ben biles03/22/2020 at 13:42 0 comments

    All my efforts have been on the multichannel field recorder project!

    Since working on that I have learned a lot more C and understand a lot 

    more about micro controllers!

    It's quite clear that to make this project work I will need to use DMA with a circular buffer to transfer the samples to from audio codec and radio hardware.

    I now know a lot more about DMA since working on the multichannel field recorder project and will re-start this project from scratch either using ESP32 or STM32f7 mico with RF hardware.

    For now i'm just to busy on the other project ! 

  • scrapped circular buffer, trying ping pong buffers

    ben biles01/27/2017 at 15:32 0 comments

    trying ping pong buffers. code here ;

    TXlooks more promising than RX

    maybe I need to have multiple pingpong buffers on the RX ?

    if packet ready get packet

    ping pong buffer

    demodulate from ADPCM

    16bit array to 32bit array 240 samples for I2S

    ( load 2nd ping pong buffer ? here )

    I2S inturrupt outputs 2nd pingpong buffer 1 sample at a time until empty ?


    how should the timing work?

    should i timestamp / number the packets , packet order ?

  • 2 lcd screens for debugging

    ben biles08/20/2016 at 18:11 0 comments

    I have setup 2 x screens for debugging on I2C to help with timing etc... you cant use Serial.ptint to slow and takes too much time in an audio application.

    I'm using liquidcrystal_i2c on the arduino DUE's .. NO not so simple more problems with arduino DUE and repeat start in I2C , sureley this bug was fixed by now !!!! anwyay maybe i'll have to find an alternative I2C library or something , hopefully will get this fixed then I can debug some timing problems I have with IMA_ADPCM codec,

  • WORKING :)

    ben biles08/10/2016 at 02:24 0 comments

    ok finally i have horrible sounding audio streaming in to the reciever in 48 byte packets made of 8bit samples. 1 every 4 samples is sent from the TX.

    my mistake was believing that this code would determin if I had a

    packet recieved or not. It turns out it was pumping out multiples of the

    same recieved packet causing a horrible ringing sound.

    if (rf24module1.available())
    uint8_t len = 48;
    if (rf24module1.recv(packetmod1, &len))

    I have now numbered the packets, so first byte in packet has a number from 1 to 255 and I test that if packetnumber != packetnumber then ignore the packet :)

    It audio sounds like rubbish of course but that is

    to be expected. the samples are being pulling in by the I2S codec from

    the recieved samples in the circular buffer and this appears to work ok.

    I also found that my home made radio config was not working at all so now I have reverted to using a canned config in the radiohead driver.

    its tricky making your own config with the SI software and then editing the template in radiohead. you can't just replace the config file with the generated one from the software. basically its a lot of time working out which registers your allowed to change and which have to stay the same and even then it might now work at all.. mmm

    I might just stick with the GFSK Rb = 150kbs, Fd = 300kHz pre made config for now

    and try and impliment IMA_ADPCM again now the link is working :)

    then I will enable true diversity recieving and do some range tests.

    So far range is looking good even with just one reciever !

  • packets going accoss but horrible ringing sound

    ben biles08/09/2016 at 13:04 0 comments

    48 byte packets are flying accross from TX to RX. my RTL SDR looks busy with 4GFSK at the correct frequency !

    I tried bit shifting >> 24 to uint8_t and back again <<24 and copying the samples back into I2S driver ( passthough ) and everything sounded as good as 8 bit gets :)

    At the reciever end I am recieving the packets, unpacking the recieved 48 byte packet array into a circular buffer as they come in. The I2S driver is pulling samples from the circular buffer as it needs them.

    So there should'nt be a timing issue ? but maybe there is !

    The circular buffer warns if it runns out of samples, its not, it warns if it overflows, its not.

    I am only TX ing 1 out of every 4 samples, I tried every other and every sample. I get differnt ringing sounds almost like a delay effect.

    could it be packet order ? maybe , next thing to do is just send a uint8_t number as the first byte of every packet.

    after that maybe send a stream of numbers that increase in value and see if they are consistant ! perhaps my GFSK radio config is malforming the data. Its hard to debug, if you use the Serial terminal then obvusly things stop working !

  • just realised my sampes are LEFT justified !

    ben biles08/08/2016 at 09:55 0 comments

    My 32bit binary samples are left justified!!!! looking at the binary numbers converted something looks wrong.

    if I copy from uint32_t to a uint8_t with a bit shift of >>24 and mask & 0xFF I should get an 8 bit number represetation of the 32bit number.

    but i'm getting only 11111111 whatever the 32 bit number. no wonder i'm getting some quite interesting noises on the reciever !

    How do you convert a LEFT JUSTIFIED 32 bit number to 8 bit ?

    do I need to right justify first ? and then bitwise shift >>24 ?

    google brings up a solution to justify binary from right to left but not from left to right !!

  • multithreaded thread safe re-entrant libraries

    ben biles08/07/2016 at 16:55 0 comments

    Soon into starting to use freeRTOS to try and tackle the timing issues i'm possibly having with I2S SSC and RH_R24 radio ( driver librarys should be multithreaded, thread safe re-entrant libraries ) are needed to use freeRTOS.

    I ask on RadioHead forum ,. answer don't no. also freeRTOS requires pin 2&3 to be connected together. I'm using those pins , did'nt want to resolder to other pins. OK , going to stick to learning about SSC timing and see if I can sync the rf24.send(data.len); function call to that timer somhow. quite quicky I found the NVIC_EnableIRQ(SSC_IRQn); in HiFi.cpp ( the I2S driver code ) i am hoping I can sync the sending of the packet to the SSC inturrupt. I might have to write as simple radio send function myself if I can't get this to work.

  • rf24 driver library locking CPU while transmitting

    ben biles08/05/2016 at 06:02 0 comments

    I did some more tests just with I2S passthrough and the decimation. The deciamtion works fine even when doing some Serial.print(samples,BIN); to check samples are coming are going.

    The millisecond I enable the rf24.send(samples, len); to send the 48 byte packet the samples freeze up. New plan !

    going to try and use

    freeRTOS scheduler library. No idea what i'm doing with it but hoping I can assign the RF function send to one task and the samples IO circular buffer and I2S some others !

  • forget 1 byte at time !

    ben biles08/03/2016 at 13:39 0 comments

    today I tired 1 byte at a time and reliased there is way too much overhead in the RF driver for this to be useful ! its obvoius really ,

    There is the preamble of x amount of 0's an 1's before each 1 byte packet is sent and other wasted time making the packet in the driver.

    So I boilled things down to basics and took some advice from the comments here ! now I am just going to bit shift to 8 bits from incoming 32bits keeping the 48khz samples and increase the RF bandwidth. I can bring the RF power right down and connect the TX with RX with coax cable so I'm not blasting illeagle RF all over the place !

    right now there is an RF bottleneck until I edit the radiohead config file ( there is'nt a pre-made , 'canned' template that can do 8 x 48000 = 384000 bits per second gfsk.

    After I make that I should know if I have timing problems or not with the reciever and the diversity RSSI packet selection.

    At the moment the I2S SSC driver just pulls a sample from the circular buffer everytime the SSC timer inturrupt happens. its wanting a crazy 32 bit 48k samples , per channel !

    Thats 1,536,000 bits per second per channel per second..

    obvoiusly theres no more information in all these bits than the 8bit 48k it came from but lets

    not go rebuilding the I2S driver unless I really have to !!!! It looks like a mess of nasty timming code.

View all 14 project logs

  • 1
    Step 1

    now using 2 x hacked lyrat 4.3 boards ( removed SD card sockets ) 

    2 x SX1276 modules



    Historic Record....

    1st attempt worked but was for 2.4ghz

    I used the Wireless Audio Module / MD85XXP1

    that can be found here

    raytac can sell you the module on a small demo board.

    I did solder the module to vero board. but its very tricky !!

    the pitch is 1.27mm and there are no holes on the edge of the module, just bumps!

    I managed to solder 1.27mm headers to the module and bend every other pin so it would fit in double rows to 2.54mm normal prototype board..

    to be honest I would just pay the extra 25$ and get the dev board with the modules if your going to test the modules..

    I used a CCdebugger from TI , cost 50$ and flashed the modules via the 10 pin header on the demo boards and my own 10 pin header on the module soldered to the vero board.

    I would say its not really worth trying to make your own 4 layer cc8530 + cc2950 PA board unless you really want to go into production with something.

    there is an example schematic of diversity antenna switching from TI and you can add the Skyworks switch for antenna diversity. does it help with range? a bit, but not that dramtic.. perhaps slightly less dropouts when you walk about with the TX.

    you can have a very high quality audio link when you configure cc85xx in PCM24 but you will find latency goes up.. low latency 13ms is only available in SLAC mode.

    theres plenty of info on the TI forum and you can get answers to many questions there.

    One really odd thing is that if you want to use antenna diversity with more than one microphone is that the diversity antennas need to be on the microphone. Its just the way the Slave - Master topology works out.

    Even more funny was I found the audio would get choppy if I uploaded a picture or streamed video over the wifi in my house.. and would completely cut out if I turned on the microwave oven.. must have a leeking microwave :)

    Drop me any questions if you want to have a go at building this, would be happy to answer..

View all instructions

Enjoy this project?



greenaum wrote 07/28/2016 at 22:10 point

Do you need 48KHz? If you're only doing 8-bit resolution, presumably sound quality is not paramount.

Halve, or quarter, the sample rate. 12KHz is easily good enough for speech. They only use 8KHz on landline telephone networks. Either discard 3 out of every 4 samples, or average them together. Add all 4, then bit-shift right, twice, for a quick divide by four.

Or you could implement ADPCM as the other poster mentioned. Or the simpler version, DPCM, that's pretty simple, really just the difference between each sample. You could look up a tutorial on it, or maybe get lucky and just paste in somebody else's code!

Since you're only doing speech, where low data rates are acceptable (and desirable), you can use the more simple compression techniques that are possible on a low-powered CPU.

  Are you sure? yes | no

ben biles wrote 07/29/2016 at 00:19 point

well ultimately I would like to use a more professional compression as used in the most expensive professional wireless mics available. These opperate in 200kHz rf mask sub 1ghz. I am trying to find an open source alternative to Aptx live or commercial versions of opus. But for now while I get the diversity recievers working and timestamp packets working some kind of simple 4 bit low kHz stream will do,  then later I can try to implement CELT or another low latency 5ms frame compression in dsp either included on cortex M4 or perhaps a ti micro / dsp combination like Omap.. I think I will first try the IMA ADCP but first there is some figuring out of the I2S codec timing. I will try to figure out what timer this library is using so i can work out when to do the maths on the samples,  would you do the bit shifting,  maths,  throwing away of samples etc before they enter the circular buffer or afterwards? 

  Are you sure? yes | no

greenaum wrote 07/30/2016 at 14:52 point

I'd do the decimating, throwing away the samples (actually don't know if there'd be a point in averaging them, but if you do...) just after you acquire them.

I dunno much about codecs, just that DPCM is nice and simple, simple enough for to understand without much experience. Just reading the main site and they mention Bruce Land has been busy again, creating a DAC from a programmable voltage reference. Anyway, his scheme uses DPCM.

And being a professor, he does a nice job of explaining it. He only uses 2 bits for each sample. See if it's any help.

That's the article ^ .

  Are you sure? yes | no

ben biles wrote 07/30/2016 at 15:04 point

Thanks greenaum, I'll check out bruce's DPCM codec .. basically the simpler the better for me ! just learning C so I don't mind if the audio sounds rubbish etc ! 1 bit 2bit is all good if it works then I can play about with timing,  ring buffers packetising timestamps etc.. a lot to learn here !

the other IMA adpcm link I posted was a red herring.. looks like I have a chance with this IMA_ADPCM library.. It builds in the arduino IDE as long as you include common.h from the files list. it even has encoder options for the samples input signed , unsigned. I'll try using this and report back here if it works

  Are you sure? yes | no

ben biles wrote 08/04/2016 at 07:33 point


turns out all my shifting etc was working. I tried various differnt decimation techneques using just the passthrough and Serial.print(samples,BIN); which is nice to see the bit stream. It turns out the problem is with the RF driver locking up too much cpu time for anything to happen at all while it sends the packets.

So now looking into schedular library that is supossed to work in arduino zero and due

  Are you sure? yes | no

greenaum wrote 08/07/2016 at 12:58 point

Ah, sorry for the delay in replying. You got it then! 

From your (edited away) code, you look like you're quite new to this programming thing. Well done on creating a practical project and learning as you go, impressive.

Does it matter if the CPU is busy when sending the packets? You mean it's missing out on samples because it's busy? Hm, that's tough. You could use interrupts, maybe, to collect your data, but that might throw off the timing of the RF driver, it might not like being interrupted, since it's kind-of a realtime thing, must happen at specific moments in time. 

Can't think of a solution for that, but there's many wiser than me around here who might. Maybe use DMA to collect the data? Again, depends on how much of a hog the RF driver is, some comms stuff for Arduino uses exact delays coded in. That's assuming I'm understanding the problem. Good luck with it!

  Are you sure? yes | no

ben biles wrote 08/07/2016 at 15:22 point

I'm using a circular buffer and the samples are entering being read from that buffer until rf24.semd(data,len); is called. disable this and you can even Serial.print 32bit audio samples in binary fliying out of the buffer ! impressive I thought for a little arduino !

So i was hoping that the buffer might ride out the blip in time when the 48 byte packet is sent. but it seams that the I2S audio coming in on SSC ( Synchronous Serial Controller ) is stopping. My latest thinking is that since the SSC is inturrupt driven perhaps the RF inturrupt is conflicting with SSC. In other words throwing inturupts at the same time. Since the SSC driver is bringing in say 22000 samples per second at 22khz in 16bit or 8bit. so timing is crucial for the RH_R24 library i'm using? I think the SSC driver is actually using DMA, but my knolledge of what DMA really is and how its working in the limited memory on an Arduino is zero ! All I know is it stands for Dynamic menmory Access and it can help move data around without hogging CPU ? anyway, I think I will try to read uint32_t ssc_get_status in the SSC driver and see what is actually returns. maybe that will give me clue. I tried the RadioHead forum , they wrote the RadioHead library , RH_R24 driver for the module) and they think the send( ); function is very fast. I'm not sure how I messure that in micros / millis yet, but will try. Yes i'm farily new to C programming. Slowly getting there :) just started to learn about passing variables into functions and classes, although I believe classes are more C++.  the arduino I2S driver is here, the SSC driver documentation is here and I think this holds the key to my timing mistery :) ..

  Are you sure? yes | no

greenaum wrote 08/07/2016 at 18:57 point

Ah... As far as DMA goes, it's "direct" memory access. Basically you set source and destination registers in the hardware, and a length register, then tell it "GO!". The DMA's hardware will then copy that many bytes from source to destination. 

At least, that's one use. DMA can do other, similar things. But basically it's hardware that does stuff to whole ranges of memory, one at a time. In the old days a DMA controller was a separate chip, now they're integrated into CPUs, but still work pretty much the same way.

While all this DMA is going on, your CPU is free to carry on, free of hassle. To check when your DMA transfer is finished, you usually check a certain address, or it might be hooked up to trigger an interrupt. DMA is one of the basic concepts a lot of computing hardware is based on, so it's worth learning, and isn't too horrible! I can see it coming in useful for this.

Your previous idea of a scheduler, I dunno if that'd help. Since, presumably, if the scheduler interrupted and temporarily halted the RF routine, the RF transmission might fail.

The prob seems to be the RF driver routine itself.  At least, that's my guess!

Often libraries are built on the very low-level stuff, then layers added on top. So maybe a simple hardware-driving byte send, then that code is used, called, by higher routines that do stuff like checksums, and re-sending if needed. The OSI networking stack model is an example of code like that.

So, perhaps you could use lower-level routines in your code, allowing you to send stuff in shorter bursts, or if not shorter, at least quicker cos you wouldn't be running as much of the overheads of the rest of the code. Of course that means you'd have to implement those higher functions yourself, but your application isn't too complicated in it's demands.

I dunno the routines in question, I'll have a brief look later on. Asking the people who are responsible for it, is just what I would have suggested too.

Maybe try with some dummy stuff? Sending dummy data, but at the same rate, same amount of data? To see if that's the problem.

As for the interrupts clashing, could be. Interrupts can be designed to tolerate being interrupted themselves. They just need to save any registers they use in their own code at the start of the interrupt service routine (ISR). Then restore them after. Interrupts are usually prioritised so that only a higher interrupt can interrupt another one. That might be something to check.

As you mention, classes are C++, and C++ is evil! Stay away, young padawan!

Well, I've been told it has it's uses. Perhaps it does. But the place for object-orientation is not the C language. Now computers are powerful enough to allow nice, friendly-looking languages, something bare and baroque like C isn't the place to start waving paradigms around. In my opinion. 

Anyway, not sure how much help this post of mine has been, but best of luck! Keeping at it, learning, and trying new things is the way forward, and that's what you're doing. Keep checking what's happening in the various parts of your code. Oh, and, rookie mistake (put my hand up), don't connect any hardware to pins 0 and 1 when you're using the Serial.print functions! Since it uses those for it's serial port. Very confusing bug, that was.

It's also worth checking for the odd misplaced ; or } , just in case. Can throw the path of your code right off.

  Are you sure? yes | no

ben biles wrote 08/08/2016 at 02:06 point

Thanks for this advise , this helps to see the trees from the woods !

Think your totally correct about freeRTOS or other form of schedular etc. for a start freeRTOS requires all librarys used to be threaded capable etc etc .. and  I dought a lot of code i'm borowing from in githib etc is !

I did'nt know interrupts can inturrupt inturrupts, intersesting. One thing I read about the arduino Due is that Inturrupts are all set to priority 0. meaning they are all high priority. So that could also kill off the idea of the schedular doing anything perhaps. on the other hand if inturrupts can inturrupt inturrupts ( need a shorter way to write that ) maybe its possible the RF driver never gets to execute. the I2S code inturrupts it before it gets a chance to run. The code being to large ( slow )

happy you think I don't need to learn about c++ classes , I have to say as I began to study how they work I was thinking , '' this is the work of the devil '' I'm interested in low level hardware things , I dont want to get into high level application progrmaing ! Although I just needed to know roughly what classes where since i was looking at code like this in the arduino I2S library.

void HiFiClass::configureTx( HiFiAudioMode_t audioMode,
HiFiClockMode_t clkMode,
uint8_t bitsPerChannel )

I completely get that it might be a good idea to just send packets from a lower level without the library. I've done this before with TI's CC1101 RF modules and it was'nt to bad to figure out. I think loading the config for SI446x Chip will be a bit tricky but once the chip is initialized it might be plain sailing. interestingly the SI446x has a 64 byte buffer too.. so maybe this would help smooth the movment of samples too. I was planning on writing my own simple packet protocol ( or at least a simple timestamp to go along with the packets that the reciever can check up on )

I have since discovered that the SSC part of the I2S library i'm using seams to use DMA. I found;

//#if (SAM3XA || SAM3U)
* \brief Get Transmit address for DMA operation.
* \param p_ssc Pointer to an SSC instance.
* \return Transmitting address for DMA access.
void *ssc_get_tx_access(Ssc *p_ssc)
return (void *)&(p_ssc->SSC_THR);

Due is SAM3X / SAM3A ... Up to 17 peripheral DMA (PDC) channels and 6-channel
central DMA plus dedicated DMA for High-Speed USB
Mini Host/Device and Ethernet MAC
Nice :)

and later in the code i found, Ssc *p_ssc being the pointer address to the DMA address returned from function void *ssc_get_tx_access() 

uint32_t ssc_write(Ssc *p_ssc, uint32_t ul_frame)
uint32_t ul_timeout = SSC_DEFAULT_TIMEOUT;
while (!(p_ssc->SSC_SR & SSC_SR_TXEMPTY)) {
if (!ul_timeout--) {
return SSC_RC_ERROR;
p_ssc->SSC_THR = ul_frame;
return SSC_RC_OK;

I'll keep examining the code to make sure this is the case. It is possible it just in the SSC code the was borrowed to write the library and yet its not being used of course.

I think like you say the next thing to try would be to write my own code to initialize the modules and write a simple sendRF(data_array,bytes); and recieve function.

like you say I could just send junk for testing and check to see if there are bits missing.

  Are you sure? yes | no

ben biles wrote 08/08/2016 at 09:52 point

wait a minuete ! my 32bit binary samples are left justified. looking at the binary numbers converted somthing looks wrong. if I copy from uint32_t to a uint8_t with a bit shift of >>24 and mask & 0xFF I should get an 8 bit number. but i'm getting only 11111111 whatever the 32 bit number. How do you convert a LEFT JUSTIFIED 32 bit number to 8 bit ? do I need to right justify first ? and then >>24 ?

  Are you sure? yes | no

greenaum wrote 08/08/2016 at 16:07 point

Ah, your 32 -> 8 bit problem looks like endianness. I think the ARMs can do either-endian, it's configurable (somewhere), but don't change it, just go with it!

As in, storing 0x12345678 could be stored that way in RAM, or as 0x78563412. There's reasons (and holy wars) for both ways. Do a binary dump of your 32 bit numbers to the screen, see where the relevant bits are. Might be you don't need to >>24, might be the relevant bits are already there.

Maybe the routine that provides those 32 bits stores them the opposite way, I dunno. You could work it out from the theory but you may as well just look! 

You say copying, you mean casting, right?

Nice simple example, though in that case they're after keeping all 32 bits. You presumably need the most significant bits, and to chop off the 24 least significant. 

Actually the example here seems to be doing the same thing you are. So I think you need to see those bits!

  Are you sure? yes | no

ben biles wrote 08/10/2016 at 02:18 point

Hi, just wanted to say I got it working. I took your advice and send 1 sample every 4. i did'nt average them since i want to work on a better compression later. my mistake was believing that this code was deterining if I had a packet recieved or not. turns out it was pumping out multiples of the same recieved packet !

if (rf24module1.available())
   uint8_t len = 48;
if (rf24module1.recv(packetmod1, &len))

I numbered the packets now, so first byte in packet has a number from 1 to 25 and make a test that if packetnumber != packetnumber then ignore the packet :)

It audio sounds like rubbish of course but that is to be expected. the samples are being pulling in by the I2S codec from the recieved samples in the circular buffer and this appears to work ok.

Thanks for your help and ideas Greenaum , ben

  Are you sure? yes | no

greenaum wrote 08/20/2016 at 16:51 point

Well done! Brains and information (the RIGHT information!) help, but persistence is 90% of it. Sorry for not replying for a while. Didn't think it had been so long.

Maybe now your radio problem's solved you could try sending the whole 48KHz after all. Remember to keep a copy of the software version that actually works, a known-working state is invaluable in debugging.

 Sorry that I didn't spot the problem. But again, well done. 

  Are you sure? yes | no

ben biles wrote 08/08/2016 at 23:46 point

Yes I ment casting. Just examined the codec data sheet more closely. I have SIGNED 24bit LEFT JUSTIFIED in a 32BIT word. but the I2S 32bit word is unsigned. and its possibly non-endian or endian ! this is a puzzle !! I'm already printing the 32 binary and its looking like a 24bit binary sample LEFT justfied, was signed leaving codec but now coming in as unsigned 32bit... 

  Are you sure? yes | no

raiatea wrote 07/26/2016 at 12:01 point

I'm working on a similar project, here are some things I found useful.

For general ideas about wireless audio streaming system, I found a detailed description in the user guide of the PurePath Wireless Audio with the SoC CC85XX by TI.

There is a possible lossy compression algorithm with almost no latency: IMA ADPCM, with a ratio of 4:1. The loss is white noise audible in some circumstances. The implementation in software is very simple, in hardware there is the VLSI chip VS1053. This chip implements also other compression algorithms (MP3), with better ratios, but more loss, distortion and latency.

Recent improvements of the ADPCM, more adapted to audio and with less noise, are the Fraunhofer Ultra Low Delay (ULD) techniques with few public research papers. It requires more computation, I found 20db less noise than the IMA ADPCM and this is inaudible.

  Are you sure? yes | no

ben biles wrote 07/28/2016 at 10:45 point

Yes I have used the low latency codecs in CC85xx and eliminated the strange 300khz bias mic problem with the AIC3101 miniDSP coeficiants.. The VLSI has to much lantensy and 2.4ghz is not relieble for a professional radio mic since the higher frequncies dont propergate well through bodys. Lower UHF frequencys are far better for this although the bandwidth is limited at 200khz per audio channel.  APTx and Fraunhofer Ultra Low Delay (ULD) techniques are both commercial solutions for low latency realtime under 10ms encoding decoding end to end for exactly this problem. but they are commercial. CELT is open source but has been comsumed by OPUS and has compile support for ARM Ax and heavy CPU. I am more interested in low power CPU such as M3 or M4 Cortex etc since wireless mic batterys should last for as long as possible. does anyone know of a ULD open source codec that can encode / decode in 5ms frames ? maybe CELT can be used . but I could'nt get it to compile as of yet in arduino DUE as of yet.

  Are you sure? yes | no

ben biles wrote 07/28/2016 at 21:29 point

just looked up IMA ADPCM and it looks like the m3 cortex could do it.  Not sure if the I2S SSC driver I'm using is using too much inturrupt time or not for the 32bit - 4bit IMA adpcm maths.. I'm thinking I could bit shift to 16bit signed samples then process to IMA adpcm 4 bit on the encoder side and the same in reverse on the decoder.. I could use the circular buffer store incoming samples and build packets with a simple time stamp for reordering on the reciever side.  Although the radiohead library might already be doing that at a lower level.  Will have to check. Does anyone know the best way I can check how much cpu time an inturrupt is using in arduino due? Need to see if the I2S library is a viable option for this. 

  Are you sure? yes | no

ben biles wrote 09/17/2015 at 05:05 point

mainly due to the fact that 2.4 ghz has dropouts generally when mics move around I have decided to contine working on the project in UHF. more news shortly.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates