chord/audio.c
2024-05-15 07:36:04 -05:00

130 lines
2.8 KiB
C

#include<ctype.h>
#include<fcntl.h>
#include<math.h>
#include<portaudio.h>
#include<stdbool.h>
#include<stdint.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include<unistd.h>
#include"audio.h"
/*******
* Create new Audio struct
*******/
Audio aud_new(size_t samplerate,size_t nsamples,size_t channels)
{
Audio aud=(Audio){0};
aud.samplerate=samplerate;
aud.nsamples=nsamples;
aud.channels=channels;
aud.data=malloc(nsamples*sizeof(uint16_t));
return aud;
}
/*******
* Free Audio struct resources
*******/
void aud_free(Audio*aud)
{
if(!aud)return;
if(aud->data)
free(aud->data);
aud->data=0;
*aud=(Audio){0};
}
/*******
* Convolver (low-pass filter)
*******/
void aud_avg(Audio*aud,size_t blocksize)
{
if(!aud->data||!aud->nsamples||!aud->channels||!aud->samplerate||!blocksize)return;
for(size_t i=blocksize-1;i<aud->nsamples;++i)
{
uint16_t sum=0;
for(size_t j=0;j<blocksize&&(i+j)<aud->nsamples;++j)
sum+=aud->data[i+j];
/* for(size_t ch=0;ch<aud->channels;++ch,++i) */
aud->data[i]=sum/blocksize;
}
}
/*******
* Randomize data
*******/
void aud_rnd(Audio*aud,size_t mode)
{
if(!aud->data||!aud->nsamples||!aud->samplerate||!aud->channels)return;
for(size_t i=0;i<aud->nsamples;++i)
{
/* for(size_t ch=0;ch<aud->channels;++ch,++i) */
uint16_t sample=rand();
if(mode==GEN)
aud->data[i]=sample;
else if(mode==ADD)
aud->data[i]=(aud->data[i]+sample)/2;
}
}
/*******
* Zero all data
*******/
void aud_zero(Audio*aud)
{
if(!aud->data||!aud->nsamples||!aud->channels)return;
memset(aud->data,0,aud->nsamples*sizeof(uint16_t));
}
/*******
* Naïve amplitude envelope
*******/
void aud_env(Audio*aud)
{
if(!aud)return;
if(!aud->data)return;
size_t range=aud->nsamples/8;
for(size_t i=0;i<range;++i)
aud->data[i]*=(float)i/range;
for(size_t i=0;i<aud->nsamples/8;++i)
aud->data[aud->nsamples-1-i]*=(float)i/range;
}
/*******
* Sine waveform generator
*******/
void aud_sine(Audio*aud,double freq,size_t mode)
{
if(!aud->data||!aud->nsamples||!aud->samplerate||!aud->channels)return;
for(size_t i=0;i<aud->nsamples;++i)
{
/* for(size_t ch=0;ch<aud->channels;++ch,++i) */
uint16_t sample=sin((2*PI)/(aud->samplerate/freq)*i)*8000;
if(mode==GEN)
aud->data[i]=sample;
else if(mode==ADD)
aud->data[i]=(aud->data[i]+sample)/2;
}
}
/*******
* Triangle waveform generator
*******/
void aud_tri(Audio*aud,double freq,size_t mode)
{
if(!aud->data||!aud->nsamples||!aud->samplerate||!aud->channels)return;
for(size_t i=0;i<aud->nsamples;++i)
{
/* for(size_t ch=0;ch<aud->channels;++ch,++i) */
//aud->data[i]=sin(i);
uint16_t sample=(i%(int)(aud->samplerate/freq))*7;
if(mode==GEN)
aud->data[i]=sample;
else if(mode==ADD)
aud->data[i]=(aud->data[i]+sample)/2;
}
}