diff --git a/assets/licar.mid b/assets/licar.mid new file mode 100644 index 0000000..ea1b402 Binary files /dev/null and b/assets/licar.mid differ diff --git a/assets/licar.mmpz b/assets/licar.mmpz new file mode 100644 index 0000000..9563f59 Binary files /dev/null and b/assets/licar.mmpz differ diff --git a/audio.h b/audio.h new file mode 100644 index 0000000..0619c1d --- /dev/null +++ b/audio.h @@ -0,0 +1,82 @@ +/** + audio: this file implements the audio system. +*/ + +#ifndef _LCR_AUDIO +#define _LCR_AUDIO + +#define LCR_SOUND_NONE 0 +#define LCR_SOUND_CLICK 1 +#define LCR_SOUND_CRASH 2 +#define LCR_SOUND_ACCELERATOR 3 + +#define LCR_AUDIO_MIN_RPM 128 +#define LCR_AUDIO_MAX_RPM 2048 + +struct +{ + uint32_t frame; + uint8_t soundPlayed; + uint16_t soundPlayedSample; + uint32_t noise; + + +int engineIntensity; +int engineOsc; + + + + +} LCR_audio; + +void LCR_audioInit(void) +{ + LCR_LOG0("initializing audio"); + LCR_audio.frame = 0; + LCR_audio.soundPlayed = LCR_SOUND_NONE; + LCR_audio.soundPlayedSample = 0; + LCR_audio.noise = 0; + +LCR_audio.engineOsc = 0; +LCR_audio.engineIntensity = 0; + +} + +void LCR_audioSetEngineIntensity(uint8_t value) +{ + LCR_audio.engineIntensity = value; +} + +void LCR_audioPlaySound(uint8_t sound) +{ + LCR_audio.soundPlayed = sound; + LCR_audio.soundPlayedSample = 0; +} + +uint8_t _LCR_audioNoise(void) +{ + LCR_audio.noise = LCR_audio.noise * 32310901 + 37; + return LCR_audio.noise >> 16; +} + +uint8_t LCR_audioGetNextSample(void) +{ + unsigned char result = 128; + + if (LCR_audio.engineIntensity > 5) + { + LCR_audio.engineOsc += + ((_LCR_audioNoise() % 256) < + (30 + LCR_audio.engineIntensity)); + + result += LCR_audio.engineOsc; + } + + LCR_audio.frame++; + + return result; +} + + + +#endif // guard diff --git a/frontend_sdl.c b/frontend_sdl.c index 02c9ee2..ce744d8 100644 --- a/frontend_sdl.c +++ b/frontend_sdl.c @@ -26,7 +26,11 @@ void audioFillCallback(void *userdata, uint8_t *s, int l) rewind(musicFile); } - s[i] = byte; +// s[i] = byte; + +s[i] = byte / 2 + LCR_gameGetNextAudioSample() / 2; + + } } diff --git a/game.h b/game.h index 5485bbd..14b225e 100644 --- a/game.h +++ b/game.h @@ -42,6 +42,11 @@ - Implement the below described functions according to their description. - Implement the main program and game loop. - Call the below described functions as described. + - If you want to support music, make your frontend play music from the "music" + file in assets. It is in raw format, storing 8bit unsigned samples at 8000 + Hz. Use the LCR_gameGetMusicVolume to check what the music volume is. If you + don't support music, set LCR_SETTING_MUSIC to 0 in your frontend code so + that the game knows music is disabled. */ /** @@ -93,6 +98,16 @@ void LCR_gameEnd(void); */ uint8_t LCR_gameStep(uint32_t timeMs); +/** + Gets the current music volume; +*/ +uint8_t LCR_gameGetMusicVolume(void); + +/** + Gets next audio sample (unsigned 8bit samples, 8 KHz). +*/ +uint8_t LCR_gameGetNextAudioSample(void); + //------------------------------------------------------------------------------ #define LCR_LOG0(s) ; @@ -133,8 +148,19 @@ struct uint8_t debugDraw; uint8_t checkpointsTaken; uint32_t runTime; + + uint8_t musicVolume; } LCR_game; +uint8_t LCR_gameGetMusicVolume(void) +{ +#if LCR_SETTING_MUSIC + return LCR_game.musicVolume; +#else + return 0; +#endif +} + void LCR_drawPixelXYUnsafe(unsigned int x, unsigned int y, uint16_t color); @@ -149,6 +175,7 @@ static inline void LCR_drawPixelXYSafe(unsigned int x, unsigned int y, #include "racing.h" #include "assets.h" #include "renderer.h" +#include "audio.h" uint8_t LCR_keyStates[LCR_KEYS_TOTAL]; /**< Assures unchanging key states during a single frame, holds @@ -219,12 +246,12 @@ void LCR_gameInit(void) LCR_rendererInit(); LCR_racingInit(); + LCR_audioInit(); + LCR_game.musicVolume = 255; LCR_game.nextRenderFrameTime = 0; LCR_game.nextRacingTickTime = 0; - LCR_game.controlMode = LCR_CONTROL_MODE_FREECAM; - LCR_gameStartRun(LCR_maps[0]); } @@ -369,6 +396,8 @@ LCR_GameUnit physicsInterpolationParam = LCR_GAME_UNIT - int val = LCR_carSpeedKMH(); +LCR_audioSetEngineIntensity(val < 256 ? val : 255); + if (val < 5) // don't show tiny oscillations when still val = 0; @@ -424,4 +453,9 @@ LCR_GameUnit physicsInterpolationParam = LCR_GAME_UNIT - return 1; } +uint8_t LCR_gameGetNextAudioSample(void) +{ + return LCR_audioGetNextSample(); +} + #endif // guard diff --git a/settings.h b/settings.h index d4accc6..5b8b987 100644 --- a/settings.h +++ b/settings.h @@ -172,4 +172,9 @@ #define LCR_SETTING_POTATO_GRAPHICS 0 #endif +#ifndef LCR_SETTING_MUSIC + /** Whether to enable in game music. */ + #define LCR_SETTING_MUSIC 1 +#endif + #endif // guard