krycha88 / GUI-Generic

MIT License
17 stars 14 forks source link

Generowanie dźwięków ;) albo wręcz odtwarzanie audio #80

Open Hrumque opened 2 years ago

Hrumque commented 2 years ago

Na modułach ESP z 4MB flash i większych (a przecież np Wemosów z 32MB nie brakuje, a kosztują ledwo 4$) - można by dodać możliwość wrzucenia przez www (jednego lub kilku) plików .wav ( czy innego małego pliku audio niekompresowanego, nie mp3, by już nie kompilować sprawy) i "odtwarzanie" audio w postaci wypuszczania PWMu na gpio pod wpływem wyzwalania lokalnego lub zdalnego (tak samo, jakby to był kanał przekaźnika).

Aby to miało sens - trzeba by zwiększyć częstotliwość PWMu (obecnie jest default 1kHz) = analogWriteFreq(new_frequency); (btw - na ustawianie tej częstotliwości dla modułów, przez WWW konfigurator, wrzucam osobne issue) można i 40kHz dać, co pozwoliłoby całkiem przyzwoicie brzmieć plikowi .wav z 8bit i 10kHz sampling, do zrobienia "gong" czy innego "ti-tu-ta" na okazję otwarcia bramy, czy zakończenia działania mikrofalówki, albo czytelny komunikat słowny "brama otwiera się" - w wielu zastosowaniach wystarczy dzwięk jak z chińskiej zabawki, nie musi być hi-fi.

Sprawdzony kod, który gra mi .WAV (8bit, mono, 8KHz) na esp:

extern "C" { #include "os_type.h" }

//use GPIO5 #define speakerPin 5 #define BufferSize 1

#include "FS.h"

File f; os_timer_t PMCtimer; int oldmicros; bool bPlaying; char buffer1[BufferSize];

void timerCallback(void *pArg) { if (f.position()>=(f.size()-1)) { stopPlayback(); //Serial.println("Finished"); return; } /*if (micros()-oldmicros>500000)//Uncomment for debugging { Serial.print(oldmicros);Serial.print(" Pos ");Serial.print(f.position()); Serial.print(" Size ");Serial.println(f.size()); oldmicros=micros(); }*/ analogWrite(speakerPin,buffer1[0]); f.readBytes(buffer1,1); } // End of timerCallback

void startPlayback() { //oldmicros=0; analogWriteRange(255);//8 Bit analogWriteFreq(32000);//Multiple of the sample rate bPlaying=true; os_timer_setfn(&PMCtimer, timerCallback, NULL); ets_timer_arm_new(&PMCtimer,125,1,0);//125us corresponds to 8000 samples/sec Serial.println("timer started");//For debugging only //Serial.print("File size in startPlayback");Serial.println(f.size());//For debugging only } void stopPlayback() { os_timer_disarm(&PMCtimer); Serial.println("timer disarmed");//For debugging only analogWrite(speakerPin, 0); bPlaying=false; } void setup() { Serial.begin(115200); Serial.println("start"); SPIFFS.begin(); Serial.println("SPIFFS started"); bPlaying=false; }

void loop() { f = SPIFFS.open("/Regal.wav", "r"); if (!f) { Serial.println("file open failed"); } else {Serial.println("file opened");} analogWriteRange(255);//8 Bit analogWriteFreq(32000);//Multiple of the sample rate Serial.print("File size ");Serial.println(f.size());//For debugging only startPlayback(); //Insert code here that will be executed while the sound file is played in the background while(bPlaying) delay(40); //use this to make sure playback is finished before closing the file f.close(); }

Plusy - w zasadzie zerowy nakład na hardware, nie potrzeba specjalistycznego DACa żadnego, zajmuje jeden pin (w przeciwieństwie do DACów wszelkich, gdzie przynajmniej i2c 2 piny trzeba by), wystarczy w najprostrzej wersji tranzystor i przetwornik piezo, albo filtr opornik-kondensator i wzmacniacz klasy D za 1$, zasilany 5v wspólnym, a dałoby to ~1W na głośniczek.