earlephilhower / ESP8266Audio

Arduino library to play MOD, WAV, FLAC, MIDI, RTTTL, MP3, and AAC files on I2S DACs or with a software emulated delta-sigma DAC on the ESP8266 and ESP32
GNU General Public License v3.0
2.05k stars 437 forks source link

Rtttl format #79

Closed CosmicMac closed 6 years ago

CosmicMac commented 6 years ago

Hi Earl,

I know this idea may sound (!) strange, but how about adding an audio generator for Rtttl format? For my current project I'd like to play MP3s as well as NES-style sounds.

The MP3 part already works very well, thanks to your excellent work.

Cheers!

earlephilhower commented 6 years ago

You mean the Nokia ringtones like https://en.wikipedia.org/wiki/Ring_Tone_Transfer_Language ? That's almost trivial as it's only monophonic, square wave, and no loops or anything. Probably 2 screens worth of code.

CosmicMac commented 6 years ago

That's it. Actually I've already done some succesful tests, based on https://github.com/spicajames/Rtttl and https://www.arduino.cc/en/Tutorial/I2SSimpleTone, but unfortunately I don't feel comfortable enough with c++ to do a clean integration with your lib.

earlephilhower commented 6 years ago

Check my latest push. Use PROGMEMFile(tune, strlen(tune)) and the AudioGeneratorRTTTL.

When I play it on my I2S DAC, something weird happens and it mutes the whole thing, but I've been doing experiments w/I2S and recording, so it could be just me. But, when I send the output to my PC and play it It sounds just fine (for such amount of fine that square-wave, monophonic tunes can give).

CosmicMac commented 6 years ago

Many thanks Earl, you're damn fast! I'll do my best to give it a try this evening (I'm in CEST time zone).

earlephilhower commented 6 years ago

It cheesed me off enough to actually debug it, and the I2S DAC was just not sync'ing when presented with perfect square waveforms. To work around it, I've added a slightly less abrupt waveform and it's playing like a champ. There's also an example now, so I think it's actually done. Maybe 3 screens of code with error checking...

CosmicMac commented 6 years ago

Excellent! It works like a charm and the sound is just... perfect (well, as perfect as it can be :-) ). I only had to drastically lower the gain (to .05) to get an acceptable level with my Adafruit's MAX98357A. Maybe 64k is a bit too much amplitude? (funny wave shape by the way).

Now, I just have to figure out how to use standard strings as a source since I plan to send melodies as MQTT messages. Your PROGMEM source looks like a good starting point and I should be able to adapt it on my own.

Once again, many thanks for your very quick and efficient help.

earlephilhower commented 6 years ago

The wave's just my hand-waving of a square wave with a slight rise and fall time and flutter for "richer" sound. :) I did try a real sinusoid in there as well but it didn't really help the sound. It's not too hard to do an ADSR envelope on the playback waveform, but at that point I think you've gone too far for the source material.

For the MQTT strings, just use the PROGMEMData source. It works fine for RAM sources as well, just slightly slower. Given that we're talking about reading 100 bytes or so, it's absolutely not an issue. The only caveat is you need to ensure the string is not free()'d or go out of scope during playback as the data source doesn't copy it.

Also, please make sure to delete the file and generator objects after playback. My examples are quick and dirty, not to be emulated, sadly.

CosmicMac commented 6 years ago

Good to know... Thanks for the advices!

CosmicMac commented 6 years ago

I confirm that PROGMEM data source works perfectly with my current MQTT flow. :)

And I confirm too that I had to flatten your wave to lower the volume and keep it consistent between MP3 and RTTTL (I want to feed my toy indifferently with MP3 URLs, MP3 SPIFFS filenames or RTTTL strings without having to adjust the gain).

+8000/-8000 (25%) seems OK, but I will do real tests during next week-end.

earlephilhower commented 6 years ago

I think the scale thing is due to a bug in the ESP8266 core I2S libs. I'm going to try a fix this evening which should make it not produce junk when the MSB is set.

https://github.com/esp8266/Arduino/issues/4571

You don't need to change any code, just add a out->SetGain(0.4) or whatever, to simplify things. Or, it may just work fine once the bug is fixed.

CosmicMac commented 6 years ago

Actually, I already use the SetGain function.

The problem is the huge difference of volume, for the same gain, between MP3 and RTTL. To keep a constant volume, I have to adjust the gain on the fly at each format change (0.3 for MP3 and 0.02 for RTTTL, for example ). Limiting the wave amplitude appeared to me as a quick and not too dirty solution to address the problem but I admit I have very limited knowledge in this domain.

Not a big deal anyway, and I'm more than happy with your solution.

earlephilhower commented 6 years ago

Great! I went back to a square wave, saves ~128 bytes of progmem and some CPU cycles. The I2S fix in ESP8266 core isn't necessary, but will help with the volume output once it's committed.

Closing.

CosmicMac commented 6 years ago

Perfect! Thanks for your time.