Add OGG converter

This commit is contained in:
Anthony 2024-04-24 16:38:53 +02:00
parent a6dbc90b78
commit 59e96befd0
9 changed files with 175 additions and 31 deletions

View file

@ -15,7 +15,7 @@ struct Resource
std::string type; std::string type;
~Resource() { ~Resource() {
std::cout << "Res deleted" << std::endl; // std::cout << "Res deleted" << std::endl;
} }
}; };

View file

@ -75,16 +75,28 @@ void EmulatorWindow::Draw()
ImGui::SeparatorText("Script control and debug"); ImGui::SeparatorText("Script control and debug");
if (ImGui::Button("Build")) if (ImGui::Button("Generate pack"))
{ {
m_story.Build(); m_story.Build(false);
}
if (ImGui::Button("Build script"))
{
m_story.Build(true);
} }
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Build & Play")) if (ImGui::Button("Play"))
{ {
m_story.Log("Play story");
m_story.Play(); m_story.Play();
} }
ImGui::SameLine();
if (ImGui::Button("Stop"))
{
m_story.Log("Stop story");
m_story.Stop();
}
ImGui::SameLine(); ImGui::SameLine();
WindowBase::EndDraw(); WindowBase::EndDraw();

View file

@ -45,11 +45,12 @@ public:
virtual void DeleteResource(FilterIterator &it) = 0; virtual void DeleteResource(FilterIterator &it) = 0;
// Node interaction // Node interaction
virtual void Build() = 0; virtual void Build(bool compileonly) = 0;
virtual std::list<std::shared_ptr<Connection>> GetNodeConnections(const std::string &nodeId) = 0; virtual std::list<std::shared_ptr<Connection>> GetNodeConnections(const std::string &nodeId) = 0;
virtual std::string GetNodeEntryLabel(const std::string &nodeId) = 0; virtual std::string GetNodeEntryLabel(const std::string &nodeId) = 0;
virtual void Play() = 0; virtual void Play() = 0;
virtual void Ok() = 0; virtual void Ok() = 0;
virtual void Stop() = 0;
virtual void Pause() = 0; virtual void Pause() = 0;
virtual void Next() = 0; virtual void Next() = 0;
virtual void Previous() = 0; virtual void Previous() = 0;

View file

@ -66,16 +66,13 @@ std::string MainWindow::GetFileNameFromMemory(uint32_t addr)
void MainWindow::Play() void MainWindow::Play()
{ {
if (m_dbg.run_result == VM_FINISHED)
{
Build();
if (m_dbg.run_result == VM_READY) if ((m_dbg.run_result == VM_READY) || (m_dbg.run_result == VM_FINISHED))
{ {
m_dbg.free_run = true; m_dbg.free_run = true;
m_dbg.run_result = VM_OK; // actually starts the execution m_dbg.run_result = VM_OK; // actually starts the execution
}
} }
} }
void MainWindow::Ok() void MainWindow::Ok()
@ -83,6 +80,11 @@ void MainWindow::Ok()
m_eventQueue.push({VmEventType::EvOkButton}); m_eventQueue.push({VmEventType::EvOkButton});
} }
void MainWindow::Stop()
{
m_eventQueue.push({VmEventType::EvOkButton});
}
void MainWindow::Pause() void MainWindow::Pause()
{ {
@ -150,6 +152,10 @@ void MainWindow::ProcessStory()
m_chip32_ctx.registers[R0] = 0x08; m_chip32_ctx.registers[R0] = 0x08;
m_dbg.run_result = VM_OK; m_dbg.run_result = VM_OK;
} }
else if (event.type == VmEventType::EvStop)
{
m_dbg.run_result = VM_FINISHED;
}
} }
} }
@ -704,6 +710,7 @@ void MainWindow::Loop()
while (!done) while (!done)
{ {
auto time = SDL_GetTicks();
bool aboutToClose = m_gui.PollEvent(); bool aboutToClose = m_gui.PollEvent();
m_gui.StartFrame(); m_gui.StartFrame();
@ -746,6 +753,12 @@ void MainWindow::Loop()
m_gui.EndFrame(); m_gui.EndFrame();
// Rendering and event handling
if ((SDL_GetTicks() - time) < 10) {
SDL_Delay(10);
}
} }
@ -799,18 +812,24 @@ void MainWindow::DeleteResource(FilterIterator &it)
return m_resources.Delete(it); return m_resources.Delete(it);
} }
void MainWindow::Build() void MainWindow::Build(bool compileonly)
{ {
// 1. First compile nodes to assembly // 1. First compile nodes to assembly
CompileToAssembler(); if (CompileToAssembler())
{
// 2. Compile the assembly to machine binary // 2. Compile the assembly to machine binary
GenerateBinary(); GenerateBinary();
// 3. Convert all media to desired type format if (!compileonly)
ConvertResources(); {
// 3. Convert all media to desired type format
ConvertResources();
}
}
} }
std::string MainWindow::GetNodeEntryLabel(const std::string &nodeId) std::string MainWindow::GetNodeEntryLabel(const std::string &nodeId)
{ {
return m_nodeEditorWindow.GetNodeEntryLabel(nodeId); return m_nodeEditorWindow.GetNodeEntryLabel(nodeId);
@ -827,9 +846,10 @@ bool MainWindow::CompileToAssembler()
// FIXME // FIXME
// 2. Generate the assembly code from the model // 2. Generate the assembly code from the model
m_currentCode = m_nodeEditorWindow.Build(); bool ret = m_nodeEditorWindow.Build(m_currentCode);
// Add global functions // Add global functions
if (ret)
{ {
std::string buffer; std::string buffer;
@ -839,11 +859,11 @@ bool MainWindow::CompileToAssembler()
f.seekg(0); f.seekg(0);
f.read(buffer.data(), buffer.size()); f.read(buffer.data(), buffer.size());
m_currentCode += buffer; m_currentCode += buffer;
m_editorWindow.SetScript(m_currentCode);
} }
m_editorWindow.SetScript(m_currentCode); return ret;
return true;
} }
void MainWindow::GenerateBinary() void MainWindow::GenerateBinary()
@ -932,14 +952,19 @@ void MainWindow::ConvertResources()
int retCode = 0; int retCode = 0;
if ((*it)->format == "PNG") if ((*it)->format == "PNG")
{ {
outputfile += ".qoi"; // FIXME: prendre la congif en cours désirée outputfile += ".qoi"; // FIXME: prendre la config en cours désirée
retCode = MediaConverter::ImageToQoi(inputfile, outputfile); retCode = MediaConverter::ImageToQoi(inputfile, outputfile);
} }
else if ((*it)->format == "MP3") else if ((*it)->format == "MP3")
{ {
outputfile += ".wav"; // FIXME: prendre la congif en cours désirée outputfile += ".wav"; // FIXME: prendre la config en cours désirée
retCode = MediaConverter::Mp3ToWav(inputfile, outputfile); retCode = MediaConverter::Mp3ToWav(inputfile, outputfile);
} }
else if ((*it)->format == "OGG")
{
outputfile += ".wav"; // FIXME: prendre la config en cours désirée
retCode = MediaConverter::OggToWav(inputfile, outputfile);
}
else else
{ {
Log("Skipped: " + inputfile + ", unknown format" + outputfile, true); Log("Skipped: " + inputfile + ", unknown format" + outputfile, true);

View file

@ -73,7 +73,7 @@ public:
void Loop(); void Loop();
private: private:
enum VmEventType { EvNoEvent, EvStep, EvOkButton, EvPreviousButton, EvNextButton, EvAudioFinished}; enum VmEventType { EvNoEvent, EvStep, EvOkButton, EvPreviousButton, EvNextButton, EvAudioFinished, EvStop};
std::shared_ptr<StoryProject> m_story; std::shared_ptr<StoryProject> m_story;
@ -134,11 +134,12 @@ private:
virtual void ClearResources() override; virtual void ClearResources() override;
virtual std::pair<FilterIterator, FilterIterator> Resources() override; virtual std::pair<FilterIterator, FilterIterator> Resources() override;
virtual void DeleteResource(FilterIterator &it) override; virtual void DeleteResource(FilterIterator &it) override;
virtual void Build() override; virtual void Build(bool compileonly) override;
virtual std::list<std::shared_ptr<Connection>> GetNodeConnections(const std::string &nodeId) override; virtual std::list<std::shared_ptr<Connection>> GetNodeConnections(const std::string &nodeId) override;
virtual std::string GetNodeEntryLabel(const std::string &nodeId) override; virtual std::string GetNodeEntryLabel(const std::string &nodeId) override;
virtual void Play() override; virtual void Play() override;
virtual void Ok() override; virtual void Ok() override;
virtual void Stop() override;
virtual void Pause() override; virtual void Pause() override;
virtual void Next() override; virtual void Next() override;
virtual void Previous() override; virtual void Previous() override;

View file

@ -3,6 +3,10 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <iostream>
#define STB_VORBIS_HEADER_ONLY
#include "stb_vorbis.c"
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
@ -158,6 +162,86 @@ int MediaConverter::Mp3ToWav(const std::string &inputFileName, const std::string
return cSuccess; return cSuccess;
} }
// Function to read the entire contents of a file into memory
static unsigned char* read_entire_file(const char* filename, int* length) {
FILE* f = fopen(filename, "rb");
if (!f) return NULL;
fseek(f, 0, SEEK_END);
long size = ftell(f);
fseek(f, 0, SEEK_SET);
unsigned char* buffer = (unsigned char*)malloc(size);
if (!buffer) {
fclose(f);
return NULL;
}
fread(buffer, 1, size, f);
fclose(f);
if (length) *length = (int)size;
return buffer;
}
int MediaConverter::OggToWav(const std::string &inputFileName, const std::string &outputFileName)
{
int ogg_length;
unsigned char* ogg_data = read_entire_file(inputFileName.c_str(), &ogg_length);
if (!ogg_data) {
std::cout << "Failed to read input file " << inputFileName << std::endl;
return 1;
}
int channels, sample_rate;
short* samples = NULL;
// (const uint8 *mem, int len, int *channels, int *sample_rate, short **output
int data_len = stb_vorbis_decode_memory(ogg_data, ogg_length, &channels, &sample_rate, &samples);
if (!samples) {
std::cout <<"Failed to decode OGG file " << inputFileName << std::endl;
free(ogg_data);
return 1;
}
// Write WAV file header
FILE* wav_file = fopen(outputFileName.c_str(), "wb");
if (!wav_file) {
std::cout << "Failed to create output file " << outputFileName << std::endl;
free(ogg_data);
free(samples);
return 1;
}
fwrite("RIFF", 1, 4, wav_file);
int total_size = 36 + channels * (sample_rate * sizeof(short));
fwrite(&total_size, 4, 1, wav_file);
fwrite("WAVEfmt ", 1, 8, wav_file);
int format_size = 16;
fwrite(&format_size, 4, 1, wav_file);
short format_type = 1; // PCM
fwrite(&format_type, 2, 1, wav_file);
fwrite(&channels, 2, 1, wav_file);
fwrite(&sample_rate, 4, 1, wav_file);
int byte_rate = sample_rate * channels * sizeof(short);
fwrite(&byte_rate, 4, 1, wav_file);
short block_align = channels * sizeof(short);
fwrite(&block_align, 2, 1, wav_file);
short bits_per_sample = 16;
fwrite(&bits_per_sample, 2, 1, wav_file);
fwrite("data", 1, 4, wav_file);
// int data_size = channels * (sample_rate * sizeof(short));
int data_size = data_len * channels * 2; // *2 to make in bytes
fwrite(&data_size, 4, 1, wav_file);
// Write sample data
fwrite(samples, sizeof(short), data_len, wav_file);
fclose(wav_file);
free(ogg_data);
free(samples);
return cSuccess;
}
/* /*
OGG TO WAV OGG TO WAV

View file

@ -22,6 +22,7 @@ public:
MediaConverter(); MediaConverter();
static int ImageToQoi(const std::string &inputFileName, const std::string &outputFileName); static int ImageToQoi(const std::string &inputFileName, const std::string &outputFileName);
static int Mp3ToWav(const std::string &inputFileName, const std::string &outputFileName); static int Mp3ToWav(const std::string &inputFileName, const std::string &outputFileName);
static int OggToWav(const std::string &inputFileName, const std::string &outputFileName);
private: private:
static short *Mp3Read(const std::string &path, MediaInfo &desc); static short *Mp3Read(const std::string &path, MediaInfo &desc);
static int WavWrite(const std::string &path, short *sample_data, MediaInfo &desc); static int WavWrite(const std::string &path, short *sample_data, MediaInfo &desc);

View file

@ -256,6 +256,7 @@ std::string NodeEditorWindow::FindFirstNode() const
for (const auto & n : m_nodes) for (const auto & n : m_nodes)
{ {
bool foundConnection = false; bool foundConnection = false;
for (const auto& l : m_links) for (const auto& l : m_links)
{ {
if (l->model->inNodeId == n->GetId()) if (l->model->inNodeId == n->GetId())
@ -275,7 +276,7 @@ std::string NodeEditorWindow::FindFirstNode() const
return id; return id;
} }
std::string NodeEditorWindow::Build() bool NodeEditorWindow::Build(std::string &codeStr)
{ {
std::stringstream code; std::stringstream code;
ed::SetCurrentEditor(m_context); ed::SetCurrentEditor(m_context);
@ -285,6 +286,12 @@ std::string NodeEditorWindow::Build()
std::string firstNode = FindFirstNode(); std::string firstNode = FindFirstNode();
if (firstNode == "")
{
m_story.Log("First node not found, there must be only one node with a free input.", true);
return false;
}
code << "\tjump " << GetNodeEntryLabel(firstNode) << "\r\n"; code << "\tjump " << GetNodeEntryLabel(firstNode) << "\r\n";
// First generate all constants // First generate all constants
@ -299,7 +306,8 @@ std::string NodeEditorWindow::Build()
} }
ed::SetCurrentEditor(nullptr); ed::SetCurrentEditor(nullptr);
return code.str(); codeStr = code.str();
return true;
} }
std::list<std::shared_ptr<Connection>> NodeEditorWindow::GetNodeConnections(const std::string &nodeId) std::list<std::shared_ptr<Connection>> NodeEditorWindow::GetNodeConnections(const std::string &nodeId)
@ -429,6 +437,18 @@ void NodeEditorWindow::Draw()
// Handle deletion action // Handle deletion action
if (ed::BeginDelete()) if (ed::BeginDelete())
{ {
ed::NodeId nodeId = 0;
while (ed::QueryDeletedNode(&nodeId))
{
if (ed::AcceptDeletedItem())
{
auto id = std::find_if(m_nodes.begin(), m_nodes.end(), [nodeId](std::shared_ptr<BaseNodeWidget> node) { return node->GetInternalId() == nodeId.Get(); });
if (id != m_nodes.end())
m_nodes.erase(id);
}
}
// There may be many links marked for deletion, let's loop over them. // There may be many links marked for deletion, let's loop over them.
ed::LinkId deletedLinkId; ed::LinkId deletedLinkId;
while (ed::QueryDeletedLink(&deletedLinkId)) while (ed::QueryDeletedLink(&deletedLinkId))

View file

@ -54,7 +54,7 @@ public:
void Clear(); void Clear();
void Load(const nlohmann::json &model); void Load(const nlohmann::json &model);
void Save(nlohmann::json &model); void Save(nlohmann::json &model);
std::string Build(); bool Build(std::string &codeStr);
std::list<std::shared_ptr<Connection> > GetNodeConnections(const std::string &nodeId); std::list<std::shared_ptr<Connection> > GetNodeConnections(const std::string &nodeId);
std::string GetNodeEntryLabel(const std::string &nodeId); std::string GetNodeEntryLabel(const std::string &nodeId);