How hard is analog audio to mp3, auto save to file on power-down - Page 1
Forum section: electronics / projects

author: peter-h
author_rank: Super Contributor
timestamp: April 04, 2022, 11:13:21 am
content: A little board which, upon power-up, automatically captures line-level audio, mono, writes it continuously to an mp3 file, and upon loss of power it saves the file, with a date/time based filename.A USB socket for accessing the files.I already have a well debugged board which has- 32F417 168MHz- FreeRTOS- FatFS (2MB - not enough; would need to put a micro-SD slot on it to get more storage, say 64GB)- USB "removable device" access to the FatFS- internal access to the FatFS- a means of detecting power fail about 10ms before CPU stops (fairly trivial to extend this)- a spare SPI for accessing a micro SD card (in the basic no-license mode)- RTC and a supercap (I know the basic issue with getting date/time; with no internet you can do GPS/NMEA)What I have no clue about is saving to mp3, and how fast one can close the file. Presumably one would use the 12 bit ADC to sample the input at 44kHz and then run some sort of mp3 codec.No user interface. Well, maybe a button which closes the current file, just like the button on a dashcam.

author: NiHaoMike
author_rank: Super Contributor
timestamp: April 04, 2022, 12:55:03 pm
content: MP3 is going to be the hard part. Might want to look at just saving uncompressed (although then the CPU would be massive overkill) or using a more modern open codec that gets better compression for the quality level.You can run the ADC at an integral multiple of the recording sample rate and then downsample to increase the effective resolution.

author: peter-h
author_rank: Super Contributor
timestamp: April 04, 2022, 01:05:15 pm
content: To add: the quality can be relatively poor. It is basically telephone-quality audio, so to be really generous, not above 10kHz. 12 bits would also be enough, and because a 12-bit on-chip ADC is good for only about 10 real bitsone could oversample by a huge factor (the ADC can sample at ~500kHz, in my tests, including software overhead) and run an FIR filter on it. One could also run the ADC continuously via DMA, into a circular buffer, and then when you want a value (at 44kHz or whatever) you just add up that buffer and divide by N.

author: CaptDon
author_rank: Super Contributor
timestamp: April 04, 2022, 02:13:29 pm
content: Probably need some supercaps to hold the power up for a few seconds and a POWERGOOD signal to tell your system death is in the near future.

author: peter-h
author_rank: Super Contributor
timestamp: April 04, 2022, 04:18:48 pm
content: That's the easy part.How hard is integration of an mp3 encoder and roughly how much FLASH and RAM is it likely to need? I would want a chunk of code which reads the ADC at one end and writes data to a file at the other end. Presumably the ADC reading needs to be either synced to a tick somehow or the whole encoder has to run as an ISR. I can have a separate RTOS thread picking up data from a buffer and writing it to a file; the FLASH FS write speed is about 30kbytes/sec.

author: NiHaoMike
author_rank: Super Contributor
timestamp: April 05, 2022, 01:20:34 am
content: Quote from: peter-h on April 04, 2022, 01:05:15 pmMight want to take a look at projects for digital voice on amateur radio. There are a number of open codecs that perform better than MP3 and are easier to implement on microcontrollers.https://github.com/drowe67/codec2

author: viperidae
author_rank: Frequent Contributor
timestamp: April 05, 2022, 02:02:11 am
content: If you have 2MB of flash data to write at 30kB/s then you'll need over a minute to write it all.

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 05, 2022, 02:09:30 am
content: Quote from: peter-h on April 04, 2022, 01:05:15 pmDon't bother with MP3 then. ADPCM might be good enough.

author: DavidAlfa
author_rank: Super Contributor
timestamp: April 05, 2022, 03:04:55 am
content: Check STX-Cube-Audio library, spiritDSP MP3 encoder.I used the decoder and it was pretty simple.

author: Sauli
author_rank: Contributor
timestamp: April 05, 2022, 12:27:36 pm
content: I think the real challenge here is to convert the raw audio data to mp3 format and write it to a file at the same rate as the data is generated. If you cannot do this, you will fill up all available RAM in seconds. A mp3 file is made up of frames, and you will be writing these to the file. When a power fail occurs, just complete any write operation and close the file.

author: peter-h
author_rank: Super Contributor
timestamp: April 05, 2022, 02:26:18 pm
content: Obviously, with a 30kbyte/sec max flash file system write speed, I need to make sure the bit rate is well below that.That translates to a 240kbps audio stream, which is very very high quality - the very top end of "hifi" unless you are into $1000 interconnects and 100x oversampled 24 bit DACsSo that in itself should be ok.One challenge I see is that the ADC sampling, which has to besynchronousfor any audio encoding, would need to be inside an ISR, or driven from a timer -> ADC -> DMA so a periodically running RTOS thread can process a whole load of ADC samples in one go. I haven't looked yet at how that ST lib does it (it is 240MB).The end file has to be mp3, for general compatibility, even if the required quality is relatively crap.My flash file system sector writes are currently blocking (for complicated reasons which I posted about, to do with the file system being accessed by USB (MSC) while the internal software is messing in there, but I can make the write non-blocking, so the sector write is about 20us and the next 15ms is the internal flash write cycle. A sector read, not relevant to this project, is just 200us (DMA transfer of 512 bytes via 21MHz SPI).As for closing the file at power-down, I can build this with plenty of capacitance on the PSU. Action cams seem to have no trouble closing off a video file when the battery goes flat, and that's a lot more complicated (some big blocks have to be written at the end, AIUI).If I drive the ADC from timer+DMA, at say 22kHz, that will generate 44kB of data per second, so a leisurely RTOS thread, getting around to this every 100ms or less, will need just 4.4kB of RAM, which is trivial. So no need for any ISR at all. Just set up a timer to drive the ADC and use DMA. I have already built a waveform generator that way. Use a circular RAM buffer so it never needs to stop, and reset the DMA pointer whenever the data has been extracted.I get the feeling that the hardest bit will be structuring the code so it all streams nicely.