[HN Gopher] Digital Audio 101: Playing Audio from a Microcontroller
___________________________________________________________________
Digital Audio 101: Playing Audio from a Microcontroller
Author : sreedevk
Score : 75 points
Date : 2021-04-15 14:05 UTC (8 hours ago)
(HTM) web link (blog.tarkalabs.com)
(TXT) w3m dump (blog.tarkalabs.com)
| kayson wrote:
| I did something similar a long time ago trying to make a little
| box that played the Kool-Aid guy saying "Oh Yeah" when you hit a
| button. It was relatively easy to make it work, by resampling and
| quantizing the .wav, then loading that into an Arduino timer/PWM
| generator. But as others have said, quality wasn't great.
|
| A big issue I ran into was filling up the data memory, which was
| what required such limiting quantization. I'm curious if anyone
| has tried doing this sort of audio but using a noise-shaping
| quantizer (i.e. Delta Sigma Modulation), as that was my next plan
| but I forgot about the project.
|
| With DSM, you can generate a higher frequency 1 bit sequence,
| that when filtered recovers the original audio signal. The
| benefit here being that for the same amount of storage space, you
| can push the quantization noise into higher frequencies that
| aren't as prevalent in speech/music, then filter it off.
| aappleby wrote:
| I had 8-ish channel FM synthesis (using a bunch of lookup tables)
| on a stock 8-bit ATMega-based Arduino back in the day.
|
| Any modern Cortex-based microcontroller has more than enough
| oomph to handle 4x as many voices plus filters, etc.
| barbegal wrote:
| This simple code produces a square wave which can sound ok when
| fed through a buzzer which has a string resonant frequency. The
| harmonics are attenuated enough that it sounds ok playing notes
| close to the resonant frequency. For anything else you'll want a
| separate DAC (digital to analog converter) which can use I2C, I2S
| or SPI digital signals and outputs an analogue signal.
|
| You can also use a scheme a little bit like PWM called PCM where
| the GPIO pin can be switched on and off at a frequency much
| higher than audio (typically 2Mhz or higher) and the duty cycle
| is varied at the sample rate. This can be implemented on an
| Arduino using code like
| https://github.com/damellis/PCM/blob/master/PCM.c
| justinzollars wrote:
| https://www.youtube.com/watch?v=3dQjIeYoIdM
| amelius wrote:
| Does anyone know where to find suitable equivalent electrical
| models of speakers and piezo buzzers?
|
| So, for example, a speaker will become an inductor with a series
| resistor to represent losses, and another resistor to represent
| power that is converted to audio.
|
| The reason for asking is that I want to be able to plug it into a
| simulator (spice) and also simulate the mechanical part (using an
| electrical equivalent circuit).
|
| EDIT: found something here: https://audiojudgement.com/speaker-
| equivalent-circuit/
| nerfhammer wrote:
| a piezo is more like a capacitor
| amelius wrote:
| Correct, you have different models for those.
| dvh wrote:
| I'm using this for guitar pickup (2.5H 5kOhm, 30pF,
| 50mV@440Hz), you can modify it to be more like dynamic speaker
| (e.g. 8ohm Rs, smaller L0 which you measure from actual
| speaker) .subckt sub_pickup_1 a b L0
| a 1 2.5 NT=1 Rs 1 b 5000 Cp a b 3.0E-11
| Rp a b 10000000 V1 a 2 DC 0 AC 0.01 0 SIN(0 0.05 440 0
| 0 0) R1 2 b 1 .ends sub_pickup_1 xL1 7
| 0 sub_pickup_1
| amelius wrote:
| Thanks, but it's not clear to me how/if you modeled the
| electrical losses related to emitted acoustic power.
| Nihilartikel wrote:
| With microcontrollers being as fast as they are, and most having
| some hardware PWM capability even the very tiny ones, like the
| ATTiny85 can be startlingly capable synths, if you're satisfied
| with ~15khz 8bit audio fidelity.
|
| At 8/16 mhz there are plenty of cycles for multi-channel audio
| synthesis. Not much room for samples, but a lot can be done with
| envelopes, saw, square, and noise waveforms.
|
| https://github.com/blakelivingston/DuinoTune
|
| https://www.youtube.com/watch?v=G3baH5iTcFM
| salehenrahman wrote:
| I could almost swear that you can even create a class-D
| amplifier with the ATTiny85, with a clock rate of ~15kHz.
|
| Obviously it's not going to be ideal for an audiophile, but the
| quality is not too shabby. A fun project for those curious.
|
| Still, stick to off-the-shelf class-D amplifiers, such as the
| PAM8403.
|
| https://www.youtube.com/watch?v=O8of40tFsD8
| Nihilartikel wrote:
| That would be really cool. Never got around to trying it, but
| I'm really curious about the subjective quality on the 12bit
| A/D conversion looping back to PWM D/A.
|
| LoFi effects pedals could be fun.
| lb1lf wrote:
| -The 12 bit A/D provides a (theoretical) 72dB of S/N, so if
| you can do that at a decent sample rate to get sufficient
| bandwidth, the digitizing should be good.
|
| As long as the PWM D/A has a good clock to keep the PWM
| ratio accurate, I think it should be eminently listenable,
| given a proper reconstruction filter and a decent power
| supply.
|
| It would be fun to try this.
| squarefoot wrote:
| > I could almost swear that you can even create a class-D
| amplifier with the ATTiny85, with a clock rate of ~15kHz.
|
| Pretty sure you can do that. A Class D amplifier is to a
| class A/B traditional one what a switching power supply is to
| a linear one, so I would expect to be able to make a class D
| amplifier using for example a PWM driven H bridge usually
| employed to drive electric motors, or a chip used to make
| switching power supplies. If they can work at high
| frequencies (say 50KHz or more) then they should work; all
| it's needed is modulating their input or feedback pins the
| right way. Probably not HiFi for the sensitive ear, still
| good enough.
| squarefoot wrote:
| Interesting, thanks for sharing. I'd be interested in
| experimenting a hybrid approach in which the microcontroller
| takes MIDI in then generates basic waves (saw, square, sine
| etc) to keep resource consumption as low as possible while
| maximizing poliphony (layering with detune, etc), then leaving
| to analog circuitry noise generation, filtering, enevelopes
| etc. It would make things more complicated hardware-wise but
| I'm sure the sound would improve significantly, at least for us
| old beards who still love analog synths from the 70s.
| nitrogen wrote:
| I have an Ensoniq SQ-80 synthesizer that did something like
| that. A microcontroller generates 8 channels of sounds from a
| PCM wavetable, and those are fed into 8 analog filters before
| mixing down to stereo. But all of the waveforms and envelopes
| were digital.
| officeplant wrote:
| Thanks for posting this. I picked up a Pico Pi recently and
| developing a simple synthesizer is one of my first goals.
| 1-6 wrote:
| The next thing I would like to hear is a voicefile.wav converted
| to instructions for microcontroller.
| Zardoz84 wrote:
| Related... the genius and simply idea of how archive a 1:8 ratio
| compression and preserve an acceptable quality for free. The
| Binary Time Constant sound compression algorithm :
| https://www.romanblack.com/btc_alg.htm
| riskable wrote:
| I'd be more interested to see methods of playing notes like this
| asynchronously; without having it block the main loop while the
| notes play.
|
| If you've got multiple cores it's no problem: Just run the note-
| playing code on a different core. However, if you've only got one
| core you'll need some method to play those notes without
| disrupting the main loop.
| virgil_disgr4ce wrote:
| I mean... a microcontroller has only one 'loop'. If you don't
| want to 'block' it, you either 1) use external devices, i.e. a
| synth chip or 2) compose the multiple notes you want into one
| signal. If you're doing PWM only then option 2 will rapidly
| start to present interesting challenges.
| chabes wrote:
| Some MCUs have multiple cores
| makapuf wrote:
| But those dual core are generally way more powerful that a
| cortex m4 at 100mhz with a dac, where pwm gen is not
| necessary.
| aappleby wrote:
| You set up a timer to fire a "calculate next sample" interrupt
| at ~4khz, then your main thread just walks through your MIDI
| file or whatever and tweaks the synthesizer settings.
| mycroftcomptro wrote:
| It's pretty easy to do with one core, too - I would guess that
| the author didn't use interrupts or peripherals because they
| were writing about MCUs in general rather than a specific
| chipset. The K210 they used as an example is actually targeted
| towards ML applications.
|
| Most chips will have some sort of PWM or advanced timer
| peripheral that can generate waveforms on a pin without direct
| CPU intervention. You write to registers to change the
| frequency, duty cycle, etc.
|
| Many chips also include asynchronous DACs, but they're usually
| too low-resolution for high-fidelity audio.
|
| Most microcontrollers also include some form of DMA, which can
| shuttle data between peripherals and memory without CPU
| intervention. You can also user timer peripherals to trigger
| DMA transfers, which lets you send buffered data to a DAC on a
| KHz schedule while the CPU does other things.
|
| And of course, you can usually use timer peripherals to
| periodically interrupt the main thread when you don't want to
| wait in a busy-loop.
| Nihilartikel wrote:
| It's a little bit more complexity, but cheesy 'multitasking'
| can be achieved with interrupts on HW timers. The main loop
| sets the synth 'state' and the interrupts act on it.
|
| In DuinoTune [1] the song playback had a per song 'tick' timer
| interrupt at 12 per beat which handles note on/off, envelope,
| pitch/audio glides. And a per-sample timer interrupt which does
| a mixdown of the voices and updates the hardware PWM duty-cycle
| to generate the waveform.
|
| [1] https://github.com/blakelivingston/DuinoTune
___________________________________________________________________
(page generated 2021-04-15 23:01 UTC)