first commit

This commit is contained in:
corey 2024-06-30 13:37:13 -05:00
commit 125936dfa0
3 changed files with 156 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.o
*.wav
/conv

10
Makefile Normal file
View File

@ -0,0 +1,10 @@
CFLAGS= -Wfatal-errors $(shell pkgconf --cflags portaudio-2.0)
LDFLAGS= -s $(shell pkgconf --libs portaudio-2.0)
all: conv
conv: main.o
$(CC) $^ -o $@ $(LDFLAGS)
%.o: %.c
$(CC) -c $^ -o $@ $(CFLAGS)
clean:
$(RM) conv *.o

143
main.c Normal file
View File

@ -0,0 +1,143 @@
#include<portaudio.h>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<stdint.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
// Open .WAV file, read into buffer
// assuming samplerate, bitdepth, and
// channels
void op(const char*fn,float*buf,int len)
{
int fd;
int16_t tmpbuf[len];
if(!fn||!buf||!len)return;
fd=open(fn,O_RDONLY);
if(fd<0)
{
write(1,"fail\n",5);
return;
}
// Skip WAVE header (assume 44.1kHz
// samplerate, mono channels, and 16bit
lseek(fd,40,SEEK_SET);
// Read file into buffer and convert from
// int16_t to float
read(fd,tmpbuf,len*sizeof(int16_t));
for(int i=0;i<len;++i)
buf[i]=((float)tmpbuf[i])/(float)INT16_MAX;
close(fd);
}
// Low-pass convolving filter
void lp(float*cur,float*prev,float*next,int len,int winsz)
{
if(!cur||!prev||!next||!len||!winsz)return;
for(int i=0,k;i<len;++i)
{
float sum=0;
k=i-winsz/2;
for(int j=0;j<winsz;++j,++k)
{
if(k<0)
sum+=prev[k+len];
else if(k>=len)
sum+=next[k%len];
else
sum+=cur[k];
}
cur[i]=sum/winsz;
}
}
// Sine oscillator
void sn(float*d,int len,int cycle,int*offset)
{
for(int j=0,cycle=44100/440;j<len;++j,*offset=(*offset+1)%cycle)
d[j]=sin(2.0*M_PI*((float)*offset)/cycle)*0.25;
}
// Saw-tooth oscillator
void sw(float*d,int len,int cycle,int*offset)
{
*offset%=cycle;
for(int j=0,cycle=44100/440;j<len;++j,*offset=(*offset+1)%cycle)
d[j]=((float)*offset)/cycle*0.25;
}
#define swapbuffers() do{float*tmp=prev;prev=cur;cur=next;next=tmp;}while(0)
int main(void)
{
PaStream*pa;
const int len=1024;
float buffer1[len];
float buffer2[len];
float buffer3[len];
float wave[44100];
float*cur=buffer2,*next=buffer3,*prev=buffer1;
int envsize=400;
int offset=0;
int wave_or_osc=0;
if(envsize>len)envsize=len;
// Init portaudio
Pa_Initialize();
Pa_OpenDefaultStream(&pa,0,1,paFloat32,44100,len,NULL,NULL);
Pa_StartStream(pa);
// Read wave file into buffer
op("w.wav",wave,44100);
// Generate initial buffer
if(wave_or_osc==0)
sw(next,len,44100/440,&offset);
else
{
memcpy(next,wave+offset,len*sizeof(float));
offset+=len;
}
// Play dynamic audio
for(int i=0,last=44100/len/2;i<last;++i)
{
swapbuffers();
// Oscillator
if(wave_or_osc==0)
sw(next,len,44100/440,&offset);
else
{
memcpy(next,wave+offset,len*sizeof(float));
offset+=len;
}
// Filter
lp(cur,prev,next,len,44100/1000);
// Amplitude envelope
if(i==0)
for(int j=0;j<envsize;++j)
cur[j]*=((float)j)/envsize;
else if(i==last-1)
for(int j=0;j<envsize;++j)
cur[len-j]*=((float)j)/envsize;
Pa_WriteStream(pa,cur,len);
}
Pa_Sleep(800);
// Quit
Pa_CloseStream(pa);
Pa_Terminate();
}