#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <unistd.h>
#include <cmath>
#include <algorithm>
#include <string>
#include <AL/al.h>
#include <AL/alc.h>
using namespace std;
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define null nullptr
#define FREQ (44100)
#define MULV (32768)
ALCdevice* dev;
ALCcontext* ctx;
ALfloat listenerPos[] = {0.0,0.0,0.0};
const ALfloat listenerVel[] = {5.0,0.0,0.0};
const ALfloat listenerOri[] = {0.0,0.0,1.0, 0.0,1.0,0.0};
const ALfloat srcPos[] = {0.0,0.0,1.0};
ALuint srcId,bufId;
float volume=0.75f;
double smoothstep(double a)
{
return 3*a*a - 2*a*a*a;
}
int main(int argc, char** argv)
{
if(argc!=6){puts("Usage: playsine <Seconds> <Hz> <TFadeoff> <Exp> <Amp>");return -1;}
string sT(argv[1]),sF(argv[2]),sExp(argv[4]),sTFO(argv[3]),sAmp(argv[5]);
int freq = stoi(sF);
int time = stoi(sT);
double Vexp = double(stof(sExp));
double Tfo = double(stof(sTFO));
double Amp = double(stof(sAmp));
int FLEN = time * FREQ;
dev = alcOpenDevice(null);
if(!dev){return -2;}
ctx = alcCreateContext(dev,null);
alcMakeContextCurrent(ctx);
if(!ctx){return -2;}
alListenerfv(AL_POSITION, listenerPos);
alListenerfv(AL_VELOCITY, listenerVel);
alListenerfv(AL_ORIENTATION, listenerOri);
if(alGetError()!=AL_NO_ERROR){return -2;}
alGenSources(1,&srcId);
if(alGetError()!=AL_NO_ERROR){return -3;}
alSourcefv(srcId, AL_POSITION, srcPos);
alGenBuffers(1,&bufId);
if(alGetError()!=AL_NO_ERROR){return -3;}
vector<short> arr;
arr.resize(FLEN);
double Seclim = Tfo;
int ilim = FLEN-int(FREQ*Tfo);
for(int i=0;i<FLEN;i++)
{
double t = double(i)/double(FREQ);
double tfe=double(FLEN-i)/double(FREQ);
double tf = tfe/Seclim;
double OT = (2.f*float(M_PI)*freq)/double(FREQ);
double Val = sin( OT * i )*MULV*Amp;
if(i>ilim)
{
Val *= pow(tf,Vexp);
}
Val *= volume;
arr[ i ] = short(Val);
}
alBufferData(bufId,AL_FORMAT_MONO16,arr.data(),FLEN*2,FREQ);
alSourcei(srcId, AL_BUFFER, bufId);
alSourcePlay(srcId);
ALint state;
//sleep(time);
do
{
alGetSourcei(srcId,AL_SOURCE_STATE,&state);
//listenerPos[0]+=1.0;
//alListenerfv(AL_POSITION, listenerPos);
usleep(1000);
}while(state == AL_PLAYING);
alDeleteSources(1,&srcId);
alDeleteBuffers(1,&bufId);
alcDestroyContext(ctx);
alcCloseDevice(dev);
return 0;
}