initial commit

took me a day to make the base...
...and ~12 hours to write a reader that reads 100% of all demo songs in
1.0
This commit is contained in:
tildearrow 2021-05-11 15:08:08 -05:00
commit 783d56c72a
26 changed files with 1660 additions and 0 deletions

30
src/audio/abstract.cpp Normal file
View file

@ -0,0 +1,30 @@
#include "taAudio.h"
void TAAudio::setSampleRateChangeCallback(void (*callback)(SampleRateChangeEvent)) {
sampleRateChanged=callback;
}
void TAAudio::setBufferSizeChangeCallback(void (*callback)(BufferSizeChangeEvent)) {
bufferSizeChanged=callback;
}
void TAAudio::setCallback(void (*callback)(float**,float**,int,int,unsigned int)) {
audioProcCallback=callback;
}
void* TAAudio::getContext() {
return NULL;
}
bool TAAudio::quit() {
return true;
}
bool TAAudio::setRun(bool run) {
running=run;
return running;
}
bool TAAudio::init(TAAudioDesc& request, TAAudioDesc& response) {
return false;
}

156
src/audio/jack.cpp Normal file
View file

@ -0,0 +1,156 @@
#include <string.h>
#include "jack.h"
int taJACKonSampleRate(jack_nframes_t rate, void* inst) {
TAAudioJACK* in=(TAAudioJACK*)inst;
in->onSampleRate(rate);
return 0;
}
int taJACKonBufferSize(jack_nframes_t bufsize, void* inst) {
TAAudioJACK* in=(TAAudioJACK*)inst;
in->onBufferSize(bufsize);
return 0;
}
int taJACKProcess(jack_nframes_t nframes, void* inst) {
TAAudioJACK* in=(TAAudioJACK*)inst;
in->onProcess(nframes);
return 0;
}
void TAAudioJACK::onSampleRate(jack_nframes_t rate) {
if (sampleRateChanged!=NULL) {
sampleRateChanged(SampleRateChangeEvent(rate));
}
}
void TAAudioJACK::onBufferSize(jack_nframes_t bufsize) {
if (bufferSizeChanged!=NULL) {
bufferSizeChanged(BufferSizeChangeEvent(bufsize));
}
}
void TAAudioJACK::onProcess(jack_nframes_t nframes) {
if (audioProcCallback!=NULL) {
audioProcCallback(inBufs,outBufs,desc.inChans,desc.outChans,desc.bufsize);
}
for (int i=0; i<desc.inChans; i++) {
iInBufs[i]=(float*)jack_port_get_buffer(ai[i],nframes);
memcpy(iInBufs[i],inBufs[i],desc.bufsize*sizeof(float));
}
for (int i=0; i<desc.outChans; i++) {
iOutBufs[i]=(float*)jack_port_get_buffer(ao[i],nframes);
memcpy(iOutBufs[i],outBufs[i],desc.bufsize*sizeof(float));
}
}
void* TAAudioJACK::getContext() {
return (void*)ac;
}
bool TAAudioJACK::quit() {
if (!initialized) return false;
if (running) {
running=false;
if (jack_deactivate(ac)) return false;
}
for (int i=0; i<desc.inChans; i++) {
jack_port_unregister(ac,ai[i]);
ai[i]=NULL;
delete[] inBufs[i];
}
for (int i=0; i<desc.outChans; i++) {
jack_port_unregister(ac,ao[i]);
ao[i]=NULL;
delete[] outBufs[i];
}
delete[] iInBufs;
delete[] iOutBufs;
delete[] inBufs;
delete[] outBufs;
delete[] ai;
delete[] ao;
jack_client_close(ac);
ac=NULL;
initialized=false;
return true;
}
bool TAAudioJACK::setRun(bool run) {
if (!initialized) return false;
if (running==run) {
return running;
}
if (run) {
if (jack_activate(ac)) return false;
for (int i=0; i<desc.outChans; i++) {
jack_connect(ac,(desc.name+String(":out")+std::to_string(i)).c_str(),(String("system:playback_")+std::to_string(i+1)).c_str());
}
running=true;
} else {
if (jack_deactivate(ac)) return true;
running=false;
}
return running;
}
bool TAAudioJACK::init(TAAudioDesc& request, TAAudioDesc& response) {
if (initialized) return false;
desc=request;
desc.outFormat=TA_AUDIO_FORMAT_F32;
jack_status_t as;
ac=jack_client_open(desc.name.c_str(),JackNoStartServer,&as);
if (ac==NULL) return false;
desc.name=String(jack_get_client_name(ac));
jack_set_sample_rate_callback(ac,taJACKonSampleRate,this);
jack_set_buffer_size_callback(ac,taJACKonBufferSize,this);
jack_set_process_callback(ac,taJACKProcess,this);
jack_nframes_t count=jack_get_buffer_size(ac);
desc.bufsize=count;
desc.fragments=1;
jack_nframes_t sampleRate=jack_get_sample_rate(ac);
desc.rate=sampleRate;
if (desc.inChans>0) {
inBufs=new float*[desc.inChans];
iInBufs=new float*[desc.inChans];
ai=new jack_port_t*[desc.inChans];
for (int i=0; i<desc.inChans; i++) {
ai[i]=jack_port_register(ac,(String("in")+std::to_string(i)).c_str(),JACK_DEFAULT_AUDIO_TYPE,JackPortIsInput,0);
if (ai[i]==NULL) {
desc.inChans=i;
break;
}
inBufs[i]=new float[count];
}
}
if (desc.outChans>0) {
outBufs=new float*[desc.outChans];
iOutBufs=new float*[desc.outChans];
ao=new jack_port_t*[desc.outChans];
for (int i=0; i<desc.outChans; i++) {
ao[i]=jack_port_register(ac,(String("out")+std::to_string(i)).c_str(),JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput,0);
if (ao[i]==NULL) {
desc.outChans=i;
break;
}
outBufs[i]=new float[count];
}
}
response=desc;
initialized=true;
return true;
}

26
src/audio/jack.h Normal file
View file

@ -0,0 +1,26 @@
#include "taAudio.h"
#include <jack/jack.h>
class TAAudioJACK: public TAAudio {
jack_client_t* ac;
jack_port_t** ai;
jack_port_t** ao;
float** iInBufs;
float** iOutBufs;
public:
void onSampleRate(jack_nframes_t rate);
void onBufferSize(jack_nframes_t bufsize);
void onProcess(jack_nframes_t nframes);
void* getContext();
bool quit();
bool setRun(bool run);
bool init(TAAudioDesc& request, TAAudioDesc& response);
TAAudioJACK():
ac(NULL),
ai(NULL),
ao(NULL) {}
};

86
src/audio/sdl.cpp Normal file
View file

@ -0,0 +1,86 @@
#include <string.h>
#include "sdl.h"
void taSDLProcess(void* inst, unsigned char* buf, int nframes) {
TAAudioSDL* in=(TAAudioSDL*)inst;
in->onProcess(buf,nframes);
}
void TAAudioSDL::onProcess(unsigned char* buf, int nframes) {
if (audioProcCallback!=NULL) {
audioProcCallback(inBufs,outBufs,desc.inChans,desc.outChans,desc.bufsize);
}
float* fbuf=(float*)buf;
for (size_t i=0; i<desc.outChans; i++) {
int k=0;
for (size_t j=i; j<desc.bufsize*desc.outChans; j+=desc.outChans) {
fbuf[j]=outBufs[i][k++];
}
}
}
void* TAAudioSDL::getContext() {
return (void*)&ac;
}
bool TAAudioSDL::quit() {
if (!initialized) return false;
SDL_CloseAudioDevice(ai);
if (running) {
running=false;
}
for (int i=0; i<desc.outChans; i++) {
delete[] outBufs[i];
}
delete[] outBufs;
initialized=false;
return true;
}
bool TAAudioSDL::setRun(bool run) {
if (!initialized) return false;
SDL_PauseAudioDevice(ai,!run);
running=run;
return running;
}
bool TAAudioSDL::init(TAAudioDesc& request, TAAudioDesc& response) {
if (initialized) return false;
if (SDL_Init(SDL_INIT_AUDIO)<0) return false;
desc=request;
desc.outFormat=TA_AUDIO_FORMAT_F32;
ac.freq=desc.rate;
ac.format=AUDIO_F32;
ac.channels=desc.outChans;
ac.samples=desc.bufsize;
ac.callback=taSDLProcess;
ac.userdata=this;
ai=SDL_OpenAudioDevice(NULL,0,&ac,&ar,SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
if (ai==0) return false;
desc.name="";
desc.rate=ar.freq;
desc.inChans=0;
desc.outChans=ar.channels;
desc.bufsize=ar.samples;
desc.fragments=1;
if (desc.outChans>0) {
outBufs=new float*[desc.outChans];
for (int i=0; i<desc.outChans; i++) {
outBufs[i]=new float[desc.bufsize];
}
}
response=desc;
initialized=true;
return true;
}

18
src/audio/sdl.h Normal file
View file

@ -0,0 +1,18 @@
#include "taAudio.h"
#include <SDL2/SDL.h>
class TAAudioSDL: public TAAudio {
SDL_AudioSpec ac, ar;
SDL_AudioDeviceID ai;
float** iInBufs;
float** iOutBufs;
public:
void onProcess(unsigned char* buf, int nframes);
void* getContext();
bool quit();
bool setRun(bool run);
bool init(TAAudioDesc& request, TAAudioDesc& response);
};

79
src/audio/taAudio.h Normal file
View file

@ -0,0 +1,79 @@
#ifndef _TAAUDIO_H
#define _TAAUDIO_H
#include "../ta-utils.h"
struct SampleRateChangeEvent {
double rate;
SampleRateChangeEvent(double r):
rate(r) {}
};
struct BufferSizeChangeEvent {
unsigned int bufsize;
BufferSizeChangeEvent(unsigned int bs):
bufsize(bs) {}
};
enum TAAudioFormat {
TA_AUDIO_FORMAT_F32=0,
TA_AUDIO_FORMAT_F64,
TA_AUDIO_FORMAT_U8,
TA_AUDIO_FORMAT_S8,
TA_AUDIO_FORMAT_U16,
TA_AUDIO_FORMAT_S16,
TA_AUDIO_FORMAT_U32,
TA_AUDIO_FORMAT_S32,
TA_AUDIO_FORMAT_U16BE,
TA_AUDIO_FORMAT_S16BE,
TA_AUDIO_FORMAT_U32BE,
TA_AUDIO_FORMAT_S32BE
};
struct TAAudioDesc {
String name;
double rate;
unsigned int bufsize, fragments;
unsigned char inChans, outChans;
TAAudioFormat outFormat;
TAAudioDesc():
rate(0.0),
bufsize(0),
fragments(0),
inChans(0),
outChans(0),
outFormat(TA_AUDIO_FORMAT_F32) {}
};
class TAAudio {
protected:
TAAudioDesc desc;
TAAudioFormat outFormat;
bool running, initialized;
float** inBufs;
float** outBufs;
void (*audioProcCallback)(float**,float**,int,int,unsigned int);
void (*sampleRateChanged)(SampleRateChangeEvent);
void (*bufferSizeChanged)(BufferSizeChangeEvent);
public:
void setSampleRateChangeCallback(void (*callback)(SampleRateChangeEvent));
void setBufferSizeChangeCallback(void (*callback)(BufferSizeChangeEvent));
void setCallback(void (*callback)(float**,float**,int,int,unsigned int));
virtual void* getContext();
virtual bool quit();
virtual bool setRun(bool run);
virtual bool init(TAAudioDesc& request, TAAudioDesc& response);
TAAudio():
outFormat(TA_AUDIO_FORMAT_F32),
running(false),
initialized(false),
inBufs(NULL),
outBufs(NULL),
audioProcCallback(NULL),
sampleRateChanged(NULL),
bufferSizeChanged(NULL) {}
};
#endif