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:
commit
783d56c72a
26 changed files with 1660 additions and 0 deletions
30
src/audio/abstract.cpp
Normal file
30
src/audio/abstract.cpp
Normal 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
156
src/audio/jack.cpp
Normal 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
26
src/audio/jack.h
Normal 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
86
src/audio/sdl.cpp
Normal 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*)∾
|
||||
}
|
||||
|
||||
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
18
src/audio/sdl.h
Normal 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
79
src/audio/taAudio.h
Normal 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue