Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature request: simple I2S tone() generator #643

Open
aIecxs opened this issue Aug 1, 2023 · 1 comment
Open

feature request: simple I2S tone() generator #643

aIecxs opened this issue Aug 1, 2023 · 1 comment

Comments

@aIecxs
Copy link

aIecxs commented Aug 1, 2023

I need a tone() function that can redirect audio to the DAC. ChatGPT is hallucinating and recommended <AudioGeneratorTone.h>, which, of course, does not exist.

MP3 works fine, but I want to use tone() on the same speaker without additional wiring. I have seen Arduino SimpleTone <I2S.h>, but I don't know how to change the default pinout for ESP32. I2S.setBCLK(bclkPin), I2S.setDOUT(doutPin), or I2S.setLRCLK(wclkPin)? are unknown on Arduino 1.8.19. That's why I prefer ESP8266Audio.

I had a look into AudioGeneratorRTTTL.cpp, but I don't understand how the tones are generated. I decided to play RTTTL notes instead, but I feel this is overloading with unnecessary code and memory waste. Furthermore, the notes sound different, and the mapping is inaccurate.

Click to expand
#include <AudioFileSourcePROGMEM.h>
#include <AudioGeneratorRTTTL.h>
#include <AudioOutputI2S.h>

#define WCLK_PIN 25
#define BCLK_PIN 26
#define DOUT_PIN 27

AudioFileSourcePROGMEM *file;
AudioGeneratorRTTTL *rtttl;
AudioOutputI2S *out;

void beep(int freq, unsigned int duration) {
  out = new AudioOutputI2S();
  out->SetPinout(BCLK_PIN, WCLK_PIN, DOUT_PIN);
  out->SetGain(1.0);
  unsigned long tempo = 240000 / duration;
  char rtttlString[26];
  String note;
  if (freq <= 262) note = "c4";
  else if (262 < freq && freq <= 277) note = abs(freq - 262) < abs(277 - freq) ? "c4" : "c#4";
  else if (277 < freq && freq <= 294) note = abs(freq - 277) < abs(294 - freq) ? "c#4" : "d4";
  else if (294 < freq && freq <= 311) note = abs(freq - 294) < abs(311 - freq) ? "d4" : "d#4";
  else if (311 < freq && freq <= 330) note = abs(freq - 311) < abs(330 - freq) ? "d#4" : "e4";
  else if (330 < freq && freq <= 349) note = abs(freq - 330) < abs(349 - freq) ? "e4" : "f4";
  else if (349 < freq && freq <= 370) note = abs(freq - 349) < abs(370 - freq) ? "f4" : "f#4";
  else if (370 < freq && freq <= 392) note = abs(freq - 370) < abs(392 - freq) ? "f#4" : "g4";
  else if (392 < freq && freq <= 415) note = abs(freq - 392) < abs(415 - freq) ? "g4" : "g#4";
  else if (415 < freq && freq <= 440) note = abs(freq - 415) < abs(440 - freq) ? "g#4" : "a4";
  else if (440 < freq && freq <= 466) note = abs(freq - 440) < abs(466 - freq) ? "a4" : "a#4";
  else if (466 < freq && freq <= 494) note = abs(freq - 466) < abs(494 - freq) ? "a#4" : "b4";
  else if (494 < freq && freq <= 523) note = abs(freq - 494) < abs(523 - freq) ? "b4" : "c5";
  else if (523 < freq && freq <= 554) note = abs(freq - 523) < abs(554 - freq) ? "c5" : "c#5";
  else if (554 < freq && freq <= 587) note = abs(freq - 554) < abs(587 - freq) ? "c#5" : "d5";
  else if (587 < freq && freq <= 622) note = abs(freq - 587) < abs(622 - freq) ? "d5" : "d#5";
  else if (622 < freq && freq <= 659) note = abs(freq - 622) < abs(659 - freq) ? "d#5" : "e5";
  else if (659 < freq && freq <= 698) note = abs(freq - 659) < abs(698 - freq) ? "e5" : "f5";
  else if (698 < freq && freq <= 740) note = abs(freq - 698) < abs(740 - freq) ? "f5" : "f#5";
  else if (740 < freq && freq <= 784) note = abs(freq - 740) < abs(784 - freq) ? "f#5" : "g5";
  else if (784 < freq && freq <= 831) note = abs(freq - 784) < abs(831 - freq) ? "g5" : "g#5";
  else if (831 < freq && freq <= 880) note = abs(freq - 831) < abs(880 - freq) ? "g#5" : "a5";
  else if (880 < freq && freq <= 932) note = abs(freq - 880) < abs(932 - freq) ? "a5" : "a#5";
  else if (932 < freq && freq <= 988) note = abs(freq - 932) < abs(988 - freq) ? "a#5" : "b5";
  else if (988 < freq && freq <= 1047) note = abs(freq - 988) < abs(1047 - freq) ? "b5" : "c6";
  else if (1047 < freq && freq <= 1109) note = abs(freq - 1047) < abs(1109 - freq) ? "c6" : "c#6";
  else if (1109 < freq && freq <= 1175) note = abs(freq - 1109) < abs(1175 - freq) ? "c#6" : "d6";
  else if (1175 < freq && freq <= 1245) note = abs(freq - 1175) < abs(1245 - freq) ? "d6" : "d#6";
  else if (1245 < freq && freq <= 1319) note = abs(freq - 1245) < abs(1319 - freq) ? "d#6" : "e6";
  else if (1319 < freq && freq <= 1397) note = abs(freq - 1319) < abs(1397 - freq) ? "e6" : "f6";
  else if (1397 < freq && freq <= 1480) note = abs(freq - 1397) < abs(1480 - freq) ? "f6" : "f#6";
  else if (1480 < freq && freq <= 1568) note = abs(freq - 1480) < abs(1568 - freq) ? "f#6" : "g6";
  else if (1568 < freq && freq <= 1661) note = abs(freq - 1568) < abs(1661 - freq) ? "g6" : "g#6";
  else if (1661 < freq && freq <= 1760) note = abs(freq - 1661) < abs(1760 - freq) ? "g#6" : "a6";
  else if (1760 < freq && freq <= 1865) note = abs(freq - 1760) < abs(1865 - freq) ? "a6" : "a#6";
  else if (1865 < freq && freq <= 1976) note = abs(freq - 1865) < abs(1976 - freq) ? "a#6" : "b6";
  else if (1976 < freq && freq <= 2093) note = abs(freq - 1976) < abs(2093 - freq) ? "b6" : "c7";
  else if (2093 < freq && freq <= 2217) note = abs(freq - 2093) < abs(2217 - freq) ? "c7" : "c#7";
  else if (2217 < freq && freq <= 2349) note = abs(freq - 2217) < abs(2349 - freq) ? "c#7" : "d7";
  else if (2349 < freq && freq <= 2489) note = abs(freq - 2349) < abs(2489 - freq) ? "d7" : "d#7";
  else if (2489 < freq && freq <= 2637) note = abs(freq - 2489) < abs(2637 - freq) ? "d#7" : "e7";
  else if (2637 < freq && freq <= 2794) note = abs(freq - 2637) < abs(2794 - freq) ? "e7" : "f7";
  else if (2794 < freq && freq <= 2960) note = abs(freq - 2794) < abs(2960 - freq) ? "f7" : "f#7";
  else if (2960 < freq && freq <= 3136) note = abs(freq - 2960) < abs(3136 - freq) ? "f#7" : "g7";
  else if (3136 < freq && freq <= 3322) note = abs(freq - 3136) < abs(3322 - freq) ? "g7" : "g#7";
  else if (3322 < freq && freq <= 3520) note = abs(freq - 3322) < abs(3520 - freq) ? "g#7" : "a7";
  else if (3520 < freq && freq <= 3729) note = abs(freq - 3520) < abs(3729 - freq) ? "a7" : "a#7";
  else if (3729 < freq && freq <= 3951) note = abs(freq - 3729) < abs(3951 - freq) ? "a#7" : "b7";
  else if (freq > 3951) note = "b7";
  snprintf(rtttlString, sizeof(rtttlString), "note:d=1,o=5,b=%d:%s", tempo, note);
  file = new AudioFileSourcePROGMEM(rtttlString, strlen_P(rtttlString));
  rtttl = new AudioGeneratorRTTTL();
  rtttl->begin(file, out);
  while (rtttl->isRunning()) {
    if (!rtttl->loop()) {
      rtttl->stop();
      break;
    }
  } 
  delete rtttl;
  delete file;
  delete out;
}

void setup()
{
  beep(300, 100);
  beep(400, 100);
  beep(500, 100);
}

void loop()
{
  // Code here if needed
}

I would be happy to see beep() with the same usage as tone() in the next release.

@hlcm0
Copy link

hlcm0 commented Aug 2, 2023

I think maybe this example, https://github.com/earlephilhower/ESP8266Audio/blob/master/examples/PlayWAVFromFunction/PlayWAVFromFunction.ino,
can meet your requirement. It generates sine waves as AudioSources.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants