386 lines
11 KiB
C++
386 lines
11 KiB
C++
|
#include <stddef.h>
|
||
|
#include <stdio.h>
|
||
|
|
||
|
#include <clownaudio/clownaudio.h>
|
||
|
|
||
|
#include "glad/glad.h"
|
||
|
#include <GLFW/glfw3.h>
|
||
|
|
||
|
#include "tinydir.h"
|
||
|
|
||
|
#include "imgui/imgui.h"
|
||
|
#include "imgui/imgui_impl_glfw.h"
|
||
|
#include "imgui/imgui_impl_opengl3.h"
|
||
|
|
||
|
typedef struct SoundDataListEntry
|
||
|
{
|
||
|
ClownAudio_SoundData *sound_data;
|
||
|
|
||
|
struct SoundDataListEntry *next;
|
||
|
} SoundDataListEntry;
|
||
|
|
||
|
typedef struct SoundListEntry
|
||
|
{
|
||
|
ClownAudio_SoundID sound_id;
|
||
|
float master_volume;
|
||
|
float volume_left;
|
||
|
float volume_right;
|
||
|
|
||
|
struct SoundListEntry *next;
|
||
|
} SoundListEntry;
|
||
|
|
||
|
static SoundDataListEntry *sound_data_list_head;
|
||
|
static SoundListEntry *sound_list_head;
|
||
|
|
||
|
int main(int argc, char *argv[])
|
||
|
{
|
||
|
const char *file_directory = argc > 1 ? argv[1] : ".";
|
||
|
|
||
|
/////////////////////
|
||
|
// Initialise GLFW //
|
||
|
/////////////////////
|
||
|
|
||
|
if (glfwInit())
|
||
|
{
|
||
|
const char *glsl_version = "#version 150 core";
|
||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
||
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
|
||
|
|
||
|
GLFWwindow *window = glfwCreateWindow(800, 600, "clownaudio test program", NULL, NULL);
|
||
|
|
||
|
if (window != NULL)
|
||
|
{
|
||
|
glfwMakeContextCurrent(window);
|
||
|
glfwSwapInterval(1);
|
||
|
|
||
|
if (gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
|
||
|
{
|
||
|
// Check if the platform supports OpenGL 3.2
|
||
|
if (GLAD_GL_VERSION_3_2)
|
||
|
{
|
||
|
///////////////////////////
|
||
|
// Initialise Dear ImGui //
|
||
|
///////////////////////////
|
||
|
|
||
|
IMGUI_CHECKVERSION();
|
||
|
ImGui::CreateContext();
|
||
|
|
||
|
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||
|
ImGui_ImplOpenGL3_Init(glsl_version);
|
||
|
|
||
|
///////////////////////////
|
||
|
// Initialise clownaudio //
|
||
|
///////////////////////////
|
||
|
|
||
|
if (ClownAudio_Init())
|
||
|
{
|
||
|
ClownAudio_SoundDataConfig data_config;
|
||
|
ClownAudio_InitSoundDataConfig(&data_config);
|
||
|
|
||
|
ClownAudio_SoundConfig sound_config;
|
||
|
ClownAudio_InitSoundConfig(&sound_config);
|
||
|
|
||
|
SoundDataListEntry *selected_sound_data = NULL;
|
||
|
SoundListEntry *selected_sound = NULL;
|
||
|
|
||
|
int intro_file = 0;
|
||
|
int loop_file = 0;
|
||
|
|
||
|
// tinydir stuff
|
||
|
tinydir_dir dir;
|
||
|
tinydir_open_sorted(&dir, file_directory);
|
||
|
|
||
|
tinydir_file *files = (tinydir_file*)malloc(sizeof(tinydir_file) * dir.n_files);
|
||
|
size_t files_total = 0;
|
||
|
|
||
|
for (size_t i = 0; i < dir.n_files; ++i)
|
||
|
{
|
||
|
tinydir_readfile_n(&dir, &files[files_total], i);
|
||
|
|
||
|
if (!files[files_total].is_dir)
|
||
|
++files_total;
|
||
|
}
|
||
|
|
||
|
tinydir_close(&dir);
|
||
|
|
||
|
while (!glfwWindowShouldClose(window))
|
||
|
{
|
||
|
glfwPollEvents();
|
||
|
|
||
|
ImGui_ImplOpenGL3_NewFrame();
|
||
|
ImGui_ImplGlfw_NewFrame();
|
||
|
ImGui::NewFrame();
|
||
|
|
||
|
ImGui::Begin("Sound Data Creation", NULL, ImGuiWindowFlags_AlwaysAutoResize);
|
||
|
struct FuncHolder
|
||
|
{
|
||
|
static bool ItemGetter(void* data, int idx, const char** out_str)
|
||
|
{
|
||
|
if (idx == 0)
|
||
|
{
|
||
|
*out_str = "No file";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tinydir_file *files = (tinydir_file*)data;
|
||
|
*out_str = files[idx - 1].name;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
ImGui::Combo("Intro file", &intro_file, &FuncHolder::ItemGetter, files, files_total + 1);
|
||
|
ImGui::Combo("Loop file", &loop_file, &FuncHolder::ItemGetter, files, files_total + 1);
|
||
|
|
||
|
ImGui::Spacing();
|
||
|
|
||
|
ImGui::Checkbox("Predecode", &data_config.predecode);
|
||
|
ImGui::Checkbox("Must predecode", &data_config.must_predecode);
|
||
|
ImGui::Checkbox("Dynamic sample rate", &data_config.dynamic_sample_rate);
|
||
|
|
||
|
ImGui::Spacing();
|
||
|
|
||
|
if (ImGui::Button("Load sound data"))
|
||
|
{
|
||
|
ClownAudio_SoundData *sound_data = ClownAudio_LoadSoundDataFromFiles(intro_file == 0 ? NULL : files[intro_file - 1].path, loop_file == 0 ? NULL : files[loop_file - 1].path, &data_config);
|
||
|
|
||
|
if (sound_data != NULL)
|
||
|
{
|
||
|
SoundDataListEntry *new_entry = (SoundDataListEntry*)malloc(sizeof(SoundDataListEntry));
|
||
|
|
||
|
new_entry->sound_data = sound_data;
|
||
|
new_entry->next = NULL;
|
||
|
|
||
|
SoundDataListEntry **entry = &sound_data_list_head;
|
||
|
while (*entry != NULL)
|
||
|
entry = &(*entry)->next;
|
||
|
|
||
|
*entry = new_entry;
|
||
|
|
||
|
if (selected_sound_data == NULL)
|
||
|
selected_sound_data = new_entry;
|
||
|
}
|
||
|
}
|
||
|
ImGui::End();
|
||
|
|
||
|
ImGui::Begin("Sound Creation", NULL, ImGuiWindowFlags_AlwaysAutoResize);
|
||
|
if (selected_sound_data == NULL)
|
||
|
{
|
||
|
ImGui::Text("No sound data selected...");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ImGui::Checkbox("Loop", &sound_config.loop);
|
||
|
ImGui::Checkbox("Do not free when done", &sound_config.do_not_free_when_done);
|
||
|
ImGui::Checkbox("Dynamic sample rate", &sound_config.dynamic_sample_rate);
|
||
|
|
||
|
ImGui::Spacing();
|
||
|
|
||
|
if (ImGui::Button("Create sound"))
|
||
|
{
|
||
|
ClownAudio_SoundID sound_id = ClownAudio_CreateSound(selected_sound_data->sound_data, &sound_config);
|
||
|
|
||
|
if (sound_id != 0)
|
||
|
{
|
||
|
SoundListEntry *new_entry = (SoundListEntry*)malloc(sizeof(SoundListEntry));
|
||
|
|
||
|
new_entry->sound_id = sound_id;
|
||
|
new_entry->master_volume = 1.0f;
|
||
|
new_entry->volume_left = 1.0f;
|
||
|
new_entry->volume_right = 1.0f;
|
||
|
new_entry->next = NULL;
|
||
|
|
||
|
SoundListEntry **entry = &sound_list_head;
|
||
|
while (*entry != NULL)
|
||
|
entry = &(*entry)->next;
|
||
|
|
||
|
*entry = new_entry;
|
||
|
|
||
|
if (selected_sound == NULL)
|
||
|
selected_sound = new_entry;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
ImGui::End();
|
||
|
|
||
|
ImGui::Begin("Sound Data", NULL);
|
||
|
for (SoundDataListEntry *entry = sound_data_list_head; entry != NULL; entry = entry->next)
|
||
|
{
|
||
|
char name[32];
|
||
|
sprintf(name, "Sound data %p", entry->sound_data);
|
||
|
if (ImGui::Selectable(name, selected_sound_data == entry))
|
||
|
selected_sound_data = entry;
|
||
|
}
|
||
|
|
||
|
if (selected_sound_data != NULL)
|
||
|
{
|
||
|
ImGui::Spacing();
|
||
|
|
||
|
if (ImGui::Button("Destroy"))
|
||
|
{
|
||
|
ClownAudio_UnloadSoundData(selected_sound_data->sound_data);
|
||
|
|
||
|
for (SoundDataListEntry **entry = &sound_data_list_head; *entry != NULL; entry = &(*entry)->next)
|
||
|
{
|
||
|
if (*entry == selected_sound_data)
|
||
|
{
|
||
|
SoundDataListEntry *next_sound_data = (*entry)->next;
|
||
|
free(*entry);
|
||
|
*entry = next_sound_data;
|
||
|
selected_sound_data = *entry == NULL ? NULL : *entry;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
ImGui::End();
|
||
|
|
||
|
ImGui::Begin("Sounds", NULL);
|
||
|
for (SoundListEntry *entry = sound_list_head; entry != NULL; entry = entry->next)
|
||
|
{
|
||
|
int status = ClownAudio_GetSoundStatus(entry->sound_id);
|
||
|
|
||
|
char name[32];
|
||
|
|
||
|
switch (status)
|
||
|
{
|
||
|
case 0:
|
||
|
sprintf(name, "Sound %u - Playing", entry->sound_id);
|
||
|
break;
|
||
|
|
||
|
case 1:
|
||
|
sprintf(name, "Sound %u - Paused", entry->sound_id);
|
||
|
break;
|
||
|
|
||
|
case -1:
|
||
|
sprintf(name, "Sound %u - Freed", entry->sound_id);
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
if (ImGui::Selectable(name, selected_sound == entry))
|
||
|
selected_sound = entry;
|
||
|
}
|
||
|
|
||
|
if (selected_sound != NULL)
|
||
|
{
|
||
|
ImGui::Spacing();
|
||
|
|
||
|
if (ImGui::Button("Destroy"))
|
||
|
{
|
||
|
ClownAudio_DestroySound(selected_sound->sound_id);
|
||
|
|
||
|
for (SoundListEntry **entry = &sound_list_head; *entry != NULL; entry = &(*entry)->next)
|
||
|
{
|
||
|
if (*entry == selected_sound)
|
||
|
{
|
||
|
SoundListEntry *next_sound = (*entry)->next;
|
||
|
free(*entry);
|
||
|
*entry = next_sound;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
selected_sound = NULL;
|
||
|
}
|
||
|
}
|
||
|
ImGui::End();
|
||
|
|
||
|
ImGui::Begin("Sound Controls", NULL, ImGuiWindowFlags_AlwaysAutoResize);
|
||
|
if (selected_sound == NULL)
|
||
|
{
|
||
|
ImGui::Text("No sound selected...");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int status = ClownAudio_GetSoundStatus(selected_sound->sound_id);
|
||
|
|
||
|
if (status == -1)
|
||
|
{
|
||
|
ImGui::Text("Selected sound has been freed...");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (status == 0)
|
||
|
{
|
||
|
if (ImGui::Button("Pause"))
|
||
|
ClownAudio_PauseSound(selected_sound->sound_id);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (ImGui::Button("Unpause"))
|
||
|
ClownAudio_UnpauseSound(selected_sound->sound_id);
|
||
|
}
|
||
|
|
||
|
ImGui::SameLine();
|
||
|
|
||
|
if (ImGui::Button("Rewind"))
|
||
|
ClownAudio_RewindSound(selected_sound->sound_id);
|
||
|
|
||
|
ImGui::Spacing();
|
||
|
|
||
|
if (ImGui::Button("Fade-out"))
|
||
|
ClownAudio_FadeOutSound(selected_sound->sound_id, 5 * 1000);
|
||
|
|
||
|
ImGui::SameLine();
|
||
|
|
||
|
if (ImGui::Button("Fade-in"))
|
||
|
ClownAudio_FadeInSound(selected_sound->sound_id, 5 * 1000);
|
||
|
|
||
|
ImGui::SameLine();
|
||
|
|
||
|
if (ImGui::Button("Cancel fade"))
|
||
|
ClownAudio_CancelFade(selected_sound->sound_id);
|
||
|
|
||
|
ImGui::Spacing();
|
||
|
|
||
|
if (ImGui::SliderFloat("Master volume", &selected_sound->master_volume, 0.0f, 1.0f, "%.3f", 2.0f))
|
||
|
ClownAudio_SetSoundVolume(selected_sound->sound_id, selected_sound->master_volume * selected_sound->volume_left * 0x100, selected_sound->master_volume * selected_sound->volume_right * 0x100);
|
||
|
|
||
|
if (ImGui::SliderFloat("Left volume", &selected_sound->volume_left, 0.0f, 1.0f, "%.3f", 2.0f))
|
||
|
ClownAudio_SetSoundVolume(selected_sound->sound_id, selected_sound->master_volume * selected_sound->volume_left * 0x100, selected_sound->master_volume * selected_sound->volume_right * 0x100);
|
||
|
|
||
|
if (ImGui::SliderFloat("Right volume", &selected_sound->volume_right, 0.0f, 1.0f, "%.3f", 2.0f))
|
||
|
ClownAudio_SetSoundVolume(selected_sound->sound_id, selected_sound->master_volume * selected_sound->volume_left * 0x100, selected_sound->master_volume * selected_sound->volume_right * 0x100);
|
||
|
|
||
|
ImGui::Spacing();
|
||
|
|
||
|
static int sample_rate = 0;
|
||
|
ImGui::InputInt("Sample rate", &sample_rate, 0);
|
||
|
|
||
|
if (ImGui::Button("Apply sample rate"))
|
||
|
ClownAudio_SetSoundSampleRate(selected_sound->sound_id, sample_rate, sample_rate);
|
||
|
}
|
||
|
}
|
||
|
ImGui::End();
|
||
|
|
||
|
ImGui::ShowDemoWindow();
|
||
|
|
||
|
ImGui::Render();
|
||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||
|
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||
|
glfwSwapBuffers(window);
|
||
|
}
|
||
|
|
||
|
free(files);
|
||
|
|
||
|
ClownAudio_Deinit();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ImGui_ImplOpenGL3_Shutdown();
|
||
|
ImGui_ImplGlfw_Shutdown();
|
||
|
ImGui::DestroyContext();
|
||
|
|
||
|
glfwDestroyWindow(window);
|
||
|
glfwTerminate();
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|