diff --git a/chirp.cpp b/chirp.cpp new file mode 100644 index 0000000..a9792cf --- /dev/null +++ b/chirp.cpp @@ -0,0 +1,146 @@ +#include "chirp.h" +#include +#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; + + + +#define AUDIO_NONE 0 +#define AUDIO_SOUND 1 +#define AUDIO_PLAY 2 + +uint8_t audio_state = AUDIO_NONE; +int audio_freq = 0; +uint32_t audio_len = 0; + +SDL_AudioDeviceID audio_device; + +static Uint8* play_pos; +static Uint32 play_len; +static Uint8 play_buffer[132300]; + +void audioCallback(void * userdata, uint8_t * stream, int len) { + 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 = SDL_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); + } +} + +void chirp_init() { + SDL_AudioSpec audioSpec = {22050, AUDIO_S8, 1, 0, 512, 0, 0, audioCallback, NULL}; + audio_device = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0); + SDL_PauseAudioDevice(audio_device, 0); +} + +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 chirp_play(const char* new_song) { + play_pos = play_buffer; + play_len = 0; + + volume=64; + octave=4; + tempo=44100; + if (song != NULL) free(song); + song = (char*)malloc( strlen( new_song ) + 1 ); + strcpy( song, new_song ); + song_ptr = song; + + audio_state = AUDIO_PLAY; +} + +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/chirp.h b/chirp.h new file mode 100644 index 0000000..30e7120 --- /dev/null +++ b/chirp.h @@ -0,0 +1,8 @@ +#pragma once +#include + +void chirp_init(); + +void chirp_play(const char* new_song); + +int32_t interpret_next_token(uint8_t* buffer); diff --git a/jail_audio.cpp b/jail_audio.cpp deleted file mode 100644 index eaa2fd9..0000000 --- a/jail_audio.cpp +++ /dev/null @@ -1,259 +0,0 @@ -#include "jail_audio.h" -#include "stb_vorbis.c" -#include -#include -#include "jfile.h" - -#define JA_MAX_SIMULTANEOUS_CHANNELS 5 - -struct JA_Sound_t { - Uint32 length {0}; - Uint8* buffer {NULL}; -}; - -struct JA_Channel_t { - JA_Sound sound; - int pos {0}; - int times {0}; - JA_Channel_state state { JA_CHANNEL_FREE }; -}; - -struct JA_Music_t { - int samples {0}; - int pos {0}; - int times {0}; - short* output {NULL}; - JA_Music_state state {JA_MUSIC_INVALID}; -}; - -JA_Music current_music{NULL}; -JA_Channel_t channels[JA_MAX_SIMULTANEOUS_CHANNELS]; - -int JA_freq {48000}; -SDL_AudioFormat JA_format {AUDIO_S16}; -Uint8 JA_channels {2}; -int JA_volume = 128; -SDL_AudioDeviceID sdlAudioDevice = 0; - -void audioCallback(void * userdata, uint8_t * stream, int len) { - SDL_memset(stream, 0, len); - if (current_music != NULL && current_music->state == JA_MUSIC_PLAYING) { - const int size = SDL_min(len, current_music->samples*2-current_music->pos); - SDL_MixAudioFormat(stream, (Uint8*)(current_music->output+current_music->pos), AUDIO_S16, size, JA_volume); - current_music->pos += size/2; - if (size < len) { - if (current_music->times != 0) { - SDL_MixAudioFormat(stream+size, (Uint8*)current_music->output, AUDIO_S16, len-size, JA_volume); - current_music->pos = (len-size)/2; - if (current_music->times > 0) current_music->times--; - } else { - current_music->pos = 0; - current_music->state = JA_MUSIC_STOPPED; - } - } - } - // Mixar els channels mi amol - for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { - if (channels[i].state == JA_CHANNEL_PLAYING) { - const int size = SDL_min(len, channels[i].sound->length - channels[i].pos); - SDL_MixAudioFormat(stream, channels[i].sound->buffer + channels[i].pos, AUDIO_S16, size, JA_volume/2); - channels[i].pos += size; - if (size < len) { - if (channels[i].times != 0) { - SDL_MixAudioFormat(stream + size, channels[i].sound->buffer, AUDIO_S16, len-size, JA_volume/2); - channels[i].pos = len-size; - if (channels[i].times > 0) channels[i].times--; - } else { - JA_StopChannel(i); - } - } - } - } -} - -void JA_Init(const int freq, const SDL_AudioFormat format, const int channels) { - JA_freq = freq; - JA_format = format; - JA_channels = channels; - SDL_AudioSpec audioSpec{JA_freq, JA_format, JA_channels, 0, 1024, 0, 0, audioCallback, NULL}; - if (sdlAudioDevice != 0) SDL_CloseAudioDevice(sdlAudioDevice); - sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0); - SDL_PauseAudioDevice(sdlAudioDevice, 0); -} - -void JA_Quit() { - SDL_PauseAudioDevice(sdlAudioDevice, 1); - if (sdlAudioDevice != 0) SDL_CloseAudioDevice(sdlAudioDevice); - sdlAudioDevice = 0; -} - -JA_Music JA_LoadMusic(const char* filename) { - int chan, samplerate; - JA_Music music = new JA_Music_t(); - - int fsize; - Uint8 *buffer = (Uint8*)file_getfilebuffer(filename, fsize); - - // [RZC 28/08/22] Carreguem primer el arxiu en memòria i després el descomprimim. Es algo més rapid. - /* - FILE *f = fopen(filename, "rb"); - fseek(f, 0, SEEK_END); - long fsize = ftell(f); - fseek(f, 0, SEEK_SET); - Uint8 *buffer = (Uint8*)malloc(fsize + 1); - fread(buffer, fsize, 1, f); - fclose(f); - */ - - music->samples = stb_vorbis_decode_memory(buffer, fsize, &chan, &samplerate, &music->output); - free(buffer); - // [RZC 28/08/22] Abans el descomprimiem mentre el teniem obert -// music->samples = stb_vorbis_decode_filename(filename, &chan, &samplerate, &music->output); - - SDL_AudioCVT cvt; - SDL_BuildAudioCVT(&cvt, AUDIO_S16, chan, samplerate, JA_format, JA_channels, JA_freq); - if (cvt.needed) { - cvt.len = music->samples * chan * 2; - cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult); - SDL_memcpy(cvt.buf, music->output, cvt.len); - SDL_ConvertAudio(&cvt); - free(music->output); - music->output = (short*)cvt.buf; - } - music->pos = 0; - music->state = JA_MUSIC_STOPPED; - - return music; -} - -void JA_PlayMusic(JA_Music music, const int loop) { - if (current_music != NULL) { - current_music->pos = 0; - current_music->state = JA_MUSIC_STOPPED; - } - current_music = music; - current_music->pos = 0; - current_music->state = JA_MUSIC_PLAYING; - current_music->times = loop; -} - -void JA_PauseMusic() { - if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return; - current_music->state = JA_MUSIC_PAUSED; -} - -void JA_ResumeMusic() { - if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return; - current_music->state = JA_MUSIC_PLAYING; -} - -void JA_StopMusic() { - if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return; - current_music->pos = 0; - current_music->state = JA_MUSIC_STOPPED; -} - -JA_Music_state JA_GetMusicState() { - if (current_music == NULL) return JA_MUSIC_INVALID; - return current_music->state; -} - -void JA_DeleteMusic(JA_Music music) { - if (current_music == music) current_music = NULL; - free(music->output); - delete music; -} - -JA_Sound JA_NewSound(Uint8* buffer, Uint32 length) { - JA_Sound sound = new JA_Sound_t(); - sound->buffer = buffer; - sound->length = length; - return sound; -} - -JA_Sound JA_LoadSound(const char* filename) { - JA_Sound sound = new JA_Sound_t(); - SDL_AudioSpec wavSpec; - - //SDL_LoadWAV(filename, &wavSpec, &sound->buffer, &sound->length); - int size; - char *buffer = file_getfilebuffer(filename, size); - SDL_LoadWAV_RW(SDL_RWFromMem(buffer, size),1, &wavSpec, &sound->buffer, &sound->length); - free(buffer); - - SDL_AudioCVT cvt; - SDL_BuildAudioCVT(&cvt, wavSpec.format, wavSpec.channels, wavSpec.freq, JA_format, JA_channels, JA_freq); - cvt.len = sound->length; - cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult); - SDL_memcpy(cvt.buf, sound->buffer, sound->length); - SDL_ConvertAudio(&cvt); - SDL_FreeWAV(sound->buffer); - sound->buffer = cvt.buf; - sound->length = cvt.len_cvt; - - return sound; -} - -int JA_PlaySound(JA_Sound sound, const int loop) { - int channel = 0; - while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE) { channel++; } - if (channel == JA_MAX_SIMULTANEOUS_CHANNELS) channel = 0; - - channels[channel].sound = sound; - channels[channel].times = loop; - channels[channel].pos = 0; - channels[channel].state = JA_CHANNEL_PLAYING; - return channel; -} - -void JA_DeleteSound(JA_Sound sound) { - for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { - if (channels[i].sound == sound) JA_StopChannel(i); - } - SDL_free(sound->buffer); - delete sound; -} - -void JA_PauseChannel(const int channel) { - if (channel == -1) { - for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { - if (channels[i].state == JA_CHANNEL_PLAYING) channels[i].state = JA_CHANNEL_PAUSED; - } - } else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) { - if (channels[channel].state == JA_CHANNEL_PLAYING) channels[channel].state = JA_CHANNEL_PAUSED; - } -} - -void JA_ResumeChannel(const int channel) { - if (channel == -1) { - for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { - if (channels[i].state == JA_CHANNEL_PAUSED) channels[i].state = JA_CHANNEL_PLAYING; - } - } else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) { - if (channels[channel].state == JA_CHANNEL_PAUSED) channels[channel].state = JA_CHANNEL_PLAYING; - } -} - -void JA_StopChannel(const int channel) { - if (channel == -1) { - for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { - channels[i].state = JA_CHANNEL_FREE; - channels[i].pos = 0; - channels[i].sound = NULL; - } - } else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) { - channels[channel].state = JA_CHANNEL_FREE; - channels[channel].pos = 0; - channels[channel].sound = NULL; - } -} - -JA_Channel_state JA_GetChannelState(const int channel) { - if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return JA_CHANNEL_INVALID; - return channels[channel].state; -} - -int JA_SetVolume(int volume) { - JA_volume = volume > 128 ? 128 : volume < 0 ? 0 : volume; - return JA_volume; -} \ No newline at end of file diff --git a/jail_audio.h b/jail_audio.h deleted file mode 100644 index 7d03400..0000000 --- a/jail_audio.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once -#include - -enum JA_Channel_state { JA_CHANNEL_INVALID, JA_CHANNEL_FREE, JA_CHANNEL_PLAYING, JA_CHANNEL_PAUSED }; -enum JA_Music_state { JA_MUSIC_INVALID, JA_MUSIC_PLAYING, JA_MUSIC_PAUSED, JA_MUSIC_STOPPED }; - -typedef struct JA_Sound_t *JA_Sound; -typedef struct JA_Music_t *JA_Music; - -void JA_Init(const int freq, const SDL_AudioFormat format, const int channels); -void JA_Quit(); - -JA_Music JA_LoadMusic(const char* filename); -void JA_PlayMusic(JA_Music music, const int loop = -1); -void JA_PauseMusic(); -void JA_ResumeMusic(); -void JA_StopMusic(); -JA_Music_state JA_GetMusicState(); -void JA_DeleteMusic(JA_Music music); - -JA_Sound JA_NewSound(Uint8* buffer, Uint32 length); -JA_Sound JA_LoadSound(const char* filename); -int JA_PlaySound(JA_Sound sound, const int loop = 0); -void JA_PauseChannel(const int channel); -void JA_ResumeChannel(const int channel); -void JA_StopChannel(const int channel); -JA_Channel_state JA_GetChannelState(const int channel); -void JA_DeleteSound(JA_Sound sound); - -int JA_SetVolume(int volume); \ No newline at end of file diff --git a/lua.cpp b/lua.cpp index 01cab0e..b749de5 100644 --- a/lua.cpp +++ b/lua.cpp @@ -649,33 +649,12 @@ extern "C" { return 1; } - static int cpp_playmusic(lua_State *L) { + static int cpp_playchirp(lua_State *L) { const char* str = luaL_checkstring(L, 1); - bool loop = lua_toboolean(L, 2); - playmusic(str, loop); + playchirp(str); return 0; } - static int cpp_pausemusic(lua_State *L) { - pausemusic(); - return 0; - } - - static int cpp_resumemusic(lua_State *L) { - resumemusic(); - return 0; - } - - static int cpp_stopmusic(lua_State *L) { - stopmusic(); - return 0; - } - - static int cpp_ismusicplaying(lua_State *L) { - lua_pushboolean(L,ismusicplaying()); - return 1; - } - static int cpp_exit(lua_State *L) { exit(); return 0; @@ -777,11 +756,7 @@ void push_lua_funcs() { lua_pushcfunction(L,cpp_freadw); lua_setglobal(L, "freadw"); lua_pushcfunction(L,cpp_freadb); lua_setglobal(L, "freadb"); - lua_pushcfunction(L,cpp_playmusic); lua_setglobal(L, "playmusic"); - lua_pushcfunction(L,cpp_pausemusic); lua_setglobal(L, "pausemusic"); - lua_pushcfunction(L,cpp_resumemusic); lua_setglobal(L, "resumemusic"); - lua_pushcfunction(L,cpp_stopmusic); lua_setglobal(L, "stopmusic"); - lua_pushcfunction(L,cpp_ismusicplaying); lua_setglobal(L, "ismusicplaying"); + lua_pushcfunction(L,cpp_playchirp); lua_setglobal(L, "playchirp"); lua_pushcfunction(L,cpp_exit); lua_setglobal(L, "quit"); diff --git a/mini.cpp b/mini.cpp index 70ebf66..7ef913b 100644 --- a/mini.cpp +++ b/mini.cpp @@ -3,7 +3,8 @@ #include #include "lua.h" #include "gif.c" -#include "jail_audio.h" + +#include "chirp.h" #pragma pack(1) @@ -54,7 +55,6 @@ SDL_Renderer *mini_ren; SDL_Texture *mini_bak; Uint32 *pixels; int pitch; -JA_Music music = NULL; uint32_t palette[256] = { 0x001a1c2c, 0x005d275d, 0x00b13e53, 0x00ef7d57, 0x00ffcd75, 0x00a7f070, 0x0038b764, 0x00257179, 0x0029366f, 0x003b5dc9, 0x0041a6f6, 0x0073eff7, 0x00f4f4f4, 0x0094b0c2, 0x00566c86, 0x00333c57 }; @@ -85,7 +85,7 @@ char* get_value_from_line(char* line) { void read_ini() { int size; FILE *f = file_getfilepointer("game.ini", size); // fopen("game.ini", "r"); - char line[256]; + char line[1024]; if (f == NULL) return; while (fgets(line, sizeof(line), f)) { char *value = get_value_from_line(line); @@ -122,14 +122,10 @@ void reinit() { } void initaudio() { - if (music!=NULL) JA_DeleteMusic(music); - music = NULL; - JA_Init(22050, AUDIO_S16, 2); + chirp_init(); } void quitaudio() { - if (music!=NULL) JA_DeleteMusic(music); - music = NULL; - JA_Quit(); + } int scrw() { @@ -898,7 +894,7 @@ int rnd(int x) { srand(x); }*/ -char tostr_tmp[256]; +char tostr_tmp[1024]; const char* tostr(int val) { return SDL_itoa(val, tostr_tmp, 10); } @@ -911,7 +907,7 @@ uint8_t ascii(const char *str, uint8_t index) { return str[index]; } -char fstr[255]; +char fstr[1024]; void fopen(const char *filename, uint8_t mode) { if (file != NULL) fclose(file); @@ -987,26 +983,8 @@ bool freadb() { return strcmp(fstr, "true")==0?true:false; } -void playmusic(const char *filename, const bool loop) { - if (music != NULL) JA_DeleteMusic(music); - music = JA_LoadMusic(filename); - JA_PlayMusic(music, loop?-1:0); -} - -void pausemusic() { - JA_PauseMusic(); -} - -void resumemusic() { - JA_ResumeMusic(); -} - -void stopmusic() { - JA_StopMusic(); -} - -bool ismusicplaying() { - return JA_GetMusicState() == JA_MUSIC_PLAYING; +void playchirp(const char *song) { + chirp_play(song); } void exit() { diff --git a/mini.h b/mini.h index 284da09..42a72ad 100644 --- a/mini.h +++ b/mini.h @@ -2,7 +2,7 @@ #include -#define MINI_VERSION "0.9.01d" +#define MINI_VERSION "0.9.02d" #define KEY_UNKNOWN 0 #define KEY_A 4 @@ -257,10 +257,6 @@ const char *freads(); const char *freadw(); bool freadb(); -void playmusic(const char *filename, const bool loop = true); -void pausemusic(); -void resumemusic(); -void stopmusic(); -bool ismusicplaying(); +void playchirp(const char *song); void exit();