Skip to content

Added Linux support to project #7

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Linux/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
synth: synth1 synth2

synth1: main1.cpp SDLConsole.o SDLAudioManager.o
g++ main1.cpp SDLConsole.o SDLAudioManager.o -g -std=c++17 -o synth1 -lSDL2 -lSDL2_ttf

synth2: main2.cpp SDLConsole.o SDLAudioManager.o
g++ main2.cpp SDLConsole.o SDLAudioManager.o -g -std=c++17 -o synth2 -lSDL2 -lSDL2_ttf

SDLConsole.o: SDLConsole.cpp SDLConsole.h
g++ SDLConsole.cpp -c -g -std=c++17 -o SDLConsole.o -lSDL2 -lSDL2_ttf

SDLAudioManager.o: SDLAudioManager.cpp SDLAudioManager.h
g++ SDLAudioManager.cpp -c -g -std=c++17 -o SDLAudioManager.o -lSDL2

clean:
rm *.o synth1 synth2
78 changes: 78 additions & 0 deletions Linux/SDLAudioManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
SDLAudioManager.cpp
Copyright 2019 David V. Makray

This file is dual licensed under both the GPL3 and MIT licenses.
*/

#include <iostream>
#include <SDL2/SDL.h>
#include "SDLAudioManager.h"

SDLAudioManager* SDLAudioManager::s_Instance = nullptr;

SDLAudioManager::SDLAudioManager()
{
s_Instance = this;

if(SDL_Init(SDL_INIT_AUDIO) < 0)
{
std::cerr << "SDL2 didn't initialize." << std::endl;
exit(1);
}
}

SDLAudioManager::~SDLAudioManager()
{
SDL_CloseAudio();
}

static void AudioCallbackWrap(void* userdata, unsigned char* stream, int streamLength)
{
SDLAudioManager::s_Instance->AudioCallback(userdata, stream, streamLength);
}

void SDLAudioManager::AudioCallback(void* userdata, unsigned char* stream, int streamLength)
{
TimeStruct* time_struct = (TimeStruct*)userdata;
if (streamLength == 0)
return;

SDL_memset(stream, 0, streamLength);
float* stream_float = (float*)stream;
int audio_index;
for (audio_index = 0; audio_index < (streamLength/sizeof(float)); audio_index++)
{
stream_float[audio_index] = (float)(m_userFunction(time_struct->audio_time + (double)audio_index / (double)44100));
}
time_struct->audio_time += (double)audio_index / 44100.0;
}

double SDLAudioManager::GetTime()
{
return time_struct.audio_time;
}

void SDLAudioManager::SetUserFunction(double(*func)(double))
{
m_userFunction = func;

//Setup the parameters of the audio stream
SDL_memset(&m_audio_req, 0, sizeof(m_audio_req));
m_audio_req.freq = 48000;
m_audio_req.format = AUDIO_F32;
m_audio_req.channels = 1;
m_audio_req.samples = 1024;
m_audio_req.callback = AudioCallbackWrap;
m_audio_req.userdata = &time_struct;

m_dev = SDL_OpenAudioDevice(NULL, 0, &m_audio_req, NULL, 0);
if(m_dev == 0)
{
std::cerr << "Error: " << SDL_GetError() << std::endl;
SDL_Quit();
exit(1);
}

SDL_PauseAudioDevice(m_dev, 0); //Play audio
}
25 changes: 25 additions & 0 deletions Linux/SDLAudioManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const double PI = 2.0 * acos(0.0);

static void AudioCallbackWrap(void*, unsigned char*, int);

struct TimeStruct
{
double audio_time = 0.0;
};

class SDLAudioManager
{
public:
SDLAudioManager();
~SDLAudioManager();
static SDLAudioManager* s_Instance;
void AudioCallback(void*, unsigned char*, int);
double GetTime();
void SetUserFunction(double(*func)(double));

private:
TimeStruct time_struct;
double(*m_userFunction)(double);
SDL_AudioSpec m_audio_req;
SDL_AudioDeviceID m_dev;
};
123 changes: 123 additions & 0 deletions Linux/SDLConsole.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
SDLConsole.cpp
Copyright 2019 David V. Makray

This file is dual licensed under both the GPL3 and MIT licenses.
*/

#include <iostream>
#include <vector>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>

#include "SDLConsole.h"

SDLConsole::SDLConsole()
{
//Initialize SDL video
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
std::cerr << "Unable to init SDL: " << SDL_GetError() << std::endl;
exit(1);
}

if (TTF_Init() != 0)
{
std::cerr << "TTF_Init failed." << std::endl;
SDL_Quit();
exit(1);
}

m_font = TTF_OpenFont("/usr/share/fonts/truetype/freefont/FreeMono.ttf", 16);
if (m_font == nullptr)
{
std::cerr << "TTF_OpenFont failed." << std::endl;
SDL_Quit();
exit(1);
}
m_font_height = TTF_FontHeight(m_font);

//Make sure SDL cleans up prior to exit
atexit(SDL_Quit);

//Create a new window
SDL_Window* window = SDL_CreateWindow(NULL, 0, 0, 800, 600, SDL_WINDOW_SHOWN);
if (window == nullptr)
{
std::cerr << "CreateWindow failed." << std::endl;
SDL_Quit();
exit(1);
}

m_renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (m_renderer == nullptr)
{
std::cerr << "CreateRenderer failed." << std::endl;
SDL_DestroyWindow(window);
SDL_Quit();
exit(1);
}
}

SDLConsole::~SDLConsole()
{
TTF_CloseFont(m_font);
SDL_Quit();
}

SDLConsole& SDLConsole::operator<<(std::string stream_text)
{
if (m_ConsoleText.size() == 0)
m_ConsoleText.push_back(stream_text);
else
m_ConsoleText.back() += stream_text;
return *this;
}

SDLConsole& SDLConsole::operator<<(Endl)
{
m_ConsoleText.push_back("");
return *this;
}

void SDLConsole::Render()
{
SDL_SetRenderDrawColor(m_renderer, 0, 0, 0, 255);
SDL_RenderClear(m_renderer);

const SDL_Color white = { 255, 255, 255, 255 };
int cumlative_font_offset = 0;

for (auto current_line : m_ConsoleText)
{
if (current_line == "")
{
cumlative_font_offset += m_font_height + 1;
continue;
}

//Render a line of text into a surface
SDL_Surface* surface = TTF_RenderText_Blended(m_font, current_line.c_str(), white);
if (surface == nullptr)
{
std::cerr << "TTF_RenderText failed." << std::endl;
SDL_Quit();
exit(1);
}

//Make surface into a texture
SDL_Texture* texture = SDL_CreateTextureFromSurface(m_renderer, surface);
SDL_FreeSurface(surface);
if (texture == nullptr)
{
std::cerr << "CreateTexture failed." << std::endl;
SDL_Quit();
exit(1);
}
SDL_Rect dest = {0, cumlative_font_offset, 0, 0};
SDL_QueryTexture(texture, NULL, NULL, &dest.w, &dest.h);
SDL_RenderCopy(m_renderer, texture, NULL, &dest);
cumlative_font_offset += m_font_height + 1;
}
SDL_RenderPresent(m_renderer);
}
18 changes: 18 additions & 0 deletions Linux/SDLConsole.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class SDLConsole
{
public:
SDLConsole();
~SDLConsole();
void Render();

std::vector<std::string> m_ConsoleText;
static struct Endl{} endl;

SDLConsole& operator<<(std::string);
SDLConsole& operator<<(Endl);

private:
SDL_Renderer* m_renderer;
TTF_Font* m_font;
int m_font_height;
};
Loading