diff --git a/lib/libesp32/Berry/default/be_i2s_audio_lib.c b/lib/libesp32/Berry/default/be_i2s_audio_lib.c index 74a523d32..d41fc683f 100644 --- a/lib/libesp32/Berry/default/be_i2s_audio_lib.c +++ b/lib/libesp32/Berry/default/be_i2s_audio_lib.c @@ -11,6 +11,13 @@ extern int i2s_output_i2s_init(bvm *vm); extern int i2s_output_i2s_deinit(bvm *vm); +extern int i2s_generator_wav_init(bvm *vm); +extern int i2s_generator_wav_deinit(bvm *vm); +extern int i2s_generator_wav_begin(bvm *vm); +extern int i2s_generator_wav_loop(bvm *vm); +extern int i2s_generator_wav_stop(bvm *vm); +extern int i2s_generator_wav_isrunning(bvm *vm); + extern int i2s_generator_mp3_init(bvm *vm); extern int i2s_generator_mp3_deinit(bvm *vm); extern int i2s_generator_mp3_begin(bvm *vm); @@ -28,6 +35,7 @@ extern int i2s_file_source_fs_deinit(bvm *vm); #include "../generate/be_fixed_be_class_audio_output.h" #include "../generate/be_fixed_be_class_audio_output_i2s.h" #include "../generate/be_fixed_be_class_audio_generator.h" +#include "../generate/be_fixed_be_class_audio_generator_wav.h" #include "../generate/be_fixed_be_class_audio_generator_mp3.h" #include "../generate/be_fixed_be_class_audio_file_source.h" #include "../generate/be_fixed_be_class_audio_file_source_fs.h" @@ -42,6 +50,10 @@ void be_load_driver_audio_lib(bvm *vm) { be_setglobal(vm, "AudioOutputI2S"); be_pop(vm, 1); + be_pushntvclass(vm, &be_class_audio_generator_wav); + be_setglobal(vm, "AudioGeneratorWAV"); + be_pop(vm, 1); + be_pushntvclass(vm, &be_class_audio_generator_mp3); be_setglobal(vm, "AudioGeneratorMP3"); be_pop(vm, 1); @@ -73,6 +85,16 @@ class be_class_audio_output_i2s (scope: global, name: AudioOutputI2S, super: be_ close, func(i2s_output_i2s_deinit) } +class be_class_audio_generator_wav (scope: global, name: AudioGeneratorWAV, super: be_class_audio_generator) { + init, func(i2s_generator_wav_init) + deinit, func(i2s_generator_wav_deinit) + close, func(i2s_generator_wav_deinit) + begin, func(i2s_generator_wav_begin) + loop, func(i2s_generator_wav_loop) + stop, func(i2s_generator_wav_stop) + isrunning, func(i2s_generator_wav_isrunning) +} + class be_class_audio_generator_mp3 (scope: global, name: AudioGeneratorMP3, super: be_class_audio_generator) { init, func(i2s_generator_mp3_init) deinit, func(i2s_generator_mp3_deinit) diff --git a/lib/libesp32/Berry/generate/be_const_strtab.h b/lib/libesp32/Berry/generate/be_const_strtab.h index 9f6673837..513a00d95 100644 --- a/lib/libesp32/Berry/generate/be_const_strtab.h +++ b/lib/libesp32/Berry/generate/be_const_strtab.h @@ -230,6 +230,7 @@ extern const bcstring be_const_str_type; extern const bcstring be_const_str__request_from; extern const bcstring be_const_str___lower__; extern const bcstring be_const_str_detect; +extern const bcstring be_const_str_AudioGeneratorWAV; extern const bcstring be_const_str_HPMA_TX; extern const bcstring be_const_str_input; extern const bcstring be_const_str_issubclass; diff --git a/lib/libesp32/Berry/generate/be_const_strtab_def.h b/lib/libesp32/Berry/generate/be_const_strtab_def.h index 7aa7d626d..b36a4fcc3 100644 --- a/lib/libesp32/Berry/generate/be_const_strtab_def.h +++ b/lib/libesp32/Berry/generate/be_const_strtab_def.h @@ -230,6 +230,7 @@ be_define_const_str(type, "type", 1361572173u, 0, 4, NULL); be_define_const_str(_request_from, "_request_from", 3965148604u, 0, 13, NULL); be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, &be_const_str_detect); be_define_const_str(detect, "detect", 8884370u, 0, 6, NULL); +be_define_const_str(AudioGeneratorWAV, "AudioGeneratorWAV", 2746509368u, 0, 17, NULL); be_define_const_str(HPMA_TX, "HPMA_TX", 173233104u, 0, 7, &be_const_str_input); be_define_const_str(input, "input", 4191711099u, 0, 5, &be_const_str_issubclass); be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, NULL); @@ -765,7 +766,7 @@ static const bstring* const m_string_table[] = { (const bstring *)&be_const_str___lower__, NULL, NULL, - NULL, + (const bstring *)&be_const_str_AudioGeneratorWAV, (const bstring *)&be_const_str_HPMA_TX, (const bstring *)&be_const_str_SYMBOL_PLAY, NULL, @@ -971,6 +972,6 @@ static const bstring* const m_string_table[] = { static const struct bconststrtab m_const_string_table = { .size = 315, - .count = 630, + .count = 631, .table = m_string_table }; diff --git a/lib/libesp32/Berry/generate/be_fixed_be_class_audio_generator_wav.h b/lib/libesp32/Berry/generate/be_fixed_be_class_audio_generator_wav.h new file mode 100644 index 000000000..3436ed6e3 --- /dev/null +++ b/lib/libesp32/Berry/generate/be_fixed_be_class_audio_generator_wav.h @@ -0,0 +1,23 @@ +#include "be_constobj.h" + +static be_define_const_map_slots(be_class_audio_generator_wav_map) { + { be_const_key(close, -1), be_const_func(i2s_generator_wav_deinit) }, + { be_const_key(stop, -1), be_const_func(i2s_generator_wav_stop) }, + { be_const_key(loop, 0), be_const_func(i2s_generator_wav_loop) }, + { be_const_key(isrunning, 1), be_const_func(i2s_generator_wav_isrunning) }, + { be_const_key(begin, -1), be_const_func(i2s_generator_wav_begin) }, + { be_const_key(deinit, 6), be_const_func(i2s_generator_wav_deinit) }, + { be_const_key(init, -1), be_const_func(i2s_generator_wav_init) }, +}; + +static be_define_const_map( + be_class_audio_generator_wav_map, + 7 +); + +BE_EXPORT_VARIABLE be_define_const_class( + be_class_audio_generator_wav, + 0, + (bclass *)&be_class_audio_generator, + AudioGeneratorWAV +); diff --git a/lib/libesp32/Berry/src/be_byteslib.c b/lib/libesp32/Berry/src/be_byteslib.c index 5d18fdd0b..c171ccf02 100644 --- a/lib/libesp32/Berry/src/be_byteslib.c +++ b/lib/libesp32/Berry/src/be_byteslib.c @@ -372,7 +372,7 @@ static int m_fromstring(bvm *vm) int argc = be_top(vm); if (argc >= 2 && be_isstring(vm, 2)) { const char *s = be_tostring(vm, 2); - size_t len = strlen(s); + size_t len = be_strlen(vm, 2); buf_impl * buf = bytes_check_data(vm, 0); buf = bytes_resize(vm, buf, len); /* resize if needed */ if (len > buf->size) { len = buf->size; } /* avoid overflow */ @@ -753,6 +753,20 @@ BERRY_API const void *be_tobytes(bvm *vm, int rel_index, size_t *len) return NULL; } +BERRY_API bbool be_isbytes(bvm *vm, int rel_index) +{ + bbool ret = bfalse; + int index = be_absindex(vm, rel_index); + if (be_isinstance(vm, index)) { + be_getbuiltin(vm, "bytes"); + if (be_isderived(vm, index)) { + ret = btrue; + } + be_pop(vm, 1); + } + return ret; +} + /* Helper code to compile bytecode diff --git a/lib/libesp32/Berry/src/be_filelib.c b/lib/libesp32/Berry/src/be_filelib.c index 2a489555a..87691809b 100644 --- a/lib/libesp32/Berry/src/be_filelib.c +++ b/lib/libesp32/Berry/src/be_filelib.c @@ -16,10 +16,17 @@ static int i_write(bvm *vm) { be_getmember(vm, 1, ".p"); - if(be_iscomptr(vm, -1) && be_isstring(vm, 2)) { + if(be_iscomptr(vm, -1) && (be_isstring(vm, 2) || be_isbytes(vm, 2))) { void *fh = be_tocomptr(vm, -1); - const char *data = be_tostring(vm, 2); - be_fwrite(fh, data, be_strlen(vm, 2)); + size_t size = 0; + const char *data = NULL; + if (be_isstring(vm, 2)) { + data = be_tostring(vm, 2); + size = be_strlen(vm, 2); + } else { + data = be_tobytes(vm, 2, &size); + } + be_fwrite(fh, data, size); } be_return_nil(vm); } @@ -52,6 +59,43 @@ static int i_read(bvm *vm) be_return_nil(vm); } +static int i_readbytes(bvm *vm) +{ + int argc = be_top(vm); + be_getmember(vm, 1, ".p"); + if (be_iscomptr(vm, -1)) { + void *fh = be_tocomptr(vm, -1); + size_t size = readsize(vm, argc, fh); + if (size) { + /* avoid double allocation, using directly the internal buffer of bytes() */ + be_getbuiltin(vm, "bytes"); + be_pushint(vm, size); + be_call(vm, 1); /* call bytes() constructor with pre-sized buffer */ + be_pop(vm, 1); /* bytes() instance is at top */ + + be_getmember(vm, -1, "resize"); + be_pushvalue(vm, -2); + be_pushint(vm, size); + be_call(vm, 2); /* call b.resize(size) */ + be_pop(vm, 3); /* bytes() instance is at top */ + + char *buffer = (char*) be_tobytes(vm, -1, NULL); /* we get the address of the internam buffer of size 'size' */ + size = be_fread(fh, buffer, size); + + /* resize if something went wrong */ + be_getmember(vm, -1, "resize"); + be_pushvalue(vm, -2); + be_pushint(vm, size); + be_call(vm, 2); /* call b.resize(size) */ + be_pop(vm, 3); /* bytes() instance is at top */ + } else { + be_pushbytes(vm, NULL, 0); + } + be_return(vm); + } + be_return_nil(vm); +} + static int i_readline(bvm *vm) { be_getmember(vm, 1, ".p"); @@ -144,6 +188,7 @@ int be_nfunc_open(bvm *vm) { ".p", NULL }, { "write", i_write }, { "read", i_read }, + { "readbytes", i_readbytes }, { "readline", i_readline }, { "seek", i_seek }, { "tell", i_tell }, diff --git a/lib/libesp32/Berry/src/berry.h b/lib/libesp32/Berry/src/berry.h index e2d8270e1..52a557fd8 100644 --- a/lib/libesp32/Berry/src/berry.h +++ b/lib/libesp32/Berry/src/berry.h @@ -444,6 +444,7 @@ BERRY_API bbool be_ismap(bvm *vm, int index); BERRY_API bbool be_iscomptr(bvm *vm, int index); BERRY_API bbool be_iscomobj(bvm *vm, int index); BERRY_API bbool be_isderived(bvm *vm, int index); +BERRY_API bbool be_isbytes(bvm *vm, int index); BERRY_API bint be_toint(bvm *vm, int index); BERRY_API breal be_toreal(bvm *vm, int index); diff --git a/tasmota/xdrv_52_3_berry_audio.ino b/tasmota/xdrv_52_3_berry_audio.ino index d3e82b63a..9612de208 100644 --- a/tasmota/xdrv_52_3_berry_audio.ino +++ b/tasmota/xdrv_52_3_berry_audio.ino @@ -25,6 +25,7 @@ // #include "AudioFileSourceSPIFFS.h" // #include "AudioFileSourceID3.h" #include "AudioOutputI2S.h" +#include "AudioGeneratorWAV.h" #include "AudioGeneratorMP3.h" #include "AudioFileSourceFS.h" @@ -83,6 +84,73 @@ extern "C" { be_return_nil(vm); } + // + // AudioGeneratorWAV() + // + int i2s_generator_wav_init(bvm *vm) { + AudioGeneratorWAV * wav = new AudioGeneratorWAV(); + be_pushcomptr(vm, (void*) wav); + be_setmember(vm, 1, ".p"); + be_return_nil(vm); + } + + AudioGeneratorWAV * i2s_generator_wav_get(bvm *vm) { + be_getmember(vm, 1, ".p"); + AudioGeneratorWAV * wav = (AudioGeneratorWAV *) be_tocomptr(vm, -1); + return wav; + } + + int i2s_generator_wav_deinit(bvm *vm) { + int argc = be_top(vm); + AudioGeneratorWAV * wav = i2s_generator_wav_get(vm); + if (wav) { + delete wav; + // clear + be_pushcomptr(vm, (void*) NULL); + be_setmember(vm, 1, ".p"); + } + + be_return_nil(vm); + } + + int i2s_generator_wav_begin(bvm *vm) { + int argc = be_top(vm); + if (argc > 2) { + AudioGeneratorWAV * wav = i2s_generator_wav_get(vm); + be_getmember(vm, 2, ".p"); + AudioFileSource * source = (AudioFileSource*) be_tocomptr(vm, -1); + be_getmember(vm, 3, ".p"); + AudioOutput * output = (AudioOutput*) be_tocomptr(vm, -1); + be_pop(vm, 2); + + bool ret = wav->begin(source, output); + be_pushbool(vm, ret); + be_return(vm); + } + be_return_nil(vm); + } + + int i2s_generator_wav_loop(bvm *vm) { + AudioGeneratorWAV * wav = i2s_generator_wav_get(vm); + bool ret = wav->loop(); + be_pushbool(vm, ret); + be_return(vm); + } + + int i2s_generator_wav_stop(bvm *vm) { + AudioGeneratorWAV * wav = i2s_generator_wav_get(vm); + bool ret = wav->stop(); + be_pushbool(vm, ret); + be_return(vm); + } + + int i2s_generator_wav_isrunning(bvm *vm) { + AudioGeneratorWAV * wav = i2s_generator_wav_get(vm); + bool ret = wav->isRunning(); + be_pushbool(vm, ret); + be_return(vm); + } + // // AudioGeneratorMP3() //