- Preparant la nova API
This commit is contained in:
@@ -25,7 +25,7 @@ namespace gamestate
|
|||||||
menu::fondo = draw::loadSurface("menuprin.gif", true);
|
menu::fondo = draw::loadSurface("menuprin.gif", true);
|
||||||
menu::cursor = draw::loadSurface("cursor.gif");
|
menu::cursor = draw::loadSurface("cursor.gif");
|
||||||
|
|
||||||
JA_LoadAndPlayMusic("mus3.ogg");
|
audio::loadAndPlayMusic("mus3.ogg");
|
||||||
|
|
||||||
font::selectFont(font::type::colored);
|
font::selectFont(font::type::colored);
|
||||||
font::setColor(font::color::white);
|
font::setColor(font::color::white);
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace gamestate
|
|||||||
fondo = draw::loadSurface("mort.gif", true);
|
fondo = draw::loadSurface("mort.gif", true);
|
||||||
cursor = draw::loadSurface("cursor.gif");
|
cursor = draw::loadSurface("cursor.gif");
|
||||||
|
|
||||||
JA_LoadAndPlayMusic("mus5.ogg");
|
audio::loadAndPlayMusic("mus5.ogg");
|
||||||
|
|
||||||
draw::fadein();
|
draw::fadein();
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ namespace gamestate
|
|||||||
// arounder_seleccionat = primerArounders
|
// arounder_seleccionat = primerArounders
|
||||||
|
|
||||||
// Enxufa el arradio
|
// Enxufa el arradio
|
||||||
JA_LoadAndPlayMusic((game::getConfig("fase")+1) % 5 == 0 ? "mus6.ogg" : "mus4.ogg");
|
audio::loadAndPlayMusic((game::getConfig("fase")+1) % 5 == 0 ? "mus6.ogg" : "mus4.ogg");
|
||||||
|
|
||||||
// Fiquem a contar el cronómetre de arounders
|
// Fiquem a contar el cronómetre de arounders
|
||||||
play::arounderCount = play::startTicks = game::getTicks();
|
play::arounderCount = play::startTicks = game::getTicks();
|
||||||
@@ -224,11 +224,11 @@ namespace gamestate
|
|||||||
if (mapa::arounders::arrivats >= mapa::arounders::necessaris) {
|
if (mapa::arounders::arrivats >= mapa::arounders::necessaris) {
|
||||||
game::setConfig("fase", game::getConfig("fase")+1);
|
game::setConfig("fase", game::getConfig("fase")+1);
|
||||||
draw::fadeout();
|
draw::fadeout();
|
||||||
JA_FadeOutMusic(250);
|
audio::fadeOutMusic();
|
||||||
play::exit = 1;
|
play::exit = 1;
|
||||||
} else {
|
} else {
|
||||||
draw::fadeout();
|
draw::fadeout();
|
||||||
JA_FadeOutMusic(250);
|
audio::fadeOutMusic();
|
||||||
play::exit = 2;
|
play::exit = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -286,13 +286,13 @@ namespace gamestate
|
|||||||
if (input::mouseY() >= 71 && input::mouseY() <= 76) {
|
if (input::mouseY() >= 71 && input::mouseY() <= 76) {
|
||||||
free(play::original_palette);
|
free(play::original_palette);
|
||||||
draw::fadeout();
|
draw::fadeout();
|
||||||
JA_FadeOutMusic(250);
|
audio::fadeOutMusic();
|
||||||
play::exit = 1;
|
play::exit = 1;
|
||||||
}
|
}
|
||||||
if (input::mouseY() >= 82 && input::mouseY() <= 87) {
|
if (input::mouseY() >= 82 && input::mouseY() <= 87) {
|
||||||
free(play::original_palette);
|
free(play::original_palette);
|
||||||
draw::fadeout();
|
draw::fadeout();
|
||||||
JA_FadeOutMusic(250);
|
audio::fadeOutMusic();
|
||||||
play::exit = 2;
|
play::exit = 2;
|
||||||
}
|
}
|
||||||
if (input::mouseY() >= 93 && input::mouseY() <= 98) {
|
if (input::mouseY() >= 93 && input::mouseY() <= 98) {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace gamestate
|
|||||||
gamestate::sequence::init();
|
gamestate::sequence::init();
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
JA_LoadAndPlayMusic("mus3.ogg");
|
audio::loadAndPlayMusic("mus3.ogg");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (game::getConfig("fase") % 5 == 0) {
|
if (game::getConfig("fase") % 5 == 0) {
|
||||||
|
|||||||
@@ -99,14 +99,14 @@ namespace gamestate
|
|||||||
|
|
||||||
} else if (command=="PLAYMUSIC") {
|
} else if (command=="PLAYMUSIC") {
|
||||||
fscanf(sequence_file, " '%[^']'", text);
|
fscanf(sequence_file, " '%[^']'", text);
|
||||||
JA_LoadAndPlayMusic(text);
|
audio::loadAndPlayMusic(text);
|
||||||
|
|
||||||
} else if (command=="FADEOUT") {
|
} else if (command=="FADEOUT") {
|
||||||
draw::fadeout();
|
draw::fadeout();
|
||||||
|
|
||||||
} else if (command=="FADEOUTMUSIC") {
|
} else if (command=="FADEOUTMUSIC") {
|
||||||
draw::fadeout();
|
draw::fadeout();
|
||||||
JA_FadeOutMusic(250);
|
audio::fadeOutMusic();
|
||||||
|
|
||||||
} else if (command=="END") {
|
} else if (command=="END") {
|
||||||
fclose(sequence_file);
|
fclose(sequence_file);
|
||||||
@@ -125,7 +125,7 @@ namespace gamestate
|
|||||||
|
|
||||||
void drawPic(std::string filename)
|
void drawPic(std::string filename)
|
||||||
{
|
{
|
||||||
draw::surface *pic = draw::loadSurface(filename, true);
|
draw::surface *pic = draw::loadSurface(filename.c_str(), true);
|
||||||
draw::draw(pic);
|
draw::draw(pic);
|
||||||
draw::freeSurface(pic);
|
draw::freeSurface(pic);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,509 +0,0 @@
|
|||||||
#ifndef JA_USESDLMIXER
|
|
||||||
#include "jail_audio.h"
|
|
||||||
#include "jfile.h"
|
|
||||||
#include "stb_vorbis.h"
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#define JA_MAX_SIMULTANEOUS_CHANNELS 5
|
|
||||||
|
|
||||||
struct JA_Sound_t
|
|
||||||
{
|
|
||||||
SDL_AudioSpec spec { SDL_AUDIO_S16, 2, 48000 };
|
|
||||||
Uint32 length { 0 };
|
|
||||||
Uint8 *buffer { NULL };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct JA_Channel_t
|
|
||||||
{
|
|
||||||
JA_Sound_t *sound { nullptr };
|
|
||||||
int pos { 0 };
|
|
||||||
int times { 0 };
|
|
||||||
SDL_AudioStream *stream { nullptr };
|
|
||||||
JA_Channel_state state { JA_CHANNEL_FREE };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct JA_Music_t
|
|
||||||
{
|
|
||||||
SDL_AudioSpec spec { SDL_AUDIO_S16, 2, 48000 };
|
|
||||||
Uint32 length { 0 };
|
|
||||||
Uint8 *buffer { nullptr };
|
|
||||||
char *filename { nullptr };
|
|
||||||
|
|
||||||
int pos { 0 };
|
|
||||||
int times { 0 };
|
|
||||||
SDL_AudioStream *stream { nullptr };
|
|
||||||
JA_Music_state state { JA_MUSIC_INVALID };
|
|
||||||
};
|
|
||||||
|
|
||||||
JA_Music_t *current_music { nullptr };
|
|
||||||
JA_Channel_t channels[JA_MAX_SIMULTANEOUS_CHANNELS];
|
|
||||||
|
|
||||||
SDL_AudioSpec JA_audioSpec { SDL_AUDIO_S16, 2, 48000 };
|
|
||||||
float JA_musicVolume { 1.0f };
|
|
||||||
float JA_soundVolume { 0.5f };
|
|
||||||
bool JA_musicEnabled { true };
|
|
||||||
bool JA_soundEnabled { true };
|
|
||||||
SDL_AudioDeviceID sdlAudioDevice { 0 };
|
|
||||||
SDL_TimerID JA_timerID { 0 };
|
|
||||||
|
|
||||||
bool fading = false;
|
|
||||||
int fade_start_time;
|
|
||||||
int fade_duration;
|
|
||||||
int fade_initial_volume;
|
|
||||||
|
|
||||||
/*
|
|
||||||
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_musicVolume);
|
|
||||||
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_musicVolume);
|
|
||||||
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_soundVolume);
|
|
||||||
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_soundVolume);
|
|
||||||
channels[i].pos = len-size;
|
|
||||||
if (channels[i].times > 0) channels[i].times--;
|
|
||||||
} else {
|
|
||||||
JA_StopChannel(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
Uint32 JA_UpdateCallback(void *userdata, SDL_TimerID timerID, Uint32 interval)
|
|
||||||
{
|
|
||||||
if (JA_musicEnabled && current_music && current_music->state == JA_MUSIC_PLAYING)
|
|
||||||
{
|
|
||||||
if (fading) {
|
|
||||||
int time = SDL_GetTicks();
|
|
||||||
if (time > (fade_start_time+fade_duration)) {
|
|
||||||
fading = false;
|
|
||||||
JA_StopMusic();
|
|
||||||
return 30;
|
|
||||||
} else {
|
|
||||||
const int time_passed = time - fade_start_time;
|
|
||||||
const float percent = (float)time_passed / (float)fade_duration;
|
|
||||||
SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume*(1.0 - percent));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_music->times != 0)
|
|
||||||
{
|
|
||||||
if (SDL_GetAudioStreamAvailable(current_music->stream) < (current_music->length/2)) {
|
|
||||||
SDL_PutAudioStreamData(current_music->stream, current_music->buffer, current_music->length);
|
|
||||||
}
|
|
||||||
if (current_music->times>0) current_music->times--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (SDL_GetAudioStreamAvailable(current_music->stream) == 0) JA_StopMusic();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (JA_soundEnabled)
|
|
||||||
{
|
|
||||||
for (int i=0; i < JA_MAX_SIMULTANEOUS_CHANNELS; ++i)
|
|
||||||
if (channels[i].state == JA_CHANNEL_PLAYING)
|
|
||||||
{
|
|
||||||
if (channels[i].times != 0)
|
|
||||||
{
|
|
||||||
if (SDL_GetAudioStreamAvailable(channels[i].stream) < (channels[i].sound->length/2)) {
|
|
||||||
SDL_PutAudioStreamData(channels[i].stream, channels[i].sound->buffer, channels[i].sound->length);
|
|
||||||
if (channels[i].times>0) channels[i].times--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (SDL_GetAudioStreamAvailable(channels[i].stream) == 0) JA_StopChannel(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return 30;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JA_Init(const int freq, const SDL_AudioFormat format, const int num_channels)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
SDL_SetLogPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SDL_Log("Iniciant JailAudio...");
|
|
||||||
JA_audioSpec = {format, num_channels, freq };
|
|
||||||
if (!sdlAudioDevice) SDL_CloseAudioDevice(sdlAudioDevice);
|
|
||||||
sdlAudioDevice = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &JA_audioSpec);
|
|
||||||
SDL_Log( (sdlAudioDevice==0) ? "Failed to initialize SDL audio!\n" : "OK!\n");
|
|
||||||
for (int i=0;i<JA_MAX_SIMULTANEOUS_CHANNELS;++i) channels[i].state = JA_CHANNEL_FREE;
|
|
||||||
//SDL_PauseAudioDevice(sdlAudioDevice);
|
|
||||||
JA_timerID = SDL_AddTimer(30, JA_UpdateCallback, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JA_Quit()
|
|
||||||
{
|
|
||||||
if (JA_timerID) SDL_RemoveTimer(JA_timerID);
|
|
||||||
|
|
||||||
if (!sdlAudioDevice) SDL_CloseAudioDevice(sdlAudioDevice);
|
|
||||||
sdlAudioDevice = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
JA_Music_t *JA_LoadMusic(Uint8* buffer, Uint32 length)
|
|
||||||
{
|
|
||||||
JA_Music_t *music = new JA_Music_t();
|
|
||||||
|
|
||||||
int chan, samplerate;
|
|
||||||
short *output;
|
|
||||||
music->length = stb_vorbis_decode_memory(buffer, length, &chan, &samplerate, &output) * chan * 2;
|
|
||||||
|
|
||||||
music->spec.channels = chan;
|
|
||||||
music->spec.freq = samplerate;
|
|
||||||
music->spec.format = SDL_AUDIO_S16;
|
|
||||||
music->buffer = (Uint8*)SDL_malloc(music->length);
|
|
||||||
SDL_memcpy(music->buffer, output, music->length);
|
|
||||||
free(output);
|
|
||||||
music->pos = 0;
|
|
||||||
music->state = JA_MUSIC_STOPPED;
|
|
||||||
|
|
||||||
return music;
|
|
||||||
}
|
|
||||||
|
|
||||||
JA_Music_t *JA_LoadMusic(const char* filename)
|
|
||||||
{
|
|
||||||
int size;
|
|
||||||
char *buffer = file_getfilebuffer(filename, size);
|
|
||||||
JA_Music_t *music = JA_LoadMusic((Uint8*)buffer, size);
|
|
||||||
|
|
||||||
music->filename = (char*)malloc(strlen(filename)+1);
|
|
||||||
strcpy(music->filename, filename);
|
|
||||||
|
|
||||||
free(buffer);
|
|
||||||
|
|
||||||
return music;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JA_PlayMusic(JA_Music_t *music, const int loop)
|
|
||||||
{
|
|
||||||
if (!JA_musicEnabled) return;
|
|
||||||
|
|
||||||
JA_StopMusic();
|
|
||||||
|
|
||||||
current_music = music;
|
|
||||||
current_music->pos = 0;
|
|
||||||
current_music->state = JA_MUSIC_PLAYING;
|
|
||||||
current_music->times = loop;
|
|
||||||
|
|
||||||
current_music->stream = SDL_CreateAudioStream(¤t_music->spec, &JA_audioSpec);
|
|
||||||
if (!SDL_PutAudioStreamData(current_music->stream, current_music->buffer, current_music->length)) printf("[ERROR] SDL_PutAudioStreamData failed!\n");
|
|
||||||
SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume);
|
|
||||||
if (!SDL_BindAudioStream(sdlAudioDevice, current_music->stream)) printf("[ERROR] SDL_BindAudioStream failed!\n");
|
|
||||||
//SDL_ResumeAudioStreamDevice(current_music->stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JA_LoadAndPlayMusic(const char* filename, const bool force_reinit)
|
|
||||||
{
|
|
||||||
if ( (JA_GetMusicState() != JA_MUSIC_PLAYING) || (strcmp(JA_GetMusicFilename(), filename)!=0) || force_reinit ) {
|
|
||||||
JA_PlayMusic(JA_LoadMusic(filename));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char *JA_GetMusicFilename(JA_Music_t *music)
|
|
||||||
{
|
|
||||||
if (!music) music = current_music;
|
|
||||||
return music->filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JA_PauseMusic()
|
|
||||||
{
|
|
||||||
if (!JA_musicEnabled) return;
|
|
||||||
if (!current_music || current_music->state == JA_MUSIC_INVALID) return;
|
|
||||||
|
|
||||||
current_music->state = JA_MUSIC_PAUSED;
|
|
||||||
//SDL_PauseAudioStreamDevice(current_music->stream);
|
|
||||||
SDL_UnbindAudioStream(current_music->stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JA_ResumeMusic()
|
|
||||||
{
|
|
||||||
if (!JA_musicEnabled) return;
|
|
||||||
if (!current_music || current_music->state == JA_MUSIC_INVALID) return;
|
|
||||||
|
|
||||||
current_music->state = JA_MUSIC_PLAYING;
|
|
||||||
//SDL_ResumeAudioStreamDevice(current_music->stream);
|
|
||||||
SDL_BindAudioStream(sdlAudioDevice, current_music->stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JA_StopMusic()
|
|
||||||
{
|
|
||||||
if (!JA_musicEnabled) return;
|
|
||||||
if (!current_music || current_music->state == JA_MUSIC_INVALID) return;
|
|
||||||
|
|
||||||
current_music->pos = 0;
|
|
||||||
current_music->state = JA_MUSIC_STOPPED;
|
|
||||||
//SDL_PauseAudioStreamDevice(current_music->stream);
|
|
||||||
SDL_DestroyAudioStream(current_music->stream);
|
|
||||||
current_music->stream = nullptr;
|
|
||||||
free(current_music->filename);
|
|
||||||
current_music->filename = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JA_FadeOutMusic(const int milliseconds)
|
|
||||||
{
|
|
||||||
if (!JA_musicEnabled) return;
|
|
||||||
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return;
|
|
||||||
|
|
||||||
fading = true;
|
|
||||||
fade_start_time = SDL_GetTicks();
|
|
||||||
fade_duration = milliseconds;
|
|
||||||
fade_initial_volume = JA_musicVolume;
|
|
||||||
}
|
|
||||||
|
|
||||||
JA_Music_state JA_GetMusicState()
|
|
||||||
{
|
|
||||||
if (!JA_musicEnabled) return JA_MUSIC_DISABLED;
|
|
||||||
if (!current_music) return JA_MUSIC_INVALID;
|
|
||||||
|
|
||||||
return current_music->state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JA_DeleteMusic(JA_Music_t *music)
|
|
||||||
{
|
|
||||||
if (current_music == music) current_music = nullptr;
|
|
||||||
SDL_free(music->buffer);
|
|
||||||
if (music->stream) SDL_DestroyAudioStream(music->stream);
|
|
||||||
delete music;
|
|
||||||
}
|
|
||||||
|
|
||||||
float JA_SetMusicVolume(float volume)
|
|
||||||
{
|
|
||||||
JA_musicVolume = SDL_clamp( volume, 0.0f, 1.0f );
|
|
||||||
if (current_music) SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume);
|
|
||||||
return JA_musicVolume;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JA_SetMusicPosition(float value)
|
|
||||||
{
|
|
||||||
if (!current_music) return;
|
|
||||||
current_music->pos = value * current_music->spec.freq;
|
|
||||||
}
|
|
||||||
|
|
||||||
float JA_GetMusicPosition()
|
|
||||||
{
|
|
||||||
if (!current_music) return 0;
|
|
||||||
return float(current_music->pos)/float(current_music->spec.freq);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JA_EnableMusic(const bool value)
|
|
||||||
{
|
|
||||||
if ( !value && current_music && (current_music->state==JA_MUSIC_PLAYING) ) JA_StopMusic();
|
|
||||||
|
|
||||||
JA_musicEnabled = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
JA_Sound_t *JA_NewSound(Uint8* buffer, Uint32 length)
|
|
||||||
{
|
|
||||||
JA_Sound_t *sound = new JA_Sound_t();
|
|
||||||
sound->buffer = buffer;
|
|
||||||
sound->length = length;
|
|
||||||
return sound;
|
|
||||||
}
|
|
||||||
|
|
||||||
JA_Sound_t *JA_LoadSound(uint8_t* buffer, uint32_t size)
|
|
||||||
{
|
|
||||||
JA_Sound_t *sound = new JA_Sound_t();
|
|
||||||
SDL_LoadWAV_IO(SDL_IOFromMem(buffer, size),1, &sound->spec, &sound->buffer, &sound->length);
|
|
||||||
|
|
||||||
return sound;
|
|
||||||
}
|
|
||||||
|
|
||||||
JA_Sound_t *JA_LoadSound(const char* filename)
|
|
||||||
{
|
|
||||||
JA_Sound_t *sound = new JA_Sound_t();
|
|
||||||
SDL_LoadWAV(filename, &sound->spec, &sound->buffer, &sound->length);
|
|
||||||
|
|
||||||
return sound;
|
|
||||||
}
|
|
||||||
|
|
||||||
int JA_PlaySound(JA_Sound_t *sound, const int loop)
|
|
||||||
{
|
|
||||||
if (!JA_soundEnabled) return -1;
|
|
||||||
|
|
||||||
int channel = 0;
|
|
||||||
while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE) { channel++; }
|
|
||||||
if (channel == JA_MAX_SIMULTANEOUS_CHANNELS) channel = 0;
|
|
||||||
JA_StopChannel(channel);
|
|
||||||
|
|
||||||
channels[channel].sound = sound;
|
|
||||||
channels[channel].times = loop;
|
|
||||||
channels[channel].pos = 0;
|
|
||||||
channels[channel].state = JA_CHANNEL_PLAYING;
|
|
||||||
channels[channel].stream = SDL_CreateAudioStream(&channels[channel].sound->spec, &JA_audioSpec);
|
|
||||||
SDL_PutAudioStreamData(channels[channel].stream, channels[channel].sound->buffer, channels[channel].sound->length);
|
|
||||||
SDL_SetAudioStreamGain(channels[channel].stream, JA_soundVolume);
|
|
||||||
SDL_BindAudioStream(sdlAudioDevice, channels[channel].stream);
|
|
||||||
|
|
||||||
return channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
int JA_PlaySoundOnChannel(JA_Sound_t *sound, const int channel, const int loop)
|
|
||||||
{
|
|
||||||
if (!JA_soundEnabled) return -1;
|
|
||||||
|
|
||||||
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return -1;
|
|
||||||
JA_StopChannel(channel);
|
|
||||||
|
|
||||||
channels[channel].sound = sound;
|
|
||||||
channels[channel].times = loop;
|
|
||||||
channels[channel].pos = 0;
|
|
||||||
channels[channel].state = JA_CHANNEL_PLAYING;
|
|
||||||
channels[channel].stream = SDL_CreateAudioStream(&channels[channel].sound->spec, &JA_audioSpec);
|
|
||||||
SDL_PutAudioStreamData(channels[channel].stream, channels[channel].sound->buffer, channels[channel].sound->length);
|
|
||||||
SDL_SetAudioStreamGain(channels[channel].stream, JA_soundVolume);
|
|
||||||
SDL_BindAudioStream(sdlAudioDevice, channels[channel].stream);
|
|
||||||
|
|
||||||
return channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JA_DeleteSound(JA_Sound_t *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 (!JA_soundEnabled) return;
|
|
||||||
|
|
||||||
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;
|
|
||||||
//SDL_PauseAudioStreamDevice(channels[i].stream);
|
|
||||||
SDL_UnbindAudioStream(channels[i].stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
|
|
||||||
{
|
|
||||||
if (channels[channel].state == JA_CHANNEL_PLAYING)
|
|
||||||
{
|
|
||||||
channels[channel].state = JA_CHANNEL_PAUSED;
|
|
||||||
//SDL_PauseAudioStreamDevice(channels[channel].stream);
|
|
||||||
SDL_UnbindAudioStream(channels[channel].stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JA_ResumeChannel(const int channel)
|
|
||||||
{
|
|
||||||
if (!JA_soundEnabled) return;
|
|
||||||
|
|
||||||
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;
|
|
||||||
//SDL_ResumeAudioStreamDevice(channels[i].stream);
|
|
||||||
SDL_BindAudioStream(sdlAudioDevice, channels[i].stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
|
|
||||||
{
|
|
||||||
if (channels[channel].state == JA_CHANNEL_PAUSED)
|
|
||||||
{
|
|
||||||
channels[channel].state = JA_CHANNEL_PLAYING;
|
|
||||||
//SDL_ResumeAudioStreamDevice(channels[channel].stream);
|
|
||||||
SDL_BindAudioStream(sdlAudioDevice, channels[channel].stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JA_StopChannel(const int channel)
|
|
||||||
{
|
|
||||||
if (!JA_soundEnabled) return;
|
|
||||||
|
|
||||||
if (channel == -1)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
|
|
||||||
if (channels[i].state != JA_CHANNEL_FREE) SDL_DestroyAudioStream(channels[i].stream);
|
|
||||||
channels[i].stream = nullptr;
|
|
||||||
channels[i].state = JA_CHANNEL_FREE;
|
|
||||||
channels[i].pos = 0;
|
|
||||||
channels[i].sound = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
|
|
||||||
{
|
|
||||||
if (channels[channel].state != JA_CHANNEL_FREE) SDL_DestroyAudioStream(channels[channel].stream);
|
|
||||||
channels[channel].stream = nullptr;
|
|
||||||
channels[channel].state = JA_CHANNEL_FREE;
|
|
||||||
channels[channel].pos = 0;
|
|
||||||
channels[channel].sound = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JA_Channel_state JA_GetChannelState(const int channel)
|
|
||||||
{
|
|
||||||
if (!JA_soundEnabled) return JA_SOUND_DISABLED;
|
|
||||||
|
|
||||||
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return JA_CHANNEL_INVALID;
|
|
||||||
|
|
||||||
return channels[channel].state;
|
|
||||||
}
|
|
||||||
|
|
||||||
float JA_SetSoundVolume(float volume)
|
|
||||||
{
|
|
||||||
JA_soundVolume = SDL_clamp( volume, 0.0f, 1.0f );
|
|
||||||
|
|
||||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
|
|
||||||
if ( (channels[i].state == JA_CHANNEL_PLAYING) || (channels[i].state == JA_CHANNEL_PAUSED) )
|
|
||||||
SDL_SetAudioStreamGain(channels[i].stream, JA_soundVolume);
|
|
||||||
|
|
||||||
return JA_soundVolume;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JA_EnableSound(const bool value)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
|
|
||||||
{
|
|
||||||
if (channels[i].state == JA_CHANNEL_PLAYING) JA_StopChannel(i);
|
|
||||||
}
|
|
||||||
JA_soundEnabled = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
float JA_SetVolume(float volume)
|
|
||||||
{
|
|
||||||
JA_SetSoundVolume(JA_SetMusicVolume(volume) / 2.0f);
|
|
||||||
|
|
||||||
return JA_musicVolume;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
|
|
||||||
enum JA_Channel_state { JA_CHANNEL_INVALID, JA_CHANNEL_FREE, JA_CHANNEL_PLAYING, JA_CHANNEL_PAUSED, JA_SOUND_DISABLED };
|
|
||||||
enum JA_Music_state { JA_MUSIC_INVALID, JA_MUSIC_PLAYING, JA_MUSIC_PAUSED, JA_MUSIC_STOPPED, JA_MUSIC_DISABLED };
|
|
||||||
|
|
||||||
struct JA_Sound_t;
|
|
||||||
struct JA_Music_t;
|
|
||||||
|
|
||||||
void JA_Init(const int freq, const SDL_AudioFormat format, const int num_channels);
|
|
||||||
void JA_Quit();
|
|
||||||
|
|
||||||
JA_Music_t *JA_LoadMusic(const char* filename);
|
|
||||||
JA_Music_t *JA_LoadMusic(Uint8* buffer, Uint32 length);
|
|
||||||
void JA_PlayMusic(JA_Music_t *music, const int loop = -1);
|
|
||||||
void JA_LoadAndPlayMusic(const char* filename, const bool force_reinit=false);
|
|
||||||
char *JA_GetMusicFilename(JA_Music_t *music = nullptr);
|
|
||||||
void JA_PauseMusic();
|
|
||||||
void JA_ResumeMusic();
|
|
||||||
void JA_StopMusic();
|
|
||||||
void JA_FadeOutMusic(const int milliseconds);
|
|
||||||
JA_Music_state JA_GetMusicState();
|
|
||||||
void JA_DeleteMusic(JA_Music_t *music);
|
|
||||||
float JA_SetMusicVolume(float volume);
|
|
||||||
void JA_SetMusicPosition(float value);
|
|
||||||
float JA_GetMusicPosition();
|
|
||||||
void JA_EnableMusic(const bool value);
|
|
||||||
|
|
||||||
JA_Sound_t *JA_NewSound(Uint8* buffer, Uint32 length);
|
|
||||||
JA_Sound_t *JA_LoadSound(Uint8* buffer, Uint32 length);
|
|
||||||
JA_Sound_t *JA_LoadSound(const char* filename);
|
|
||||||
int JA_PlaySound(JA_Sound_t *sound, const int loop = 0);
|
|
||||||
int JA_PlaySoundOnChannel(JA_Sound_t *sound, const int channel, 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_t *sound);
|
|
||||||
float JA_SetSoundVolume(float volume);
|
|
||||||
void JA_EnableSound(const bool value);
|
|
||||||
|
|
||||||
float JA_SetVolume(float volume);
|
|
||||||
493
source/jaudio.cpp
Normal file
493
source/jaudio.cpp
Normal file
@@ -0,0 +1,493 @@
|
|||||||
|
#include "jaudio.h"
|
||||||
|
#include "jfile.h"
|
||||||
|
#include "stb_vorbis.h"
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
namespace audio {
|
||||||
|
|
||||||
|
#define MAX_CHANNELS 5
|
||||||
|
|
||||||
|
struct sound
|
||||||
|
{
|
||||||
|
SDL_AudioSpec spec { SDL_AUDIO_S16, 2, 48000 };
|
||||||
|
Uint32 length { 0 };
|
||||||
|
Uint8 *buffer { NULL };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct channel
|
||||||
|
{
|
||||||
|
audio::sound *sound { nullptr };
|
||||||
|
int pos { 0 };
|
||||||
|
int times { 0 };
|
||||||
|
SDL_AudioStream *stream { nullptr };
|
||||||
|
audio::state state { audio::state::available };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct music
|
||||||
|
{
|
||||||
|
SDL_AudioSpec spec { SDL_AUDIO_S16, 2, 48000 };
|
||||||
|
Uint32 length { 0 };
|
||||||
|
Uint8 *buffer { nullptr };
|
||||||
|
char *filename { nullptr };
|
||||||
|
|
||||||
|
int pos { 0 };
|
||||||
|
int times { 0 };
|
||||||
|
SDL_AudioStream *stream { nullptr };
|
||||||
|
audio::state state { audio::state::invalid };
|
||||||
|
};
|
||||||
|
|
||||||
|
audio::music *current_music { nullptr };
|
||||||
|
audio::channel channels[MAX_CHANNELS];
|
||||||
|
|
||||||
|
SDL_AudioSpec audio_spec { SDL_AUDIO_S16, 2, 48000 };
|
||||||
|
float music_volume { 1.0f };
|
||||||
|
float sound_volume { 0.5f };
|
||||||
|
bool music_enabled { true };
|
||||||
|
bool sound_enabled { true };
|
||||||
|
SDL_AudioDeviceID audio_device { 0 };
|
||||||
|
SDL_TimerID timer_id { 0 };
|
||||||
|
|
||||||
|
bool fading { false };
|
||||||
|
int fade_start_time;
|
||||||
|
int fade_duration;
|
||||||
|
int fade_initial_volume;
|
||||||
|
|
||||||
|
Uint32 updateCallback(void *userdata, SDL_TimerID timer_id, Uint32 interval)
|
||||||
|
{
|
||||||
|
if (music_enabled && current_music && current_music->state == audio::state::playing)
|
||||||
|
{
|
||||||
|
if (fading)
|
||||||
|
{
|
||||||
|
const int time = SDL_GetTicks();
|
||||||
|
if (time > (fade_start_time+fade_duration)) {
|
||||||
|
fading = false;
|
||||||
|
stopMusic();
|
||||||
|
return 30;
|
||||||
|
} else {
|
||||||
|
const int time_passed = time - fade_start_time;
|
||||||
|
const float percent = (float)time_passed / (float)fade_duration;
|
||||||
|
SDL_SetAudioStreamGain(current_music->stream, music_volume*(1.0 - percent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_music->times != 0)
|
||||||
|
{
|
||||||
|
if (SDL_GetAudioStreamAvailable(current_music->stream) < int(current_music->length/2))
|
||||||
|
{
|
||||||
|
SDL_PutAudioStreamData(current_music->stream, current_music->buffer, current_music->length);
|
||||||
|
}
|
||||||
|
if (current_music->times>0) current_music->times--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (SDL_GetAudioStreamAvailable(current_music->stream) == 0) stopMusic();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sound_enabled)
|
||||||
|
{
|
||||||
|
for (int i=0; i < MAX_CHANNELS; ++i)
|
||||||
|
if (channels[i].state == audio::state::playing)
|
||||||
|
{
|
||||||
|
if (channels[i].times != 0)
|
||||||
|
{
|
||||||
|
if (SDL_GetAudioStreamAvailable(channels[i].stream) < int(channels[i].sound->length/2))
|
||||||
|
{
|
||||||
|
SDL_PutAudioStreamData(channels[i].stream, channels[i].sound->buffer, channels[i].sound->length);
|
||||||
|
if (channels[i].times>0) channels[i].times--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (SDL_GetAudioStreamAvailable(channels[i].stream) == 0) stopChannel(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(const int freq, const SDL_AudioFormat format, const int num_channels)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
SDL_SetLogPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_Log("Iniciant JailAudio...");
|
||||||
|
audio_spec = {format, num_channels, freq };
|
||||||
|
if (!audio_device) SDL_CloseAudioDevice(audio_device);
|
||||||
|
audio_device = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &audio_spec);
|
||||||
|
SDL_Log( (audio_device==0) ? "Failed to initialize SDL audio!\n" : "OK!\n");
|
||||||
|
for (int i=0;i<MAX_CHANNELS;++i) channels[i].state = audio::state::available;
|
||||||
|
timer_id = SDL_AddTimer(30, updateCallback, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void quit()
|
||||||
|
{
|
||||||
|
if (timer_id) SDL_RemoveTimer(timer_id);
|
||||||
|
|
||||||
|
if (!audio_device) SDL_CloseAudioDevice(audio_device);
|
||||||
|
audio_device = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio::music *loadMusic(Uint8* buffer, Uint32 length)
|
||||||
|
{
|
||||||
|
audio::music *music = new audio::music();
|
||||||
|
|
||||||
|
int chan, samplerate;
|
||||||
|
short *output;
|
||||||
|
music->length = stb_vorbis_decode_memory(buffer, length, &chan, &samplerate, &output) * chan * 2;
|
||||||
|
|
||||||
|
music->spec.channels = chan;
|
||||||
|
music->spec.freq = samplerate;
|
||||||
|
music->spec.format = SDL_AUDIO_S16;
|
||||||
|
music->buffer = (Uint8*)SDL_malloc(music->length);
|
||||||
|
SDL_memcpy(music->buffer, output, music->length);
|
||||||
|
free(output);
|
||||||
|
music->pos = 0;
|
||||||
|
music->state = audio::state::stopped;
|
||||||
|
|
||||||
|
return music;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio::music *loadMusic(const char* filename)
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
char *buffer = file_getfilebuffer(filename, size);
|
||||||
|
if (buffer == nullptr) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "ERROR (audio::loadMusic): No s'ha trobat l'arxiu %s\n", filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
audio::music *music = loadMusic((Uint8*)buffer, size);
|
||||||
|
|
||||||
|
music->filename = (char*)malloc(strlen(filename)+1);
|
||||||
|
strcpy(music->filename, filename);
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
|
return music;
|
||||||
|
}
|
||||||
|
|
||||||
|
void playMusic(audio::music *music, const int loop)
|
||||||
|
{
|
||||||
|
if (!music_enabled) return;
|
||||||
|
|
||||||
|
stopMusic();
|
||||||
|
|
||||||
|
current_music = music;
|
||||||
|
current_music->pos = 0;
|
||||||
|
current_music->state = audio::state::playing;
|
||||||
|
current_music->times = loop;
|
||||||
|
|
||||||
|
current_music->stream = SDL_CreateAudioStream(¤t_music->spec, &audio_spec);
|
||||||
|
if (!current_music->stream) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "ERROR (audio::playMusic): SDL_CreateAudioStream: %s\n", SDL_GetError());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SDL_PutAudioStreamData(current_music->stream, current_music->buffer, current_music->length)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "ERROR (audio::playMusic): SDL_PutAudioStreamData: %s\n", SDL_GetError());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetAudioStreamGain(current_music->stream, music_volume);
|
||||||
|
|
||||||
|
if (!SDL_BindAudioStream(audio_device, current_music->stream)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "ERROR (audio::playMusic): SDL_BindAudioStream: %s\n", SDL_GetError());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadAndPlayMusic(const char* filename, const bool force_reinit)
|
||||||
|
{
|
||||||
|
if ( (getMusicState() != audio::state::playing) || (strcmp(getMusicFilename(), filename)!=0) || force_reinit )
|
||||||
|
{
|
||||||
|
playMusic(loadMusic(filename));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *getMusicFilename(audio::music *music)
|
||||||
|
{
|
||||||
|
if (!music) music = current_music;
|
||||||
|
return music->filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pauseMusic()
|
||||||
|
{
|
||||||
|
if (!music_enabled) return;
|
||||||
|
if (!current_music || current_music->state == audio::state::invalid) return;
|
||||||
|
|
||||||
|
current_music->state = audio::state::paused;
|
||||||
|
SDL_UnbindAudioStream(current_music->stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resumeMusic()
|
||||||
|
{
|
||||||
|
if (!music_enabled) return;
|
||||||
|
if (!current_music || current_music->state == audio::state::invalid) return;
|
||||||
|
|
||||||
|
current_music->state = audio::state::playing;
|
||||||
|
SDL_BindAudioStream(audio_device, current_music->stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stopMusic()
|
||||||
|
{
|
||||||
|
if (!music_enabled) return;
|
||||||
|
if (!current_music || current_music->state == audio::state::invalid) return;
|
||||||
|
|
||||||
|
current_music->pos = 0;
|
||||||
|
current_music->state = audio::state::stopped;
|
||||||
|
SDL_DestroyAudioStream(current_music->stream);
|
||||||
|
current_music->stream = nullptr;
|
||||||
|
free(current_music->filename);
|
||||||
|
current_music->filename = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fadeOutMusic(const int milliseconds)
|
||||||
|
{
|
||||||
|
if (!music_enabled) return;
|
||||||
|
if (current_music == NULL || current_music->state == audio::state::invalid) return;
|
||||||
|
|
||||||
|
fading = true;
|
||||||
|
fade_start_time = SDL_GetTicks();
|
||||||
|
fade_duration = milliseconds;
|
||||||
|
fade_initial_volume = music_volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio::state getMusicState()
|
||||||
|
{
|
||||||
|
if (!music_enabled) return audio::state::disabled;
|
||||||
|
if (!current_music) return audio::state::invalid;
|
||||||
|
|
||||||
|
return current_music->state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deleteMusic(audio::music *music)
|
||||||
|
{
|
||||||
|
if (current_music == music) current_music = nullptr;
|
||||||
|
SDL_free(music->buffer);
|
||||||
|
if (music->stream) SDL_DestroyAudioStream(music->stream);
|
||||||
|
delete music;
|
||||||
|
}
|
||||||
|
|
||||||
|
float setMusicVolume(float volume)
|
||||||
|
{
|
||||||
|
music_volume = SDL_clamp( volume, 0.0f, 1.0f );
|
||||||
|
if (current_music) SDL_SetAudioStreamGain(current_music->stream, music_volume);
|
||||||
|
return music_volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMusicPosition(float value)
|
||||||
|
{
|
||||||
|
if (!current_music) return;
|
||||||
|
current_music->pos = value * current_music->spec.freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getMusicPosition()
|
||||||
|
{
|
||||||
|
if (!current_music) return 0;
|
||||||
|
return float(current_music->pos)/float(current_music->spec.freq);
|
||||||
|
}
|
||||||
|
|
||||||
|
void enableMusic(const bool value)
|
||||||
|
{
|
||||||
|
if ( !value && current_music && (current_music->state==audio::state::playing) ) stopMusic();
|
||||||
|
|
||||||
|
music_enabled = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
audio::sound *newSound(Uint8* buffer, Uint32 length)
|
||||||
|
{
|
||||||
|
audio::sound *sound = new audio::sound();
|
||||||
|
sound->buffer = buffer;
|
||||||
|
sound->length = length;
|
||||||
|
return sound;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio::sound *loadSound(uint8_t* buffer, uint32_t size)
|
||||||
|
{
|
||||||
|
audio::sound *sound = new audio::sound();
|
||||||
|
SDL_LoadWAV_IO(SDL_IOFromMem(buffer, size),1, &sound->spec, &sound->buffer, &sound->length);
|
||||||
|
|
||||||
|
return sound;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio::sound *loadSound(const char* filename)
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
uint8_t *buffer = (uint8_t *)file_getfilebuffer(filename, size);
|
||||||
|
|
||||||
|
if (buffer == nullptr) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "ERROR (audio::loadSound): No s'ha trobat l'arxiu %s\n", filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
audio::sound *sound = loadSound(buffer, size);
|
||||||
|
free(buffer);
|
||||||
|
return sound;
|
||||||
|
}
|
||||||
|
|
||||||
|
int playSound(audio::sound *sound, const int loop)
|
||||||
|
{
|
||||||
|
if (!sound_enabled) return -1;
|
||||||
|
|
||||||
|
int channel = 0;
|
||||||
|
while (channel < MAX_CHANNELS && channels[channel].state != audio::state::available) { channel++; }
|
||||||
|
if (channel == MAX_CHANNELS) channel = 0;
|
||||||
|
stopChannel(channel);
|
||||||
|
|
||||||
|
channels[channel].sound = sound;
|
||||||
|
channels[channel].times = loop;
|
||||||
|
channels[channel].pos = 0;
|
||||||
|
channels[channel].state = audio::state::playing;
|
||||||
|
channels[channel].stream = SDL_CreateAudioStream(&channels[channel].sound->spec, &audio_spec);
|
||||||
|
SDL_PutAudioStreamData(channels[channel].stream, channels[channel].sound->buffer, channels[channel].sound->length);
|
||||||
|
SDL_SetAudioStreamGain(channels[channel].stream, sound_volume);
|
||||||
|
SDL_BindAudioStream(audio_device, channels[channel].stream);
|
||||||
|
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
int playSoundOnChannel(audio::sound *sound, const int channel, const int loop)
|
||||||
|
{
|
||||||
|
if (!sound_enabled) return -1;
|
||||||
|
|
||||||
|
if (channel < 0 || channel >= MAX_CHANNELS) return -1;
|
||||||
|
stopChannel(channel);
|
||||||
|
|
||||||
|
channels[channel].sound = sound;
|
||||||
|
channels[channel].times = loop;
|
||||||
|
channels[channel].pos = 0;
|
||||||
|
channels[channel].state = audio::state::playing;
|
||||||
|
channels[channel].stream = SDL_CreateAudioStream(&channels[channel].sound->spec, &audio_spec);
|
||||||
|
SDL_PutAudioStreamData(channels[channel].stream, channels[channel].sound->buffer, channels[channel].sound->length);
|
||||||
|
SDL_SetAudioStreamGain(channels[channel].stream, sound_volume);
|
||||||
|
SDL_BindAudioStream(audio_device, channels[channel].stream);
|
||||||
|
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deleteSound(audio::sound *sound)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MAX_CHANNELS; i++) {
|
||||||
|
if (channels[i].sound == sound) stopChannel(i);
|
||||||
|
}
|
||||||
|
SDL_free(sound->buffer);
|
||||||
|
delete sound;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pauseChannel(const int channel)
|
||||||
|
{
|
||||||
|
if (!sound_enabled) return;
|
||||||
|
|
||||||
|
if (channel == -1)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MAX_CHANNELS; i++)
|
||||||
|
if (channels[i].state == audio::state::playing)
|
||||||
|
{
|
||||||
|
channels[i].state = audio::state::paused;
|
||||||
|
SDL_UnbindAudioStream(channels[i].stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (channel >= 0 && channel < MAX_CHANNELS)
|
||||||
|
{
|
||||||
|
if (channels[channel].state == audio::state::playing)
|
||||||
|
{
|
||||||
|
channels[channel].state = audio::state::paused;
|
||||||
|
SDL_UnbindAudioStream(channels[channel].stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void resumeChannel(const int channel)
|
||||||
|
{
|
||||||
|
if (!sound_enabled) return;
|
||||||
|
|
||||||
|
if (channel == -1)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MAX_CHANNELS; i++)
|
||||||
|
if (channels[i].state == audio::state::paused)
|
||||||
|
{
|
||||||
|
channels[i].state = audio::state::playing;
|
||||||
|
SDL_BindAudioStream(audio_device, channels[i].stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (channel >= 0 && channel < MAX_CHANNELS)
|
||||||
|
{
|
||||||
|
if (channels[channel].state == audio::state::paused)
|
||||||
|
{
|
||||||
|
channels[channel].state = audio::state::playing;
|
||||||
|
SDL_BindAudioStream(audio_device, channels[channel].stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void stopChannel(const int channel)
|
||||||
|
{
|
||||||
|
if (!sound_enabled) return;
|
||||||
|
|
||||||
|
if (channel == -1)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MAX_CHANNELS; i++) {
|
||||||
|
if (channels[i].state != audio::state::available) SDL_DestroyAudioStream(channels[i].stream);
|
||||||
|
channels[i].stream = nullptr;
|
||||||
|
channels[i].state = audio::state::available;
|
||||||
|
channels[i].pos = 0;
|
||||||
|
channels[i].sound = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (channel >= 0 && channel < MAX_CHANNELS)
|
||||||
|
{
|
||||||
|
if (channels[channel].state != audio::state::available) SDL_DestroyAudioStream(channels[channel].stream);
|
||||||
|
channels[channel].stream = nullptr;
|
||||||
|
channels[channel].state = audio::state::available;
|
||||||
|
channels[channel].pos = 0;
|
||||||
|
channels[channel].sound = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
audio::state getChannelState(const int channel)
|
||||||
|
{
|
||||||
|
if (!sound_enabled) return audio::state::disabled;
|
||||||
|
|
||||||
|
if (channel < 0 || channel >= MAX_CHANNELS) return audio::state::invalid;
|
||||||
|
|
||||||
|
return channels[channel].state;
|
||||||
|
}
|
||||||
|
|
||||||
|
float setSoundVolume(float volume)
|
||||||
|
{
|
||||||
|
sound_volume = SDL_clamp( volume, 0.0f, 1.0f );
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_CHANNELS; i++)
|
||||||
|
if ( (channels[i].state == audio::state::playing) || (channels[i].state == audio::state::paused) )
|
||||||
|
SDL_SetAudioStreamGain(channels[i].stream, sound_volume);
|
||||||
|
|
||||||
|
return sound_volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
void enableSound(const bool value)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MAX_CHANNELS; i++)
|
||||||
|
{
|
||||||
|
if (channels[i].state == audio::state::playing) stopChannel(i);
|
||||||
|
}
|
||||||
|
sound_enabled = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
float setVolume(float volume)
|
||||||
|
{
|
||||||
|
setSoundVolume(setMusicVolume(volume) / 2.0f);
|
||||||
|
|
||||||
|
return music_volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef MAX_CHANNELS
|
||||||
|
|
||||||
|
}
|
||||||
44
source/jaudio.h
Normal file
44
source/jaudio.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
namespace audio
|
||||||
|
{
|
||||||
|
enum state { invalid, available, playing, paused, stopped, disabled };
|
||||||
|
|
||||||
|
struct sound;
|
||||||
|
struct music;
|
||||||
|
|
||||||
|
void init(const int freq, const SDL_AudioFormat format, const int num_channels);
|
||||||
|
void quit();
|
||||||
|
|
||||||
|
audio::music *loadMusic(const char* filename);
|
||||||
|
audio::music *loadMusic(Uint8* buffer, Uint32 length);
|
||||||
|
void playMusic(audio::music *music, const int loop = -1);
|
||||||
|
void loadAndPlayMusic(const char* filename, const bool force_reinit=false);
|
||||||
|
char *getMusicFilename(audio::music *music = nullptr);
|
||||||
|
void pauseMusic();
|
||||||
|
void resumeMusic();
|
||||||
|
void stopMusic();
|
||||||
|
void fadeOutMusic(const int milliseconds=250);
|
||||||
|
audio::state getMusicState();
|
||||||
|
void deleteMusic(audio::music *music);
|
||||||
|
float setMusicVolume(float volume);
|
||||||
|
void setMusicPosition(float value);
|
||||||
|
float getMusicPosition();
|
||||||
|
void enableMusic(const bool value);
|
||||||
|
|
||||||
|
audio::sound *newSound(Uint8* buffer, Uint32 length);
|
||||||
|
audio::sound *loadSound(Uint8* buffer, Uint32 length);
|
||||||
|
audio::sound *loadSound(const char* filename);
|
||||||
|
int playSound(audio::sound *sound, const int loop = 0);
|
||||||
|
int playSoundOnChannel(audio::sound *sound, const int channel, const int loop = 0);
|
||||||
|
void pauseChannel(const int channel);
|
||||||
|
void resumeChannel(const int channel);
|
||||||
|
void stopChannel(const int channel);
|
||||||
|
audio::state getChannelState(const int channel);
|
||||||
|
void deleteSound(audio::sound *sound);
|
||||||
|
float setSoundVolume(float volume);
|
||||||
|
void enableSound(const bool value);
|
||||||
|
|
||||||
|
float setVolume(float volume);
|
||||||
|
}
|
||||||
@@ -10,22 +10,22 @@ namespace draw
|
|||||||
// Aleshores, en "render" el contingut de screen se volca a la textura SDL que crearem,
|
// Aleshores, en "render" el contingut de screen se volca a la textura SDL que crearem,
|
||||||
// i eixa textura se pintarà a pantalla com se sol fer amb SDL. Ho anirem veient en el codi.
|
// i eixa textura se pintarà a pantalla com se sol fer amb SDL. Ho anirem veient en el codi.
|
||||||
|
|
||||||
SDL_Window *sdl_window = nullptr; // La finestra de SDL
|
SDL_Window *sdl_window {nullptr}; // La finestra de SDL
|
||||||
SDL_Renderer *sdl_renderer = nullptr; // El renderer de SDL
|
SDL_Renderer *sdl_renderer {nullptr}; // El renderer de SDL
|
||||||
SDL_Texture *sdl_texture = nullptr; // La textura de SDL a la que pintarem la nostra superficie "screen" i que despres volcarem a pantalla
|
SDL_Texture *sdl_texture {nullptr}; // La textura de SDL a la que pintarem la nostra superficie "screen" i que despres volcarem a pantalla
|
||||||
|
|
||||||
static int screen_zoom = 1;
|
static int screen_zoom = 1;
|
||||||
|
|
||||||
surface *screen = nullptr; // La superficie screen, que representa la pantalla. Se crea i destrueix internament
|
surface *screen {nullptr}; // La superficie screen, que representa la pantalla. Se crea i destrueix internament
|
||||||
surface *destination = nullptr; // Punter a la actual superficie de destí
|
surface *destination {nullptr}; // Punter a la actual superficie de destí
|
||||||
surface *source = nullptr; // Punter a la actual superficie d'oritge
|
surface *source {nullptr}; // Punter a la actual superficie d'oritge
|
||||||
surface *pushedSource = nullptr; // Punter a la superficie d'oritge que s'ha pushat
|
surface *pushed_source {nullptr}; // Punter a la superficie d'oritge que s'ha pushat
|
||||||
|
|
||||||
uint32_t palette[256]; // La paleta de colors
|
uint32_t palette[256]; // La paleta de colors
|
||||||
uint32_t aux_palette[256]; // La paleta de colors
|
uint32_t aux_palette[256]; // La paleta de colors, para els fadein
|
||||||
uint8_t color_indices[256]; // Indices dels colors per defecte
|
uint8_t color_indices[256]; // Indices dels colors per defecte
|
||||||
uint8_t sel_color = 0; // Color seleccionat per defecte
|
uint8_t sel_color {0}; // Color seleccionat per defecte
|
||||||
uint8_t transparent = 0; // El color transparent
|
uint8_t transparent {0}; // El color transparent
|
||||||
|
|
||||||
//surface *textsurf = nullptr; // Surface on guardar el gif amb la font
|
//surface *textsurf = nullptr; // Surface on guardar el gif amb la font
|
||||||
|
|
||||||
@@ -35,23 +35,26 @@ namespace draw
|
|||||||
bool fading_in = false;
|
bool fading_in = false;
|
||||||
|
|
||||||
// Inicialització de tot el que fa falta per a carregar gràfics i pintar en pantalla
|
// Inicialització de tot el que fa falta per a carregar gràfics i pintar en pantalla
|
||||||
void init(const std::string &titol, const uint16_t width, const uint16_t height, const int zoom)
|
void init(const char *titol, const uint16_t width, const uint16_t height, const int zoom)
|
||||||
{
|
{
|
||||||
screen_zoom = zoom;
|
screen_zoom = zoom;
|
||||||
|
|
||||||
// [TODO] Incloure gestió de pantalla completa
|
// [TODO] Incloure gestió de pantalla completa
|
||||||
|
|
||||||
// Inicialització de les estructures de SDL
|
// Inicialització de les estructures de SDL
|
||||||
sdl_window = SDL_CreateWindow(titol.c_str(), width * zoom, height * zoom, 0);
|
sdl_window = SDL_CreateWindow(titol, width * zoom, height * zoom, 0);
|
||||||
if (!sdl_window) { SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "ERROR: Failed to initialize window!\n"); exit(1); }
|
if (!sdl_window) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "ERROR (draw::init): Failed to initialize window!\n"); exit(1);
|
||||||
|
}
|
||||||
sdl_renderer = SDL_CreateRenderer(sdl_window, NULL);
|
sdl_renderer = SDL_CreateRenderer(sdl_window, NULL);
|
||||||
if (!sdl_renderer) { SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "ERROR: Failed to initialize renderer!\n"); exit(1); }
|
if (!sdl_renderer) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "ERROR (draw::init): Failed to initialize renderer!\n"); exit(1);
|
||||||
|
}
|
||||||
sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height);
|
sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height);
|
||||||
SDL_SetTextureScaleMode(sdl_texture, SDL_SCALEMODE_NEAREST);
|
SDL_SetTextureScaleMode(sdl_texture, SDL_SCALEMODE_NEAREST);
|
||||||
if (!sdl_texture) { SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "ERROR: Failed to initialize texture!\n"); exit(1); }
|
if (!sdl_texture) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "ERROR (draw::init): Failed to initialize texture!\n"); exit(1);
|
||||||
// Establim el tamany "logic", indepndent del tamany de finestra
|
}
|
||||||
//SDL_SetRenderLogicalPresentation(sdl_renderer, width, height,);
|
|
||||||
|
|
||||||
// Creem la superficie "screen" i la establim com a superficie destinació
|
// Creem la superficie "screen" i la establim com a superficie destinació
|
||||||
screen = createSurface(width, height);
|
screen = createSurface(width, height);
|
||||||
@@ -113,12 +116,12 @@ namespace draw
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Carrega un gràfic d'un arxiu (en format GIF) a una nova superficie, i torna un punter a ella
|
// Carrega un gràfic d'un arxiu (en format GIF) a una nova superficie, i torna un punter a ella
|
||||||
surface *loadSurface(const std::string &filename, const bool loadPalette)
|
surface *loadSurface(const char *filename, const bool loadPalette)
|
||||||
{
|
{
|
||||||
// Agafem un buffer de bytes de l'arxiu especificat
|
// Agafem un buffer de bytes de l'arxiu especificat
|
||||||
// getFileBuffer() simplement ens torna el arxiu sencer dins de un array de char
|
// getFileBuffer() simplement ens torna el arxiu sencer dins de un array de char
|
||||||
int size;
|
int size;
|
||||||
uint8_t *buffer = (uint8_t *)file_getfilebuffer(filename.c_str(), size);
|
uint8_t *buffer = (uint8_t *)file_getfilebuffer(filename, size);
|
||||||
|
|
||||||
// Si ens ha tornat nullptr, es que no l'ha trobat, tornem nosaltres també nullptr ja que no s'ha pogut crear la superficie
|
// Si ens ha tornat nullptr, es que no l'ha trobat, tornem nosaltres també nullptr ja que no s'ha pogut crear la superficie
|
||||||
if (buffer == nullptr)
|
if (buffer == nullptr)
|
||||||
@@ -195,12 +198,12 @@ namespace draw
|
|||||||
|
|
||||||
void pushSource()
|
void pushSource()
|
||||||
{
|
{
|
||||||
pushedSource = source;
|
pushed_source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
void popSource()
|
void popSource()
|
||||||
{
|
{
|
||||||
source = pushedSource;
|
source = pushed_source;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setViewport(const int x, const int y, const int w, const int h)
|
void setViewport(const int x, const int y, const int w, const int h)
|
||||||
@@ -229,12 +232,12 @@ namespace draw
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Carrega la paleta d'un GIF i la torna en un array de uint32_t
|
// Carrega la paleta d'un GIF i la torna en un array de uint32_t
|
||||||
uint32_t *loadPalette(const std::string &filename, int *paletteSize)
|
uint32_t *loadPalette(const char *filename, int *paletteSize)
|
||||||
{
|
{
|
||||||
// Agafem un buffer de bytes de l'arxiu especificat
|
// Agafem un buffer de bytes de l'arxiu especificat
|
||||||
// getFileBuffer() simplement ens torna el arxiu sencer dins de un array de char
|
// getFileBuffer() simplement ens torna el arxiu sencer dins de un array de char
|
||||||
int size;
|
int size;
|
||||||
uint8_t *buffer = (uint8_t *)file_getfilebuffer(filename.c_str(), size);
|
uint8_t *buffer = (uint8_t *)file_getfilebuffer(filename, size);
|
||||||
|
|
||||||
// Li passem el array del arxiu a LoadPalette. Ell ens torna un array de uint32_t amb la paleta
|
// Li passem el array del arxiu a LoadPalette. Ell ens torna un array de uint32_t amb la paleta
|
||||||
// Van a ser 256 entrades de 32 bits, cada entrada es un color, amb el format 0xAARRGGBB
|
// Van a ser 256 entrades de 32 bits, cada entrada es un color, amb el format 0xAARRGGBB
|
||||||
@@ -325,7 +328,7 @@ namespace draw
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pinta un troç de la superficie "source" en la superficie "destination".
|
// Pinta un troç de la superficie "source" en la superficie "destination".
|
||||||
void draw(const int dx, const int dy, const int w, const int h, const int sx, const int sy, const int flip)
|
void draw(const int dx, const int dy, const int w, const int h, const int sx, const int sy, const draw::flip flip)
|
||||||
{
|
{
|
||||||
// Si no hi ha superficie d'oritge especificada, no fem res, o petarà el mame
|
// Si no hi ha superficie d'oritge especificada, no fem res, o petarà el mame
|
||||||
if (source == nullptr)
|
if (source == nullptr)
|
||||||
@@ -337,14 +340,14 @@ namespace draw
|
|||||||
int sdx = 1, sdy = 1, ssx = sx, ssy = sy;
|
int sdx = 1, sdy = 1, ssx = sx, ssy = sy;
|
||||||
|
|
||||||
// Però si s'ha especificat que fem flip en horitzontal...
|
// Però si s'ha especificat que fem flip en horitzontal...
|
||||||
if (flip & DRAW_FLIP_HORIZONTAL)
|
if (flip & draw::flip::horizontal)
|
||||||
{
|
{
|
||||||
sdx = -1; // Avançarem 1 pixel en negatiu
|
sdx = -1; // Avançarem 1 pixel en negatiu
|
||||||
ssx = sx + w - 1; // I començarem al final, o siga, sumarem a sx el ample
|
ssx = sx + w - 1; // I començarem al final, o siga, sumarem a sx el ample
|
||||||
}
|
}
|
||||||
|
|
||||||
// De igual forma per al flip en vertical, per a la y
|
// De igual forma per al flip en vertical, per a la y
|
||||||
if (flip & DRAW_FLIP_VERTICAL)
|
if (flip & draw::flip::vertical)
|
||||||
{
|
{
|
||||||
sdy = -1;
|
sdy = -1;
|
||||||
ssy = sy + h - 1;
|
ssy = sy + h - 1;
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#define DRAW_FLIP_NONE 0
|
//#define DRAW_FLIP_NONE 0
|
||||||
#define DRAW_FLIP_HORIZONTAL 1
|
//#define DRAW_FLIP_HORIZONTAL 1
|
||||||
#define DRAW_FLIP_VERTICAL 2
|
//#define DRAW_FLIP_VERTICAL 2
|
||||||
#define DRAW_FLIP_BOTH 3
|
//#define DRAW_FLIP_BOTH 3
|
||||||
|
|
||||||
// Unitat per a la gestió dels recursos gràfics i dibuixat en pantalla
|
// Unitat per a la gestió dels recursos gràfics i dibuixat en pantalla
|
||||||
namespace draw
|
namespace draw
|
||||||
{
|
{
|
||||||
|
enum flip { none, horizontal, vertical, both };
|
||||||
|
|
||||||
// Estructura per a mantindre una superficie de pintat, la "pantalla virtual" de tota la vida
|
// Estructura per a mantindre una superficie de pintat, la "pantalla virtual" de tota la vida
|
||||||
struct surface
|
struct surface
|
||||||
{
|
{
|
||||||
@@ -24,7 +25,7 @@ namespace draw
|
|||||||
/// @param width es el ample de la finestra "virtual"
|
/// @param width es el ample de la finestra "virtual"
|
||||||
/// @param height es el alt de la finestra "virtual"
|
/// @param height es el alt de la finestra "virtual"
|
||||||
/// @param zoom es com de grans son els pixels.
|
/// @param zoom es com de grans son els pixels.
|
||||||
void init(const std::string &titol, const uint16_t width, const uint16_t height, const int zoom);
|
void init(const char *titol, const uint16_t width, const uint16_t height, const int zoom);
|
||||||
|
|
||||||
/// @brief Finalització del sistema (tancar coses de SDL, superficies fixes, etc...)
|
/// @brief Finalització del sistema (tancar coses de SDL, superficies fixes, etc...)
|
||||||
void quit();
|
void quit();
|
||||||
@@ -41,7 +42,7 @@ namespace draw
|
|||||||
/// @param filename nom de l'arxiu GIF d'on carregar la superficie
|
/// @param filename nom de l'arxiu GIF d'on carregar la superficie
|
||||||
/// @param loadPalette si es true també se carrega la paleta del GIF
|
/// @param loadPalette si es true també se carrega la paleta del GIF
|
||||||
/// @return un punter a una nova superficie
|
/// @return un punter a una nova superficie
|
||||||
surface *loadSurface(const std::string &filename, const bool loadPalette = false);
|
surface *loadSurface(const char* filename, const bool loadPalette = false);
|
||||||
|
|
||||||
/// @brief Allibera la memòria d'una superficie, els seus pixels inclosos
|
/// @brief Allibera la memòria d'una superficie, els seus pixels inclosos
|
||||||
/// @param surf punter a la superficie a alliberar
|
/// @param surf punter a la superficie a alliberar
|
||||||
@@ -67,7 +68,7 @@ namespace draw
|
|||||||
/// @brief Carrega la paleta d'un GIF i la torna en un array de uint32_t
|
/// @brief Carrega la paleta d'un GIF i la torna en un array de uint32_t
|
||||||
/// @param filename nom de l'arxiu GIF d'on carregar la paleta
|
/// @param filename nom de l'arxiu GIF d'on carregar la paleta
|
||||||
/// @param paletteSize si no es NULL ens torna el tamany de la paleta carregada
|
/// @param paletteSize si no es NULL ens torna el tamany de la paleta carregada
|
||||||
uint32_t *loadPalette(const std::string &filename, int *paletteSize = nullptr);
|
uint32_t *loadPalette(const char *filename, int *paletteSize = nullptr);
|
||||||
|
|
||||||
/// @brief Estableix la paleta del sistema, o part de ella, des d'un array especificat
|
/// @brief Estableix la paleta del sistema, o part de ella, des d'un array especificat
|
||||||
/// @param pal un array de uint32_t
|
/// @param pal un array de uint32_t
|
||||||
@@ -104,7 +105,7 @@ namespace draw
|
|||||||
/// @param sx coordenada x de l'oritge
|
/// @param sx coordenada x de l'oritge
|
||||||
/// @param sy coordenada y de l'oritge
|
/// @param sy coordenada y de l'oritge
|
||||||
/// @param flip si s'ha de fer flip en hortizontal o vertical (o ambdos)
|
/// @param flip si s'ha de fer flip en hortizontal o vertical (o ambdos)
|
||||||
void draw(const int dx, const int dy, const int w, const int h, const int sx, const int sy, const int flip = DRAW_FLIP_NONE);
|
void draw(const int dx, const int dy, const int w, const int h, const int sx, const int sy, const draw::flip flip = draw::flip::none);
|
||||||
|
|
||||||
/// @brief Pinta tota la superficie "source" en la superficie "destination", posició (x,y).
|
/// @brief Pinta tota la superficie "source" en la superficie "destination", posició (x,y).
|
||||||
/// @param x coordenada x de la destinació
|
/// @param x coordenada x de la destinació
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ bool file_getdictionary() {
|
|||||||
fi.read((char*)&toc_offset, 4);
|
fi.read((char*)&toc_offset, 4);
|
||||||
fi.seekg(toc_offset);
|
fi.seekg(toc_offset);
|
||||||
|
|
||||||
for (int i=0; i<num_files; ++i)
|
for (uint i=0; i<num_files; ++i)
|
||||||
{
|
{
|
||||||
uint32_t file_offset, file_size;
|
uint32_t file_offset, file_size;
|
||||||
fi.read( (char*)&file_offset, 4 );
|
fi.read( (char*)&file_offset, 4 );
|
||||||
@@ -83,6 +83,7 @@ bool file_getdictionary() {
|
|||||||
toc.push_back({filename, file_size, file_offset});
|
toc.push_back({filename, file_size, file_offset});
|
||||||
}
|
}
|
||||||
fi.close();
|
fi.close();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *file_getfilenamewithfolder(const char* filename) {
|
char *file_getfilenamewithfolder(const char* filename) {
|
||||||
@@ -129,10 +130,11 @@ FILE *file_getfilepointer(const char *resourcename, int& filesize, const bool bi
|
|||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *file_getfilebuffer(const char *resourcename, int& filesize) {
|
char *file_getfilebuffer(const char *resourcename, int& filesize, const bool zero_terminate) {
|
||||||
FILE *f = file_getfilepointer(resourcename, filesize, true);
|
FILE *f = file_getfilepointer(resourcename, filesize, true);
|
||||||
char* buffer = (char*)malloc(filesize);
|
char* buffer = (char*)malloc(zero_terminate?filesize:filesize+1);
|
||||||
fread(buffer, filesize, 1, f);
|
fread(buffer, filesize, 1, f);
|
||||||
|
if (zero_terminate) buffer[filesize]=0;
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ void file_setresourcefolder(const char *str);
|
|||||||
void file_setsource(const int src);
|
void file_setsource(const int src);
|
||||||
|
|
||||||
FILE *file_getfilepointer(const char *resourcename, int& filesize, const bool binary=false);
|
FILE *file_getfilepointer(const char *resourcename, int& filesize, const bool binary=false);
|
||||||
char *file_getfilebuffer(const char *resourcename, int& filesize);
|
char *file_getfilebuffer(const char *resourcename, int& filesize, const bool zero_terminate=false);
|
||||||
|
|
||||||
const char* file_getconfigvalue(const char *key);
|
const char* file_getconfigvalue(const char *key);
|
||||||
void file_setconfigvalue(const char* key, const char* value);
|
void file_setconfigvalue(const char* key, const char* value);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "jinput.h"
|
#include "jinput.h"
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#ifdef MACOS_BUNDLE
|
#ifdef MACOS_BUNDLE
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
#include "jdraw.h"
|
#include "jdraw.h"
|
||||||
#include "jinput.h"
|
#include "jinput.h"
|
||||||
#include "jail_audio.h"
|
#include "jaudio.h"
|
||||||
#include "jfile.h"
|
#include "jfile.h"
|
||||||
|
|
||||||
namespace game
|
namespace game
|
||||||
{
|
{
|
||||||
extern bool windowHasFocus;
|
extern bool windowHasFocus;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ void game::init()
|
|||||||
draw::setTrans(0);
|
draw::setTrans(0);
|
||||||
|
|
||||||
input::init(3);
|
input::init(3);
|
||||||
JA_Init(48000, SDL_AUDIO_S16, 2);
|
audio::init(48000, SDL_AUDIO_S16, 2);
|
||||||
|
|
||||||
font::init();
|
font::init();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user