/*******************************************************************************************
*
*   raylib [audio] example - module playing
*
*   Example complexity rating: [★☆☆☆] 1/4
*
*   Example originally created with raylib 1.5, last time updated with raylib 3.5
*
*   Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
*   BSD-like license that allows static linking with closed source software
*
*   Copyright (c) 2016-2025 Ramon Santamaria (@raysan5)
*   converted to C3 by Christoffer Lerno
*
********************************************************************************************/
module raylib_audio_module;
import raylib55;

const MAX_CIRCLES = 64;

struct CircleWave
{
	RLVector2 position;
	float radius;
	float alpha;
	float speed;
	RLColor color;
}

//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
fn int main()
{
	// Initialization
	//--------------------------------------------------------------------------------------
	const int SCREEN_WIDTH = 800;
	const int SCREEN_HEIGHT = 450;

	rl::set_config_flags(MSAA_4X_HINT);  // NOTE: Try to enable MSAA 4X

	rl::init_window(SCREEN_WIDTH, SCREEN_HEIGHT, "raylib [audio] example - module playing");

	rl::init_audio_device();                  // Initialize audio device

	RLColor[14] colors = {
		rl::ORANGE, rl::RED, rl::GOLD, rl::LIME, rl::BLUE, rl::VIOLET, rl::BROWN, rl::LIGHTGRAY,
		rl::PINK, rl::YELLOW, rl::GREEN, rl::SKYBLUE, rl::PURPLE, rl::BEIGE };

	// Creates some circles for visual effect
	CircleWave[MAX_CIRCLES] circles;

	foreach_r(&circle : circles)
	{
		circle.alpha = 0.0f;
		circle.radius = (float)rl::get_random_value(10, 40);
		circle.position.x = (float)rl::get_random_value((int)circle.radius, (int)(SCREEN_WIDTH - circle.radius));
		circle.position.y = (float)rl::get_random_value((int)circle.radius, (int)(SCREEN_HEIGHT - circle.radius));
		circle.speed = (float)rl::get_random_value(1, 100)/2000.0f;
		circle.color = colors[rl::get_random_value(0, 13)];
	}

	RLMusic music = rl::load_music_stream_from_memory(".xm", &MUSIC_DATA, MUSIC_DATA.len);
	music.looping = false;
	float pitch = 1.0f;

	rl::play_music_stream(music);

	float time_played = 0.0f;
	bool pause = false;

	rl::set_target_fps(60);               // Set our game to run at 60 frames-per-second
	//--------------------------------------------------------------------------------------

	// Main game loop
	while (!rl::window_should_close())    // Detect window close button or ESC key
	{
		// Update
		//----------------------------------------------------------------------------------
		rl::update_music_stream(music);      // Update music buffer with new stream data

		// Restart music playing (stop and play)
		switch
		{
			case rl::is_key_pressed(SPACE):
				rl::stop_music_stream(music);
				rl::play_music_stream(music);
				pause = false;
			case rl::is_key_pressed(P):
				pause = !pause;
				if (pause)
				{
					rl::pause_music_stream(music);
				}
				else
				{
					rl::resume_music_stream(music);
				}
			case rl::is_key_pressed(DOWN):
				pitch -= 0.01f;
			case rl::is_key_pressed(UP):
				pitch += 0.01f;
		}
		rl::set_music_pitch(music, pitch);

		// Get timePlayed scaled to bar dimensions
		time_played = (music.get_time_played() / music.get_time_length()) * (SCREEN_WIDTH - 40);

		// Color circles animation
		if (!pause)
		{
			foreach_r(&circle : circles)
			{
				circle.alpha += circle.speed;
				circle.radius += circle.speed * 10.0f;

				if (circle.alpha > 1) circle.speed *= -1;

				if (circle.alpha <= 0.0f)
				{
					circle.alpha = 0.0f;
					circle.radius = (float)rl::get_random_value(10, 40);
					circle.position = {
						.x = rl::get_random_value((int)circle.radius, (int)(SCREEN_WIDTH - circle.radius)),
						.y = rl::get_random_value((int)circle.radius, (int)(SCREEN_HEIGHT - circle.radius))
					};
					circle.color = colors[rl::get_random_value(0, 13)];
					circle.speed = (float)rl::get_random_value(1, 100) / 2000.0f;
				}
			}
		}
		//----------------------------------------------------------------------------------

		// Draw
		//----------------------------------------------------------------------------------
		rl::begin_drawing();
		rl::clear_background(rl::RAYWHITE);

		foreach_r(&circle : circles)
		{
			rl::draw_circle_v(circle.position, circle.radius, circle.color.fade(circle.alpha));
		}
			// Draw time bar
		rl::draw_rectangle(20, SCREEN_HEIGHT - 20 - 12, SCREEN_WIDTH - 40, 12, rl::LIGHTGRAY);
		rl::draw_rectangle(20, SCREEN_HEIGHT - 20 - 12, (int)time_played, 12, rl::MAROON);
		rl::draw_rectangle_lines(20, SCREEN_HEIGHT - 20 - 12, SCREEN_WIDTH - 40, 12, rl::GRAY);

		// Draw help instructions
		rl::draw_rectangle(20, 20, 425, 145, rl::WHITE);
		rl::draw_rectangle_lines(20, 20, 425, 145, rl::GRAY);
		rl::draw_text("PRESS SPACE TO RESTART MUSIC", 40, 40, 20, rl::BLACK);
		rl::draw_text("PRESS P TO PAUSE/RESUME", 40, 70, 20, rl::BLACK);
		rl::draw_text("PRESS UP/DOWN TO CHANGE SPEED", 40, 100, 20, rl::BLACK);
		rl::draw_text(rl::text_format("SPEED: %f", pitch), 40, 130, 20, rl::MAROON);

		rl::end_drawing();
		//----------------------------------------------------------------------------------
	}

	// De-Initialization
	//--------------------------------------------------------------------------------------
	rl::unload_music_stream(music);          // Unload music stream buffers from RAM

	rl::close_audio_device();     // Close audio device (music streaming is automatically stopped)

	rl::close_window();          // Close window and OpenGL context
	//--------------------------------------------------------------------------------------

	return 0;
}

const char[*] MUSIC_DATA = b64`
[encoded data, 34650 characters]
cnUNd3d3LnN5c2tpbGxlcnMubmFyb2QucnU=`;