From 77f31587f648049e5f1abeb45f49885fb97093fd Mon Sep 17 00:00:00 2001 From: JailDoctor Date: Wed, 8 Dec 2021 12:39:15 +0100 Subject: [PATCH] v0.5.2: [FEAT] play(str) [FEAT] Chime on boot [FEAT] simple song example on 'game.lua' --- ascii.cpp | 65 ++++++++++++++++++++++++++++++++++---------- ascii.h | 3 ++- game.lua | 14 +++------- lua.cpp | 9 ++++++- play.cpp | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ play.h | 6 +++++ 6 files changed, 151 insertions(+), 27 deletions(-) create mode 100644 play.cpp create mode 100644 play.h diff --git a/ascii.cpp b/ascii.cpp index 35daa69..bb7d8ed 100644 --- a/ascii.cpp +++ b/ascii.cpp @@ -3,9 +3,14 @@ #include #include "lua.h" #include "rom.c" +#include "play.h" #define swap(a, b) {auto tmp=a;a=b;b=tmp;} +#define AUDIO_NONE 0 +#define AUDIO_SOUND 1 +#define AUDIO_PLAY 2 + char lua_filename[1024]; char window_title[256]; uint8_t mem[8192]; //2400 @@ -17,7 +22,7 @@ uint8_t current_color = 0x1e; uint8_t current_mode = 1; uint8_t cursor_x = 0; uint8_t cursor_y = 0; -bool sounding = false; +uint8_t audio_state = AUDIO_NONE; int audio_freq = 0; uint32_t audio_len = 0; @@ -92,16 +97,41 @@ void reinit() { } } +static Uint8* play_pos; +static Uint32 play_len; +static Uint8 play_buffer[132300]; + void audioCallback(void * userdata, uint8_t * stream, int len) { - //if (audio_len <= 0) nosound(); - static int period=0; - static int v = 16; - SDL_memset(stream, 0, len); - const int flen = min(audio_len, len); - audio_len -= flen; - for (int i=0; i=audio_freq) {period = 0; v=-v;} + if (audio_state == AUDIO_SOUND) { + if (audio_len <= 0) audio_state = AUDIO_NONE; + static int period=0; + static int v = 16; + SDL_memset(stream, 0, len); + const int flen = min(audio_len, len); + audio_len -= flen; + for (int i=0; i=audio_freq) {period = 0; v=-v;} + } + } else if (audio_state == AUDIO_PLAY) { + while( len > 0 ) { + while( play_len == 0 ) { + play_len = interpret_next_token(play_buffer); + if (play_len == -1) { audio_state=AUDIO_NONE; SDL_memset( stream, 0, len ); return; } + play_pos = play_buffer; + } + const int actual_len = ( len > play_len ? play_len : len ); + //SDL_memset( stream, 0, actual_len ); + //SDL_MixAudio( stream, audio_pos, actual_len, SDL_MIX_MAXVOLUME ); + SDL_memcpy(stream, play_pos, actual_len); + + stream += actual_len; + play_pos += actual_len; + play_len -= actual_len; + len -= actual_len; + } + } else { + SDL_memset(stream, 0, len); } } @@ -126,7 +156,7 @@ int main(int argc,char*argv[]) { bool exit = false; SDL_Event mini_eve; - SDL_AudioSpec audioSpec = {44100, AUDIO_S8, 1, 0, 512, 0, 0, audioCallback, NULL}; + SDL_AudioSpec audioSpec = {22050, AUDIO_S8, 1, 0, 512, 0, 0, audioCallback, NULL}; mini_audio_device = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0); SDL_PauseAudioDevice(mini_audio_device, 0); @@ -480,14 +510,21 @@ void memcpy(uint16_t dst, uint16_t src, uint16_t size) { void sound(float freq, uint32_t len) { // [TODO] audio_len = len*44.1f; - audio_freq = 44100.0f/freq/2.0f; - sounding = true; + audio_freq = 22050.0f/freq/2.0f; + audio_state = AUDIO_SOUND; } void nosound() { //SDL_PauseAudioDevice(mini_audio_device, 1); audio_len = 0; - sounding = false; + audio_state = AUDIO_NONE; +} + +void play(const char* str) { + play_pos = play_buffer; + play_len = 0; + play_init(str); + audio_state = AUDIO_PLAY; } void setmode(const uint8_t mode) { diff --git a/ascii.h b/ascii.h index 800848d..040a9fd 100644 --- a/ascii.h +++ b/ascii.h @@ -170,8 +170,9 @@ void memcpy(uint16_t dst, uint16_t src, uint16_t size); void sound(float freq, uint32_t len); void nosound(); -void setmode(const uint8_t mode); +void play(const char* str); +void setmode(const uint8_t mode); void load(const char* str); void fileout(const char* str, uint16_t addr, uint16_t size); diff --git a/game.lua b/game.lua index d7e3d26..30bb146 100644 --- a/game.lua +++ b/game.lua @@ -1,17 +1,9 @@ function init() setmode(0) + cls() + play("o4v5l1crcl4dcferl1crcl4dcgfr") end function update() - cls() - locate(0,0) - if mousebutton(1) then - print("Has pulsat el boto esquerre") - elseif mousebutton(2) then - print("Has pulsat el boto del mig") - elseif mousebutton(3) then - print("Has pulsat el boto dret") - else - print("No has pulsat cap boto") - end + end \ No newline at end of file diff --git a/lua.cpp b/lua.cpp index ef1c027..18d8c92 100644 --- a/lua.cpp +++ b/lua.cpp @@ -220,6 +220,12 @@ extern "C" { return 0; } + static int cpp_play(lua_State *L) { + const char* str = luaL_optstring(L, 1, NULL); + play(str); + return 0; + } + static int cpp_setmode(lua_State *L) { int val = luaL_checkinteger(L, 1); setmode(val); @@ -268,7 +274,7 @@ bool lua_is_playing() { return lua_state == STATE_PLAYING; } -const char boot[] = "function init()setmode(1)cls()memcpy(360,4608,240)memcpy(1560,4848,240)ink(1)print('G A M E',8,16)ink(4)print('S Y S T E M',20,16)ink(8)print('v0.5.1',26,8)w=0 end function update()w=w+1 if w>90 then cls()load()end end"; +const char boot[] = "function init()setmode(1)cls()play('o5l0v5cegv4cegv3cegv2cegv1ceg')memcpy(360,4608,240)memcpy(1560,4848,240)ink(1)print('G A M E',8,16)ink(4)print('S Y S T E M',20,16)ink(8)print('v0.5.1',26,8)w=0 end function update()w=w+1 if w>90 then cls()load()end end"; void lua_init(const char* filename, const bool start_playing) { if (lua_state != STATE_STOPPED) lua_quit(); @@ -335,6 +341,7 @@ void lua_init(const char* filename, const bool start_playing) { lua_pushcfunction(L,cpp_memcpy); lua_setglobal(L, "memcpy"); lua_pushcfunction(L,cpp_sound); lua_setglobal(L, "sound"); lua_pushcfunction(L,cpp_nosound); lua_setglobal(L, "nosound"); + lua_pushcfunction(L,cpp_play); lua_setglobal(L, "play"); lua_pushcfunction(L,cpp_setmode); lua_setglobal(L, "setmode"); lua_pushcfunction(L,cpp_load); lua_setglobal(L, "load"); lua_pushcfunction(L,cpp_log); lua_setglobal(L, "log"); diff --git a/play.cpp b/play.cpp new file mode 100644 index 0000000..2ae8d51 --- /dev/null +++ b/play.cpp @@ -0,0 +1,81 @@ +#include "play.h" +#include +#include + +const static uint16_t lengths[10] = { 313, 625, 938, 1250, 1875, 2500, 3750, 5000, 7500, 10000 }; +const static uint16_t tempos[10] = { 13230, 8820, 6615, 5292, 4410, 3780, 3308, 2940, 2646, 2406 }; +const float periods[108] = { 1348.49207, 1272.80688, 1201.37, 1133.94214, 1070.29871, 1010.22772, 953.527893, 900.010376, 849.496887, 801.818176, 756.815613, 714.338745, 674.246033, 636.403564, 600.684875, 566.971069, 535.149475, 505.11377, 476.763947, 450.005249, 424.748352, 400.909088, 378.407806, 357.169373, 337.123016, 318.201782, 300.342438, 283.485535, 267.574738, 252.556885, 238.381973, 225.002625, 212.374176, 200.454544, 189.203888, 178.584702, 168.561508, 159.100876, 150.171234, 141.742767, 133.787354, 126.278458, 119.190987, 112.501305, 106.187096, 100.227272, 94.6019516, 89.2923508, 84.2807541, 79.5504379, 75.0856171, 70.8713837, 66.8936768, 63.139225, 59.5954933, 56.2506561, 53.0935478, 50.113636, 47.3009758, 44.6461754, 42.140377, 39.775219, 37.5428085, 35.4356918, 33.4468384, 31.5696125, 29.7977467, 28.1253281, 26.5467739, 25.056818, 23.650486, 22.3230877, 21.0701885, 19.8876095, 18.7714043, 17.7178459, 16.7234192, 15.7848072, 14.8988733, 14.0626631, 13.273387, 12.528409, 11.8252439, 11.1615429, 10.5350943, 9.94380569, 9.38570118, 8.85892296, 8.36171055, 7.89240265, 7.44943666, 7.03133202, 6.636693, 6.2642045, 5.91262197, 5.58077145, 5.26754713, 4.97190285, 4.69285059, 4.42946148, 4.18085527, 3.94620132, 3.72471833, 3.51566601, 3.3183465, 3.13210225, 2.95631051, 2.7903862 }; + +static float default_length = 0.25f; +static uint8_t volume = 64; +static uint8_t octave = 4; +static uint32_t tempo = 44100; +static char* song_ptr = NULL; +static char* song = NULL; + +uint32_t interpret_note(uint8_t* buffer, const char note, const char param ) { + const uint32_t length = ( param == -1 ? default_length : ((float)lengths[param])/10000.0f ) * tempo; + if( note == 100 ) { memset( buffer, 0, length ); return length; } + const uint16_t period = periods[note + octave*12]; + + for( int i = 0; i < length; i++ ) buffer[i] = ( (i % period) < (period >> 1) ? volume : -volume ); + return length; +} + +void play_init(const char* new_song) { + if (song != NULL) free(song); + song = (char*)malloc( strlen( new_song ) + 1 ); + strcpy( song, new_song ); + song_ptr = song; +} + +int32_t interpret_next_token(uint8_t* buffer) { + char** token = &song_ptr; + char note = 0; + char param = -1; + + switch( **token ) { + case 'b': note += 2; + case 'a': note += 2; + case 'g': note += 2; + case 'f': note += 1; + case 'e': note += 2; + case 'd': note += 2; + case 'c': + param = *++*token; + if( param == '#' || param == '+' ) { note++; param = *++*token; } else if( param == '-' ) { note--; param = *++*token; } + if( param >= 48 && param <= 57 ) { param -= 48; ++*token; } else { param = -1; } + return interpret_note( buffer, note, param ); + case 'r': + param = *++*token; + if( param >= 48 && param <= 57 ) { param -= 48; ++*token; } else { param = -1; } + return interpret_note( buffer, 100, param ); + case 'o': + param = *++*token; + if( param >= 48 && param <= 57 ) { octave = (param - 48) % 8; ++*token; } + return 0; + case '>': + octave = (octave+1) % 8; ++*token; + return 0; + case '<': + octave = (octave-1) % 8; ++*token; + return 0; + case 'l': + param = *++*token; + if( param >= 48 && param <= 57 ) { default_length = ((float)lengths[param - 48])/10000.0f; ++*token; } + return 0; + case 'v': + param = *++*token; + if( param >= 48 && param <= 57 ) { volume = (param - 48) << 4; ++*token; } + return 0; + case 't': + param = *++*token; + if( param >= 48 && param <= 57 ) { tempo = tempos[param - 48] * 10; ++*token; } + return 0; + case '\0': + return -1; + default: + ++*token; + return 0; + }; +} \ No newline at end of file diff --git a/play.h b/play.h new file mode 100644 index 0000000..68abe2a --- /dev/null +++ b/play.h @@ -0,0 +1,6 @@ +#pragma once +#include + +void play_init(const char* new_song); + +int32_t interpret_next_token(uint8_t* buffer);